╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │31 settings: Settings, │ │32 auth: Auth, │ │33 quit: Quit, │ │34 -// the full files route this page renders ("owner/name" or "owner/name/files/<dir>"),│ │35 -// mirrored into current_page when the files tab is selected. │ │34 +// the full files route this page renders, mirrored into current_page when │ │35 +// the files tab is selected. │ │36 route_name: Array, │ │37 -// the content window (?after=N) of that files route; mirrored alongside the name │ │38 -// so the url keeps the query param even when focus isn't in the files view. │ │39 -files_after: usize, │ │37 // the commits route this page renders ("owner/name/commits[/<oid>]"), mirrored │ │38 // when the commits tab is selected. │ │39 commits_route_name: Array, │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │43 -// the diff window (?after=N) of that commits route; mirrored alongside the name│ │44 -// so the url keeps the query param even when focus isn't in the commits view. │ │45 -commits_after: usize, │ │40 // "owner/name" alone, mirrored when the settings/auth tab is selected. │ │41 identity: Array, │ │42 │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │53 // every repo route's stored string starts with "owner/name"; the files and│ │54 // commits routes additionally encode a ref/oid (files also a directory). │ │55 const name_str: []const u8 = switch (route) { │ │62 - .repo_files => |f| f.name.slice(), │ │63 - .repo_settings, .repo_auth => |n| n.slice(), │ │64 - .repo_commits => |c| c.name.slice(), │ │56 + .repo_files, .repo_settings, .repo_auth => |n| n.slice(), │ │57 + .repo_commits => |c| c.slice(), │ │58 .repo_refs => |r| r.name.slice(), │ │59 .repo_issues => |i| i.name.slice(), │ │60 else => return error.UnexpectedRoute, │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │68 // (even by key, without a reload) on the same ref. a null ref means the │ │69 // default branch (Files/Commits.init resolve it). the directory and the diff │ │70 // window only apply to their own tab. │ │78 - const commits_ref = if (tag == .repo_commits) ui.RoutablePage.repoCommitsRef(name_str) else ui.RoutablePage.CommitsRef{ .ref_or_oid = null, .value = "" }; │ │71 + const commits_ref = if (tag == .repo_commits) ui.RoutablePage.repoCommitsRef(name_str) else ui.RoutablePage.CommitsRef{ .ref_or_oid = null, .value = "", .start = 0 };│ │72 const requested_ref_or_oid: ?ui.RoutablePage.RefOrOid = switch (tag) { │ │73 .repo_files => rf.ref_kind, │ │74 .repo_commits => commits_ref.ref_or_oid, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │ 80 else => "", │ │ 81 }; │ │ 82 const files_dir = if (tag == .repo_files) rf.dir else ""; │ │ 90 - // the line offset the files view's selected file content window starts at. │ │ 91 - const files_after: usize = switch (route) { │ │ 92 - .repo_files => |f| f.after, │ │ 93 - else => 0, │ │ 94 - }; │ │ 95 - // how many diff hunks the commits view's selected commit shows ("load more").│ │ 96 - const commits_after: usize = switch (route) { │ │ 97 - .repo_commits => |c| c.after, │ │ 98 - else => 0, │ │ 99 - }; │ │100 - // the refs tab paginates one column at a time: this offset applies to │ │101 - // `refs_kind`'s column, the other stays at its first window. │ │ 83 + // 0 for non-files routes, whose tails parse as the bare root │ │ 84 + const files_start = rf.start; │ │ 85 + // the hunk the commits view's selected commit's diff window starts at. │ │ 86 + const commits_start = commits_ref.start; │ │ 87 + // the refs tab windows one column at a time: `refs_from` (a url-encoded │ │ 88 + // ref name) roots `refs_kind`'s column, the other stays at its first window. │ │ 89 const refs_kind: ui.RoutablePage.RefKind = switch (route) { │ │ 90 .repo_refs => |r| r.kind, │ │ 91 else => .branch, │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │ 92 }; │ │106 - const refs_after: usize = switch (route) { │ │107 - .repo_refs => |r| r.after, │ │108 - else => 0, │ │ 93 + const refs_from: []const u8 = switch (route) { │ │ 94 + .repo_refs => |r| r.from.slice(), │ │ 95 + else => "", │ │ 96 }; │ │ 97 // the issues tab's tag filter, the issue its window is rooted at, and the│ │ 98 // view it shows. │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │166 const is_local = session.local != null; │ │167 if (is_local) try evt.syncLocalEvents(repo_kind, opened.self_repo_opts, io, gpa, opened); │ │168 break :blk .{ │ │182 - try Files.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, requested_ref_or_oid, requested_ref_value, files_dir, files_after),│ │183 - try Commits.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, requested_ref_or_oid, requested_ref_value, commits_after), │ │184 - try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, refs_kind, refs_after), │ │169 + try Files.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, requested_ref_or_oid, requested_ref_value, files_dir, files_start),│ │170 + try Commits.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, requested_ref_or_oid, requested_ref_value, commits_start), │ │171 + try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, refs_kind, refs_from), │ │172 try Issues.init(repo_kind, opened.self_repo_opts, arena, opened, io, is_local, rf.identity, issues_tag, issues_selected, issues_view), │ │173 }; │ │174 }, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │180 break :blk .{ │ │181 try Files.emptyResult(aa, rf.identity, requested_ref_or_oid orelse .branch, requested_ref_value, files_dir),│ │182 try Commits.emptyResult(aa, rf.identity, requested_ref_or_oid orelse .branch, requested_ref_value), │ │196 - try Refs.emptyResult(arena, rf.identity, refs_kind, refs_after), │ │183 + try Refs.emptyResult(arena, rf.identity, refs_kind, refs_from), │ │184 try Issues.emptyResult(aa, rf.identity, issues_tag, issues_selected, issues_view), │ │185 }; │ │186 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │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 } │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯