╭ changed ──────────────╮ │src/ui/Repo/Threads.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1097 } │ │1098 │ │1099 if (self.session.data.is_local or self.session.data.user_id != null) { │ │1059 - const thread_route = commentsRoute(self.data.identity, entry.id, 0) orelse return error.RouteTooLong; │ │1060 - const remove_url = try std.fmt.allocPrint(pa, "{s}/remove", .{try thread_route.toUrl(self.session.page_arena)}); │ │1061 - const action_kind: []const u8 = if (entryConflicted(entry)) blk: { │ │1062 - row.getFocus().kind = .{ .custom = try std.fmt.allocPrint(pa, "form:{s}", .{remove_url}) }; │ │1063 - break :blk "submit"; │ │1064 - } else try std.fmt.allocPrint(pa, "{s}{s}", .{ ui.submit_action_prefix, remove_url }); │ │1065 - │ │1100 var remove = try wgt.TextBox(ui.Widget).init(allocator, "✕", .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none });│ │1101 errdefer remove.deinit(allocator); │ │1102 remove.getFocus().focusable = true; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1069 - remove.getFocus().kind = .{ .custom = action_kind }; │ │1070 - self.remove_button_id[index] = remove.getFocus().id; │ │1103 + const route = removeRoute(self.data.identity, entry.id, "") orelse return error.RouteTooLong; │ │1104 + remove.getFocus().kind = .{ .custom = try std.fmt.allocPrint(pa, "a:{s}", .{try route.toUrl(self.session.page_arena)}) }; │ │1105 try row.children.put(allocator, remove.getFocus().id, .{ .widget = .{ .text_box = remove }, .rect = null, .min_size = .{ .width = 3, .height = null } });│ │1106 } │ │1107 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1261 return; │ │1262 } │ │1263 if (self.formViewActive()) { │ │1230 - if (has_conflicts and self.data.view == .resolve) { │ │1264 + if (self.data.view == .remove) { │ │1265 + try self.removeFormInput(allocator, key, root_focus); │ │1266 + } else if (has_conflicts and self.data.view == .resolve) { │ │1267 try self.resolveInput(allocator, key, root_focus); │ │1268 } else if (self.data.view == .new_comment or self.data.view == .edit_comment) {│ │1269 try self.commentFormInput(allocator, key, root_focus); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1382 const row = self.toolRow(index); │ │1383 const cur = if (row.getFocus().child_id) |cid| row.children.getIndex(cid) orelse return else return; │ │1384 const on_status = if (self.status_button_id[index]) |id| row.getFocus().child_id == id else false; │ │1349 - const on_remove = if (self.remove_button_id[index]) |id| row.getFocus().child_id == id else false; │ │1385 switch (key) { │ │1386 .arrow_left => if (cur > first_in_row_index) root_focus.setFocus(row.children.keys()[cur - 1]) else try self.focusList(index, root_focus),│ │1387 .arrow_right => if (cur + 1 < row.children.count()) root_focus.setFocus(row.children.keys()[cur + 1]), │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1390 self.focusDetailEdge(index, root_focus, false); │ │1391 self.detailScroll(index).y = 0; │ │1392 }, │ │1358 - .enter => if (on_remove) try self.removeThread(allocator, index) else if (on_status) try self.toggleStatus(allocator, index), │ │1359 - .mouse => |mouse| if (self.remove_button_id[index]) |id| { │ │1360 - if (inp.leftClickOn(root_focus, id, mouse)) return self.removeThread(allocator, index); │ │1361 - if (self.status_button_id[index]) |status_id| if (inp.leftClickOn(root_focus, status_id, mouse)) try self.toggleStatus(allocator, index);│ │1362 - } else if (self.status_button_id[index]) |id| { │ │1393 + .enter => if (on_status) try self.toggleStatus(allocator, index), │ │1394 + .mouse => |mouse| if (self.status_button_id[index]) |id| { │ │1395 if (inp.leftClickOn(root_focus, id, mouse)) try self.toggleStatus(allocator, index); │ │1396 }, │ │1397 else => {}, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1454 } │ │1455 │ │1456 fn commentInput(self: *This, allocator: std.mem.Allocator, index: usize, key: Key, root_focus: *Focus) !void { │ │1425 - const item = self.focusedComment(index, root_focus); │ │1457 + _ = allocator; │ │1458 switch (key) { │ │1459 .arrow_left => if (!self.moveCommentHorizontal(index, root_focus, false)) return self.focusList(index, root_focus),│ │1460 .arrow_right => _ = self.moveCommentHorizontal(index, root_focus, true), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1461 .arrow_up => _ = self.moveDetailVertical(index, root_focus, false), │ │1462 .arrow_down => _ = self.moveDetailVertical(index, root_focus, true), │ │1431 - .enter => if (item) |comment| if (comment.removeFocused()) try self.removeComment(allocator, comment),│ │1432 - .mouse => |mouse| if (item) |comment| if (comment.remove_button_id) |id| { │ │1433 - if (inp.leftClickOn(root_focus, id, mouse)) try self.removeComment(allocator, comment); │ │1434 - }, │ │1463 else => return, │ │1464 } │ │1437 - } │ │1438 - │ │1439 - fn focusedComment(self: *This, index: usize, root_focus: *Focus) ?*Comment.Item { │ │1440 - const child_index = self.focusedDetailChild(index, root_focus) orelse return null; │ │1441 - return switch (self.detailInner(index).children.values()[child_index].widget) { │ │1442 - .repo_comment => |*comment| comment, │ │1443 - else => null, │ │1444 - }; │ │1465 } │ │1466 │ │1467 // page the detail scroll, then focus the first or last visible widget. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1725 } │ │1726 } │ │1727 │ │1728 + fn removeFormInput(self: *This, allocator: std.mem.Allocator, key: Key, root_focus: *Focus) !void { │ │1729 + const form = self.removeForm() orelse return; │ │1730 + const button_id = form.children.keys()[1]; │ │1731 + switch (key) { │ │1732 + .arrow_up, .back_tab => self.focusHeader(root_focus), │ │1733 + .enter => try self.submitRemove(allocator), │ │1734 + .mouse => |mouse| if (inp.leftClickOn(root_focus, button_id, mouse)) try self.submitRemove(allocator),│ │1735 + else => {}, │ │1736 + } │ │1737 + } │ │1738 + │ │1739 // the multiline hunk inputs keep enter and any up/down that has a row to │ │1740 // move to; enter on a "use this" link is a navigation the host follows │ │1741 // before this runs. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2041 try self.session.navigate(route); │ │2042 } │ │2043 │ │2013 - fn removeThread(self: *This, allocator: std.mem.Allocator, index: usize) !void { │ │2014 - const sel = self.detailed_index[index] orelse return; │ │2015 - const entry = self.window(index).items[sel]; │ │2016 - │ │2017 - var id_bytes: [evt.event_id_size]u8 = undefined; │ │2018 - _ = std.fmt.hexToBytes(&id_bytes, entry.id) catch return; │ │2019 - try self.removeEvent(allocator, kind, id_bytes); │ │2044 + fn submitRemove(self: *This, allocator: std.mem.Allocator) !void { │ │2045 + const comment = self.data.comment_id.len != 0; │ │2046 + const event_id = if (comment) self.data.comment_id else self.data.selected_id; │ │2047 + var id: [evt.event_id_size]u8 = undefined; │ │2048 + _ = std.fmt.hexToBytes(&id, event_id) catch return; │ │2049 + try self.removeEvent(allocator, if (comment) .comment else kind, id); │ │2050 } │ │2051 │ │2022 - fn removeComment(self: *This, allocator: std.mem.Allocator, comment: *Comment.Item) !void { │ │2023 - try self.removeEvent(allocator, .comment, comment.id); │ │2024 - } │ │2025 - │ │2052 fn removeEvent(self: *This, allocator: std.mem.Allocator, event_kind: evt.EventKind, id: [evt.event_id_size]u8) !void {│ │2053 if (comptime wasm) return; │ │2054 const io = self.session.io orelse return; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯