╭ changed ──────────────╮ │src/ui/Repo/Threads.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭─────────────────────────────────────────────────╮ │43 description_id: [view_count]?usize, │ │44 author_id: [view_count]?usize, │ │45 status_button_id: [view_count]?usize,│ │46 - remove_button_id: [view_count]?usize,│ │46 │ │47 const header_index: usize = 0; │ │48 const stack_index: usize = 1; │ ╰─────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │73 pub fn viewIndex(view: ViewKind) usize { │ │74 const name = @tagName(view); │ │75 if (std.mem.eql(u8, name, "tags")) return tags_view_index; │ │77 - if (std.mem.eql(u8, name, "new") or std.mem.eql(u8, name, "edit") or std.mem.eql(u8, name, "new_comment") or std.mem.eql(u8, name, "edit_comment") or std.mem.eql(u8, name, "resolve")) return form_view_index; │ │76 + if (std.mem.eql(u8, name, "new") or std.mem.eql(u8, name, "edit") or std.mem.eql(u8, name, "new_comment") or std.mem.eql(u8, name, "edit_comment") or std.mem.eql(u8, name, "remove") or std.mem.eql(u8, name, "resolve")) return form_view_index;│ │77 if (std.mem.eql(u8, name, "conflicts")) return conflict_view_index; │ │78 if (std.mem.eql(u8, name, "description")) unreachable; │ │79 inline for (@typeInfo(Status).@"enum".fields, 0..) |field, index| { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │118 │ │119 fn editCommentRoute(identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage {│ │120 return ui.RoutablePage.repoThreadCommentEditRoute(kind, identity, thread_id, comment_id); │ │121 + } │ │122 + │ │123 + fn removeRoute(identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage { │ │124 + return ui.RoutablePage.repoThreadRemoveRoute(kind, identity, thread_id, comment_id); │ │125 } │ │126 │ │127 fn editRoute(identity: []const u8, selected: []const u8) ?ui.RoutablePage { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │232 // logged-out session can't create events, so the unauthorized view │ │233 // stands in. │ │234 if (session.data.is_local or session.data.user_id != null) { │ │232 - if (data.view == .new_comment or data.view == .edit_comment) { │ │235 + if (data.view == .remove) { │ │236 + const aa = session.page_arena.allocator(); │ │237 + const route = removeRoute(data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong;│ │238 + const action = try std.fmt.allocPrint(aa, "form:{s}", .{try route.toUrl(session.page_arena)}); │ │239 + const event_name = if (data.comment_id.len == 0) @tagName(kind) else "comment"; │ │240 + const label = try std.fmt.allocPrint(aa, "remove {s}", .{event_name}); │ │241 + var center = try initRemoveForm(allocator, action, label); │ │242 + errdefer center.deinit(allocator); │ │243 + try stack.children.put(allocator, center.getFocus().id, .{ .center = center }); │ │244 + } else if (data.view == .new_comment or data.view == .edit_comment) { │ │245 const editing = data.view == .edit_comment; │ │246 const route = if (editing) │ │247 editCommentRoute(data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────╮ │336 .description_id = @splat(null), │ │337 .author_id = @splat(null), │ │338 .status_button_id = @splat(null),│ │327 - .remove_button_id = @splat(null),│ │339 }; │ │340 } │ │341 │ ╰──────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │486 try addSubmitButtonLabeled(allocator, &box, "submit"); │ │487 box.getFocus().child_id = box.children.keys()[comment_author_field_index]; │ │488 return box; │ │489 + } │ │490 + │ │491 + fn initRemoveForm(allocator: std.mem.Allocator, action: []const u8, label: []const u8) !ui.Center { │ │492 + var box = try wgt.Box(ui.Widget).init(allocator, .{ .border_style = null, .rounded_corners = true, .direction = .vert }); │ │493 + errdefer box.deinit(allocator); │ │494 + box.getFocus().kind = .{ .custom = action }; │ │495 + │ │496 + var prompt = try wgt.Text(ui.Widget).init(allocator, "are you sure?"); │ │497 + errdefer prompt.deinit(allocator); │ │498 + try box.children.put(allocator, prompt.getFocus().id, .{ .widget = .{ .text = prompt }, .rect = null, .min_size = null }); │ │499 + │ │500 + var button = try wgt.TextBox(ui.Widget).init(allocator, label, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none });│ │501 + errdefer button.deinit(allocator); │ │502 + button.getFocus().focusable = true; │ │503 + button.getFocus().kind = .{ .custom = "submit" }; │ │504 + try box.children.put(allocator, button.getFocus().id, .{ .widget = .{ .text_box = button }, .rect = null, .min_size = null }); │ │505 + box.getFocus().child_id = button.getFocus().id; │ │506 + │ │507 + return ui.Center.init(allocator, .{ .box = box }); │ │508 } │ │509 │ │510 // a form's submit button, then a spacer absorbing the leftover │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │759 }; │ │760 } │ │761 │ │762 + fn removeForm(self: *This) ?*wgt.Box(ui.Widget) { │ │763 + return switch (self.viewStack().children.values()[form_view_index]) { │ │764 + .center => |*center| switch (center.child.*) { │ │765 + .box => |*box| box, │ │766 + else => null, │ │767 + }, │ │768 + else => null, │ │769 + }; │ │770 + } │ │771 + │ │772 // the resolve form's scroll on the terminal (the web page scrolls itself)│ │773 fn resolveScroll(self: *This) ?*wgt.Scroll(ui.Widget) { │ │774 return switch (self.viewStack().children.values()[form_view_index]) { │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │871 .edit => editRoute(self.data.identity, self.data.selected_id), │ │872 .new_comment => newCommentRoute(self.data.identity, self.data.selected_id, self.data.comment_id), │ │873 .edit_comment => editCommentRoute(self.data.identity, self.data.selected_id, self.data.comment_id),│ │874 + .remove => removeRoute(self.data.identity, self.data.selected_id, self.data.comment_id), │ │875 .resolve => resolveRoute(self.data.identity, self.data.selected_id, self.data.theirs_picks), │ │876 else => newRoute(self.data.identity), │ │877 } else switch (self.data.view) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │878 .edit => editRoute(self.data.identity, self.data.selected_id), │ │879 .new_comment => newCommentRoute(self.data.identity, self.data.selected_id, self.data.comment_id), │ │880 .edit_comment => editCommentRoute(self.data.identity, self.data.selected_id, self.data.comment_id),│ │881 + .remove => removeRoute(self.data.identity, self.data.selected_id, self.data.comment_id), │ │882 else => newRoute(self.data.identity), │ │883 }) │ │884 else if (has_conflicts and index == conflict_view_index) │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │1018 inner.getFocus().child_id = null; │ │1019 self.author_id[index] = null; │ │1020 self.status_button_id[index] = null; │ │ 979 - self.remove_button_id[index] = null; │ │1021 │ │1022 // the tool row: the open/close and edit buttons; the description page│ │1023 // shows none. │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯