╭ changed ───────────────────╮ │src/ui/UserNotifications.zig│ ╰────────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │60 } │ │61 result.rows = rows; │ │62 return result; │ │63 +} │ │64 + │ │65 +// a first window without notifs, which shows the empty message │ │66 +fn isEmpty(self: *const Self) bool { │ │67 + return self.rows.len == 0 and self.start == 0; │ │68 } │ │69 │ │70 // leave the user tab for the page it belongs to, where the web's logout redirect also lands│ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │78 // the notifications and user settings sub tabs over their content, with the logout button across from them│ │79 pub const View = struct { │ │80 box: wgt.Box(ui.Widget), │ │81 + data: *const Self, │ │82 session: *ui.Session, │ │83 // the sub tabs' ids then the logout button's, in header order │ │84 control_ids: [3]usize, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │133 { │ │134 var stack = try wgt.Stack(ui.Widget).init(allocator); │ │135 errdefer stack.deinit(allocator); │ │130 - { │ │136 + // an empty first window has no rows, not even paging ones │ │137 + if (data.isEmpty()) { │ │138 + var center = try ui.widget.initEmpty(allocator); │ │139 + errdefer center.deinit(allocator); │ │140 + try stack.children.put(allocator, center.getFocus().id, .{ .center = center }); │ │141 + } else { │ │142 var list = try ui.widget.FlowBox.Scroll.init(allocator, .{}, !session.is_terminal);│ │143 errdefer list.deinit(allocator); │ │144 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │175 try box.children.put(allocator, stack.getFocus().id, .{ .widget = .{ .stack = stack }, .rect = null, .min_size = null });│ │176 } │ │177 box.getFocus().child_id = box.children.keys()[content_index]; │ │167 - return .{ .box = box, .session = session, .control_ids = control_ids, .view_index = @backingInt(data.view) }; │ │178 + return .{ .box = box, .data = data, .session = session, .control_ids = control_ids, .view_index = @backingInt(data.view) }; │ │179 } │ │180 │ │181 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │221 const focused = root_focus.grandchild_id orelse return; │ │222 if (key == .enter and focused == logout_id) return logOut(self.session); │ │223 if (direction == .down) { │ │213 - // an empty list has nothing to focus │ │214 - if (self.contentStack().getSelected()) |selected| if (selected.* == .flow_box_scroll and selected.flow_box_scroll.isEmpty()) return;│ │224 + // the empty message has nothing to focus │ │225 + if (self.view_index == @backingInt(ui.RoutablePage.UserView.notifications) and self.data.isEmpty()) return; │ │226 root_focus.setFocus(self.contentStack().getFocus().id); │ │227 } else if (std.mem.indexOfScalar(usize, &self.control_ids, focused)) |current| { │ │228 if (inp.moveTab(key, current, self.control_ids.len)) |next| root_focus.setFocus(self.control_ids[next]); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯