╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │326 // the issues tab mirrors this page's tag filter (issue urls │ │327 // themselves never carry the tag). │ │328 .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,│ │323 - .home_settings => self.session.data.current_page = .{ .repo_settings = self.data.identity }, │ │324 - .home_auth => self.session.data.current_page = .{ .repo_auth = self.data.identity }, │ │329 + .home_settings => { │ │330 + if (ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len).from(self.data.identity.slice())) |identity| │ │331 + self.session.data.current_page = .{ .repo_settings = identity }; │ │332 + }, │ │333 + .home_auth => { │ │334 + if (ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len).from(self.data.identity.slice())) |identity| │ │335 + self.session.data.current_page = .{ .repo_auth = identity }; │ │336 + }, │ │337 // the quit tab is tty-only and not a route, so leave current_page │ │338 // alone (nothing to mirror into the url). │ │339 .quit => {}, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │793 // `identity`, showing the selected commit's first `start` hunks (0 = default). │ │794 fn commitsLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, oid: []const u8, start: usize) ![]const u8 {│ │795 const route = ui.RoutablePage.repoCommitsRoute(identity, .object, oid, start) orelse return error.RouteTooLong; │ │796 - const url = try route.urlAlloc(page_arena); │ │796 + const url = try route.toUrl(page_arena); │ │797 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); │ │798 } │ │799 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │801 // directory, within `identity` ("owner/name"). │ │802 fn filesObjectLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, oid: []const u8) ![]const u8 { │ │803 const route = ui.RoutablePage.repoFilesRoute(identity, .object, oid, "", 0) orelse return error.RouteTooLong;│ │804 - const url = try route.urlAlloc(page_arena); │ │804 + const url = try route.toUrl(page_arena); │ │805 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); │ │806 } │ │807 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │810 // in-page (crossPageLink ignores it); the href is only followed with js off. │ │811 fn commitRowLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, oid: []const u8) ![]const u8 { │ │812 const route = ui.RoutablePage.repoCommitsRoute(identity, .object, oid, 0) orelse return error.RouteTooLong;│ │813 - const url = try route.urlAlloc(page_arena); │ │813 + const url = try route.toUrl(page_arena); │ │814 return std.fmt.allocPrint(page_arena.allocator(), "ai:{s}", .{url}); │ │815 } │ │816 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │577 const page_arena = self.session.page_arena; │ │578 const path = try childDir(page_arena.allocator(), self.data.dir, entry.name); │ │579 const route = ui.RoutablePage.repoFilesRoute(self.data.identity, self.data.ref_or_oid, self.data.ref_or_oid_value, path, target_start) orelse return error.RouteTooLong;│ │580 - const link = try std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.urlAlloc(page_arena)}); │ │580 + const link = try std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │581 var tb = try wgt.TextBox(ui.Widget).init(allocator, label, .{ .border_style = .hidden, .rounded_corners = true, .wrap_kind = .none }); │ │582 errdefer tb.deinit(allocator); │ │583 tb.getFocus().focusable = true; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │799 // following it navigates to that directory's listing. │ │800 fn dirLink(page_arena: *std.heap.ArenaAllocator, data: *const Self, path: []const u8) ![]const u8 { │ │801 const route = ui.RoutablePage.repoFilesRoute(data.identity, data.ref_or_oid, data.ref_or_oid_value, path, 0) orelse return error.RouteTooLong;│ │802 - return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.urlAlloc(page_arena)}); │ │802 + return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │803 } │ │804 │ │805 // an "ai:" link to the file's route: crossPageLink ignores it, so a wasm click │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │806 // selects the row in place and shows its contents in the detail pane. │ │807 fn fileLink(page_arena: *std.heap.ArenaAllocator, data: *const Self, path: []const u8) ![]const u8 { │ │808 const route = ui.RoutablePage.repoFilesRoute(data.identity, data.ref_or_oid, data.ref_or_oid_value, path, 0) orelse return error.RouteTooLong;│ │809 - return std.fmt.allocPrint(page_arena.allocator(), "ai:{s}", .{try route.urlAlloc(page_arena)}); │ │809 + return std.fmt.allocPrint(page_arena.allocator(), "ai:{s}", .{try route.toUrl(page_arena)}); │ │810 } │ │811 │ │812 // `dir`/`name`, or just `name` at the root. │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │78 // (the bare route, so it resolves to the default branch). │ │79 { │ │80 const files_root_route = ui.RoutablePage.repoFilesRoute(identity, null, "", "", 0) orelse return error.RouteTooLong;│ │81 - const title_link = try std.fmt.allocPrint(aa, "a:{s}", .{try files_root_route.urlAlloc(session.page_arena)}); │ │81 + const title_link = try std.fmt.allocPrint(aa, "a:{s}", .{try files_root_route.toUrl(session.page_arena)}); │ │82 var title_view = try ui.Title.View.init(allocator, &data.title); │ │83 errdefer title_view.deinit(allocator); │ │84 title_view.getFocus().focusable = true; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │113 // both tabs link to the ref/oid this page is viewing, so switching tabs │ │114 // keeps the same ref (the files tab opens at its root directory). │ │115 const files_route = ui.RoutablePage.repoFilesRoute(identity, data.ref_or_oid, data.ref_or_oid_value, "", 0) orelse return error.RouteTooLong;│ │116 - const files_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try files_route.urlAlloc(session.page_arena)}); │ │116 + const files_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try files_route.toUrl(session.page_arena)}); │ │117 const commits_route = ui.RoutablePage.repoCommitsRoute(identity, data.ref_or_oid, data.ref_or_oid_value, 0) orelse return error.RouteTooLong;│ │118 - const commits_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try commits_route.urlAlloc(session.page_arena)}); │ │118 + const commits_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try commits_route.toUrl(session.page_arena)}); │ │119 const refs_route = ui.RoutablePage.repoRefsRoute(identity, .branch, "") orelse return error.RouteTooLong; │ │120 - const refs_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try refs_route.urlAlloc(session.page_arena)}); │ │120 + const refs_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try refs_route.toUrl(session.page_arena)}); │ │121 const issues_route = ui.RoutablePage.repoIssuesRoute(identity, .open, data.issues_tag, "") orelse return error.RouteTooLong; │ │122 - const issues_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try issues_route.urlAlloc(session.page_arena)}); │ │122 + const issues_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try issues_route.toUrl(session.page_arena)}); │ │123 const settings_route = ui.RoutablePage{ .repo_settings = Array.from(identity) orelse return error.RouteTooLong }; │ │124 - const settings_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try settings_route.urlAlloc(session.page_arena)}); │ │124 + const settings_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try settings_route.toUrl(session.page_arena)}); │ │125 const auth_route = ui.RoutablePage{ .repo_auth = Array.from(identity) orelse return error.RouteTooLong }; │ │126 - const auth_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try auth_route.urlAlloc(session.page_arena)}); │ │126 + const auth_link = try std.fmt.allocPrint(aa, "ai:{s}", .{try auth_route.toUrl(session.page_arena)}); │ │127 │ │128 // the tab matching the current page is focused initially; matching by │ │129 // link (rather than position) keeps this robust to tab changes. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │885 // with an empty `id` this is the bare list link. │ │886 fn issuesLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, status: evt.Issue.Status, tag: []const u8, id: []const u8) ![]const u8 {│ │887 const route = ui.RoutablePage.repoIssuesRoute(identity, status, tag, id) orelse return error.RouteTooLong; │ │888 - const url = try route.urlAlloc(page_arena); │ │888 + const url = try route.toUrl(page_arena); │ │889 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{url}); │ │890 } │ │891 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯