╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Comment.zig│ ╰───────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │190 }); │ │191 errdefer parent.deinit(allocator); │ │192 parent.getFocus().focusable = true; │ │193 - const route = ui.RoutablePage.repoCommentsRoute(identity, &entry.comment.event.thread_id, &entry.comment.event.parent_id, 0) orelse return error.RouteTooLong; │ │193 + const route = commentsRoute(thread_kind, identity, &entry.comment.event.thread_id, &entry.comment.event.parent_id, 0) orelse return error.RouteTooLong; │ │194 parent.getFocus().kind = .{ .custom = try std.fmt.allocPrint(session.page_arena.allocator(), "a:{s}", .{try route.toUrl(session.page_arena)}) }; │ │195 try bar.children.put(allocator, parent.getFocus().id, .{ .widget = .{ .text_box = parent }, .rect = null, .min_size = .{ .width = @max(parent_text.len, " replying to ".len) + 2, .height = null } });│ │196 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │197 │ │198 if (!entry.comment.removed and (session.data.is_local or session.data.user_id != null)) { │ │199 - const route = ui.RoutablePage.repoCommentsRoute(identity, &entry.comment.event.thread_id, &entry.id, 0) orelse return error.RouteTooLong; │ │199 + const route = commentsRoute(thread_kind, identity, &entry.comment.event.thread_id, &entry.id, 0) orelse return error.RouteTooLong; │ │200 bar.getFocus().kind = .{ .custom = try std.fmt.allocPrint(session.page_arena.allocator(), "form:{s}/remove", .{try route.toUrl(session.page_arena)}) };│ │201 var remove = try wgt.TextBox(ui.Widget).init(allocator, "✕", .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); │ │202 errdefer remove.deinit(allocator); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │299 }; │ │300 │ │301 // append one comment's metadata bar and body. │ │302 -pub fn appendComment(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), session: *ui.Session, identity: []const u8, entry: CommentWithId) !void { │ │303 - var item = try Item.init(allocator, session, identity, entry); │ │302 +pub fn appendComment(allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), session: *ui.Session, identity: []const u8, thread_kind: evt.EventKind, entry: CommentWithId) !void {│ │303 + var item = try Item.init(allocator, session, identity, thread_kind, entry); │ │304 errdefer item.deinit(allocator); │ │305 try box.children.put(allocator, item.getFocus().id, .{ .widget = .{ .repo_comment = item }, .rect = null, .min_size = null }); │ │306 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │312 try box.children.put(allocator, count_box.getFocus().id, .{ .widget = .{ .text_box = count_box }, .rect = null, .min_size = null }); │ │313 } │ │314 │ │315 -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 { │ │315 +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 {│ │316 const has_prev = window.start > 0; │ │317 const has_more = window.start < window.count and window.count - window.start > page_size; │ │318 if (!has_prev and !has_more) return; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │320 errdefer row.deinit(allocator); │ │321 if (has_prev) { │ │322 const start = window.start -| page_size; │ │323 - const route = if (selected_id) |id| │ │324 - ui.RoutablePage.repoCommentsRoute(identity, thread_id, id, start) │ │325 - else │ │326 - ui.RoutablePage.repoIssueCommentsRoute(identity, thread_id, start); │ │323 + const route = commentsRoute(thread_kind, identity, thread_id, selected_id, start); │ │324 var previous = try linkBox(allocator, session, "← previous", route orelse return error.RouteTooLong); │ │325 errdefer previous.deinit(allocator); │ │326 try row.children.put(allocator, previous.getFocus().id, .{ .widget = .{ .text_box = previous }, .rect = null, .min_size = null });│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │327 } │ │328 if (has_more) { │ │329 const start = window.start + page_size; │ │333 - const route = if (selected_id) |id| │ │334 - ui.RoutablePage.repoCommentsRoute(identity, thread_id, id, start) │ │335 - else │ │336 - ui.RoutablePage.repoIssueCommentsRoute(identity, thread_id, start); │ │330 + const route = commentsRoute(thread_kind, identity, thread_id, selected_id, start); │ │331 var next = try linkBox(allocator, session, "next →", route orelse return error.RouteTooLong); │ │332 errdefer next.deinit(allocator); │ │333 try row.children.put(allocator, next.getFocus().id, .{ .widget = .{ .text_box = next }, .rect = null, .min_size = null });│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │334 } │ │335 row.getFocus().child_id = row.children.keys()[0]; │ │336 try box.children.put(allocator, row.getFocus().id, .{ .widget = .{ .box = row }, .rect = null, .min_size = null }); │ │337 +} │ │338 + │ │339 +fn commentsRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, selected_id: ?[]const u8, start: usize) ?ui.RoutablePage { │ │340 + return switch (kind) { │ │341 + .issue => if (selected_id) |id| ui.RoutablePage.repoCommentsRoute(identity, thread_id, id, start) else ui.RoutablePage.repoIssueCommentsRoute(identity, thread_id, start), │ │342 + .discussion => if (selected_id) |id| ui.RoutablePage.repoDiscussionCommentRoute(identity, thread_id, id, start) else ui.RoutablePage.repoDiscussionCommentsRoute(identity, thread_id, start),│ │343 + else => null, │ │344 + }; │ │345 +} │ │346 + │ │347 +fn commentNewRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, parent_id: []const u8) ?ui.RoutablePage { │ │348 + return switch (kind) { │ │349 + .issue => ui.RoutablePage.repoCommentNewRoute(identity, thread_id, parent_id), │ │350 + .discussion => ui.RoutablePage.repoDiscussionCommentNewRoute(identity, thread_id, parent_id), │ │351 + else => null, │ │352 + }; │ │353 } │ │354 │ │355 +fn commentEditRoute(kind: evt.EventKind, identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage { │ │356 + return switch (kind) { │ │357 + .issue => ui.RoutablePage.repoCommentEditRoute(identity, thread_id, comment_id), │ │358 + .discussion => ui.RoutablePage.repoDiscussionCommentEditRoute(identity, thread_id, comment_id), │ │359 + else => null, │ │360 + }; │ │361 +} │ │362 + │ │363 pub fn linkBox(allocator: std.mem.Allocator, session: *ui.Session, text: []const u8, route: ui.RoutablePage) !wgt.TextBox(ui.Widget) { │ │364 var box = try wgt.TextBox(ui.Widget).init(allocator, text, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); │ │365 errdefer box.deinit(allocator); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Events.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────╮ │187 .user => evt.User, │ │188 .repo => evt.Repo, │ │189 .issue => evt.Issue, │ │190 + .discussion => evt.Discussion,│ │191 .comment => evt.Comment, │ │192 .attach => evt.Attachment, │ │193 }; │ ╰───────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │230 item.author = try ui.Author.initFromEmail(admin_moment, arena, record.author_email); │ │231 if (!include_view_url) return item; │ │232 const route = ui.RoutablePage.repoIssueCommentsRoute(identity, item.id, 0) orelse return error.RouteTooLong; │ │233 + item.view_url = try route.toUrl(arena); │ │234 + }, │ │235 + .discussion => { │ │236 + const record = (try readRecord(evt.Discussion, hash_kind, arena, haxy_moment, id)) orelse return null; │ │237 + item.author = try ui.Author.initFromEmail(admin_moment, arena, record.author_email); │ │238 + if (!include_view_url) return item; │ │239 + const route = ui.RoutablePage.repoDiscussionCommentsRoute(identity, item.id, 0) orelse return error.RouteTooLong;│ │240 item.view_url = try route.toUrl(arena); │ │241 }, │ │242 .comment => { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │248 const thread_kind = (try evt.readEventKind(hash_kind, kind_map, &thread_id)) orelse return item; │ │249 const route = switch (thread_kind) { │ │250 .issue => ui.RoutablePage.repoCommentsRoute(identity, &record.event.thread_id, item.id, 0), │ │251 + .discussion => ui.RoutablePage.repoDiscussionCommentRoute(identity, &record.event.thread_id, item.id, 0),│ │252 else => null, │ │253 } orelse return item; │ │254 item.view_url = try route.toUrl(arena); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯