╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │812 } │ │813 │ │814 fn primaryAction(self: *This, allocator: std.mem.Allocator) !void { │ │814 - const entry = self.entry orelse return; │ │815 - if (supports_drafts and entryDraft(entry)) │ │816 - try self.publishDraft(allocator) │ │817 - else │ │818 - try self.toggleStatus(allocator); │ │819 - } │ │820 - │ │821 - fn publishDraft(self: *This, allocator: std.mem.Allocator) !void { │ │822 - if (!supports_drafts or comptime wasm) return; │ │823 - const entry = self.entry orelse return; │ │824 - if (!entryDraft(entry) or !entry.revision_ready) return; │ │825 - try self.data.publishDraft(self.session, allocator, entry.id); │ │826 - const route = listRoute(self.data.identity, @enumFromInt(0), "", entry.id) orelse return;│ │827 - try self.session.navigate(route); │ │815 + try self.toggleStatus(allocator); │ │816 } │ │817 │ │818 fn descriptionInput(self: *This, key: Key, root_focus: *Focus) void { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1240 pub fn viewIndex(view: ViewKind) usize { │ │1241 const name = @tagName(view); │ │1242 if (std.mem.eql(u8, name, "tags")) return tags_view_index; │ │1255 - 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; │ │1243 + if (std.mem.eql(u8, name, "new") or std.mem.eql(u8, name, "edit") or std.mem.eql(u8, name, "publish") 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;│ │1244 if (std.mem.eql(u8, name, "conflicts")) return conflict_view_index; │ │1245 if (std.mem.eql(u8, name, "drafts")) return drafts_view_index; │ │1246 if (std.mem.eql(u8, name, "description")) unreachable; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1250 unreachable; │ │1251 } │ │1252 │ │1253 + const Confirmation = enum { remove, publish }; │ │1254 + │ │1255 + fn confirmation(view: ViewKind) ?Confirmation { │ │1256 + if (view == .remove) return .remove; │ │1257 + if (supports_drafts and std.mem.eql(u8, @tagName(view), "publish")) return .publish;│ │1258 + return null; │ │1259 + } │ │1260 + │ │1261 // the status a status split lists; the conflicts split has none (its │ │1262 // threads carry their own). │ │1263 fn splitStatus(index: usize) Status { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │1282 │ │1283 fn draftsRoute(identity: []const u8) ?ui.RoutablePage { │ │1284 return if (supports_drafts) Data.draftsRoute(identity) else null; │ │1285 + } │ │1286 + │ │1287 + fn publishRoute(identity: []const u8, selected: []const u8) ?ui.RoutablePage { │ │1288 + return if (supports_drafts) Data.publishRoute(identity, selected) else null;│ │1289 } │ │1290 │ │1291 fn conflictsRoute(identity: []const u8, selected: []const u8) ?ui.RoutablePage {│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1378 // logged-out session can't create events, so the unauthorized view │ │1379 // stands in. │ │1380 if (session.data.is_local or session.data.user_id != null) { │ │1381 - if (data.view == .remove) { │ │1381 + if (confirmation(data.view)) |confirmation_kind| { │ │1382 const aa = session.page_arena.allocator(); │ │1383 - const route = ui.RoutablePage.repoThreadRemoveRoute(kind, data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong;│ │1383 + const route = switch (confirmation_kind) { │ │1384 + .remove => ui.RoutablePage.repoThreadRemoveRoute(kind, data.identity, data.selected_id, data.comment_id), │ │1385 + .publish => publishRoute(data.identity, data.selected_id), │ │1386 + } orelse return error.RouteTooLong; │ │1387 const action = try std.fmt.allocPrint(aa, "form:{s}", .{try route.toUrl(session.page_arena)}); │ │1388 const event_name = if (data.comment_id.len == 0) thread_name else "comment"; │ │1389 var label_buf: ["remove ".len + @max(thread_name.len, "comment".len)]u8 = undefined; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1387 - const label = try std.fmt.bufPrint(&label_buf, "remove {s}", .{event_name}); │ │1388 - var center = try initRemoveForm(allocator, action, label); │ │1390 + const label = switch (confirmation_kind) { │ │1391 + .remove => try std.fmt.bufPrint(&label_buf, "remove {s}", .{event_name}), │ │1392 + .publish => "publish patch", │ │1393 + }; │ │1394 + var center = try initConfirmationForm(allocator, action, label); │ │1395 errdefer center.deinit(allocator); │ │1396 try stack.children.put(allocator, center.getFocus().id, .{ .center = center });│ │1397 } else if (data.view == .new_comment or data.view == .edit_comment) { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1622 return box; │ │1623 } │ │1624 │ │1619 - fn initRemoveForm(allocator: std.mem.Allocator, action: []const u8, label: []const u8) !Center { │ │1625 + fn initConfirmationForm(allocator: std.mem.Allocator, action: []const u8, label: []const u8) !Center { │ │1626 var box = try wgt.Box(Widget).init(allocator, .{ .border_style = null, .rounded_corners = true, .direction = .vert });│ │1627 errdefer box.deinit(allocator); │ │1628 box.getFocus().kind = .{ .custom = action }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │1885 }; │ │1886 } │ │1887 │ │1882 - fn removeForm(self: *This) ?*wgt.Box(Widget) { │ │1888 + fn confirmationForm(self: *This) ?*wgt.Box(Widget) { │ │1889 return switch (self.viewStack().children.values()[form_view_index]) {│ │1890 .center => |*center| switch (center.child.*) { │ │1891 .box => |*box| box, │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2056 return; │ │2057 } │ │2058 if (self.formViewActive()) { │ │2053 - if (self.data.view == .remove) { │ │2054 - try self.removeFormInput(allocator, key, root_focus); │ │2059 + if (confirmation(self.data.view) != null) { │ │2060 + try self.confirmationFormInput(allocator, key, root_focus); │ │2061 } else if (supports_conflicts and self.data.view == .resolve) { │ │2062 try self.resolveInput(allocator, key, root_focus); │ │2063 } else if (self.data.view == .new_comment or self.data.view == .edit_comment) {│ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2167 } │ │2168 } │ │2169 │ │2164 - fn removeFormInput(self: *This, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { │ │2165 - const form = self.removeForm() orelse return; │ │2170 + fn confirmationFormInput(self: *This, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void {│ │2171 + const form = self.confirmationForm() orelse return; │ │2172 const button_id = form.children.keys()[1]; │ │2173 switch (key) { │ │2174 .arrow_up, .back_tab => self.focusHeader(root_focus), │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯