╭ changed ────────────╮ │src/ui/Home/Users.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │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 │ ╰─────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │88 // a trailing "next" row when more remain. each window row navigates to the │ │89 // adjacent window (full reload on web, Nav rebuild on the TUI). │ │90 var items: std.ArrayList(ui.FlowBox.Item) = .empty; │ │91 - if (data.after > 0) │ │92 - try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/users?after={d}", .{data.after -| page_size}) });│ │91 + if (data.start > 0) │ │92 + try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/users/start:{d}", .{data.start -| page_size}) });│ │93 for (data.users) |user| │ │94 // clicking a user opens their page; the "a:" prefix makes the web │ │95 // renderer emit an <a href="/user/foo"> anchor. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 97 .text = try std.fmt.allocPrint(aa, "{s} ({s})", .{ user.name, user.display_name }), │ │ 98 .link = try std.fmt.allocPrint(aa, "a:/user/{s}", .{user.name}), │ │ 99 }); │ │100 - if (data.next_after) |next_after| │ │101 - try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/users?after={d}", .{next_after}) });│ │100 + if (data.next_start) |next_start| │ │101 + try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/users/start:{d}", .{next_start}) });│ │102 try self.list.setItems(allocator, items.items); │ │103 │ │104 return self; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯