╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1254 else │ │1255 try arena.allocator().print("{s}/" ++ discuss_seg ++ "{s}/" ++ comment_seg ++ "{s}/new", .{ prefix, t.selected.slice(), t.comment.slice() }); │ │1256 if (t.view == .edit_comment) break :blk try arena.allocator().print("{s}/" ++ discuss_seg ++ "{s}/" ++ comment_seg ++ "{s}/edit", .{ prefix, t.selected.slice(), t.comment.slice() });│ │1248 - if (t.view == .remove) break :blk if (t.comment.len == 0) │ │1249 - try arena.allocator().print("{s}/" ++ discuss_seg ++ "{s}/remove", .{ prefix, t.selected.slice() }) │ │1250 - else │ │1251 - try arena.allocator().print("{s}/" ++ discuss_seg ++ "{s}/" ++ comment_seg ++ "{s}/remove", .{ prefix, t.selected.slice(), t.comment.slice() }); │ │1257 + if (t.view == .remove) break :blk try threadRemoveUrl(arena, prefix, discuss_seg, t.selected.slice(), t.comment.slice(), t.attachment.slice()); │ │1258 if (t.comment.len != 0) break :blk if (t.comments_start == 0) │ │1259 try arena.allocator().print("{s}/" ++ discuss_seg ++ "{s}/" ++ comment_seg ++ "{s}", .{ prefix, t.selected.slice(), t.comment.slice() }) │ │1260 else │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1456 return repoSubRoute("", path[1..]); │ │1457 } │ │1458 │ │1459 + // a thread remove view's url: the thread, then any comment and attachment │ │1460 + // it narrows to, then "remove" │ │1461 + fn threadRemoveUrl(arena: *std.heap.ArenaAllocator, prefix: []const u8, comptime thread_seg: []const u8, selected: []const u8, comment: []const u8, attachment: []const u8) ![]const u8 {│ │1462 + var out: std.Io.Writer.Allocating = .init(arena.allocator()); │ │1463 + try out.writer.print("{s}/" ++ thread_seg ++ "{s}", .{ prefix, selected }); │ │1464 + if (comment.len != 0) try out.writer.print("/" ++ comment_seg ++ "{s}", .{comment}); │ │1465 + if (attachment.len != 0) try out.writer.print("/" ++ attachment_seg ++ "{s}", .{attachment}); │ │1466 + try out.writer.writeAll("/remove"); │ │1467 + return out.written(); │ │1468 + } │ │1469 + │ │1470 // the url prefix for a repo route's identity: "/<identity>", or "" │ │1471 // when the identity is elided. │ │1472 fn repoUrlPrefix(arena: *std.heap.ArenaAllocator, identity: []const u8) ![]const u8 { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1681 if (comment_id.len == 0) return null; │ │1682 const word = params.scanTail(&segments) catch return null; │ │1683 if (word) |last| { │ │1684 + if (std.mem.eql(u8, last, "remove")) return if (params.only(&.{.attachment})) repoThreadRemoveRoute(.issue, pair, issue_id, comment_id, params.values.get(.attachment) orelse "") else null;│ │1685 if (!params.only(&.{})) return null; │ │1686 if (std.mem.eql(u8, last, "new")) return repoThreadCommentNewRoute(.issue, pair, issue_id, comment_id); │ │1687 if (std.mem.eql(u8, last, "edit")) return repoThreadCommentEditRoute(.issue, pair, issue_id, comment_id); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1670 - if (std.mem.eql(u8, last, "remove")) return repoThreadRemoveRoute(.issue, pair, issue_id, comment_id);│ │1688 return null; │ │1689 } │ │1690 if (!params.only(&.{.start})) return null; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1695 if (word) |tail| { │ │1696 if (std.mem.eql(u8, tail, "new")) return if (params.only(&.{})) repoThreadCommentNewRoute(.issue, pair, issue_id, "") else null; │ │1697 if (std.mem.eql(u8, tail, "edit")) return if (params.only(&.{})) repoThreadEditRoute(.issue, pair, issue_id) else null; │ │1681 - if (std.mem.eql(u8, tail, "remove")) return if (params.only(&.{})) repoThreadRemoveRoute(.issue, pair, issue_id, "") else null; │ │1698 + if (std.mem.eql(u8, tail, "remove")) return if (params.only(&.{.attachment})) repoThreadRemoveRoute(.issue, pair, issue_id, "", params.values.get(.attachment) orelse "") else null;│ │1699 if (std.mem.eql(u8, tail, "description")) return if (params.only(&.{})) repoThreadDescriptionRoute(.issue, pair, issue_id) else null; │ │1700 if (std.mem.eql(u8, tail, "resolve")) { │ │1701 if (!params.only(&.{.theirs})) return null; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1716 if (comment_id.len == 0) return null; │ │1717 const word = params.scanTail(&segments) catch return null; │ │1718 if (word) |last| { │ │1719 + if (std.mem.eql(u8, last, "remove")) return if (params.only(&.{.attachment})) repoThreadRemoveRoute(.patch, pair, patch_id, comment_id, params.values.get(.attachment) orelse "") else null;│ │1720 if (!params.only(&.{})) return null; │ │1721 if (std.mem.eql(u8, last, "new")) return repoThreadCommentNewRoute(.patch, pair, patch_id, comment_id); │ │1722 if (std.mem.eql(u8, last, "edit")) return repoThreadCommentEditRoute(.patch, pair, patch_id, comment_id); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1705 - if (std.mem.eql(u8, last, "remove")) return repoThreadRemoveRoute(.patch, pair, patch_id, comment_id);│ │1723 return null; │ │1724 } │ │1725 if (!params.only(&.{.start})) return null; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1732 if (std.mem.eql(u8, tail, "edit")) return if (params.only(&.{})) repoThreadEditRoute(.patch, pair, patch_id) else null; │ │1733 if (std.mem.eql(u8, tail, "publish")) return if (params.only(&.{})) repoPatchPublishRoute(pair, patch_id) else null; │ │1734 if (std.mem.eql(u8, tail, "merge")) return if (params.only(&.{})) repoPatchMergeRoute(pair, patch_id) else null; │ │1718 - if (std.mem.eql(u8, tail, "remove")) return if (params.only(&.{})) repoThreadRemoveRoute(.patch, pair, patch_id, "") else null; │ │1735 + if (std.mem.eql(u8, tail, "remove")) return if (params.only(&.{.attachment})) repoThreadRemoveRoute(.patch, pair, patch_id, "", params.values.get(.attachment) orelse "") else null;│ │1736 if (std.mem.eql(u8, tail, "description")) return if (params.only(&.{})) repoThreadDescriptionRoute(.patch, pair, patch_id) else null; │ │1737 if (std.mem.eql(u8, tail, "resolve")) { │ │1738 if (!params.only(&.{.theirs})) return null; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1753 if (comment_id.len == 0) return null; │ │1754 const word = params.scanTail(&segments) catch return null; │ │1755 if (word) |last| { │ │1756 + if (std.mem.eql(u8, last, "remove")) return if (params.only(&.{.attachment})) repoThreadRemoveRoute(.discuss, pair, discussion_id, comment_id, params.values.get(.attachment) orelse "") else null;│ │1757 if (!params.only(&.{})) return null; │ │1758 if (std.mem.eql(u8, last, "new")) return repoThreadCommentNewRoute(.discuss, pair, discussion_id, comment_id); │ │1759 if (std.mem.eql(u8, last, "edit")) return repoThreadCommentEditRoute(.discuss, pair, discussion_id, comment_id); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1742 - if (std.mem.eql(u8, last, "remove")) return repoThreadRemoveRoute(.discuss, pair, discussion_id, comment_id);│ │1760 return null; │ │1761 } │ │1762 if (!params.only(&.{.start})) return null; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯