╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │176 switch (index) { │ │177 // files/commits carry this page's content route (directory / log │ │178 // page); settings/auth carry only "owner/name". │ │173 - 1 => self.session.data.current_page = .{ .repo_commits = self.data.commits_route_name }, │ │179 + 1 => self.session.data.current_page = .{ .repo_commits = .{ .name = self.data.commits_route_name } },│ │180 2 => self.session.data.current_page = .{ .repo_settings = self.data.identity }, │ │181 3 => self.session.data.current_page = .{ .repo_auth = self.data.identity }, │ │182 // the quit tab is tty-only and not a route, so leave current_page │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │14 │ │15 // how many commits a page shows before a "next" link appears. │ │16 const page_size = 20; │ │17 -// max diff lines rendered per chunk (the initial render and each "load more") │ │18 -const diff_budget = 100; │ │17 +// how many diff hunks a commit shows per page; "load more" reveals another page.│ │18 +const diff_page = 10; │ │19 │ │20 pub const Hunk = struct { │ │21 lines: []const []const u8, │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │39 commits: []const Commit, │ │40 // the first oid of the next page, or null when this is the last page. │ │41 next_start: ?[]const u8, │ │42 -// the on-disk repo directory name (hex event id), for reopening to render more│ │43 -// diff hunks when "load more" is activated in the TUI. │ │44 -repo_dir_hex: []const u8, │ │42 │ │43 const Self = @This(); │ │44 │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │48 event_id: *const [evt.event_id_size]u8, │ │49 identity: []const u8, │ │50 start_oid: []const u8, │ │51 + // how many hunks the selected commit (the first one, == start_oid) shows;│ │52 + // 0 means the default page. raised by "load more" via the url. │ │53 + after: usize, │ │54 ) !Self { │ │55 const aa = arena.allocator(); │ │56 const hex = std.fmt.bytesToHex(event_id.*, .lower); │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │58 .identity = try aa.dupe(u8, identity), │ │59 .commits = &.{}, │ │60 .next_start = null, │ │61 - .repo_dir_hex = try aa.dupe(u8, &hex), │ │61 }; │ │62 │ │63 // no filesystem (wasm) or nowhere to look: empty listing. the wasm path│ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │115 // the diff machinery isn't wasm-clean and the wasm client never runs it (it │ │116 // renders from the snapshot), so gate it out of the wasm build. │ │117 if (!builtin.cpu.arch.isWasm()) { │ │119 - for (buf[0..count], oids[0..count]) |*commit, oid| { │ │120 - const rendered = renderCommitDiff(io, gpa, aa, &repo, oid, 0, diff_budget) catch│ │118 + for (buf[0..count], oids[0..count], 0..) |*commit, oid, i| { │ │119 + // the selected commit (the first, == start_oid) shows `after` hunks │ │120 + // when the url asks; the rest show one default page. │ │121 + const max_hunks = if (i == 0 and after > 0) after else diff_page; │ │122 + const rendered = renderCommitDiff(io, gpa, aa, &repo, oid, max_hunks) catch │ │123 RenderedDiff{ .hunks = &.{}, .shown_hunks = 0, .has_more = false }; │ │124 commit.hunks = rendered.hunks; │ │125 commit.shown_hunks = rendered.shown_hunks; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │131 .identity = empty.identity, │ │132 .commits = try aa.dupe(Commit, buf[0..count]),│ │133 .next_start = next_start, │ │132 - .repo_dir_hex = empty.repo_dir_hex, │ │134 }; │ │135 } │ │136 │ ╰───────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │141 }; │ │142 │ │143 // render a commit's diff against its first parent into `arena`-owned hunks,│ │143 -// skipping the first `skip_hunks` hunks and emitting at most `budget` lines│ │144 +// emitting at most `max_hunks` hunks (has_more is set when more remain) │ │145 fn renderCommitDiff( │ │146 io: std.Io, │ │147 gpa: std.mem.Allocator, │ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │148 arena: std.mem.Allocator, │ │149 repo: *rp.Repo(.xit, .{}), │ │150 oid: [xit.hash.hexLen(.sha1)]u8, │ │150 - skip_hunks: usize, │ │151 - budget: usize, │ │151 + max_hunks: usize, │ │152 ) !RenderedDiff { │ │153 const empty = RenderedDiff{ .hunks = &.{}, .shown_hunks = 0, .has_more = false };│ │154 │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │167 var file_iter = repo.filePairs(io, gpa, .{ .tree = .{ .tree_diff = &tree_diff } }) catch return empty;│ │168 │ │169 var hunks: std.ArrayList(Hunk) = .empty; │ │170 - var total_lines: usize = 0; │ │171 - var hunks_seen: usize = 0; │ │170 var has_more = false; │ │171 │ │172 file_loop: while (file_iter.next() catch null) |pair_val| { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯