╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────────╮ │src/ui/Home/Repos.zig│ ╰─────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │30 var repos: std.ArrayList(evt.Repo) = .empty; │ │31 var owner_names: std.ArrayList([]const u8) = .empty; │ │32 │ │33 - const empty: Self = .{ .repos = &.{}, .owner_names = &.{}, .after = after, .next_after = null };│ │33 + const empty: Self = .{ .repos = &.{}, .owner_names = &.{}, .start = start, .next_start = null };│ │34 │ │35 // the repos ordered by creation time (oldest first); absent until the first │ │36 // repo exists. keyed by orderKey ([timestamp][event-id]); the trailing bytes │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │42 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->repo")) orelse return empty;│ │43 const event_id_to_repo = try DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │44 │ │45 - // read the window [after, after+page_size) with one seek to the start rank, │ │45 + // read the window [start, start+page_size) with one seek to the start rank, │ │46 // then a sequential walk │ │47 - const end = @min(after + page_size, count); │ │48 - var iter = try repo_id_set.iteratorFromIndex(after); │ │49 - var i = after; │ │47 + const end = @min(start + page_size, count); │ │48 + var iter = try repo_id_set.iteratorFromIndex(start); │ │49 + var i = start; │ │50 while (i < end) : (i += 1) { │ │51 var id_cursor = (try iter.next()) orelse break; │ │52 const id_kv = try id_cursor.readKeyValuePair(); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │65 return .{ │ │66 .repos = repos.items, │ │67 .owner_names = owner_names.items, │ │68 - .after = after, │ │69 - .next_after = if (end < count) end else null,│ │68 + .start = start, │ │69 + .next_start = if (end < count) end else null,│ │70 }; │ │71 } │ │72 │ ╰─────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 94 // a trailing "next" row when more remain. each window row navigates to the │ │ 95 // adjacent window (full reload on web, Nav rebuild on the TUI). │ │ 96 var items: std.ArrayList(ui.FlowBox.Item) = .empty; │ │ 97 - if (data.after > 0) │ │ 98 - try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/repos?after={d}", .{data.after -| page_size}) });│ │ 97 + if (data.start > 0) │ │ 98 + try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/repos/start:{d}", .{data.start -| page_size}) });│ │ 99 for (data.repos, 0..) |repo, i| { │ │100 // clicking a repo opens its page; the "a:" prefix makes the web │ │101 // renderer emit an <a href="/repo/alice/foo"> anchor. skip the link │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │106 .link = if (owner.len > 0) try std.fmt.allocPrint(aa, "a:/repo/{s}/{s}", .{ owner, repo.name }) else "", │ │107 }); │ │108 } │ │109 - if (data.next_after) |next_after| │ │110 - try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/repos?after={d}", .{next_after}) });│ │109 + if (data.next_start) |next_start| │ │110 + try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/repos/start:{d}", .{next_start}) });│ │111 try self.list.setItems(allocator, items.items); │ │112 │ │113 return self; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Home/Users.zig│ ╰─────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │13 pub const page_size = 20; // how many users one window shows │ │14 │ │15 users: []const evt.User.Safe, │ │16 -after: usize, // the window start this page was built with, mirrored into the url │ │17 -next_after: ?usize, // the `after` for the "next" row, or null when this is the last window│ │16 +start: usize, // the window start this page was built with, mirrored into the url │ │17 +next_start: ?usize, // the `start` for the "next" row, or null when this is the last window│ │18 │ │19 const Self = @This(); │ │20 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────╮ │21 pub fn init( │ │22 arena: *std.heap.ArenaAllocator, │ │23 haxy_moment: evt.AdminDB.HashMap(.read_only),│ │24 - after: usize, │ │24 + start: usize, │ │25 ) !Self { │ │26 const DB = evt.AdminDB; │ │27 const hash_kind = evt.admin_repo_opts.hash; │ ╰─────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │32 // user exists. keyed by orderKey ([timestamp][event-id]); the trailing bytes │ │33 // of each key are the user event id. │ │34 const user_id_set_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "user-id-set")) orelse│ │35 - return .{ .users = &.{}, .after = after, .next_after = null }; │ │35 + return .{ .users = &.{}, .start = start, .next_start = null }; │ │36 const user_id_set = try DB.SortedSet(.read_only).init(user_id_set_cursor); │ │37 const count = try user_id_set.count(); │ │38 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │39 const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->user")) orelse│ │40 - return .{ .users = &.{}, .after = after, .next_after = null }; │ │40 + return .{ .users = &.{}, .start = start, .next_start = null }; │ │41 const event_id_to_user = try DB.HashMap(.read_only).init(event_id_to_user_cursor); │ │42 │ │43 - // read the window [after, after+page_size) with one seek to the start rank, │ │43 + // read the window [start, start+page_size) with one seek to the start rank, │ │44 // then a sequential walk │ │45 - const end = @min(after + page_size, count); │ │46 - var iter = try user_id_set.iteratorFromIndex(after); │ │47 - var i = after; │ │45 + const end = @min(start + page_size, count); │ │46 + var iter = try user_id_set.iteratorFromIndex(start); │ │47 + var i = start; │ │48 while (i < end) : (i += 1) { │ │49 var id_cursor = (try iter.next()) orelse break; │ │50 const id_kv = try id_cursor.readKeyValuePair(); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │59 │ │60 return .{ │ │61 .users = users.items, │ │62 - .after = after, │ │63 - .next_after = if (end < count) end else null,│ │62 + .start = start, │ │63 + .next_start = if (end < count) end else null,│ │64 }; │ │65 } │ │66 │ ╰─────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯