╭ changed ──────╮ │src/ui/User.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │21 header: Header, │ │22 user: evt.User.Safe, │ │23 repos: []const evt.Repo, │ │24 -repos_after: usize, // the repos window this page was built with, mirrored into the url│ │25 -repos_next_after: ?usize, // the `after` for the "next" row, or null on the last window│ │24 +repos_start: usize, // the repos window this page was built with, mirrored into the url│ │25 +repos_next_start: ?usize, // the `start` for the "next" row, or null on the last window│ │26 settings: Settings, │ │27 auth: Auth, │ │28 quit: Quit, │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │34 arena: *std.heap.ArenaAllocator, │ │35 haxy_moment: evt.AdminDB.HashMap(.read_only), │ │36 name: ui.RoutablePage.Array(evt.User.name_max_len),│ │37 - after: usize, │ │37 + start: usize, │ │38 ) !Self { │ │39 const DB = evt.AdminDB; │ │40 const hash_kind = evt.admin_repo_opts.hash; │ ╰───────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │51 const user = (try evt.User.readById(DB, hash_kind, haxy_moment, arena, user_id)) orelse return error.NotFound;│ │52 │ │53 var repos: std.ArrayList(evt.Repo) = .empty; │ │54 - var repos_next_after: ?usize = null; │ │54 + var repos_next_start: ?usize = null; │ │55 │ │56 // the user-id->repo-id-set index maps each user to a set of their repo event │ │57 // ids ordered by creation time (oldest first); it only exists once a repo has │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │65 const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->repo")) orelse return error.NotFound;│ │66 const event_id_to_repo = try DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │67 │ │68 - // read the window [after, after+page_size) with one seek to the start │ │68 + // read the window [start, start+page_size) with one seek to the start │ │69 // rank, then a sequential walk. │ │70 - const end = @min(after + page_size, count); │ │71 - var repos_iter = try user_repos.iteratorFromIndex(after); │ │72 - var i = after; │ │70 + const end = @min(start + page_size, count); │ │71 + var repos_iter = try user_repos.iteratorFromIndex(start); │ │72 + var i = start; │ │73 while (i < end) : (i += 1) { │ │74 var kv_cursor = (try repos_iter.next()) orelse break; │ │75 const kv = try kv_cursor.readKeyValuePair(); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │83 const repo_event = try evt.read(evt.Repo, DB, hash_kind, arena, repo_map);│ │84 try repos.append(arena.allocator(), repo_event); │ │85 } │ │86 - repos_next_after = if (end < count) end else null; │ │86 + repos_next_start = if (end < count) end else null; │ │87 } │ │88 } │ │89 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────╮ │91 .header = try Header.init(arena, user.name),│ │92 .user = evt.User.Safe.init(user), │ │93 .repos = repos.items, │ │94 - .repos_after = after, │ │95 - .repos_next_after = repos_next_after, │ │94 + .repos_start = start, │ │95 + .repos_next_start = repos_next_start, │ │96 .settings = Settings.init(), │ │97 .auth = Auth.init(), │ │98 .quit = Quit.init(), │ ╰────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │139 // then a trailing "next" row when more remain. each window row │ │140 // navigates to the adjacent window of this user's repos. │ │141 var items: std.ArrayList(ui.FlowBox.Item) = .empty; │ │142 - if (data.repos_after > 0) │ │143 - try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/user/{s}?after={d}", .{ data.user.name, data.repos_after -| page_size }) }); │ │142 + if (data.repos_start > 0) │ │143 + try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/user/{s}/repos/start:{d}", .{ data.user.name, data.repos_start -| page_size }) });│ │144 for (data.repos) |repo| │ │145 // clicking a repo opens its page; the "a:" prefix makes the web │ │146 // renderer emit an <a href="/repo/alice/foo"> anchor. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │148 .text = try std.fmt.allocPrint(aa, "{s} - {s}", .{ repo.name, repo.description }), │ │149 .link = try std.fmt.allocPrint(aa, "a:/repo/{s}/{s}", .{ data.user.name, repo.name }), │ │150 }); │ │151 - if (data.repos_next_after) |next_after| │ │152 - try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/user/{s}?after={d}", .{ data.user.name, next_after }) }); │ │151 + if (data.repos_next_start) |next_start| │ │152 + try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/user/{s}/repos/start:{d}", .{ data.user.name, next_start }) });│ │153 try list.setItems(allocator, items.items); │ │154 │ │155 try stack.children.put(allocator, list.getFocus().id, .{ .flow_box_scroll = list }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │204 // alone (nothing to mirror into the url). │ │205 .quit => {}, │ │206 // the repos list (the default tab) │ │207 - else => self.session.data.current_page = .{ .user_repos = .{ .name = name, .after = self.data.repos_after } },│ │207 + else => self.session.data.current_page = .{ .user_repos = .{ .name = name, .start = self.data.repos_start } },│ │208 } │ │209 } │ │210 try self.box.build(allocator, constraint, root_focus); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯