╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │566 │ │345 - for (items) |item| { │ │346 - const line = try allocator.dupe(u8, item); │ │347 - { │ │348 - errdefer allocator.free(line); │ │349 - try self.lines.append(allocator, line); │ │350 - } │ │567 + for (items, 0..) |item, i| { │ │568 + const line = try aa.dupe(u8, item); │ │569 │ │570 var text_box = try wgt.TextBox(Widget).init(allocator, line, .{ .border_style = .hidden, .rounded_corners = true, .wrap_kind = .word });│ │571 errdefer text_box.deinit(allocator); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │572 text_box.getFocus().focusable = true; │ │573 + │ │574 + if (links) |link_items| { │ │575 + if (i < link_items.len and link_items[i].len > 0) { │ │576 + text_box.getFocus().kind = .{ .custom = try aa.dupe(u8, link_items[i]) };│ │577 + } │ │578 + } │ │579 + │ │580 try self.text_boxes.append(allocator, text_box); │ │581 } │ │582 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │675 scroll: wgt.Scroll(Widget), │ │676 │ │677 pub fn init(allocator: std.mem.Allocator, options: FlowBox.Options) !Scroll { │ │453 - var layout_inner = FlowBox.init(options); │ │678 + var layout_inner = FlowBox.init(allocator, options); │ │679 errdefer layout_inner.deinit(allocator); │ │680 var scroll = try wgt.Scroll(Widget).init(allocator, .{ .flow_box = layout_inner }, .vert);│ │681 errdefer scroll.deinit(allocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │686 self.scroll.deinit(allocator); │ │687 } │ │688 │ │464 - pub fn setItems(self: *Scroll, allocator: std.mem.Allocator, items: []const []const u8) !void { │ │689 + pub fn setItems(self: *Scroll, allocator: std.mem.Allocator, items: []const []const u8, links: ?[]const []const u8) !void {│ │690 self.scroll.x = 0; │ │691 self.scroll.y = 0; │ │467 - try self.inner().setItems(allocator, items); │ │692 + try self.inner().setItems(allocator, items, links); │ │693 } │ │694 │ │695 pub fn build(self: *Scroll, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────────╮ │src/ui/Auth/Login.zig│ ╰─────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │32 nav_ids: [3]usize, │ │33 // focus id of the header's "users" tab; on a successful submit we jump│ │34 // focus there so the user isn't stranded on the login button. │ │35 - users_tab_id: usize, │ │35 + success_redirect_tab_id: usize, │ │36 │ │37 const username_index: usize = 0; │ │38 const password_index: usize = 1; │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │39 const button_index: usize = 2; │ │40 │ │41 - pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session, users_tab_id: usize) !View { │ │41 + pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session, success_redirect_tab_id: usize) !View {│ │42 var box = wgt.Box(ui.Widget).init(.{ .border_style = null, .rounded_corners = true, .direction = .vert }); │ │43 errdefer box.deinit(allocator); │ │44 // marks this subtree as an HTML form scope for the web overlay │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │45 - box.getFocus().kind = .{ .custom = "form:/login" }; │ │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}),│ │47 + else => "form:/login", │ │48 + } }; │ │49 │ │50 var nav_ids: [3]usize = undefined; │ │51 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────╮ │ 95 .data = data, │ │ 96 .session = session, │ │ 97 .nav_ids = nav_ids, │ │ 95 - .users_tab_id = users_tab_id, │ │ 98 + .success_redirect_tab_id = success_redirect_tab_id,│ │ 99 }; │ │100 } │ │101 │ ╰────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────╮ │260 │ │261 // jump focus back to the users tab — the login button we │ │262 // just pressed is about to be hidden by the tab-label swap│ │260 - try root_focus.setFocus(self.users_tab_id); │ │263 + try root_focus.setFocus(self.success_redirect_tab_id); │ │264 }, │ │265 } │ │266 } │ ╰────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Auth/Logout.zig│ ╰──────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │30 var box = wgt.Box(ui.Widget).init(.{ .border_style = null, .rounded_corners = true, .direction = .vert }); │ │31 errdefer box.deinit(allocator); │ │32 // marks this subtree as an HTML form scope for the web overlay │ │33 - box.getFocus().kind = .{ .custom = "form:/logout" }; │ │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}),│ │35 + else => "form:/logout", │ │36 + } }; │ │37 │ │38 { │ │39 var prompt = wgt.Text(ui.Widget).init("are you sure?"); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯