╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Events.zig│ ╰──────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │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); │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │434 box.getFocus().child_id = null; │ │435 │ │406 - const item = self.data.events[index]; │ │407 - try self.addViewEvent(allocator, box, item); │ │408 - try addField(allocator, box, @tagName(item.kind), " kind "); │ │409 - try self.addAuthor(allocator, box, item.author); │ │410 - if (item.deleted) try addField(allocator, box, "(deleted)", " data "); │ │436 + const item = self.eventWindow().events[index]; │ │437 + if (item.view_url) |url| { │ │438 + var link = try wgt.TextBox(ui.Widget).init(allocator, "view event", .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); │ │439 + errdefer link.deinit(allocator); │ │440 + link.getFocus().focusable = true; │ │441 + link.getFocus().kind = .{ .custom = try std.fmt.allocPrint(self.session.page_arena.allocator(), "a:{s}", .{url}) }; │ │442 + try box.children.put(allocator, link.getFocus().id, .{ .widget = .{ .text_box = link }, .rect = null, .min_size = null }); │ │443 + } │ │444 + { │ │445 + var kind = try wgt.TextBox(ui.Widget).init(allocator, @tagName(item.kind), .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .word, .label = " kind " });│ │446 + errdefer kind.deinit(allocator); │ │447 + kind.getFocus().focusable = true; │ │448 + try box.children.put(allocator, kind.getFocus().id, .{ .widget = .{ .text_box = kind }, .rect = null, .min_size = null }); │ │449 + } │ │450 + { │ │451 + var author = try ui.authorBox(allocator, self.session.page_arena, item.author); │ │452 + errdefer author.deinit(allocator); │ │453 + try box.children.put(allocator, author.getFocus().id, .{ .widget = .{ .text_box = author }, .rect = null, .min_size = null }); │ │454 + } │ │455 │ │456 if (box.children.count() > 0) box.getFocus().child_id = box.children.keys()[0]; │ │457 self.detailScroll().x = 0; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │458 self.detailScroll().y = 0; │ │459 self.detailScroll().getFocus().version +%= 1; │ │416 - self.detailed_index = index; │ │460 + detailed_index.* = index; │ │461 } │ │462 │ │463 pub fn input(self: *View, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void {│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │465 if (key == .arrow_down) root_focus.setFocus(self.content().getFocus().id) else try self.header().input(allocator, key, root_focus);│ │466 return; │ │467 } │ │424 - if (key == .arrow_up and self.contentAtTop() and self.header().focusButton(root_focus)) return; │ │468 + if (key == .arrow_up and self.contentAtTop()) { │ │469 + self.header().focusCurrent(root_focus); │ │470 + return; │ │471 + } │ │472 if (self.detailActive()) { │ │473 if (key == .arrow_left) { │ │474 root_focus.setFocus(self.listScroll().getFocus().id); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │481 .arrow_right => if (self.detailBox().children.count() > 0) root_focus.setFocus(self.detailScroll().getFocus().id), │ │482 .enter => if (self.selectedEventIndex() != null) │ │483 root_focus.setFocus(self.detailScroll().getFocus().id) │ │437 - else if (self.data.next) |next| if (ui.RoutablePage.repoEventsRoute(self.data.identity, next.kind, next.id)) |route| try self.session.navigate(route), │ │484 + else if (self.eventWindow().next) |next| if (ui.RoutablePage.repoEventsRoute(self.data.identity, self.selectedView(), next.kind, next.id)) |route| try self.session.navigate(route),│ │485 else => {}, │ │486 } │ │487 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │494 } │ │495 │ │496 pub fn getSelectedIndex(self: *View) ?usize { │ │450 - if (self.headerActive()) return 0; │ │451 - return if (self.header().isFocusable() or !self.contentAtTop()) 1 else 0;│ │497 + return if (self.headerActive()) 0 else 1; │ │498 } │ │499 │ │500 pub fn clearGrid(self: *View) void { │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────╮ │511 }; │ │512 │ │513 pub const Header = struct { │ │468 - status: []const u8, │ │469 - is_local: bool, │ │514 + sync_status: ?[]const u8, │ │515 │ │516 const nothing = "nothing to sync";│ │517 const unsynced = "sync needed!"; │ ╰───────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │539 failure: ?[]const u8, │ │540 ) !Header { │ │541 if (failure != null) return Header.empty(aa, failure); │ │497 - const remote_name = (try remoteName(repo_kind, repo_opts, repo, io, aa)) orelse return .{ .status = nothing, .is_local = true };│ │542 + const remote_name = (try remoteName(repo_kind, repo_opts, repo, io, aa)) orelse return .{ .sync_status = nothing }; │ │543 const remote_ref: rf.Ref = .{ .kind = .{ .remote = remote_name }, .name = evt.events_ref.name }; │ │499 - const local_oid = (try repo.readRef(io, evt.events_ref)) orelse return .{ .status = nothing, .is_local = true }; │ │500 - const remote_oid = (try repo.readRef(io, remote_ref)) orelse return .{ .status = nothing, .is_local = true }; │ │501 - return .{ .status = if (std.mem.eql(u8, &local_oid, &remote_oid)) nothing else unsynced, .is_local = true }; │ │544 + const local_oid = (try repo.readRef(io, evt.events_ref)) orelse return .{ .sync_status = nothing }; │ │545 + const remote_oid = (try repo.readRef(io, remote_ref)) orelse return .{ .sync_status = nothing }; │ │546 + return .{ .sync_status = if (std.mem.eql(u8, &local_oid, &remote_oid)) nothing else unsynced }; │ │547 } │ │548 │ │549 pub fn empty(aa: std.mem.Allocator, failure: ?[]const u8) !Header { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │505 - return .{ .status = if (failure) |name| try std.fmt.allocPrint(aa, "error: {s}", .{name}) else nothing, .is_local = true }; │ │550 + return .{ .sync_status = if (failure) |name| try std.fmt.allocPrint(aa, "error: {s}", .{name}) else nothing }; │ │551 } │ │552 │ │508 - pub fn remote(aa: std.mem.Allocator, count: usize) !Header { │ │509 - return .{ .status = try std.fmt.allocPrint(aa, "{d} events found", .{count}), .is_local = false }; │ │553 + pub fn remote() Header { │ │554 + return .{ .sync_status = null }; │ │555 } │ │556 │ │512 - fn withCount(self: Header, aa: std.mem.Allocator, count: usize) !Header { │ │513 - return .{ .status = try std.fmt.allocPrint(aa, "{d} events found - {s}", .{ count, self.status }), .is_local = self.is_local };│ │514 - } │ │515 - │ │557 pub const View = struct { │ │558 box: wgt.Box(ui.Widget), │ │559 session: *ui.Session, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯