-
Notifications
You must be signed in to change notification settings - Fork 1.6k
fix(web): allow removing projects that still contain threads #1922
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1318,19 +1318,25 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec | |
| } | ||
| if (clicked !== "delete") return; | ||
|
|
||
| if (projectThreads.length > 0) { | ||
| toastManager.add({ | ||
| type: "warning", | ||
| title: "Project is not empty", | ||
| description: "Delete all threads in this project before removing it.", | ||
| }); | ||
| return; | ||
| } | ||
|
|
||
| const confirmed = await api.dialogs.confirm(`Remove project "${project.name}"?`); | ||
| const confirmed = await api.dialogs.confirm( | ||
| [ | ||
| `Remove project "${project.name}"?`, | ||
| projectThreads.length > 0 | ||
| ? `This will also delete ${projectThreads.length} thread${projectThreads.length === 1 ? "" : "s"} in this project.` | ||
| : null, | ||
| "Your files on disk will not be affected.", | ||
| ] | ||
| .filter(Boolean) | ||
| .join("\n"), | ||
| ); | ||
| if (!confirmed) return; | ||
|
|
||
| try { | ||
| // Delete all threads in the project first | ||
| for (const thread of projectThreads) { | ||
| await deleteThread(scopeThreadRef(thread.environmentId, thread.id)); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thread deletion before project validation risks data lossHigh Severity All threads are irreversibly deleted before validating that the project API is available and before attempting the project deletion command. If Additional Locations (1)Reviewed by Cursor Bugbot for commit 88532c1. Configure here. |
||
|
|
||
| const projectDraftThread = getDraftThreadByProjectRef( | ||
| scopeProjectRef(project.environmentId, project.id), | ||
| ); | ||
|
|
@@ -1363,12 +1369,13 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec | |
| clearComposerDraftForThread, | ||
| clearProjectDraftThreadId, | ||
| copyPathToClipboard, | ||
| deleteThread, | ||
| getDraftThreadByProjectRef, | ||
| project.cwd, | ||
| project.environmentId, | ||
| project.id, | ||
| project.name, | ||
| projectThreads.length, | ||
| projectThreads, | ||
| suppressProjectClickForContextMenuRef, | ||
| ], | ||
| ); | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cascading delete triggers per-thread worktree confirmation dialogs
High Severity
The loop calls
deleteThreadfor each thread, butdeleteThreadinternally shows a native confirmation dialog for every thread that has an orphaned worktree (asking "Delete the worktree too?"). After the user already confirmed the project removal, they can be bombarded with additional unexpected dialogs — one per qualifying thread. This also contradicts the parent confirmation message claiming "Your files on disk will not be affected," sincedeleteThreadcan actually remove worktrees from disk if the user clicks through those prompts.Reviewed by Cursor Bugbot for commit 88532c1. Configure here.