Skip to content

Commit 638aeaf

Browse files
committed
refactor: route /new to chat creation
1 parent 9572334 commit 638aeaf

File tree

9 files changed

+189
-555
lines changed

9 files changed

+189
-555
lines changed

src/App.tsx

Lines changed: 21 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { useApp } from "./contexts/AppContext";
44
import type { WorkspaceSelection } from "./components/ProjectSidebar";
55
import type { FrontendWorkspaceMetadata } from "./types/workspace";
66
import { LeftSidebar } from "./components/LeftSidebar";
7-
import NewWorkspaceModal from "./components/NewWorkspaceModal";
87
import { ProjectCreateModal } from "./components/ProjectCreateModal";
98
import { AIView } from "./components/AIView";
109
import { ErrorBoundary } from "./components/ErrorBoundary";
@@ -25,13 +24,20 @@ import { CommandPalette } from "./components/CommandPalette";
2524
import { buildCoreSources, type BuildSourcesParams } from "./utils/commands/sources";
2625

2726
import type { ThinkingLevel } from "./types/thinking";
28-
import type { RuntimeConfig } from "./types/runtime";
2927
import { CUSTOM_EVENTS } from "./constants/events";
3028
import { 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";
3238
import type { BranchListResult } from "./types/ipc";
3339
import { useTelemetry } from "./hooks/useTelemetry";
34-
import { parseRuntimeString } from "./utils/chatCommands";
40+
import { useStartWorkspaceCreation } from "./hooks/useStartWorkspaceCreation";
3541

3642
const 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)}

src/components/NewWorkspaceModal.stories.tsx

Lines changed: 0 additions & 105 deletions
This file was deleted.

0 commit comments

Comments
 (0)