╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────╮ │src/ui/User.zig│ ╰───────────────╯ ╭─────────────────────────────────────────────╮ │34 forks: []const ForkItem, │ │35 forks_start: usize, │ │36 forks_next_start: ?usize, │ │37 +user_notifications: ui.UserNotifications,│ │38 quit: Quit, │ │39 │ │40 const Self = @This(); │ ╰─────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────╮ │48 // the url-encoded repos search ("" = none)│ │49 repos_search: []const u8, │ │50 forks_start: usize, │ │51 + user_tab: ui.RoutablePage.UserTab, │ │52 ) !Self { │ │53 // admin and user repos share one db type │ │54 const DB = evt.AdminDB; │ ╰───────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │173 .forks = forks.items, │ │174 .forks_start = forks_start, │ │175 .forks_next_start = forks_next_start, │ │176 + .user_notifications = try ui.UserNotifications.init(arena, session, user_tab),│ │177 .quit = Quit.init(), │ │178 }; │ │179 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │249 } │ │250 │ │251 { │ │249 - var user_view = try ui.UserSettings.initView(allocator, session); │ │252 + const route = ui.RoutablePage{ .user_user = .{ .name = ui.RoutablePage.Array(evt.User.name_max_len).from(data.user.name) orelse return error.RouteTooLong } };│ │253 + var user_view = try ui.UserSettings.initView(allocator, session, &data.user_notifications, route); │ │254 errdefer user_view.deinit(allocator); │ │255 try stack.children.put(allocator, user_view.getFocus().id, user_view); │ │256 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │319 .user_repos => |*v| return v.focusHeader(root_focus), │ │320 // an empty list has nothing to focus │ │321 .flow_box_scroll => |*v| if (v.isEmpty()) return, │ │322 + .user_notifications => |*v| if (v.focusHeader(root_focus)) return,│ │323 else => {}, │ │324 }; │ │325 index = stack_index; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/User/Header.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │104 const forks_link = try ui.inPageTabLink(session, .{ .user_forks = .{ .name = name } }, current_tag == .user_forks);│ │105 const new_repo_link = try ui.inPageTabLink(session, .{ .user_repo_new = name }, current_tag == .user_repo_new); │ │106 const new_user_link = try ui.inPageTabLink(session, .{ .user_user_new = name }, current_tag == .user_user_new); │ │107 - const user_link = try ui.inPageTabLink(session, .{ .user_user = name }, current_tag == .user_user); │ │107 + const user_link = try ui.inPageTabLink(session, .{ .user_user = .{ .name = name } }, current_tag == .user_user); │ │108 │ │109 // the tab matching the current page is focused initially; matching by │ │110 // link (rather than position) keeps this robust to tab changes. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │189 // user tab │ │190 { │ │191 const label = ui.UserSettings.tabLabel(session); │ │192 - var text_box = try wgt.TextBox.init(allocator, label, .{ .border = .single, .round_corners = true, .wrap_kind = .none }); │ │192 + const count_label = try ui.UserSettings.tabBottomLabel(session); │ │193 + var text_box = try wgt.TextBox.init(allocator, label, .{ .border = .single, .round_corners = true, .wrap_kind = .none, .bottom_label = .{ .text = count_label } });│ │194 errdefer text_box.deinit(allocator); │ │195 text_box.getFocus().mode = .all; │ │196 text_box.getFocus().kind = .{ .custom = user_link }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │199 try tabs_box.children.put(allocator, text_box.getFocus().id, .{ │ │200 .widget = .{ .text_box = text_box }, │ │201 .rect = null, │ │201 - .min_size = .{ .width = label.len + 2, .height = null }, │ │202 + .min_size = .{ .width = @max(label.len, count_label.len) + 2, .height = null },│ │203 }); │ │204 } │ │205 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/ui/UserLogin.zig│ ╰────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │25 const password_index: usize = 1; │ │26 const button_index: usize = 2; │ │27 │ │28 - pub fn init(allocator: std.mem.Allocator, session: *ui.Session) !View { │ │28 + // the form posts under `route`, the page's user tab route │ │29 + pub fn init(allocator: std.mem.Allocator, session: *ui.Session, route: ui.RoutablePage) !View { │ │30 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border = null, .round_corners = true, .direction = .vert });│ │31 errdefer box.deinit(allocator); │ │32 // marks this subtree as an HTML form scope for the web renderer │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │32 - box.getFocus().kind = .{ .custom = "form:login" }; │ │33 + box.getFocus().kind = .{ .custom = try session.page_arena.allocator().print("form:{s}/login", .{try route.toUrl(session.page_arena)}) };│ │34 │ │35 var nav_ids: [3]usize = undefined; │ │36 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯