feat(desktop): add import repo option to open workspace dropdown#947
Conversation
Add "Import repo" action to the project selector in the Open Workspace modal, allowing users to import a local repository without leaving the workflow. Uses DropdownMenu pattern (instead of Select) to properly separate selection items from action items.
📝 WalkthroughWalkthroughThe NewWorkspaceModal component's project selector has been refactored from a Select component to a DropdownMenu. A new "Import repo" option with folder-open icon has been added, wired to a handleImportRepo function that manages external project imports using the useOpenNew hook and handles git initialization checks with user feedback via toast messages. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`:
- Around line 168-187: The component's handleImportRepo
setsSelectedProjectId(result.project.id) but recentProjects (used by
selectedProject derivation) isn't updated yet, causing selectedProject to be
undefined; fix by either invalidating/refetching the getRecents query after a
successful import (add an onSuccess in the openNew mutation or call
trpc.getRecents.invalidate/refetch from the workspace/openNew.ts procedure) or,
simpler in the component, render a fallback using result.project.name when
selectedProject is undefined but selectedProjectId matches result.project.id;
update handleImportRepo and/or the openNew mutation onSuccess to ensure
getRecents is refreshed or show result.project.name as a temporary display until
recents refetches.
🧹 Nitpick comments (2)
apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx (2)
268-271: Consider disabling "Import repo" while the import is in progress.If the user clicks "Import repo" while
openNewis already pending, it could trigger multiple file pickers or race conditions. Consider adding a disabled state:♻️ Proposed fix
- <DropdownMenuItem onClick={handleImportRepo}> + <DropdownMenuItem + onClick={handleImportRepo} + disabled={openNew.isPending} + > <LuFolderOpen className="size-4" /> Import repo </DropdownMenuItem>
254-267: Minor: Separator may appear without items above it.When
recentProjectsis empty, theDropdownMenuSeparatorwill render with no items above it, which may look visually odd. Consider conditionally rendering the separator only when there are projects.♻️ Proposed fix
{recentProjects .filter((project) => project.id) .map((project) => ( <DropdownMenuItem key={project.id} onClick={() => setSelectedProjectId(project.id)} > {project.name} {project.id === selectedProjectId && ( <HiCheck className="ml-auto size-4" /> )} </DropdownMenuItem> ))} - <DropdownMenuSeparator /> + {recentProjects.length > 0 && <DropdownMenuSeparator />} <DropdownMenuItem onClick={handleImportRepo}>
| const handleImportRepo = async () => { | ||
| try { | ||
| const result = await openNew.mutateAsync(undefined); | ||
| if (result.canceled) return; | ||
| if ("error" in result) { | ||
| toast.error("Failed to open project", { description: result.error }); | ||
| return; | ||
| } | ||
| if ("needsGitInit" in result) { | ||
| toast.error("Selected folder is not a git repository"); | ||
| return; | ||
| } | ||
| setSelectedProjectId(result.project.id); | ||
| } catch (error) { | ||
| toast.error("Failed to open project", { | ||
| description: | ||
| error instanceof Error ? error.message : "An unknown error occurred", | ||
| }); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Race condition exists: imported project won't appear in dropdown until getRecents query refetches.
After setSelectedProjectId(result.project.id), the selectedProject derivation (which looks up selectedProjectId in recentProjects) will return undefined until the getRecents query refetches. The mutation handler in apps/desktop/src/main/ipc/trpc/procedures/workspace/openNew.ts does not invalidate the getRecents query, and the component has no onSuccess handler to trigger a refetch.
This causes the button to display "Select project" immediately after import, even though selectedProjectId is set.
Recommend either:
- Invalidating the
getRecentsquery in the mutation'sonSuccesshandler, or - Displaying
result.project.nameas a fallback whenselectedProjectis undefined butselectedProjectIdis set.
🤖 Prompt for AI Agents
In `@apps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsx`
around lines 168 - 187, The component's handleImportRepo
setsSelectedProjectId(result.project.id) but recentProjects (used by
selectedProject derivation) isn't updated yet, causing selectedProject to be
undefined; fix by either invalidating/refetching the getRecents query after a
successful import (add an onSuccess in the openNew mutation or call
trpc.getRecents.invalidate/refetch from the workspace/openNew.ts procedure) or,
simpler in the component, render a fallback using result.project.name when
selectedProject is undefined but selectedProjectId matches result.project.id;
update handleImportRepo and/or the openNew mutation onSuccess to ensure
getRecents is refreshed or show result.project.name as a temporary display until
recents refetches.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
Summary
Test plan
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.