╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │103 }; │ │104 const route = self.handle.location.filesRoute(self.ref_or_oid, self.ref_or_oid_value, path, line) orelse return null;│ │105 return route.withFind(self.find orelse return route); │ │106 +} │ │107 + │ │108 +// an empty root listing, which shows the empty message │ │109 +fn isEmpty(self: *const Self) bool { │ │110 + return self.entries.len == 0 and self.dir.len == 0; │ │111 } │ │112 │ │113 // build the listing for an opened repo. generic over the repo's backend and │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │384 errdefer header_view.deinit(allocator); │ │385 // a row taller than the header, leaving a blank line beneath it │ │386 try outer.children.put(allocator, header_view.getFocus().id, .{ .widget = .{ .search_header = header_view }, .rect = null, .min_size = .{ .width = null, .height = 4 } });│ │387 + } │ │388 + │ │389 + // an empty root listing shows the empty message in place of the split │ │390 + if (data.isEmpty()) { │ │391 + var center = try ui.widget.initEmpty(allocator); │ │392 + errdefer center.deinit(allocator); │ │393 + try outer.children.put(allocator, center.getFocus().id, .{ .widget = .{ .center = center }, .rect = null, .min_size = null }); │ │394 + // with nothing below to focus, focus rests on the sub-header │ │395 + outer.getFocus().child_id = outer.children.keys()[header_index]; │ │396 + return .{ .box = outer, .data = data, .session = session }; │ │397 } │ │398 │ │399 var box = try wgt.Box(ui.Widget).init(allocator, .{ .border = null, .direction = .horiz }); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │617 │ │618 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void {│ │619 self.clearGrid(); │ │605 - if (self.data.no_commits) return self.box.build(allocator, constraint, root_focus); │ │620 + if (self.data.no_commits or self.data.isEmpty()) return self.box.build(allocator, constraint, root_focus); │ │621 │ │622 // whether the detail pane fits beside the list, which decides the list │ │623 // cap below and whether the detail carries a way back to the list │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │784 // active means there is one │ │785 const header_view = self.header() orelse unreachable; │ │786 if (direction == .down) { │ │772 - root_focus.setFocus(self.contentBox().getFocus().id); │ │787 + // the empty message has nothing to focus │ │788 + if (!self.data.isEmpty()) root_focus.setFocus(self.contentBox().getFocus().id);│ │789 return; │ │790 } │ │791 if (key == .enter) if (try header_view.submittedText(allocator)) |term| { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 998 │ │ 999 // only the header's own row sits directly below the repository header. │ │1000 pub fn atTop(self: *View) bool { │ │ 985 - if (self.data.no_commits) return true; │ │1001 + if (self.data.no_commits or self.data.isEmpty()) return true; │ │1002 const focusable = if (self.header()) |header_view| header_view.hasFocusable() else false;│ │1003 return self.headerActive() or (!focusable and self.contentAtTop()); │ │1004 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯