╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │23 pub const Settings = @import("./Settings.zig"); │ │24 pub const Auth = @import("./Auth.zig"); │ │25 pub const Quit = @import("./Quit.zig"); │ │26 - │ │27 -const Array = ui.RoutablePage.Array(ui.RoutablePage.repo_identity_max_len);│ │26 │ │27 header: Header, │ │28 repo: evt.Repo.Record, │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │36 settings: Settings, │ │37 auth: Auth, │ │38 quit: Quit, │ │41 -// the full files route this page renders, mirrored into current_page when │ │42 -// the files tab is selected. │ │43 -route_name: ui.RoutablePage.RepoFilesRoute, │ │44 -// the commits route this page renders ("owner/name/commits[/<oid>]"), mirrored│ │45 -// when the commits tab is selected. │ │46 -commits_route_name: ui.RoutablePage.RepoCommitsRoute, │ │47 -// "owner/name" alone, mirrored when the settings/auth tab is selected. │ │48 -identity: Array, │ │39 │ │40 const Self = @This(); │ │41 │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │81 .repo_commits => |c| c.content, │ │82 else => .{ .diff = .{} }, │ │83 }; │ │94 - const commits_start = switch (commits_content) { │ │95 - .diff => |d| d.start, │ │96 - .message => 0, │ │97 - }; │ │84 // the refs tab windows one column at a time: `refs_from` (a url-encoded │ │85 // ref name) roots `refs_kind`'s column, the other stays at its first window.│ │86 const refs_kind: ui.RoutablePage.RefKind = switch (route) { │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │214 │ │215 // open the on-disk repo once and read every tab's data from it. files and │ │216 // commits resolve the same requested ref (the default branch when the │ │231 - // route named none), so they end up viewing the same one and either's │ │232 - // resolved ref can canonicalize the tab mirror urls below. no filesystem │ │217 + // route named none), so they end up viewing the same one. no filesystem │ │218 // (wasm), nowhere to look, or a failed open: empty tabs. │ │219 const files, const commits, const refs, var issues, var patches, var discussions, const events = blk: {│ │220 read: { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │260 patches.target_branch = if (files.ref_or_oid == .branch) files.ref_or_oid_value else ""; │ │261 discussions.repo_source = source; │ │262 │ │278 - // each tab mirror carries this page's route for that tab; tabs not targeted │ │279 - // by the incoming route fall back to their root/first-page route. the files │ │280 - // mirror carries the selected file (when the route named one) so the url │ │281 - // keeps it before focus enters the view. │ │282 - const files_path = if (files.selected_file) |f| try Files.childDir(arena.allocator(), files.dir, f) else files.dir; │ │283 - // the content window only applies to a selected file, so the bare │ │284 - // directory route drops it. │ │285 - const files_route_line = if (files.selected_file != null) files_line else 0; │ │286 - const route_name = (ui.RoutablePage.repoFilesRoute(repo_identity.identity, files.ref_or_oid, files.ref_or_oid_value, files_path, files_route_line) orelse return error.NotFound).repo_files;│ │287 - // the message page mirrors its own url, not the log's │ │288 - const commits_route = switch (commits.content) { │ │289 - .message => ui.RoutablePage.repoCommitMessageRoute(repo_identity.identity, commits.ref_or_oid, commits.ref_or_oid_value), │ │290 - .diff => |d| ui.RoutablePage.repoCommitsRoute(repo_identity.identity, commits.ref_or_oid, commits.ref_or_oid_value, commits_start, d.path), │ │291 - }; │ │292 - const commits_route_name = (commits_route orelse return error.NotFound).repo_commits; │ │293 - │ │263 return .{ │ │264 // files and commits resolve the same ref, so either's serves the header, │ │265 // which points both tabs at it. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │275 .settings = Settings.init(), │ │276 .auth = Auth.init(), │ │277 .quit = Quit.init(), │ │309 - .route_name = route_name, │ │310 - .commits_route_name = commits_route_name, │ │311 - .identity = Array.from(repo_identity.identity) orelse return error.NotFound,│ │278 }; │ │279 } │ │280 │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────╮ │281 pub const View = struct { │ │282 box: wgt.Box(ui.Widget), │ │317 - data: *const Self, │ │318 - session: *ui.Session, │ │283 │ │284 const header_index: usize = 0;│ │285 const stack_index: usize = 1; │ ╰───────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │372 try box.children.put(allocator, stack.getFocus().id, .{ .widget = .{ .stack = stack }, .rect = null, .min_size = null });│ │373 } │ │374 │ │411 - var self = View{ .box = box, .data = data, .session = session }; │ │375 + var self = View{ .box = box }; │ │376 self.getFocus().child_id = box.children.keys()[header_index]; │ │377 return self; │ │378 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │386 const header = &self.box.children.values()[header_index].widget.repo_header; │ │387 const stack = &self.box.children.values()[stack_index].widget.stack; │ │388 │ │425 - // each header tab maps 1:1 to a stack child by position. mirror the │ │426 - // selection into current_page so the host can push the matching url; │ │427 - // all repo tabs share the .repo parent, so this stays on the page │ │428 - // rather than navigating. │ │429 - if (header.getSelectedIndex()) |index| { │ │389 + // each header tab maps 1:1 to a stack child by position │ │390 + if (header.getSelectedIndex()) |index| │ │391 stack.getFocus().child_id = stack.children.keys()[index]; │ │431 - switch (std.meta.activeTag(stack.children.values()[index])) { │ │432 - // files/commits carry this page's content route (directory / log │ │433 - // page); settings/auth carry only "owner/name". │ │434 - .repo_commits => self.session.data.current_page = .{ .repo_commits = self.data.commits_route_name }, │ │435 - // the refs tab mirrors this page's windowed column. │ │436 - .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, │ │437 - // the issues tab mirrors this page's tag filter (issue urls │ │438 - // themselves never carry the tag). │ │439 - .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, │ │440 - .repo_patches => self.session.data.current_page = ui.RoutablePage.repoPatchesRoute(self.data.identity.slice(), .open, self.data.patches.tag, "") orelse self.session.data.current_page, │ │441 - .repo_discussions => self.session.data.current_page = ui.RoutablePage.repoDiscussionsRoute(self.data.identity.slice(), self.data.discussions.tag, "") orelse self.session.data.current_page,│ │442 - .repo_events => self.session.data.current_page = ui.RoutablePage.repoEventsRoute(self.data.identity.slice(), self.data.events.view, null, "") orelse self.session.data.current_page, │ │443 - .home_settings => { │ │444 - if (ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len).from(self.data.identity.slice())) |identity| │ │445 - self.session.data.current_page = .{ .repo_settings = identity }; │ │446 - }, │ │447 - .home_auth => { │ │448 - if (ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len).from(self.data.identity.slice())) |identity| │ │449 - self.session.data.current_page = .{ .repo_auth = identity }; │ │450 - }, │ │451 - // the quit tab is tty-only and not a route, so leave current_page │ │452 - // alone (nothing to mirror into the url). │ │453 - .quit => {}, │ │454 - // the files tab (this page's directory route) │ │455 - else => self.session.data.current_page = .{ .repo_files = self.data.route_name }, │ │456 - } │ │457 - } │ │392 try self.box.build(allocator, constraint, root_focus); │ │393 } │ │394 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯