Skip to content

fix(desktop): restore new workspace modal persistence#2225

Merged
Kitenite merged 1 commit into
mainfrom
kitenite/did-we-remove-persistence-on-the-new-workspace-mod
Mar 8, 2026
Merged

fix(desktop): restore new workspace modal persistence#2225
Kitenite merged 1 commit into
mainfrom
kitenite/did-we-remove-persistence-on-the-new-workspace-mod

Conversation

@Kitenite
Copy link
Copy Markdown
Collaborator

@Kitenite Kitenite commented Mar 8, 2026

Summary

  • restore new workspace modal draft persistence across close/reopen for tab selection, selected project, prompt draft, advanced options, and per-tab searches
  • render the prompt flow outside the cmdk command list again so the textarea keeps native multiline and arrow-key behavior
  • keep the global modal store focused on open/close state only, and move draft persistence into a modal-local useState context with shared close/reset and async-success helpers to cut down repeated action wiring

Testing

  • bunx biome check apps/desktop/src/renderer/stores/new-workspace-modal.ts apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModalDraftContext.tsx apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx apps/desktop/src/renderer/components/NewWorkspaceModal/components/BranchesGroup/BranchesGroup.tsx apps/desktop/src/renderer/components/NewWorkspaceModal/components/PullRequestsGroup/PullRequestsGroup.tsx
  • bunx tsc -p apps/desktop/tsconfig.json --noEmit

Summary by CodeRabbit

  • New Features

    • Modal now preserves inputs and per-tab searches via a centralized draft provider and hook.
    • Unified modal content with tabbed views for Prompt, Issues, Pull Requests, and Branches; project selector always visible.
  • Bug Fixes

    • More consistent create/import flows with clear loading/success/error feedback and reliable draft cleanup.
    • Navigation and project selection now behave consistently across tabs.
  • Style

    • Updated dialog layout and clearer tab-to-prompt navigation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 8, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Centralizes NewWorkspaceModal state into a new draft context/provider, replaces CommandDialog with Dialog-based UI, moves per-tab and selection state into the draft, rewires child group components to use the draft and runAsyncAction/closeAndResetDraft flows, and introduces NewWorkspaceModalContent.

Changes

Cohort / File(s) Summary
Draft context & API
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModalDraftContext.tsx
Adds NewWorkspaceModalDraftProvider, useNewWorkspaceModalDraft hook, NewWorkspaceModalTab/NewWorkspaceModalDraft types, draftVersion semantics, and actions: updateDraft, resetDraft, resetDraftIfVersion, closeModal, closeAndResetDraft, runAsyncAction.
Main modal
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx
Replaces CommandDialog with Dialog components; wraps modal in NewWorkspaceModalDraftProvider; removes local modal state and delegates to draft; wires NewWorkspaceModalContent and handlers for import/new-project.
Modal content
apps/desktop/src/renderer/components/NewWorkspaceModal/components/NewWorkspaceModalContent/...
New NewWorkspaceModalContent component implementing tab navigation, project selector, per-tab query routing, and rendering of Prompt vs list-group views driven by draft state.
Group components
apps/desktop/src/renderer/components/NewWorkspaceModal/components/BranchesGroup/BranchesGroup.tsx, .../IssuesGroup/IssuesGroup.tsx, .../PullRequestsGroup/PullRequestsGroup.tsx
Remove onClose prop; consume useNewWorkspaceModalDraft; replace direct onClose/toast.promise patterns with closeAndResetDraft, runAsyncAction, and draft-version reset flows for create/open operations.
Prompt UI group
apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx
Moves local prompt/branch/base/advanced state into draft; replaces local setters with updateDraft; uses runAsyncAction for async creation flows and closeModal/resetDraft behaviors on navigation.
Exports / barrels
apps/desktop/src/renderer/components/NewWorkspaceModal/components/NewWorkspaceModalContent/index.ts
Adds barrel export for NewWorkspaceModalContent.
Minor store touch
apps/desktop/src/renderer/stores/new-workspace-modal.ts
Trivial comment removal only; no API changes.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant M as Dialog Modal
  participant D as DraftProvider
  participant C as NewWorkspaceModalContent
  participant G as Group (Prompt / List)
  participant API as Workspace API
  participant T as toast.promise

  U->>M: open modal / interact (select project, type, switch tab)
  M->>D: read/updateDraft (selectedProjectId, activeTab, queries)
  C->>D: read draft snapshot (to render UI)
  U->>C: trigger create/import action
  G->>D: gather draft payload
  G->>API: call mutateAsync (create workspace) -- returns Promise
  G->>T: runAsyncAction / toast.promise(promise)
  API-->>T: success / failure
  T-->>G: show result
  G->>D: closeAndResetDraft or resetDraftIfVersion on success
  D->>M: modal closed/state reset
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I hopped through drafts and tabs with care,
Gathered states and tucked them in a lair,
Promises toasted, then gently swept,
Reset the burrow, close — secrets kept,
A tiny hop, a modal fixed with flair.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly describes the main fix: restoring draft persistence for the new workspace modal.
Description check ✅ Passed Description covers key changes (persistence restoration, prompt rendering fix, context-based state management) and testing approach, though missing related issues link.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kitenite/did-we-remove-persistence-on-the-new-workspace-mod

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

@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 6 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/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx">

<violation number="1" location="apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx:161">
P3: Empty `.catch(() => undefined)` silently swallows the rejection. Although `toast.promise` shows the error to the user, this hides it from console/logs. Replace with a minimal log so failures remain observable during debugging.

(Based on your team's feedback about avoiding empty catch blocks that hide failures.) [FEEDBACK_USED]</violation>
</file>

<file name="apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx">

<violation number="1" location="apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx:113">
P1: `DialogHeader` with `DialogTitle` and `DialogDescription` must be inside `DialogContent`, not a sibling. Because `DialogContent` renders through a Radix portal, these elements end up in a different DOM subtree, breaking the `aria-labelledby`/`aria-describedby` associations and triggering Radix console warnings.</violation>
</file>

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

Comment thread apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx Outdated
.then(() => {
clearInputsIfDraftVersion(submitDraftVersion);
})
.catch(() => undefined);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Mar 8, 2026

Choose a reason for hiding this comment

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

P3: Empty .catch(() => undefined) silently swallows the rejection. Although toast.promise shows the error to the user, this hides it from console/logs. Replace with a minimal log so failures remain observable during debugging.

(Based on your team's feedback about avoiding empty catch blocks that hide failures.)

View Feedback: 1 2

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx, line 161:

<comment>Empty `.catch(() => undefined)` silently swallows the rejection. Although `toast.promise` shows the error to the user, this hides it from console/logs. Replace with a minimal log so failures remain observable during debugging.

(Based on your team's feedback about avoiding empty catch blocks that hide failures.) </comment>

<file context>
@@ -125,26 +134,31 @@ export function IssuesGroup({ projectId, onClose }: IssuesGroupProps) {
+							.then(() => {
+								clearInputsIfDraftVersion(submitDraftVersion);
+							})
+							.catch(() => undefined);
 					}}
 					className="group h-12"
</file context>
Fix with Cubic

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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/desktop/src/renderer/stores/new-workspace-modal.ts (1)

80-81: Consider whether tab changes should increment draftVersion.

Currently, setActiveTab increments draftVersion, which means switching tabs after initiating workspace creation (but before the promise resolves) will prevent inputs from being cleared. This may be intentional (preserving draft if user continues interacting), but it could also surprise users if they switch tabs while waiting and then return to find stale inputs.

If the intent is to only track content edits, consider not incrementing draftVersion on tab changes:

♻️ Optional: Don't increment draftVersion on tab change
-			setActiveTab: (activeTab) =>
-				set((state) => ({ activeTab, draftVersion: state.draftVersion + 1 })),
+			setActiveTab: (activeTab) => set({ activeTab }),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/stores/new-workspace-modal.ts` around lines 80 -
81, The setActiveTab updater currently increments draftVersion which causes tab
switches to count as content edits; update the setActiveTab implementation (the
setActiveTab function that calls set(...) and touches draftVersion) to stop
modifying draftVersion when changing tabs so that only real content edits bump
draftVersion; if you intend to preserve the current behavior, instead add a
clear comment in setActiveTab noting why draftVersion increments on tab change
and consider adding an explicit method (e.g., bumpDraftVersion) for content
edits to avoid surprising side-effects.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`:
- Around line 58-66: The useEffect in NewWorkspaceModal runs
setSelectedProjectId unconditionally when no matching project is found, causing
an infinite loop because setSelectedProjectId always increments draftVersion;
update the effect to only call setSelectedProjectId when the new id differs from
the current selectedProjectId and is non-null (e.g. compute const newId =
recentProjects[0]?.id ?? null and call setSelectedProjectId(newId) only if newId
!== selectedProjectId), or skip calling it when recentProjects is empty;
reference the useEffect block and the selectedProjectId / setSelectedProjectId
variables to locate the change.

---

Nitpick comments:
In `@apps/desktop/src/renderer/stores/new-workspace-modal.ts`:
- Around line 80-81: The setActiveTab updater currently increments draftVersion
which causes tab switches to count as content edits; update the setActiveTab
implementation (the setActiveTab function that calls set(...) and touches
draftVersion) to stop modifying draftVersion when changing tabs so that only
real content edits bump draftVersion; if you intend to preserve the current
behavior, instead add a clear comment in setActiveTab noting why draftVersion
increments on tab change and consider adding an explicit method (e.g.,
bumpDraftVersion) for content edits to avoid surprising side-effects.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 97cc95b5-5fa5-486a-8c6d-140071217c22

📥 Commits

Reviewing files that changed from the base of the PR and between 9b0c2ec and 05380ec.

📒 Files selected for processing (6)
  • apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/BranchesGroup/BranchesGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PullRequestsGroup/PullRequestsGroup.tsx
  • apps/desktop/src/renderer/stores/new-workspace-modal.ts

Comment thread apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx Outdated
@Kitenite Kitenite force-pushed the kitenite/did-we-remove-persistence-on-the-new-workspace-mod branch from 05380ec to 3d770ee Compare March 8, 2026 06:53
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.

♻️ Duplicate comments (1)
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx (1)

103-126: ⚠️ Potential issue | 🟠 Major

Infinite loop when recentProjects is empty and selectedProjectId is null.

When recentProjects is empty, hasSelectedProject is false, triggering updateDraft({ selectedProjectId: null }). Since updateDraft always increments draftVersion, this causes a re-render and the effect runs again indefinitely.

🐛 Proposed fix: Guard against setting the same value
 	useEffect(() => {
 		if (!isOpen) return;

 		if (
 			preSelectedProjectId &&
 			preSelectedProjectId !== draft.selectedProjectId
 		) {
 			updateDraft({ selectedProjectId: preSelectedProjectId });
 			return;
 		}

 		const hasSelectedProject = recentProjects.some(
 			(project) => project.id === draft.selectedProjectId,
 		);
 		if (!hasSelectedProject) {
-			updateDraft({ selectedProjectId: recentProjects[0]?.id ?? null });
+			const newProjectId = recentProjects[0]?.id ?? null;
+			if (newProjectId !== draft.selectedProjectId) {
+				updateDraft({ selectedProjectId: newProjectId });
+			}
 		}
 	}, [
 		draft.selectedProjectId,
 		isOpen,
 		preSelectedProjectId,
 		recentProjects,
 		updateDraft,
 	]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`
around lines 103 - 126, The effect in NewWorkspaceModal's useEffect is causing
an infinite loop because when recentProjects is empty it calls updateDraft({
selectedProjectId: null }) even if draft.selectedProjectId is already null;
change the logic in the effect to only call updateDraft when the new
selectedProjectId differs from the current draft.selectedProjectId (i.e.,
compute const newId = recentProjects[0]?.id ?? null and only call updateDraft({
selectedProjectId: newId }) if newId !== draft.selectedProjectId), leaving the
existing preSelectedProjectId branch intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`:
- Around line 103-126: The effect in NewWorkspaceModal's useEffect is causing an
infinite loop because when recentProjects is empty it calls updateDraft({
selectedProjectId: null }) even if draft.selectedProjectId is already null;
change the logic in the effect to only call updateDraft when the new
selectedProjectId differs from the current draft.selectedProjectId (i.e.,
compute const newId = recentProjects[0]?.id ?? null and only call updateDraft({
selectedProjectId: newId }) if newId !== draft.selectedProjectId), leaving the
existing preSelectedProjectId branch intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 19dea91e-d775-45a0-aa75-92593853691b

📥 Commits

Reviewing files that changed from the base of the PR and between 05380ec and 3d770ee.

📒 Files selected for processing (7)
  • apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModalDraftContext.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/BranchesGroup/BranchesGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PullRequestsGroup/PullRequestsGroup.tsx
  • apps/desktop/src/renderer/stores/new-workspace-modal.ts
💤 Files with no reviewable changes (1)
  • apps/desktop/src/renderer/stores/new-workspace-modal.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx

@Kitenite Kitenite force-pushed the kitenite/did-we-remove-persistence-on-the-new-workspace-mod branch from 3d770ee to 68457a5 Compare March 8, 2026 07:04
@Kitenite Kitenite force-pushed the kitenite/did-we-remove-persistence-on-the-new-workspace-mod branch from 68457a5 to 0fb2d5b Compare March 8, 2026 07:08
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.

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx (1)

100-116: ⚠️ Potential issue | 🟠 Major

Don't overwrite the caller's preselected project in the fallback effect.

After the first sync, Lines 111-116 still run. If openModal(projectId) supplied a valid project that is not in getRecents(), this effect immediately replaces it with recentProjects[0]. When recentProjects is empty, it also keeps writing null, which can spin the modal because updateDraft() bumps draftVersion on every call.

Proposed fix
 	useEffect(() => {
 		if (!isOpen) return;
 
 		if (
 			preSelectedProjectId &&
 			preSelectedProjectId !== draft.selectedProjectId
 		) {
 			updateDraft({ selectedProjectId: preSelectedProjectId });
 			return;
 		}
 
+		if (preSelectedProjectId) {
+			return;
+		}
+
+		const fallbackProjectId = recentProjects[0]?.id ?? null;
 		const hasSelectedProject = recentProjects.some(
 			(project) => project.id === draft.selectedProjectId,
 		);
-		if (!hasSelectedProject) {
-			updateDraft({ selectedProjectId: recentProjects[0]?.id ?? null });
+		if (!hasSelectedProject && fallbackProjectId !== draft.selectedProjectId) {
+			updateDraft({ selectedProjectId: fallbackProjectId });
 		}
 	}, [
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`
around lines 100 - 116, The effect in NewWorkspaceModal.tsx currently overwrites
a caller-supplied preSelectedProjectId via the fallback that sets
draft.selectedProjectId from recentProjects; change the logic in the useEffect
so the fallback block (the hasSelectedProject check and call to updateDraft)
only runs when preSelectedProjectId is falsy, and avoid writing null into
updateDraft when recentProjects is empty (keep the existing
draft.selectedProjectId instead). In practice: after the existing
preSelectedProjectId check/return, add a guard that if preSelectedProjectId is
truthy skip the fallback, and when picking a fallback id use
recentProjects[0]?.id ?? draft.selectedProjectId (or simply skip updateDraft if
no recentProjects[0]) to prevent spinning updates from writing null.
🧹 Nitpick comments (1)
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx (1)

90-219: Extract NewWorkspaceModalContent into its own file.

This file now contains two components, which makes the modal shell harder to scan and falls outside the repo's component layout rules.

As per coding guidelines, **/{components,pages}/**/*.{tsx,ts}: No multi-component files - maintain one component per file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`
around lines 90 - 219, Extract the NewWorkspaceModalContent component into its
own file: create a new NewWorkspaceModalContent.tsx that exports the
NewWorkspaceModalContent function (and its props type
NewWorkspaceModalContentProps if declared inline) and move all logic including
useNewWorkspaceModalDraft, useEffect, listQuery/handleListQueryChange, and JSX
rendering (Tabs, ProjectSelector, Command/CommandInput/CommandList,
PullRequestsGroup, BranchesGroup, IssuesGroup, PromptGroup) into it; then
replace the in-file definition with an import of NewWorkspaceModalContent in the
original file and ensure any referenced symbols (useNewWorkspaceModalDraft,
ProjectSelector, PullRequestsGroup, BranchesGroup, IssuesGroup, PromptGroup,
COMMAND_CLASS_NAME) are imported in the new file and exported types/props are
re-exported if the parent expects them.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/components/PullRequestsGroup/PullRequestsGroup.tsx`:
- Line 36: The code currently calls closeAndResetDraft() from
useNewWorkspaceModalDraft when navigating users to Integrations, which clears
the draft and loses restored modal state; change those calls to closeModal()
instead so the modal is closed but the draft is preserved. Update the two places
that call closeAndResetDraft() (the one at PullRequestsGroup.tsx where
closeAndResetDraft is destructured and the call sites around the Integrations
navigation — also the similar calls at the other mentioned location around lines
107-109) to call closeModal() while leaving closeAndResetDraft() reserved for
successful create/open flows.

---

Duplicate comments:
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`:
- Around line 100-116: The effect in NewWorkspaceModal.tsx currently overwrites
a caller-supplied preSelectedProjectId via the fallback that sets
draft.selectedProjectId from recentProjects; change the logic in the useEffect
so the fallback block (the hasSelectedProject check and call to updateDraft)
only runs when preSelectedProjectId is falsy, and avoid writing null into
updateDraft when recentProjects is empty (keep the existing
draft.selectedProjectId instead). In practice: after the existing
preSelectedProjectId check/return, add a guard that if preSelectedProjectId is
truthy skip the fallback, and when picking a fallback id use
recentProjects[0]?.id ?? draft.selectedProjectId (or simply skip updateDraft if
no recentProjects[0]) to prevent spinning updates from writing null.

---

Nitpick comments:
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`:
- Around line 90-219: Extract the NewWorkspaceModalContent component into its
own file: create a new NewWorkspaceModalContent.tsx that exports the
NewWorkspaceModalContent function (and its props type
NewWorkspaceModalContentProps if declared inline) and move all logic including
useNewWorkspaceModalDraft, useEffect, listQuery/handleListQueryChange, and JSX
rendering (Tabs, ProjectSelector, Command/CommandInput/CommandList,
PullRequestsGroup, BranchesGroup, IssuesGroup, PromptGroup) into it; then
replace the in-file definition with an import of NewWorkspaceModalContent in the
original file and ensure any referenced symbols (useNewWorkspaceModalDraft,
ProjectSelector, PullRequestsGroup, BranchesGroup, IssuesGroup, PromptGroup,
COMMAND_CLASS_NAME) are imported in the new file and exported types/props are
re-exported if the parent expects them.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a351f52d-c0f7-45ab-90b4-3699f0c88e80

📥 Commits

Reviewing files that changed from the base of the PR and between 3d770ee and 68457a5.

📒 Files selected for processing (7)
  • apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModalDraftContext.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/BranchesGroup/BranchesGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/PullRequestsGroup/PullRequestsGroup.tsx
  • apps/desktop/src/renderer/stores/new-workspace-modal.ts
💤 Files with no reviewable changes (1)
  • apps/desktop/src/renderer/stores/new-workspace-modal.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/desktop/src/renderer/components/NewWorkspaceModal/components/IssuesGroup/IssuesGroup.tsx

const navigate = useNavigate();
const { gateFeature } = usePaywall();
const createFromPr = useCreateFromPr();
const { closeAndResetDraft, runAsyncAction } = useNewWorkspaceModalDraft();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Keep the draft when sending users to Integrations.

This path is not a successful create/open action, so clearing here throws away the restored modal state the PR is trying to preserve. Use closeModal() instead and reserve closeAndResetDraft() for successful workspace open/create flows.

Proposed fix
-	const { closeAndResetDraft, runAsyncAction } = useNewWorkspaceModalDraft();
+	const { closeModal, closeAndResetDraft, runAsyncAction } =
+		useNewWorkspaceModalDraft();
…
 						gateFeature(GATED_FEATURES.INTEGRATIONS, () => {
-							closeAndResetDraft();
+							closeModal();
 							navigate({ to: "/settings/integrations" });
 						});

Also applies to: 107-109

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/components/PullRequestsGroup/PullRequestsGroup.tsx`
at line 36, The code currently calls closeAndResetDraft() from
useNewWorkspaceModalDraft when navigating users to Integrations, which clears
the draft and loses restored modal state; change those calls to closeModal()
instead so the modal is closed but the draft is preserved. Update the two places
that call closeAndResetDraft() (the one at PullRequestsGroup.tsx where
closeAndResetDraft is destructured and the call sites around the Integrations
navigation — also the similar calls at the other mentioned location around lines
107-109) to call closeModal() while leaving closeAndResetDraft() reserved for
successful create/open flows.

@Kitenite Kitenite merged commit 699f3e4 into main Mar 8, 2026
5 of 6 checks passed
@Kitenite Kitenite deleted the kitenite/did-we-remove-persistence-on-the-new-workspace-mod branch March 8, 2026 07:21
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 8, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch
  • ⚠️ Electric Fly.io app

Thank you for your contribution! 🎉

saddlepaddle added a commit that referenced this pull request Mar 8, 2026
The switch from CommandDialog to Dialog/DialogContent in #2225 lost the
bg-popover/text-popover-foreground colors that Command previously provided,
causing the modal background to use bg-background instead.
saddlepaddle added a commit that referenced this pull request Mar 8, 2026
The switch from CommandDialog to Dialog/DialogContent in #2225 lost the
bg-popover/text-popover-foreground colors that Command previously provided,
causing the modal background to use bg-background instead.
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