╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭────────────────────────────────────────────────────────╮ │494 + freeArena(allocator, oldest.arena);│ │495 } │ │496 self.root = new_root; │ │419 - self.route = session.data.current_page;│ │497 + self.route = route; │ │498 + self.arena = arena; │ │499 } │ │500 return true; │ │501 } │ ╰────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Auth/Login.zig│ ╰─────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │43 errdefer box.deinit(allocator); │ │44 // marks this subtree as an HTML form scope for the web overlay │ │45 box.getFocus().kind = .{ .custom = switch (session.data.current_page) { │ │46 - .user, .user_settings, .user_auth => |name| try std.fmt.allocPrint(session.arena.allocator(), "form:/user/{s}/login", .{name}), │ │46 + .user, .user_settings, .user_auth => |name| try std.fmt.allocPrint(session.page_arena.allocator(), "form:/user/{s}/login", .{name.slice()}),│ │47 else => "form:/login", │ │48 } }; │ │49 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Auth/Logout.zig│ ╰──────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │31 errdefer box.deinit(allocator); │ │32 // marks this subtree as an HTML form scope for the web overlay │ │33 box.getFocus().kind = .{ .custom = switch (session.data.current_page) { │ │34 - .user, .user_settings, .user_auth => |name| try std.fmt.allocPrint(session.arena.allocator(), "form:/user/{s}/logout", .{name}), │ │34 + .user, .user_settings, .user_auth => |name| try std.fmt.allocPrint(session.page_arena.allocator(), "form:/user/{s}/logout", .{name.slice()}),│ │35 else => "form:/logout", │ │36 } }; │ │37 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────╮ │src/ui/Settings.zig│ ╰───────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │34 // server sends us back to this page's settings tab; logged out, the │ │35 // empty action blocks the POST and the input goes to the TUI instead. │ │36 box.getFocus().kind = .{ .custom = if (!logged_in) "form:" else switch (session.data.current_page) { │ │37 - .user, .user_settings, .user_auth => |name| try std.fmt.allocPrint(session.arena.allocator(), "form:/user/{s}/ansi", .{name}), │ │37 + .user, .user_settings, .user_auth => |name| try std.fmt.allocPrint(session.page_arena.allocator(), "form:/user/{s}/ansi", .{name.slice()}),│ │38 else => "form:/ansi", │ │39 } }; │ │40 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/User.zig│ ╰───────────────╯ ╭─────────────────────────────────────────────────────────────╮ │19 repos: []const evt.Repo, │ │20 settings: Settings, │ │21 auth: Auth, │ │22 +route_name: ui.RoutablePage.Array(evt.User.name_max_len),│ │23 │ │24 const Self = @This(); │ │25 │ ╰─────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │26 pub fn init( │ │27 arena: *std.heap.ArenaAllocator, │ │28 haxy_moment: evt.AdminDB.HashMap(.read_only), │ │28 - name: []const u8, │ │29 + name: ui.RoutablePage.Array(evt.User.name_max_len),│ │30 ) !Self { │ │31 const DB = evt.AdminDB; │ │32 const hash_kind = evt.admin_repo_opts.hash; │ ╰───────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │35 // the name->user-id index, which everything below keys off of. │ │36 const name_to_user_id_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "name->user-id")) orelse return error.NotFound;│ │37 const name_to_user_id = try DB.HashMap(.read_only).init(name_to_user_id_cursor); │ │37 - const user_id_cursor = try name_to_user_id.getCursor(hash.hashInt(hash_kind, name)) orelse return error.NotFound; │ │38 + const user_id_cursor = try name_to_user_id.getCursor(hash.hashInt(hash_kind, name.slice())) orelse return error.NotFound; │ │39 var user_id_buf: [evt.event_id_size]u8 = undefined; │ │40 _ = try user_id_cursor.readBytes(&user_id_buf); │ │41 const user_id: []const u8 = &user_id_buf; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────╮ │72 .repos = repos.items, │ │73 .settings = Settings.init(),│ │74 .auth = Auth.init(), │ │75 + .route_name = name, │ │76 }; │ │77 } │ │78 │ ╰────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │155 // rather than navigating. │ │156 if (header.getSelectedIndex()) |index| { │ │157 stack.getFocus().child_id = stack.children.keys()[index];│ │156 - const name = self.data.user.name; │ │158 + const name = self.data.route_name; │ │159 self.session.data.current_page = switch (index) { │ │160 1 => .{ .user_settings = name }, │ │161 2 => .{ .user_auth = name }, │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/User/Header.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │61 │ │62 // every tab link is user-scoped so selecting one stays on this page — │ │63 // switching its stack and updating the url — instead of navigating to │ │64 - // the global settings or auth pages. allocated in the session arena so │ │65 - // the focus kinds that borrow them outlive this view. │ │66 - const aa = session.arena.allocator(); │ │64 + // the global settings or auth pages. allocated in the page arena so the │ │65 + // focus kinds that borrow them live as long as this page's widget tree. │ │66 + const aa = session.page_arena.allocator(); │ │67 const repos_link = try std.fmt.allocPrint(aa, "a:/user/{s}", .{data.name}); │ │68 const settings_link = try std.fmt.allocPrint(aa, "a:/user/{s}/settings", .{data.name});│ │69 const auth_link = try std.fmt.allocPrint(aa, "a:/user/{s}/auth", .{data.name}); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯