@@ -4,7 +4,6 @@ import { useApp } from "./contexts/AppContext";
44import type { WorkspaceSelection } from "./components/ProjectSidebar" ;
55import type { FrontendWorkspaceMetadata } from "./types/workspace" ;
66import { LeftSidebar } from "./components/LeftSidebar" ;
7- import NewWorkspaceModal from "./components/NewWorkspaceModal" ;
87import { ProjectCreateModal } from "./components/ProjectCreateModal" ;
98import { AIView } from "./components/AIView" ;
109import { ErrorBoundary } from "./components/ErrorBoundary" ;
@@ -25,13 +24,20 @@ import { CommandPalette } from "./components/CommandPalette";
2524import { buildCoreSources , type BuildSourcesParams } from "./utils/commands/sources" ;
2625
2726import type { ThinkingLevel } from "./types/thinking" ;
28- import type { RuntimeConfig } from "./types/runtime" ;
2927import { CUSTOM_EVENTS } from "./constants/events" ;
3028import { isWorkspaceForkSwitchEvent } from "./utils/workspaceFork" ;
31- import { getThinkingLevelKey , getRuntimeKey } from "./constants/storage" ;
29+ import {
30+ getThinkingLevelKey ,
31+ getRuntimeKey ,
32+ getInputKey ,
33+ getPendingScopeId ,
34+ getModelKey ,
35+ getProjectScopeId ,
36+ getTrunkBranchKey ,
37+ } from "./constants/storage" ;
3238import type { BranchListResult } from "./types/ipc" ;
3339import { useTelemetry } from "./hooks/useTelemetry" ;
34- import { parseRuntimeString } from "./utils/chatCommands " ;
40+ import { useStartWorkspaceCreation } from "./hooks/useStartWorkspaceCreation " ;
3541
3642const THINKING_LEVELS : ThinkingLevel [ ] = [ "off" , "low" , "medium" , "high" ] ;
3743
@@ -43,29 +49,25 @@ function AppInner() {
4349 removeProject,
4450 workspaceMetadata,
4551 setWorkspaceMetadata,
46- createWorkspace,
4752 removeWorkspace,
4853 renameWorkspace,
4954 selectedWorkspace,
5055 setSelectedWorkspace,
5156 } = useApp ( ) ;
5257 const [ projectCreateModalOpen , setProjectCreateModalOpen ] = useState ( false ) ;
53- const [ workspaceModalOpen , setWorkspaceModalOpen ] = useState ( false ) ;
54- const [ workspaceModalProject , setWorkspaceModalProject ] = useState < string | null > ( null ) ;
55- const [ workspaceModalProjectName , setWorkspaceModalProjectName ] = useState < string > ( "" ) ;
56- const [ workspaceModalBranches , setWorkspaceModalBranches ] = useState < string [ ] > ( [ ] ) ;
57- const [ workspaceModalDefaultTrunk , setWorkspaceModalDefaultTrunk ] = useState < string | undefined > (
58- undefined
59- ) ;
60- const [ workspaceModalLoadError , setWorkspaceModalLoadError ] = useState < string | null > ( null ) ;
61- const workspaceModalProjectRef = useRef < string | null > ( null ) ;
6258
6359 // Track when we're in "new workspace creation" mode (show FirstMessageInput)
6460 const [ pendingNewWorkspaceProject , setPendingNewWorkspaceProject ] = useState < string | null > ( null ) ;
6561
6662 // Auto-collapse sidebar on mobile by default
6763 const isMobile = typeof window !== "undefined" && window . innerWidth <= 768 ;
6864 const [ sidebarCollapsed , setSidebarCollapsed ] = usePersistedState ( "sidebarCollapsed" , isMobile ) ;
65+ const startWorkspaceCreation = useStartWorkspaceCreation ( {
66+ projects,
67+ setPendingNewWorkspaceProject,
68+ setSelectedWorkspace,
69+ } ) ;
70+
6971
7072 const handleToggleSidebar = useCallback ( ( ) => {
7173 setSidebarCollapsed ( ( prev ) => ! prev ) ;
@@ -133,7 +135,6 @@ function AppInner() {
133135 void window . api . window . setTitle ( "mux" ) ;
134136 }
135137 } , [ selectedWorkspace , workspaceMetadata ] ) ;
136-
137138 // Validate selected workspace exists and has all required fields
138139 useEffect ( ( ) => {
139140 if ( selectedWorkspace ) {
@@ -177,12 +178,9 @@ function AppInner() {
177178
178179 const handleAddWorkspace = useCallback (
179180 ( projectPath : string ) => {
180- // Show FirstMessageInput for this project
181- setPendingNewWorkspaceProject ( projectPath ) ;
182- // Clear any selected workspace so FirstMessageInput is shown
183- setSelectedWorkspace ( null ) ;
181+ startWorkspaceCreation ( projectPath ) ;
184182 } ,
185- [ setSelectedWorkspace ]
183+ [ startWorkspaceCreation ]
186184 ) ;
187185
188186 // Memoize callbacks to prevent LeftSidebar/ProjectSidebar re-renders
@@ -204,47 +202,6 @@ function AppInner() {
204202 [ handleRemoveProject ]
205203 ) ;
206204
207- const handleCreateWorkspace = async (
208- branchName : string ,
209- trunkBranch : string ,
210- runtime ?: string
211- ) => {
212- if ( ! workspaceModalProject ) return ;
213-
214- console . assert (
215- typeof trunkBranch === "string" && trunkBranch . trim ( ) . length > 0 ,
216- "Expected trunk branch to be provided by the workspace modal"
217- ) ;
218-
219- // Parse runtime config if provided
220- let runtimeConfig : RuntimeConfig | undefined ;
221- if ( runtime ) {
222- try {
223- runtimeConfig = parseRuntimeString ( runtime , branchName ) ;
224- } catch ( err ) {
225- console . error ( "Failed to parse runtime config:" , err ) ;
226- throw err ; // Let modal handle the error
227- }
228- }
229-
230- const newWorkspace = await createWorkspace (
231- workspaceModalProject ,
232- branchName ,
233- trunkBranch ,
234- runtimeConfig
235- ) ;
236- if ( newWorkspace ) {
237- // Track workspace creation
238- telemetry . workspaceCreated ( newWorkspace . workspaceId ) ;
239- setSelectedWorkspace ( newWorkspace ) ;
240-
241- // Save runtime preference for this project if provided
242- if ( runtime ) {
243- const runtimeKey = getRuntimeKey ( workspaceModalProject ) ;
244- localStorage . setItem ( runtimeKey , runtime ) ;
245- }
246- }
247- } ;
248205
249206 const handleGetSecrets = useCallback ( async ( projectPath : string ) => {
250207 return await window . api . projects . secrets . get ( projectPath ) ;
@@ -398,9 +355,9 @@ function AppInner() {
398355
399356 const openNewWorkspaceFromPalette = useCallback (
400357 ( projectPath : string ) => {
401- void handleAddWorkspace ( projectPath ) ;
358+ startWorkspaceCreation ( projectPath ) ;
402359 } ,
403- [ handleAddWorkspace ]
360+ [ startWorkspaceCreation ]
404361 ) ;
405362
406363 const getBranchesForProject = useCallback (
@@ -469,7 +426,7 @@ function AppInner() {
469426 selectedWorkspace,
470427 getThinkingLevel : getThinkingLevelForWorkspace ,
471428 onSetThinkingLevel : setThinkingLevelFromPalette ,
472- onOpenNewWorkspaceModal : openNewWorkspaceFromPalette ,
429+ onStartWorkspaceCreation : openNewWorkspaceFromPalette ,
473430 getBranchesForProject,
474431 onSelectWorkspace : selectWorkspaceFromPalette ,
475432 onRemoveWorkspace : removeWorkspaceFromPalette ,
@@ -686,26 +643,6 @@ function AppInner() {
686643 workspaceId : selectedWorkspace ?. workspaceId ,
687644 } ) }
688645 />
689- { workspaceModalOpen && workspaceModalProject && (
690- < NewWorkspaceModal
691- isOpen = { workspaceModalOpen }
692- projectName = { workspaceModalProjectName }
693- projectPath = { workspaceModalProject }
694- branches = { workspaceModalBranches }
695- defaultTrunkBranch = { workspaceModalDefaultTrunk }
696- loadErrorMessage = { workspaceModalLoadError }
697- onClose = { ( ) => {
698- workspaceModalProjectRef . current = null ;
699- setWorkspaceModalOpen ( false ) ;
700- setWorkspaceModalProject ( null ) ;
701- setWorkspaceModalProjectName ( "" ) ;
702- setWorkspaceModalBranches ( [ ] ) ;
703- setWorkspaceModalDefaultTrunk ( undefined ) ;
704- setWorkspaceModalLoadError ( null ) ;
705- } }
706- onAdd = { handleCreateWorkspace }
707- />
708- ) }
709646 < ProjectCreateModal
710647 isOpen = { projectCreateModalOpen }
711648 onClose = { ( ) => setProjectCreateModalOpen ( false ) }
0 commit comments