(workspaceId: string, options?: { bypassForceConfirm?: boolean })
| 668 | }; |
| 669 | |
| 670 | const handleDelete = async (workspaceId: string, options?: { bypassForceConfirm?: boolean }) => { |
| 671 | setProcessingIds((prev) => new Set(prev).add(workspaceId)); |
| 672 | try { |
| 673 | const result = await removeWorkspace(workspaceId); |
| 674 | if (result.success) { |
| 675 | onWorkspacesChanged?.(); |
| 676 | return; |
| 677 | } |
| 678 | |
| 679 | // Shift-click: skip force-delete confirmation, auto-force immediately. |
| 680 | if (options?.bypassForceConfirm) { |
| 681 | const forced = await removeWorkspace(workspaceId, { force: true }); |
| 682 | if (forced.success) { |
| 683 | onWorkspacesChanged?.(); |
| 684 | return; |
| 685 | } |
| 686 | |
| 687 | // Force delete also failed — fall through to show modal with the error. |
| 688 | setForceDeleteModal({ |
| 689 | workspaceId, |
| 690 | error: forced.error ?? result.error ?? "Failed to remove workspace", |
| 691 | }); |
| 692 | return; |
| 693 | } |
| 694 | |
| 695 | setForceDeleteModal({ |
| 696 | workspaceId, |
| 697 | error: result.error ?? "Failed to remove workspace", |
| 698 | }); |
| 699 | } finally { |
| 700 | setProcessingIds((prev) => { |
| 701 | const next = new Set(prev); |
| 702 | next.delete(workspaceId); |
| 703 | return next; |
| 704 | }); |
| 705 | } |
| 706 | }; |
| 707 | |
| 708 | const hasSelection = selectedIds.size > 0; |
| 709 | const hasBulkDeleteWorktreeSelection = workspaces.some( |
no test coverage detected