╭ changed ─────────────╮ │src/ui/Home/Header.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │25 pub const View = struct { │ │26 box: wgt.Box(ui.Widget), │ │27 data: *const Self, │ │28 - tab_ids: [4]usize, │ │28 + tab_ids: std.AutoArrayHashMapUnmanaged(usize, void), │ │29 │ │30 pub fn init(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session) !View { │ │31 var box = wgt.Box(ui.Widget).init(.{ .border_style = .hidden, .rounded_corners = true, .direction = .horiz });│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │32 errdefer box.deinit(allocator); │ │33 │ │34 - var tab_ids: [4]usize = undefined; │ │34 + var tab_ids: std.AutoArrayHashMapUnmanaged(usize, void) = .empty;│ │35 + errdefer tab_ids.deinit(allocator); │ │36 │ │37 // title sits to the left of the tabs │ │38 { │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │57 } │ │58 │ │59 // tabs │ │59 - var tab_index: usize = 0; │ │60 for ( │ │61 [_][]const u8{ "users", "repos", "", "settings", "" }, │ │62 [_][]const u8{ "a:/users", "a:/repos", "", "a:/settings", "a:/auth" },│ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │75 else if (std.mem.eql(u8, "a:/auth", focus_name)) { │ │76 var auth_tab = try AuthTab.View.init(allocator, &data.auth_tab, session);│ │77 errdefer auth_tab.deinit(allocator); │ │78 - tab_ids[tab_index] = auth_tab.getFocus().id; │ │79 - tab_index += 1; │ │78 + try tab_ids.put(allocator, auth_tab.getFocus().id, {}); │ │79 try box.children.put(allocator, auth_tab.getFocus().id, .{ │ │80 .widget = .{ .auth_tab = auth_tab }, │ │81 .rect = null, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────╮ │88 errdefer text_box.deinit(allocator); │ │89 text_box.getFocus().focusable = true; │ │90 text_box.getFocus().kind = .{ .custom = focus_name }; │ │92 - tab_ids[tab_index] = text_box.getFocus().id; │ │93 - tab_index += 1; │ │91 + try tab_ids.put(allocator, text_box.getFocus().id, {}); │ │92 try box.children.put(allocator, text_box.getFocus().id, .{│ │93 .widget = .{ .text_box = text_box }, │ │94 .rect = null, │ ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 97 } │ │ 98 } │ │ 99 │ │100 + // quit tab │ │101 + if (session.is_terminal) { │ │102 + var text_box = try wgt.TextBox(ui.Widget).init(allocator, ui.Quit.tab_label, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none });│ │103 + errdefer text_box.deinit(allocator); │ │104 + text_box.getFocus().focusable = true; │ │105 + text_box.getFocus().kind = .{ .custom = ui.Quit.tab_kind }; │ │106 + try tab_ids.put(allocator, text_box.getFocus().id, {}); │ │107 + try box.children.put(allocator, text_box.getFocus().id, .{ │ │108 + .widget = .{ .text_box = text_box }, │ │109 + .rect = null, │ │110 + // the label is a single column; +2 for the border │ │111 + .min_size = .{ .width = 1 + 2, .height = null }, │ │112 + }); │ │113 + } │ │114 + │ │115 var self = View{ .box = box, .data = data, .tab_ids = tab_ids }; │ │116 // initial selected tab │ │104 - self.getFocus().child_id = tab_ids[ │ │117 + self.getFocus().child_id = self.tab_ids.keys()[ │ │118 switch (session.data.current_page) { │ │119 .home_users => 0, │ │120 .home_repos => 1, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │128 │ │129 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ │130 self.box.deinit(allocator); │ │131 + self.tab_ids.deinit(allocator); │ │132 } │ │133 │ │134 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void {│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │152 var new_tab = current_tab; │ │153 switch (key) { │ │154 .arrow_left => new_tab -|= 1, │ │141 - .arrow_right => if (new_tab + 1 < self.tab_ids.len) { │ │155 + .arrow_right => if (new_tab + 1 < self.tab_ids.count()) {│ │156 new_tab += 1; │ │157 }, │ │158 else => {}, │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │159 } │ │160 if (new_tab != current_tab) { │ │147 - try root_focus.setFocus(self.tab_ids[new_tab]); │ │161 + try root_focus.setFocus(self.tab_ids.keys()[new_tab]);│ │162 } │ │163 } │ │164 │ ╰───────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────╮ │180 │ │181 fn currentTabIndex(self: View) ?usize { │ │182 const child_id = self.box.focus.child_id orelse return null;│ │169 - for (self.tab_ids, 0..) |id, i| { │ │170 - if (id == child_id) return i; │ │171 - } │ │172 - return null; │ │183 + return self.tab_ids.getIndex(child_id); │ │184 } │ │185 }; │ │186 │ ╰─────────────────────────────────────────────────────────────────────────╯