╭ changed ─────────────╮ │src/ui/Repo/Events.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │285 + var content_stack = try wgt.Stack(ui.Widget).init(allocator); │ │286 + errdefer content_stack.deinit(allocator); │ │287 + inline for ([_]ui.RoutablePage.EventsView{ .active, .removed }) |view| { │ │288 + var content_box = try initContent(allocator, data, session, view); │ │289 + errdefer content_box.deinit(allocator); │ │290 + try content_stack.children.put(allocator, content_box.getFocus().id, .{ .box = content_box }); │ │291 + } │ │292 + content_stack.getFocus().child_id = content_stack.children.keys()[@intFromEnum(data.view)]; │ │293 + try outer.children.put(allocator, content_stack.getFocus().id, .{ .widget = .{ .stack = content_stack }, .rect = null, .min_size = null });│ │294 + outer.getFocus().child_id = outer.children.keys()[header_index]; │ │295 + return .{ .box = outer, .data = data, .session = session, .detailed_index = .{ null, null } }; │ │296 + } │ │297 + │ │298 + fn initContent(allocator: std.mem.Allocator, data: *const Self, session: *ui.Session, view: ui.RoutablePage.EventsView) !wgt.Box(ui.Widget) { │ │299 var content_box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz }); │ │300 errdefer content_box.deinit(allocator); │ │301 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │302 var list_box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .vert, .stretch = true }); │ │303 errdefer list_box.deinit(allocator); │ │271 - for (data.events) |event| { │ │272 - const route = ui.RoutablePage.repoEventsRoute(data.identity, event.kind, event.id) orelse return error.RouteTooLong; │ │304 + const event_window = data.window(view); │ │305 + for (event_window.events) |event| { │ │306 + const route = ui.RoutablePage.repoEventsRoute(data.identity, view, event.kind, event.id) orelse return error.RouteTooLong;│ │307 const link = try std.fmt.allocPrint(session.page_arena.allocator(), "ai:{s}", .{try route.toUrl(session.page_arena)}); │ │308 try addRow(allocator, &list_box, @tagName(event.kind), link); │ │309 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │276 - if (data.next) |next| { │ │277 - const route = ui.RoutablePage.repoEventsRoute(data.identity, next.kind, next.id) orelse return error.RouteTooLong; │ │310 + if (event_window.next) |next| { │ │311 + const route = ui.RoutablePage.repoEventsRoute(data.identity, view, next.kind, next.id) orelse return error.RouteTooLong;│ │312 const link = try std.fmt.allocPrint(session.page_arena.allocator(), "a:{s}", .{try route.toUrl(session.page_arena)}); │ │313 try addRow(allocator, &list_box, "next →", link); │ │314 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │324 try content_box.children.put(allocator, detail_scroll.getFocus().id, .{ .widget = .{ .scroll = detail_scroll }, .rect = null, .min_size = .{ .width = detail_min_width, .height = null } });│ │325 │ │326 content_box.getFocus().child_id = content_box.children.keys()[list_index]; │ │293 - try outer.children.put(allocator, content_box.getFocus().id, .{ .widget = .{ .box = content_box }, .rect = null, .min_size = null }); │ │294 - outer.getFocus().child_id = outer.children.keys()[if (data.header.is_local) header_index else content_index]; │ │295 - return .{ .box = outer, .data = data, .session = session, .detailed_index = null }; │ │327 + return content_box; │ │328 } │ │329 │ │330 fn addRow(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), text: []const u8, link: []const u8) !void { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │335 try box.children.put(allocator, row.getFocus().id, .{ .widget = .{ .text_box = row }, .rect = null, .min_size = null }); │ │336 } │ │337 │ │306 - fn addField(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), text: []const u8, label: []const u8) !void { │ │307 - var field = try wgt.TextBox(ui.Widget).init(allocator, text, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .word, .label = label });│ │308 - errdefer field.deinit(allocator); │ │309 - field.getFocus().focusable = true; │ │310 - try box.children.put(allocator, field.getFocus().id, .{ .widget = .{ .text_box = field }, .rect = null, .min_size = null }); │ │338 + pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ │339 + self.box.deinit(allocator); │ │340 } │ │341 │ │313 - fn addAuthor(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), value: ui.Author) !void { │ │314 - var author = try ui.authorBox(allocator, self.session.page_arena, value); │ │315 - errdefer author.deinit(allocator); │ │316 - try box.children.put(allocator, author.getFocus().id, .{ .widget = .{ .text_box = author }, .rect = null, .min_size = null }); │ │342 + fn header(self: *View) *Header.View { │ │343 + return &self.box.children.values()[header_index].widget.repo_events_header; │ │344 } │ │345 │ │319 - fn addViewEvent(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), item: Item) !void { │ │320 - const url = item.view_url orelse return; │ │321 - │ │322 - var link = try wgt.TextBox(ui.Widget).init(allocator, "view event", .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); │ │323 - errdefer link.deinit(allocator); │ │324 - link.getFocus().focusable = true; │ │325 - link.getFocus().kind = .{ .custom = try std.fmt.allocPrint(self.session.page_arena.allocator(), "a:{s}", .{url}) }; │ │326 - try box.children.put(allocator, link.getFocus().id, .{ .widget = .{ .text_box = link }, .rect = null, .min_size = null }); │ │346 + fn contentStack(self: *View) *wgt.Stack(ui.Widget) { │ │347 + return &self.box.children.values()[content_index].widget.stack; │ │348 } │ │349 │ │329 - pub fn deinit(self: *View, allocator: std.mem.Allocator) void { │ │330 - self.box.deinit(allocator); │ │350 + fn selectedView(self: *View) ui.RoutablePage.EventsView { │ │351 + const stack = self.contentStack(); │ │352 + const id = stack.getFocus().child_id orelse return .active; │ │353 + return @enumFromInt(stack.children.getIndex(id) orelse 0); │ │354 } │ │355 │ │333 - fn header(self: *View) *Header.View { │ │334 - return &self.box.children.values()[header_index].widget.repo_events_header; │ │356 + fn eventWindow(self: *View) *const Window { │ │357 + return self.data.window(self.selectedView()); │ │358 } │ │359 │ │360 fn content(self: *View) *wgt.Box(ui.Widget) { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │338 - return &self.box.children.values()[content_index].widget.box; │ │361 + const stack = self.contentStack(); │ │362 + return &stack.children.values()[@intFromEnum(self.selectedView())].box;│ │363 } │ │364 │ │365 fn listScroll(self: *View) *wgt.Scroll(ui.Widget) { │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │389 fn selectedEventIndex(self: *View) ?usize { │ │390 const id = self.listBox().getFocus().child_id orelse return null; │ │391 const index = self.listBox().children.getIndex(id) orelse return null; │ │368 - return if (index < self.data.events.len) index else null; │ │392 + return if (index < self.eventWindow().events.len) index else null; │ │393 } │ │394 │ │395 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void {│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │396 self.clearGrid(); │ │397 + if (self.header().getSelectedIndex()) |index| │ │398 + self.contentStack().getFocus().child_id = self.contentStack().children.keys()[index];│ │399 + const view = self.selectedView(); │ │400 + if (ui.RoutablePage.repoEventsRoute(self.data.identity, view, null, "")) |route| │ │401 + self.session.data.current_page = route; │ │402 try self.refreshDetail(allocator); │ │403 │ │404 if (root_focus.grandchild_id) |id| if (self.box.getFocus().children.contains(id)) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │405 if (self.selectedEventIndex()) |index| { │ │377 - const event = self.data.events[index]; │ │378 - if (ui.RoutablePage.repoEventsRoute(self.data.identity, event.kind, event.id)) |route| │ │406 + const event = self.eventWindow().events[index]; │ │407 + if (ui.RoutablePage.repoEventsRoute(self.data.identity, view, event.kind, event.id)) |route|│ │408 self.session.data.current_page = route; │ │409 } │ │410 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │426 │ │427 fn refreshDetail(self: *View, allocator: std.mem.Allocator) !void { │ │428 const index = self.selectedEventIndex() orelse return; │ │400 - if (self.detailed_index) |old| if (old == index) return; │ │429 + const detailed_index = &self.detailed_index[@intFromEnum(self.selectedView())];│ │430 + if (detailed_index.*) |old| if (old == index) return; │ │431 const box = self.detailBox(); │ │432 for (box.children.values()) |*child| child.widget.deinit(allocator); │ │433 box.children.clearAndFree(allocator); │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯