╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │429 try box.children.put(allocator, tb.getFocus().id, .{ .widget = .{ .text_box = tb }, .rect = null, .min_size = null }); │ │430 } │ │431 │ │432 + // a focusable row for the top of the diff pane linking to the files tab at │ │433 + // this commit's tree, so its files are always viewable as of this object. │ │434 + fn addViewFilesLink(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), oid: []const u8) !void { │ │435 + const link = try filesObjectLink(self.session.page_arena, self.data.identity, oid); │ │436 + var tb = try wgt.TextBox(ui.Widget).init(allocator, "view files at this commit", .{ .border_style = .hidden, .rounded_corners = true, .wrap_kind = .none });│ │437 + errdefer tb.deinit(allocator); │ │438 + tb.getFocus().focusable = true; │ │439 + tb.getFocus().kind = .{ .custom = link }; │ │440 + try box.children.put(allocator, tb.getFocus().id, .{ .widget = .{ .text_box = tb }, .rect = null, .min_size = null }); │ │441 + } │ │442 + │ │443 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ │444 self.box.deinit(allocator); │ │445 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │564 inner.children.clearAndFree(allocator); │ │565 inner.getFocus().child_id = null; │ │566 │ │556 - // a "previous" row at the top and a "next" row at the bottom reload the │ │557 - // page on the adjacent diff window. │ │567 + // the first row always links to viewing the repo's files at this commit. │ │568 + try self.addViewFilesLink(allocator, inner, commit.oid); │ │569 + │ │570 + // a "previous" row and a "next" row at the bottom reload the page on the │ │571 + // adjacent diff window. │ │572 if (commit.has_prev) try self.addNavLink(allocator, inner, "← previous", commit.oid, commit.window_start -| diff_page);│ │573 for (commit.hunks) |hunk| { │ │574 if (hunk.path) |path| try self.addPathBox(allocator, inner, path); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │832 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); │ │833 } │ │834 │ │835 +// the "a:" link to the files tab at commit `oid` (an object ref), at its root │ │836 +// directory, within `identity` ("owner/name"). │ │837 +fn filesObjectLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, oid: []const u8) ![]const u8 { │ │838 + const route = ui.RoutablePage.repoFilesRoute(identity, .object, oid, "") orelse return error.RouteTooLong;│ │839 + const url = try route.urlAlloc(page_arena); │ │840 + return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); │ │841 +} │ │842 + │ │843 // the in-page "ai:" anchor for selecting `oid` in `identity`'s commit list. it │ │844 // points at the same route as commitsLink but the "ai:" prefix keeps wasm clicks │ │845 // in-page (crossPageLink ignores it); the href is only followed with js off. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯