╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Comment.zig ──────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
258 if (target >= bar.children.count()) return false; 259 if (bar.children.values()[target].widget != .spacer) break; 260 } 261 root_focus.setFocus(bar.children.keys()[target]); 262 return true; 263 } 264 265 pub fn rowRect(self: *Item, body_row: bool) ?layout.IRect { 266 if (!body_row) return self.box.children.values()[metadata_index].rect; 267 var rect = self.box.children.values()[body_index].rect orelse return null; 268 if (self.box.children.values()[gap_index].rect) |gap| rect.size.height += gap.size.height; 269 return rect; 270 } 271 272 pub fn deinit(self: *Item, allocator: std.mem.Allocator) void { 273 self.box.deinit(allocator); 274 } 275 276 pub fn build(self: *Item, allocator: std.mem.Allocator, constraint: layout.Constraint, root_focus: *Focus) !void { 277 try self.box.build(allocator, constraint, root_focus); 278 } 279 280 pub fn input(self: *Item, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { 281 try self.box.input(allocator, key, root_focus); 282 } 283 284 pub fn clearGrid(self: *Item) void { 285 self.box.clearGrid(); 286 } 287 288 pub fn getGrid(self: Item) ?Grid { 289 return self.box.getGrid(); 290 } 291 292 pub fn getFocus(self: *Item) *Focus { 293 return self.box.getFocus(); 294 } 295 }; 296 297 // append one comment's metadata bar and body. 298 pub fn appendComment(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), session: *ui.Session, identity: []const u8, thread_kind: evt.EventKind, can_reply: bool, entry: CommentWithId) !void { 299 var item = try Item.init(allocator, session, identity, thread_kind, can_reply, entry); 300 errdefer item.deinit(allocator); 301 try box.children.put(allocator, item.getFocus().id, .{ .widget = .{ .repo_comment = item }, .rect = null, .min_size = null }); 302 } 303 304 pub fn appendCount(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), count: usize, singular: []const u8, plural: []const u8) !void { 305 var text_buf: [64]u8 = undefined; 306 const text = try std.fmt.bufPrint(&text_buf, "{d} {s}", .{ count, if (count == 1) singular else plural }); 307 var count_box = try wgt.TextBox.init(allocator, text, .{ .border_style = .hidden, .wrap_kind = .none }); 308 errdefer count_box.deinit(allocator); 309 try box.children.put(allocator, count_box.getFocus().id, .{ .widget = .{ .text_box = count_box }, .rect = null, .min_size = null }); 310 } 311 312 pub fn appendWindowNav(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), session: *ui.Session, identity: []const u8, thread_kind: evt.EventKind, thread_id: []const u8, selected_id: ?[]const u8, window: Window) !void { 313 const has_prev = window.start > 0; 314 const has_more = window.start < window.count and window.count - window.start > page_size; 315 if (!has_prev and !has_more) return; 316 var row = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz }); 317 errdefer row.deinit(allocator); 318 if (has_prev) { 319 const start = window.start -| page_size; 320 const route = commentsRoute(thread_kind, identity, thread_id, selected_id, start); 321 var previous = try linkBox(allocator, session, "← previous", route orelse return error.RouteTooLong); 322 errdefer previous.deinit(allocator); 323 try row.children.put(allocator, previous.getFocus().id, .{ .widget = .{ .text_box = previous }, .rect = null, .min_size = null }); 324 } 325 if (has_more) { 326 const start = window.start + page_size; 327 const route = commentsRoute(thread_kind, identity, thread_id, selected_id, start); 328 var next = try linkBox(allocator, session, "next →", route orelse return error.RouteTooLong); 329 errdefer next.deinit(allocator); 330 try row.children.put(allocator, next.getFocus().id, .{ .widget = .{ .text_box = next }, .rect = null, .min_size = null }); 331 } 332 row.getFocus().child_id = row.children.keys()[0]; 333 try box.children.put(allocator, row.getFocus().id, .{ .widget = .{ .box = row }, .rect = null, .min_size = null }); 334 } 335 336 fn commentsRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, selected_id: ?[]const u8, start: usize) ?ui.RoutablePage { 337 return if (selected_id) |id| 338 ui.RoutablePage.repoThreadCommentRoute(kind, identity, thread_id, id, start) 339 else 340 ui.RoutablePage.repoThreadCommentsRoute(kind, identity, thread_id, start); 341 } 342 343 fn commentNewRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, parent_id: []const u8) ?ui.RoutablePage { 344 return ui.RoutablePage.repoThreadCommentNewRoute(kind, identity, thread_id, parent_id); 345 } 346 347 fn commentEditRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage { 348 return ui.RoutablePage.repoThreadCommentEditRoute(kind, identity, thread_id, comment_id); 349 } 350 351 fn removeRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage { 352 return ui.RoutablePage.repoThreadRemoveRoute(kind, identity, thread_id, comment_id); 353 } 354 355 pub fn linkBox(allocator: std.mem.Allocator, session: *ui.Session, text: []const u8, route: ui.RoutablePage) !wgt.TextBox { 356 var box = try wgt.TextBox.init(allocator, text, .{ .border_style = .single, .round_corners = true, .wrap_kind = .none }); 357 errdefer box.deinit(allocator); 358 box.getFocus().mode = .all; 359 box.getFocus().kind = .{ .custom = try std.fmt.allocPrint(session.page_arena.allocator(), "a:{s}", .{try route.toUrl(session.page_arena)}) }; 360 return box; 361 } 362