╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Comment.zig│ ╰───────────────────────╯ ╭────────────────────────────────────────╮ │ 92 .comments = comments.items,│ │ 93 .start = start, │ │ 94 .count = count, │ │103 - .has_prev = start > 0, │ │104 - .has_more = end < count, │ │ 95 }; │ │ 96 } │ │ 97 │ ╰────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │102 haxy_moment: evt.EventDB(hash_kind).HashMap(.read_only), │ │103 id: []const u8, │ │104 ) !?CommentWithId { │ │115 - const bytes = (try idBytes(id)) orelse return null; │ │116 - return readOneBytes(hash_kind, arena, admin_moment, haxy_moment, &bytes, id);│ │105 + const bytes = idBytes(id) orelse return null; │ │106 + return readOneBytes(hash_kind, arena, admin_moment, haxy_moment, &bytes); │ │107 } │ │108 │ │109 fn readOneBytes( │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │111 arena: *std.heap.ArenaAllocator, │ │112 admin_moment: ?evt.AdminDB.HashMap(.read_only), │ │113 haxy_moment: evt.EventDB(hash_kind).HashMap(.read_only), │ │124 - id_bytes: []const u8, │ │125 - id: []const u8, │ │114 + id_bytes: *const [evt.event_id_size]u8, │ │115 ) !?CommentWithId { │ │116 const DB = evt.EventDB(hash_kind); │ │117 const comment = (try evt.Comment.readById(DB, hash_kind, haxy_moment, arena, id_bytes)) orelse return null;│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │118 const parent_author: ?ui.Author = if (!std.mem.eql(u8, &comment.event.parent_id, &comment.event.thread_id)) blk: { │ │130 - const parent_bytes = (try idBytes(&comment.event.parent_id)) orelse break :blk null; │ │119 + const parent_bytes = idBytes(&comment.event.parent_id) orelse break :blk null; │ │120 const parent = (try evt.Comment.readById(DB, hash_kind, haxy_moment, arena, &parent_bytes)) orelse break :blk null;│ │121 break :blk try ui.Author.initFromEmail(admin_moment, arena, parent.author_email); │ │122 } else null; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │123 return .{ │ │135 - .id = try arena.allocator().dupe(u8, id), │ │124 + .id = std.fmt.bytesToHex(id_bytes.*, .lower), │ │125 .comment = comment, │ │126 .author = try ui.Author.initFromEmail(admin_moment, arena, comment.author_email),│ │127 .parent_author = parent_author, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────╮ │128 }; │ │129 } │ │130 │ │142 -fn idBytes(id: []const u8) !?[evt.event_id_size]u8 { │ │131 +fn idBytes(id: []const u8) ?[evt.event_id_size]u8 { │ │132 if (id.len != evt.event_id_size * 2) return null; │ │133 var bytes: [evt.event_id_size]u8 = undefined; │ │134 _ = std.fmt.hexToBytes(&bytes, id) catch return null;│ ╰──────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │154 errdefer author.deinit(allocator); │ │155 try bar.children.put(allocator, author.getFocus().id, .{ .widget = .{ .text_box = author }, .rect = null, .min_size = null, .shrink = true }); │ │156 │ │168 - var reply = try linkBox(allocator, session, "new reply", ui.RoutablePage.repoCommentNewRoute(identity, &entry.comment.event.thread_id, entry.id) orelse return error.RouteTooLong); │ │157 + var reply = try linkBox(allocator, session, "new reply", ui.RoutablePage.repoCommentNewRoute(identity, &entry.comment.event.thread_id, &entry.id) orelse return error.RouteTooLong);│ │158 errdefer reply.deinit(allocator); │ │159 try bar.children.put(allocator, reply.getFocus().id, .{ .widget = .{ .text_box = reply }, .rect = null, .min_size = .{ .width = "new reply".len + 2, .height = null } }); │ │160 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │172 - var permalink = try linkBox(allocator, session, "permalink", ui.RoutablePage.repoCommentsRoute(identity, &entry.comment.event.thread_id, entry.id, 0) orelse return error.RouteTooLong); │ │161 + var permalink = try linkBox(allocator, session, "permalink", ui.RoutablePage.repoCommentsRoute(identity, &entry.comment.event.thread_id, &entry.id, 0) orelse return error.RouteTooLong);│ │162 errdefer permalink.deinit(allocator); │ │163 try bar.children.put(allocator, permalink.getFocus().id, .{ .widget = .{ .text_box = permalink }, .rect = null, .min_size = .{ .width = "permalink".len + 2, .height = null } }); │ │164 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │270 } │ │271 │ │272 pub fn appendWindowNav(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), session: *ui.Session, identity: []const u8, thread_id: []const u8, selected_id: ?[]const u8, window: Window) !void {│ │284 - if (!window.has_prev and !window.has_more) return; │ │273 + const has_prev = window.start > 0; │ │274 + const has_more = window.start < window.count and window.count - window.start > page_size; │ │275 + if (!has_prev and !has_more) return; │ │276 var row = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .direction = .horiz }); │ │277 errdefer row.deinit(allocator); │ │287 - if (window.has_prev) { │ │278 + if (has_prev) { │ │279 const start = window.start -| page_size; │ │280 const route = if (selected_id) |id| │ │281 ui.RoutablePage.repoCommentsRoute(identity, thread_id, id, start) │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │285 errdefer previous.deinit(allocator); │ │286 try row.children.put(allocator, previous.getFocus().id, .{ .widget = .{ .text_box = previous }, .rect = null, .min_size = null });│ │287 } │ │297 - if (window.has_more) { │ │288 + if (has_more) { │ │289 const start = window.start + page_size; │ │290 const route = if (selected_id) |id| │ │291 ui.RoutablePage.repoCommentsRoute(identity, thread_id, id, start) │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯