Skip to content

fix(desktop): toast and switch workspace when deleting in v2#3661

Merged
Kitenite merged 11 commits into
mainfrom
when-deleting-a-workspace-in-v2-please-toast-that-its-deleting-and-choose-a-different-workspace-to-m
Apr 23, 2026
Merged

fix(desktop): toast and switch workspace when deleting in v2#3661
Kitenite merged 11 commits into
mainfrom
when-deleting-a-workspace-in-v2-please-toast-that-its-deleting-and-choose-a-different-workspace-to-m

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Apr 22, 2026

Summary

  • Fire a "Deleting 'name'..." toast when the user confirms delete in the v2 sidebar. 10–20s of silent destroy felt broken.
  • Navigate off the workspace the moment delete or hide kicks off — not after destroy completes — so the user isn't stuck staring at a row that's being torn down or hidden. Falls back to a sibling workspace (via the existing focus-target util) or home.
  • Split handleDeleted in useDashboardSidebarWorkspaceItemActions into a local navigateAway, a trimmed handleDeleted (just removes the row on destroy success), and a new handleRemoveFromSidebar (nav + remove, used by the "Remove from Sidebar" context menu). Delete wires nav via a new onDeleting callback on DashboardSidebarDeleteDialog, mirroring the existing onDeleted.

Test plan

  • Delete the active workspace → toast appears immediately, view moves to a sibling (or home), row hides; destroy continues in the background.
  • Delete an inactive workspace → toast appears, view doesn't move, row hides.
  • Hide (Remove from Sidebar) the active workspace → view moves to a sibling (or home), row removed.
  • Hide an inactive workspace → view doesn't move, row removed.
  • Conflict / teardown-failed errors → dialog reopens in the error pane as before.

Summary by cubic

Show a one-time "Deleting ''..." toast when a v2 workspace delete starts. Immediately navigate off the active workspace on delete or hide to the next visible workspace or home.

  • Bug Fixes
    • Early navigation now uses useNavigateAwayFromWorkspace (reads URL workspaceId via useParams) and runs before dialog close/state updates, so it lands reliably.
    • "Remove from Sidebar" navigates first via the hook, then removes; delete’s post-success handler now only removes the row.

Written for commit 1c343e3. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Show an immediate "Deleting…" toast when a delete is initiated.
    • Expose an optional callback so integrations can react as deletion starts.
  • Bug Fixes

    • Navigate users away from an item as deletion begins so it isn't left active.
    • Context menu removal now directly triggers sidebar removal to avoid duplicate actions.

Destroy can take 10–20s; showing no feedback and leaving the user on
the workspace being torn down felt broken. Show a loading toast that
resolves to success/error, and navigate to a sibling workspace (or
home) the moment destroy kicks off instead of waiting for it to finish.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an optional onDeleting callback and immediate "Deleting…" toast when a workspace deletion is initiated; updates dialog props and hook usage, and refactors workspace-item actions to separate navigation-away, deleting, and sidebar removal steps.

Changes

Cohort / File(s) Summary
Destroy dialog state & toast
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts
Added optional onDeleting?: () => void; trigger onDeleting and show a "Deleting…" toast immediately when the dialog closes and the workspace is marked deleting, before the async destroy call.
Delete dialog component props
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/DashboardSidebarDeleteDialog.tsx
Prop onDeleting?: () => void added and forwarded into useDestroyDialogState.
Workspace item actions & wiring
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx, apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts
Hook refactored to expose handleDeleting and handleRemoveFromSidebar; handleDeleting triggers navigation-away if active before teardown, handleDeleted now only removes the sidebar row; component uses handleDeleting for onDeleting and replaces direct removeWorkspaceFromSidebar usage with handleRemoveFromSidebar.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant WorkspaceItem
  participant DeleteDialog
  participant DestroyHook
  participant SidebarStore
  participant Router
  participant Toast

  User->>WorkspaceItem: open menu & choose Delete
  WorkspaceItem->>DeleteDialog: show dialog (passes onDeleting)
  User->>DeleteDialog: confirm
  DeleteDialog->>DestroyHook: close dialog, mark deleting
  DestroyHook->>Toast: show "Deleting…" toast
  DestroyHook->>WorkspaceItem: call onDeleting (handleDeleting)
  WorkspaceItem->>Router: navigateAwayIfActive
  DestroyHook->>SidebarStore: optimistic close/remove UI
  DestroyHook->>DestroyHook: call async destroy()
  alt destroy succeeds
    DestroyHook->>SidebarStore: handleDeleted (finalize removal)
  else destroy conflicts/errors
    DestroyHook->>DeleteDialog: reopen dialog / show error toast
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble keys and tap delete,
A toast proclaims "Deleting…"—swift and neat,
I hop away while routes reframe,
The row slips off without a blame,
Farewell, tidy sidebar—onward I leap! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: showing a toast and switching workspaces when deleting in the v2 sidebar, which aligns with the core objectives of the PR.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description provides clear context on changes, test plan, and objectives, though it lacks some template sections like explicit bug fix categorization and screenshots.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch when-deleting-a-workspace-in-v2-please-toast-that-its-deleting-and-choose-a-different-workspace-to-m

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx (1)

203-211: ⚠️ Potential issue | 🔴 Critical

Missing onDeleting wire-up in the expanded (default) sidebar branch — breaks the PR’s primary behavior.

The collapsed branch at line 143 correctly forwards onDeleting={handleDeleting}, but this expanded render — which is the default, non-collapsed sidebar and therefore the common path — only passes onDeleted. As a result, deleting the active workspace from the expanded sidebar won’t navigate the user off the workspace that’s being torn down, which is the main UX fix described in the PR objectives.

Proposed fix
 			{!isPending && (
 				<DashboardSidebarDeleteDialog
 					workspaceId={id}
 					workspaceName={name || branch}
 					open={isDeleteDialogOpen}
 					onOpenChange={setIsDeleteDialogOpen}
+					onDeleting={handleDeleting}
 					onDeleted={handleDeleted}
 				/>
 			)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`
around lines 203 - 211, The expanded (default) branch rendering
DashboardSidebarDeleteDialog is missing the onDeleting prop which the collapsed
branch passes; update the expanded render of DashboardSidebarDeleteDialog to
include onDeleting={handleDeleting} (alongside workspaceId={id},
workspaceName={name || branch}, open={isDeleteDialogOpen},
onOpenChange={setIsDeleteDialogOpen}, and onDeleted={handleDeleted}) so deleting
the active workspace triggers the handleDeleting flow and navigates away as
intended.
🧹 Nitpick comments (1)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts (1)

80-93: Minor: inconsistent quoting of workspaceName between success and error toasts.

The loading and success toasts wrap the name in quotes (Deleting "name"..., Deleted "name"), but the error toast does not (Failed to delete name: ...). Worth aligning for consistency.

Proposed tweak
-					toast.error(`Failed to delete ${workspaceName}: ${e.message}`, {
+					toast.error(`Failed to delete "${workspaceName}": ${e.message}`, {
 						id: toastId,
 					});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts`
around lines 80 - 93, The error toast message in useDestroyDialogState is
inconsistent with the success toast: update the toast.error call (in the catch
block where err is cast to DestroyWorkspaceError and handled) to wrap
workspaceName in quotes just like the success and loading toasts (e.g., `Failed
to delete "workspaceName": ${e.message}`), preserving the existing toastId and
error message usage; ensure this change is applied in the catch branch that
currently calls toast.error and does not affect the conflict/teardown-failed
branch that uses setError/onOpenChange.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`:
- Around line 203-211: The expanded (default) branch rendering
DashboardSidebarDeleteDialog is missing the onDeleting prop which the collapsed
branch passes; update the expanded render of DashboardSidebarDeleteDialog to
include onDeleting={handleDeleting} (alongside workspaceId={id},
workspaceName={name || branch}, open={isDeleteDialogOpen},
onOpenChange={setIsDeleteDialogOpen}, and onDeleted={handleDeleted}) so deleting
the active workspace triggers the handleDeleting flow and navigates away as
intended.

---

Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts`:
- Around line 80-93: The error toast message in useDestroyDialogState is
inconsistent with the success toast: update the toast.error call (in the catch
block where err is cast to DestroyWorkspaceError and handled) to wrap
workspaceName in quotes just like the success and loading toasts (e.g., `Failed
to delete "workspaceName": ${e.message}`), preserving the existing toastId and
error message usage; ensure this change is applied in the catch branch that
currently calls toast.error and does not affect the conflict/teardown-failed
branch that uses setError/onOpenChange.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a63c32d4-5b93-411b-a0dc-a9e50ba70917

📥 Commits

Reviewing files that changed from the base of the PR and between 57aa28c and e6837fd.

📒 Files selected for processing (4)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/DashboardSidebarDeleteDialog.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 22, 2026

Greptile Summary

This PR improves the v2 sidebar workspace-delete UX by (1) showing a loading → success/error toast instead of destroying silently over 10–20 s, and (2) navigating the user off the active workspace the moment deletion kicks off rather than waiting for the async destroy to finish. It achieves this by splitting the old handleDeleted callback into handleDeleting (navigate immediately) + handleDeleted (remove sidebar row on success) and threading a new onDeleting prop through DashboardSidebarDeleteDialoguseDestroyDialogState.

Issues found:

  • P0 bug — onDeleting missing in the expanded sidebar branch (DashboardSidebarWorkspaceItem.tsx lines 203–211): The collapsed branch (line 143) correctly passes onDeleting={handleDeleting}, but the expanded (default) branch omits it entirely. Deleting an active workspace in the normal sidebar state will never trigger navigation, leaving the user stuck on the workspace being torn down — the exact regression this PR was written to prevent.
  • P2 — Inconsistent quoting in error toast: The success toast wraps the name in quotes (Deleted \"${workspaceName}\"), but the error toast does not (Failed to delete ${workspaceName}: …).

Confidence Score: 2/5

Not safe to merge — the primary (expanded) delete path is missing the new onDeleting prop, leaving the core UX fix inoperative for the default sidebar layout.

The overall design — loading toast, early navigation, split callbacks — is correct and well-structured. However, the P0 regression in DashboardSidebarWorkspaceItem.tsx means the fix only works for the collapsed sidebar variant; the expanded (default) variant never fires handleDeleting, so active-workspace navigation on delete is silently absent for the vast majority of users. One targeted fix is required before merging.

DashboardSidebarWorkspaceItem.tsx — the expanded-branch DashboardSidebarDeleteDialog at lines 203–211 is missing onDeleting={handleDeleting}.

Important Files Changed

Filename Overview
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx Correctly wires onDeleting={handleDeleting} in the collapsed branch but omits it in the expanded (default) branch — leaving the primary delete path without navigation-on-delete behavior.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts Cleanly introduces loading toast lifecycle (loading → success/error/dismiss) and onDeleting callback; minor inconsistency in error toast quoting vs. success toast.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts Correctly splits the old handleDeleted into handleDeleting (navigate-immediately) and handleDeleted (remove-row-on-success); logic is sound.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/DashboardSidebarDeleteDialog.tsx Correctly threads the new onDeleting prop through to useDestroyDialogState; no issues.

Sequence Diagram

sequenceDiagram
    participant U as User
    participant D as DeleteDialog
    participant H as useDestroyDialogState
    participant A as useSidebarItemActions
    participant T as Toast (global)
    participant S as Sidebar State

    U->>D: Confirm delete
    D->>H: run(force=false)
    H->>H: onOpenChange(false) — close dialog
    H->>S: markDeleting(workspaceId) — hide row
    H->>A: onDeleting() — handleDeleting()
    alt isActive workspace
        A->>A: navigate to sibling or /
    end
    H->>T: toast.loading("Deleting …")
    H->>H: await destroy()
    alt success
        H->>T: toast.success("Deleted …")
        H->>A: onDeleted() → removeWorkspaceFromSidebar()
    else conflict / teardown-failed
        H->>T: toast.dismiss(toastId)
        H->>D: onOpenChange(true) — reopen in error pane
        H->>S: clearDeleting() — row reappears
    else unknown error
        H->>T: toast.error("Failed to delete …", {id})
        H->>S: clearDeleting() — row reappears
    end
Loading

Comments Outside Diff (1)

  1. apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx, line 203-211 (link)

    P0 onDeleting missing in the expanded (default) sidebar branch

    The collapsed branch at line 143 correctly passes onDeleting={handleDeleting}, but the expanded branch rendered here omits it. Since the expanded layout is the default sidebar state, deleting an active workspace in the normal view will never call handleDeleting, meaning the user is never navigated away and will be left staring at the workspace being torn down for 10–20 seconds — exactly the regression this PR was written to fix.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
    Line: 203-211
    
    Comment:
    **`onDeleting` missing in the expanded (default) sidebar branch**
    
    The collapsed branch at line 143 correctly passes `onDeleting={handleDeleting}`, but the expanded branch rendered here omits it. Since the expanded layout is the default sidebar state, deleting an active workspace in the normal view will never call `handleDeleting`, meaning the user is never navigated away and will be left staring at the workspace being torn down for 10–20 seconds — exactly the regression this PR was written to fix.
    
    
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
Line: 203-211

Comment:
**`onDeleting` missing in the expanded (default) sidebar branch**

The collapsed branch at line 143 correctly passes `onDeleting={handleDeleting}`, but the expanded branch rendered here omits it. Since the expanded layout is the default sidebar state, deleting an active workspace in the normal view will never call `handleDeleting`, meaning the user is never navigated away and will be left staring at the workspace being torn down for 10–20 seconds — exactly the regression this PR was written to fix.

```suggestion
		{!isPending && (
			<DashboardSidebarDeleteDialog
				workspaceId={id}
				workspaceName={name || branch}
				open={isDeleteDialogOpen}
				onOpenChange={setIsDeleteDialogOpen}
				onDeleting={handleDeleting}
				onDeleted={handleDeleted}
			/>
		)}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts
Line: 91-93

Comment:
**Inconsistent quoting in error toast vs. success toast**

The success toast quotes the workspace name (`Deleted "${workspaceName}"`), but the error toast does not (`Failed to delete ${workspaceName}: ...`). Minor, but the inconsistency is visible to users when an error occurs.

```suggestion
				toast.error(`Failed to delete "${workspaceName}": ${e.message}`, {
					id: toastId,
				});
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(desktop): toast and switch workspace..." | Re-trigger Greptile

Comment on lines +91 to +93
toast.error(`Failed to delete ${workspaceName}: ${e.message}`, {
id: toastId,
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Inconsistent quoting in error toast vs. success toast

The success toast quotes the workspace name (Deleted "${workspaceName}"), but the error toast does not (Failed to delete ${workspaceName}: ...). Minor, but the inconsistency is visible to users when an error occurs.

Suggested change
toast.error(`Failed to delete ${workspaceName}: ${e.message}`, {
id: toastId,
});
toast.error(`Failed to delete "${workspaceName}": ${e.message}`, {
id: toastId,
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts
Line: 91-93

Comment:
**Inconsistent quoting in error toast vs. success toast**

The success toast quotes the workspace name (`Deleted "${workspaceName}"`), but the error toast does not (`Failed to delete ${workspaceName}: ...`). Minor, but the inconsistency is visible to users when an error occurs.

```suggestion
				toast.error(`Failed to delete "${workspaceName}": ${e.message}`, {
					id: toastId,
				});
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx:143">
P1: The new `onDeleting` flow is wired only for collapsed items; expanded sidebar items still skip it, so deleting the active workspace won’t navigate away immediately in the default layout.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

A loading toast that persists for 10–20s and then resolves to success
is noisier than the problem warrants. Just fire an info toast at start;
success is already conveyed by the row disappearing.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts:74">
P2: The delete flow no longer uses a loading toast lifecycle, so users can lose in-progress status and never receive a success confirmation toast after deletion completes.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Reverts the handleDeleting split and onDeleting plumbing introduced in
e6837fd / 1df7960. Only change now is a single toast fired at the
start of the destroy flow.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts">

<violation number="1">
P2: The new UX comment is incorrect: it claims there is no loading toast, but the code still shows a delete-start toast.</violation>
</file>

<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts">

<violation number="1">
P2: Navigation for active workspace deletion is now delayed until destroy success because it runs in `onDeleted`. Move route switching to a start-of-delete callback so users are redirected immediately.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Delete takes 10–20s; hide is immediate. In both cases we don't want
to leave the user staring at a row that's being torn down or hidden.
Fires `onDeleting` at the start of destroy (before teardown completes)
and wraps `removeWorkspaceFromSidebar` to nav first, then remove.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx (1)

203-210: ⚠️ Potential issue | 🟠 Major

Pass onDeleting in the expanded delete dialog too.

The collapsed dialog wires onDeleting={handleDeleting}, but the expanded dialog does not. Deleting from the expanded sidebar therefore hides/deletes without navigating off the active workspace.

🐛 Proposed fix
 			{!isPending && (
 				<DashboardSidebarDeleteDialog
 					workspaceId={id}
 					workspaceName={name || branch}
 					open={isDeleteDialogOpen}
 					onOpenChange={setIsDeleteDialogOpen}
+					onDeleting={handleDeleting}
 					onDeleted={handleDeleted}
 				/>
 			)}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`
around lines 203 - 210, The expanded delete dialog instance of
DashboardSidebarDeleteDialog is missing the onDeleting prop, so when deleting
from the expanded sidebar handleDeleting isn't called; add
onDeleting={handleDeleting} to the DashboardSidebarDeleteDialog invocation (the
one rendered inside the {!isPending && ( ... )} block) so both collapsed and
expanded dialogs call the same handleDeleting handler.
apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts (1)

68-88: ⚠️ Potential issue | 🟠 Major

Track the loading toast ID and settle it on every outcome.

Line 74 emits a plain toast, so it never resolves to success/error. Conflict/teardown paths reopen the dialog while the "Deleting…" toast remains visible. Store the toast ID from toast.loading(), update it on success/unknown failure, and dismiss it before reopening the dialog for decision-required errors.

🐛 Proposed toast lifecycle fix
 			setError(null);
 			onOpenChange(false);
 			markDeleting(workspaceId);
 			onDeleting?.();
-			toast(`Deleting "${workspaceName}"...`);
+			const deletingToastId = toast.loading(`Deleting "${workspaceName}"...`);
 
 			try {
 				const result = await destroy({ deleteBranch, force });
 				for (const warning of result.warnings) toast.warning(warning);
 				setDeleteBranch(false);
+				toast.success(`Deleted "${workspaceName}"`, { id: deletingToastId });
 				onDeleted?.();
 			} catch (err) {
 				const e = err as DestroyWorkspaceError;
 				if (e.kind === "conflict" || e.kind === "teardown-failed") {
+					toast.dismiss(deletingToastId);
 					setError(e);
 					onOpenChange(true);
 				} else {
-					toast.error(`Failed to delete ${workspaceName}: ${e.message}`);
+					toast.error(`Failed to delete ${workspaceName}: ${e.message}`, {
+						id: deletingToastId,
+					});
 				}
 			} finally {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts`
around lines 68 - 88, The "Deleting…" toast is emitted with toast(...) and never
settled; change the flow in the delete handler (the block using setError,
onOpenChange, markDeleting, onDeleting, destroy, setDeleteBranch, onDeleted) to
call toast.loading(...) and capture its returned toastId, then on success call
toast.update/toast.success (or toast.dismiss then toast.success) with that id,
on unknown failure call toast.update/toast.error with the id, and on
decision-required errors first dismiss/update the loading toast before calling
setError and onOpenChange(true) so the stale "Deleting…" toast is removed when
the dialog is reopened; ensure you reference the same toastId for all toast
updates/ dismissals.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts`:
- Around line 68-88: The "Deleting…" toast is emitted with toast(...) and never
settled; change the flow in the delete handler (the block using setError,
onOpenChange, markDeleting, onDeleting, destroy, setDeleteBranch, onDeleted) to
call toast.loading(...) and capture its returned toastId, then on success call
toast.update/toast.success (or toast.dismiss then toast.success) with that id,
on unknown failure call toast.update/toast.error with the id, and on
decision-required errors first dismiss/update the loading toast before calling
setError and onOpenChange(true) so the stale "Deleting…" toast is removed when
the dialog is reopened; ensure you reference the same toastId for all toast
updates/ dismissals.

In
`@apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx`:
- Around line 203-210: The expanded delete dialog instance of
DashboardSidebarDeleteDialog is missing the onDeleting prop, so when deleting
from the expanded sidebar handleDeleting isn't called; add
onDeleting={handleDeleting} to the DashboardSidebarDeleteDialog invocation (the
one rendered inside the {!isPending && ( ... )} block) so both collapsed and
expanded dialogs call the same handleDeleting handler.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 06d0b66e-00c4-40e7-92ef-1f34ee83af82

📥 Commits

Reviewing files that changed from the base of the PR and between 854c6e4 and 53f487c.

📒 Files selected for processing (4)
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/DashboardSidebarDeleteDialog.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/DashboardSidebarWorkspaceItem.tsx
  • apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts

matchRoute with params + fuzzy was returning false for this item's hook
when the user was viewing it, so navigateAwayIfActive no-op'd. useParams
matches v1's pattern (useDeleteWorkspace) which is known to work.
Previous attempts threaded an onDeleting callback through dialog props
and relied on the sidebar item's isActive closure, which wasn't firing.
Replace all that with useNavigateAwayFromWorkspace: reads the current
URL's workspaceId via useParams, reads the sidebar list from collections,
picks the first sibling that isn't the one being removed. Delete and
Hide both call it directly — no callback plumbing.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarWorkspaceItem/hooks/useDashboardSidebarWorkspaceItemActions/useDashboardSidebarWorkspaceItemActions.ts:78">
P2: Navigation-away now targets the first remaining workspace, not an adjacent sibling, which can redirect users to an unrelated workspace after hide/delete.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Drops the useNavigateAwayFromWorkspace hook. Nav logic stays inline in
the sidebar item hook (where it already lived for the post-destroy path)
and is shared between handleDeleting and handleRemoveFromSidebar. The
dialog gets the nav via a new onDeleting callback mirroring onDeleted —
same pattern, no hook extraction, zero new files.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts">

<violation number="1" location="apps/desktop/src/renderer/routes/_authenticated/_dashboard/components/DashboardSidebar/components/DashboardSidebarDeleteDialog/hooks/useDestroyDialogState/useDestroyDialogState.ts:73">
P1: `onDeleting` is called outside the `try/finally`, so a thrown callback can leave deletion state stuck (`inFlight` never resets and `clearDeleting` never runs).</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

matchRoute with params + fuzzy returns false for this hook's isActive
check in the early-nav callback path, even when the user is viewing the
workspace. useParams is what v1's useDeleteWorkspace uses and is known
to work.
Nav was never landing — dialog close and markDeleting state thrash were
swallowing it. Move onDeleting to be the first thing run() does so the
navigate call goes out before any other state update can interfere.
The onDeleting callback route was silently dropping the navigation. The
hook-extracted version was the only one that actually worked — call
navigateAway(id) directly inside useDestroyDialogState and the sidebar
item hook, no prop plumbing.
- Refresh useDestroyDialogState JSDoc: it now navigates first and fires a
  one-shot toast (was "run destroy silently, no toast").
- Restore the "deleteBranch preserved on optimistic close" comment that
  was accidentally dropped.
- Revert the isActive matchRoute→useParams swap in the sidebar item hook
  — isActive is only used for styling now, so the change was noise.
@Kitenite Kitenite merged commit 0bc1d0a into main Apr 23, 2026
7 checks passed
@Kitenite Kitenite deleted the when-deleting-a-workspace-in-v2-please-toast-that-its-deleting-and-choose-a-different-workspace-to-m branch April 23, 2026 07:02
@github-actions
Copy link
Copy Markdown
Contributor

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

Thank you for your contribution! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant