╭ changed ─────────────╮ │src/ui/User/Header.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │27 pub const View = struct { │ │28 box: wgt.Box(ui.Widget), │ │29 data: *const Self, │ │30 - tab_ids: [3]usize, │ │30 + tab_ids: std.AutoArrayHashMapUnmanaged(usize, void), │ │31 │ │32 pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session) !View { │ │33 var box = wgt.Box(ui.Widget).init(.{ .border_style = .hidden, .rounded_corners = true, .direction = .horiz });│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │34 errdefer box.deinit(allocator); │ │35 │ │36 - var tab_ids: [3]usize = undefined; │ │36 + var tab_ids: std.AutoArrayHashMapUnmanaged(usize, void) = .empty;│ │37 + errdefer tab_ids.deinit(allocator); │ │38 │ │39 // title sits to the left of the tabs │ │40 { │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │75 errdefer text_box.deinit(allocator); │ │76 text_box.getFocus().focusable = true; │ │77 text_box.getFocus().kind = .{ .custom = repos_link }; │ │77 - tab_ids[0] = text_box.getFocus().id; │ │78 + try tab_ids.put(allocator, text_box.getFocus().id, {}); │ │79 try box.children.put(allocator, text_box.getFocus().id, .{│ │80 .widget = .{ .text_box = text_box }, │ │81 .rect = null, │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────╮ │100 errdefer text_box.deinit(allocator); │ │101 text_box.getFocus().focusable = true; │ │102 text_box.getFocus().kind = .{ .custom = settings_link }; │ │102 - tab_ids[1] = text_box.getFocus().id; │ │103 + try tab_ids.put(allocator, text_box.getFocus().id, {}); │ │104 try box.children.put(allocator, text_box.getFocus().id, .{│ │105 .widget = .{ .text_box = text_box }, │ │106 .rect = null, │ ╰───────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │114 var auth_tab = try AuthTab.View.init(allocator, &data.auth_tab, session);│ │115 errdefer auth_tab.deinit(allocator); │ │116 auth_tab.text_box.getFocus().kind = .{ .custom = auth_link }; │ │116 - tab_ids[2] = auth_tab.getFocus().id; │ │117 + try tab_ids.put(allocator, auth_tab.getFocus().id, {}); │ │118 try box.children.put(allocator, auth_tab.getFocus().id, .{ │ │119 .widget = .{ .auth_tab = auth_tab }, │ │120 .rect = null, │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │121 .min_size = .{ .width = AuthTab.min_width, .height = null }, │ │122 + }); │ │123 + } │ │124 + │ │125 + // quit tab │ │126 + if (session.is_terminal) { │ │127 + var text_box = try wgt.TextBox(ui.Widget).init(allocator, ui.Quit.tab_label, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none });│ │128 + errdefer text_box.deinit(allocator); │ │129 + text_box.getFocus().focusable = true; │ │130 + text_box.getFocus().kind = .{ .custom = ui.Quit.tab_kind }; │ │131 + try tab_ids.put(allocator, text_box.getFocus().id, {}); │ │132 + try box.children.put(allocator, text_box.getFocus().id, .{ │ │133 + .widget = .{ .text_box = text_box }, │ │134 + .rect = null, │ │135 + // the label is a single column; +2 for the border │ │136 + .min_size = .{ .width = 1 + 2, .height = null }, │ │137 }); │ │138 } │ │139 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │140 var self = View{ .box = box, .data = data, .tab_ids = tab_ids };│ │141 // open on the tab named by the current route │ │126 - self.getFocus().child_id = tab_ids[ │ │142 + self.getFocus().child_id = self.tab_ids.keys()[ │ │143 switch (session.data.current_page) { │ │144 .user_settings => 1, │ │145 .user_auth => 2, │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │151 │ │152 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ │153 self.box.deinit(allocator); │ │154 + self.tab_ids.deinit(allocator); │ │155 } │ │156 │ │157 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void {│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │176 var new_tab = current_tab; │ │177 switch (key) { │ │178 .arrow_left => new_tab -|= 1, │ │162 - .arrow_right => if (new_tab + 1 < self.tab_ids.len) { │ │179 + .arrow_right => if (new_tab + 1 < self.tab_ids.count()) {│ │180 new_tab += 1; │ │181 }, │ │182 else => {}, │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │183 } │ │184 if (new_tab != current_tab) { │ │168 - try root_focus.setFocus(self.tab_ids[new_tab]); │ │185 + try root_focus.setFocus(self.tab_ids.keys()[new_tab]);│ │186 } │ │187 } │ │188 │ ╰───────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯