╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │741 current_page: RoutablePage = .default, │ │742 // whether to render the ANSI art backdrop │ │743 enable_ansi: bool = true, │ │744 + // true when this session views a single local repo. unlike `local` │ │745 + // (the host-side filesystem source) this travels in the snapshot, so │ │746 + // the wasm side also parses elided link urls and hides the multi-user │ │747 + // chrome. │ │748 + is_local: bool = false, │ │749 }; │ │750 │ │751 // a user-initiated state change. widgets enqueue these on the session during│ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │902 const root_focus = root.getFocus(); │ │903 if (root_focus.grandchild_id) |gid| { │ │904 // follow a cross-page link │ │863 - if (crossPageLink(root_focus, gid, session.data.current_page)) |route| {│ │905 + if (crossPageLink(root_focus, gid, session.data)) |route| { │ │906 return session.navigate(route); │ │907 } │ │908 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │926 } │ │927 if (clicked) |focus_id| { │ │928 // follow a cross-page link │ │887 - if (crossPageLink(root_focus, focus_id, session.data.current_page)) |route| {│ │929 + if (crossPageLink(root_focus, focus_id, session.data)) |route| { │ │930 return session.navigate(route); │ │931 } │ │932 root_focus.setFocus(focus_id); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │947 // different parent page, or a different files directory within the repo page), │ │948 // return its route; otherwise null. lets a host turn a click / enter on such a │ │949 // link into a navigation rather than a focus change. │ │908 -pub fn crossPageLink(root_focus: *Focus, focus_id: usize, current: RoutablePage) ?RoutablePage {│ │950 +pub fn crossPageLink(root_focus: *Focus, focus_id: usize, data: Session.Data) ?RoutablePage { │ │951 + const current = data.current_page; │ │952 const child = root_focus.children.get(focus_id) orelse return null; │ │953 const custom = switch (child.focus.kind) { │ │954 .custom => |c| c, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │958 if (!std.mem.startsWith(u8, custom, a_prefix)) return null; │ │959 const url = custom[a_prefix.len..]; │ │960 const q = std.mem.indexOfScalar(u8, url, '?'); │ │918 - const route = RoutablePage.fromUrl(if (q) |i| url[0..i] else url, if (q) |i| url[i + 1 ..] else null) orelse return null; │ │961 + const path = if (q) |i| url[0..i] else url; │ │962 + const query = if (q) |i| url[i + 1 ..] else null; │ │963 + // local sessions build (and parse) links with the repo identity elided │ │964 + const route = (if (data.is_local) RoutablePage.fromUrlLocal(path, query) else RoutablePage.fromUrl(path, query)) orelse return null;│ │965 // a link to a different parent page always navigates; within a page, a │ │966 // files-directory / commits-page / list-window change navigates while tab │ │967 // links stay in-page (header-handled). │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1775 │ │1776 _ = self.arena.reset(.retain_capacity); │ │1777 const aa = self.arena.allocator(); │ │1732 - const page = self.session.data.current_page; │ │1733 - const path = (if (self.session.local != null) page.urlAllocLocal(&self.arena) else page.urlAlloc(&self.arena)) catch return;│ │1778 + const path = self.session.data.current_page.urlAlloc(&self.arena) catch return; │ │1779 const text = if (self.session.web_port) |port| │ │1780 std.fmt.allocPrint(aa, "http://localhost:{d}{s}", .{ port, path }) catch return │ │1781 else │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │125 var owner_name: []const u8 = undefined; │ │126 if (session.local) |local| { │ │127 source = local; │ │128 + // local routes elide the identity, so the display name comes from the │ │129 + // repo's directory rather than the route. │ │130 repo = .{ │ │131 .user_id = "", │ │130 - .name = try arena.allocator().dupe(u8, rf.name), │ │132 + .name = try arena.allocator().dupe(u8, std.fs.path.basename(local.path)),│ │133 .description = "", │ │134 .enable_issue = true, │ │135 }; │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │134 - owner_name = try arena.allocator().dupe(u8, rf.owner); │ │136 + owner_name = ""; │ │137 } else { │ │138 const haxy_moment = session.haxy_moment orelse return error.NoMoment; │ │139 const found = (try evt.Repo.readByOwnerAndName(DB, hash_kind, haxy_moment, arena, rf.owner, rf.name)) orelse return error.NotFound;│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │254 │ │255 // the header has no auth tab in local mode, so keep the stack's │ │256 // children 1:1 with the tabs by skipping the auth view too. │ │255 - if (session.local == null) { │ │257 + if (!session.data.is_local) { │ │258 var auth_view = try Auth.View.init(allocator, &data.auth, session, files_tab_id); │ │259 errdefer auth_view.deinit(allocator); │ │260 try stack.children.put(allocator, auth_view.getFocus().id, .{ .home_auth = auth_view });│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │12 pub const AuthTab = @import("./../AuthTab.zig"); │ │13 │ │14 const RefOrOid = ui.RoutablePage.RefOrOid; │ │15 +const Array = ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len);│ │16 │ │17 name: []const u8, │ │18 owner_name: []const u8, │ ╰────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯