╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │190 // mirror carries the selected file (when the route named one) so the url │ │191 // keeps it before focus enters the view. │ │192 const files_path = if (files.selected_file) |f| try Files.childDir(arena.allocator(), files.dir, f) else files.dir; │ │206 - // the content window offset only applies to a selected file, so the bare │ │193 + // the content window only applies to a selected file, so the bare │ │194 // directory route drops it. │ │208 - const files_route_after = if (files.selected_file != null) files_after else 0; │ │209 - const route_name = (ui.RoutablePage.repoFilesRoute(rf.identity, files.ref_or_oid, files.ref_or_oid_value, files_path, files_route_after) orelse return error.NotFound).repo_files.name;│ │210 - const commits_route_name = (ui.RoutablePage.repoCommitsRoute(rf.identity, commits.ref_or_oid, commits.ref_or_oid_value, commits_after) orelse return error.NotFound).repo_commits.name;│ │195 + const files_route_start = if (files.selected_file != null) files_start else 0; │ │196 + const route_name = (ui.RoutablePage.repoFilesRoute(rf.identity, files.ref_or_oid, files.ref_or_oid_value, files_path, files_route_start) orelse return error.NotFound).repo_files; │ │197 + const commits_route_name = (ui.RoutablePage.repoCommitsRoute(rf.identity, commits.ref_or_oid, commits.ref_or_oid_value, commits_start) orelse return error.NotFound).repo_commits; │ │198 │ │199 return .{ │ │200 // files and commits resolve the same ref, so either's serves the header, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │209 .auth = Auth.init(), │ │210 .quit = Quit.init(), │ │211 .route_name = route_name, │ │225 - .files_after = files_route_after, │ │212 .commits_route_name = commits_route_name, │ │227 - .commits_after = commits_after, │ │213 .identity = Array.from(rf.identity) orelse return error.NotFound,│ │214 }; │ │215 } │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │314 switch (std.meta.activeTag(stack.children.values()[index])) { │ │315 // files/commits carry this page's content route (directory / log │ │316 // page); settings/auth carry only "owner/name". │ │332 - .repo_commits => self.session.data.current_page = .{ .repo_commits = .{ .name = self.data.commits_route_name, .after = self.data.commits_after } }, │ │333 - // the refs tab mirrors this page's paginated column + offset. │ │334 - .repo_refs => self.session.data.current_page = .{ .repo_refs = .{ .name = self.data.identity, .kind = self.data.refs.kind, .after = self.data.refs.after } }, │ │317 + .repo_commits => self.session.data.current_page = .{ .repo_commits = self.data.commits_route_name }, │ │318 + // the refs tab mirrors this page's windowed column. │ │319 + .repo_refs => self.session.data.current_page = ui.RoutablePage.repoRefsRoute(self.data.identity.slice(), self.data.refs.kind, self.data.refs.from) orelse self.session.data.current_page,│ │320 // the issues tab mirrors this page's tag filter (issue urls │ │321 // themselves never carry the tag). │ │322 .repo_issues => self.session.data.current_page = ui.RoutablePage.repoIssuesRoute(self.data.identity.slice(), .open, self.data.issues.tag, "") orelse self.session.data.current_page, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │326 // alone (nothing to mirror into the url). │ │327 .quit => {}, │ │328 // the files tab (this page's directory route) │ │344 - else => self.session.data.current_page = .{ .repo_files = .{ .name = self.data.route_name, .after = self.data.files_after } },│ │329 + else => self.session.data.current_page = .{ .repo_files = self.data.route_name }, │ │330 } │ │331 } │ │332 try self.box.build(allocator, constraint, root_focus); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │54 │ │55 // walk the log for an opened repo. generic over the repo's backend and hash │ │56 // kind so the oid buffers and diff types it threads through match the repo's │ │57 -// opts. `after` is the hunk index the selected commit's (the first one, the │ │57 +// opts. `start` is the hunk index the selected commit's (the first one, the │ │58 // walk root) diff window starts at; 0 is the first window, moved by │ │59 // "next"/"previous". walks with the arena's backing allocator (transient; the│ │60 // commits we keep are duped into the page arena so they outlive it). │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │68 identity: []const u8, │ │69 requested_ref_or_oid: ?ui.RoutablePage.RefOrOid, │ │70 requested_value: []const u8, │ │71 - after: usize, │ │71 + start: usize, │ │72 ) !Self { │ │73 const aa = arena.allocator(); │ │74 const hex_len = ui.ResolvedRefOrOid(repo_kind, repo_opts).hex_len;│ ╰──────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │121 for (buf[0..count], oids[0..count], 0..) |*commit, oid, i| { │ │122 // the selected commit (the first, == start_oid) shows the window the │ │123 // url asks for; the rest show their first window. │ │124 - const start = if (i == 0) after else 0; │ │125 - const rendered = renderCommitDiff(repo_kind, repo_opts, io, gpa, aa, repo, oid, start, diff_page) catch │ │124 + const window_start = if (i == 0) start else 0; │ │125 + const rendered = renderCommitDiff(repo_kind, repo_opts, io, gpa, aa, repo, oid, window_start, diff_page) catch│ │126 RenderedDiff{ .hunks = &.{}, .has_prev = false, .has_more = false }; │ │127 commit.hunks = rendered.hunks; │ │128 - commit.window_start = start; │ │128 + commit.window_start = window_start; │ │129 commit.has_prev = rendered.has_prev; │ │130 commit.has_more = rendered.has_more; │ │131 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │419 } │ │420 │ │421 // a focusable window-navigation row ("previous"/"next"). it's a link to this │ │422 - // commit's route at `target_after`, so activating it (the host follows the │ │422 + // commit's route at `target_start`, so activating it (the host follows the │ │423 // "a:" link) reloads the page on the adjacent window — same on TUI and web. │ │424 - fn addNavLink(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), label: []const u8, oid: []const u8, target_after: usize) !void {│ │425 - const link = try commitsLink(self.session.page_arena, self.data.identity, oid, target_after); │ │424 + fn addNavLink(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), label: []const u8, oid: []const u8, target_start: usize) !void {│ │425 + const link = try commitsLink(self.session.page_arena, self.data.identity, oid, target_start); │ │426 var tb = try wgt.TextBox(ui.Widget).init(allocator, label, .{ .border_style = .hidden, .rounded_corners = true, .wrap_kind = .none }); │ │427 errdefer tb.deinit(allocator); │ │428 tb.getFocus().focusable = true; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │514 } │ │515 } │ │516 │ │517 - // the selected hunk (or the "load more" row) shows a single border (the│ │518 - // focused TextBox upgrades it to a double border itself, so it stays │ │519 - // single when focus is on the commit list); the rest keep their │ │517 + // the selected hunk (or a window-navigation row) shows a single border │ │518 + // (the focused TextBox upgrades it to a double border itself, so it │ │519 + // stays single when focus is on the commit list); the rest keep their │ │520 // space-reserving hidden border. │ │521 const inner = self.diffInner(); │ │522 for (inner.children.keys(), inner.children.values()) |id, *child| { │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │790 }; │ │791 │ │792 // the "a:" navigation link for the commits page walking from commit `oid` within │ │793 -// `identity`, showing the selected commit's first `after` hunks (0 = default). │ │794 -fn commitsLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, oid: []const u8, after: usize) ![]const u8 {│ │795 - const route = ui.RoutablePage.repoCommitsRoute(identity, .object, oid, after) orelse return error.RouteTooLong; │ │793 +// `identity`, showing the selected commit's first `start` hunks (0 = default). │ │794 +fn commitsLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, oid: []const u8, start: usize) ![]const u8 {│ │795 + const route = ui.RoutablePage.repoCommitsRoute(identity, .object, oid, start) orelse return error.RouteTooLong; │ │796 const url = try route.urlAlloc(page_arena); │ │797 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); │ │798 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯