╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Repos.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
77 list: ui.widget.FlowBox.Scroll, 78 data: *const Self, 79 80 pub fn init(allocator: std.mem.Allocator, data: *const Self, web_native: bool) !View { 81 var self = blk: { 82 var list = try ui.widget.FlowBox.Scroll.init(allocator, .{}, web_native); 83 errdefer list.deinit(allocator); 84 85 break :blk View{ 86 .list = list, 87 .data = data, 88 }; 89 }; 90 errdefer self.deinit(allocator); 91 92 var arena = std.heap.ArenaAllocator.init(allocator); 93 defer arena.deinit(); 94 const aa = arena.allocator(); 95 96 // a leading "previous" row off the first window, one row per repo, then 97 // a trailing "next" row when more remain. each window row navigates to the 98 // adjacent window (full reload on web, Nav rebuild on the TUI). 99 var items: std.ArrayList(ui.widget.FlowBox.Item) = .empty; 100 if (data.start > 0) 101 try items.append(aa, .{ .text = "← previous", .link = try std.fmt.allocPrint(aa, "a:/repos/start:{d}", .{data.start -| page_size}) }); 102 for (data.repos, 0..) |repo, i| { 103 // clicking a repo opens its page; the "a:" prefix makes the web 104 // renderer emit an <a href="/repo/alice/foo"> anchor. skip the link 105 // when the owner is unknown so it isn't a dead route. 106 const owner = data.owner_names[i]; 107 try items.append(aa, .{ 108 .text = try std.fmt.allocPrint(aa, "{s} - {s}", .{ repo.event.name, repo.event.description }), 109 .link = if (owner.len > 0) try std.fmt.allocPrint(aa, "a:/repo/{s}/{s}", .{ owner, repo.event.name }) else "", 110 }); 111 } 112 if (data.next_start) |next_start| 113 try items.append(aa, .{ .text = "next →", .link = try std.fmt.allocPrint(aa, "a:/repos/start:{d}", .{next_start}) }); 114 try self.list.setItems(allocator, items.items); 115 116 return self; 117 } 118 119 pub fn deinit(self: *View, allocator: std.mem.Allocator) void { 120 self.list.deinit(allocator); 121 } 122 123 pub fn build(self: *View, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { 124 try self.list.build(allocator, constraint, root_focus); 125 } 126 127 pub fn input(self: *View, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { 128 try self.list.input(allocator, key, root_focus); 129 } 130 131 pub fn clearGrid(self: *View) void { 132 self.list.clearGrid(); 133 } 134 135 pub fn getGrid(self: View) ?Grid { 136 return self.list.getGrid(); 137 } 138 139 pub fn getFocus(self: *View) *Focus { 140 return self.list.getFocus(); 141 } 142 143 pub fn atTop(self: View) bool { 144 return self.list.atTop(); 145 } 146 }; 147