From 71d8f741436b69c1adc21245af6a8fd2969e467f Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Tue, 17 Feb 2026 21:50:40 -0800 Subject: [PATCH] Refactor project script persistence flow in ChatView Co-authored-by: codex --- apps/web/src/components/ChatView.tsx | 184 ++++++++++++--------------- 1 file changed, 80 insertions(+), 104 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index b9b06ac1a63fbd348527c8ca395fbf09836bc8c7..b514da8d418d4ebf6b8e9c4194d44f16b9776c90 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -739,6 +739,72 @@ export default function ChatView() { }, [activeProject, activeThread, activeThreadId, api, dispatch, gitCwd], ); + const persistProjectScripts = useCallback( + async (input: { + projectId: string; + projectCwd: string; + previousScripts: ProjectScript[]; + nextScripts: ProjectScript[]; + keybinding?: string | null; + keybindingCommand: string; + }) => { + dispatch({ + type: "SET_PROJECT_SCRIPTS", + projectId: input.projectId, + scripts: input.nextScripts, + }); + + if (!isElectron || !api) return; + + let scriptsPersisted = false; + try { + const updated = await api.projects.updateScripts({ + id: input.projectId, + scripts: input.nextScripts, + }); + scriptsPersisted = true; + + if (input.keybinding) { + const keybindingUpdate = await api.server.upsertKeybinding({ + key: input.keybinding, + command: input.keybindingCommand, + }); + queryClient.setQueryData( + serverQueryKeys.config(), + (current: { cwd: string; keybindings: ResolvedKeybindingsConfig } | undefined) => + current + ? { ...current, keybindings: keybindingUpdate.keybindings } + : { + cwd: input.projectCwd, + keybindings: keybindingUpdate.keybindings, + }, + ); + } + + dispatch({ + type: "SET_PROJECT_SCRIPTS", + projectId: updated.project.id, + scripts: updated.project.scripts, + }); + } catch (error) { + if (scriptsPersisted) { + await api.projects + .updateScripts({ + id: input.projectId, + scripts: input.previousScripts, + }) + .catch(() => undefined); + } + dispatch({ + type: "SET_PROJECT_SCRIPTS", + projectId: input.projectId, + scripts: input.previousScripts, + }); + throw error; + } + }, + [api, dispatch, queryClient], + ); const saveProjectScript = useCallback( async (input: NewProjectScriptInput) => { if (!activeProject) return; @@ -762,61 +828,16 @@ export default function ChatView() { ] : [...activeProject.scripts, nextScript]; - dispatch({ - type: "SET_PROJECT_SCRIPTS", + await persistProjectScripts({ projectId: activeProject.id, - scripts: nextScripts, + projectCwd: activeProject.cwd, + previousScripts: activeProject.scripts, + nextScripts, + keybinding: input.keybinding, + keybindingCommand: commandForProjectScript(nextId), }); - - if (!isElectron || !api) return; - let scriptsPersisted = false; - try { - const updated = await api.projects.updateScripts({ - id: activeProject.id, - scripts: nextScripts, - }); - scriptsPersisted = true; - - if (input.keybinding) { - const keybindingUpdate = await api.server.upsertKeybinding({ - key: input.keybinding, - command: commandForProjectScript(nextId), - }); - queryClient.setQueryData( - serverQueryKeys.config(), - (current: { cwd: string; keybindings: ResolvedKeybindingsConfig } | undefined) => - current - ? { ...current, keybindings: keybindingUpdate.keybindings } - : { - cwd: activeProject.cwd, - keybindings: keybindingUpdate.keybindings, - }, - ); - } - - dispatch({ - type: "SET_PROJECT_SCRIPTS", - projectId: updated.project.id, - scripts: updated.project.scripts, - }); - } catch (error) { - if (scriptsPersisted) { - await api.projects - .updateScripts({ - id: activeProject.id, - scripts: activeProject.scripts, - }) - .catch(() => undefined); - } - dispatch({ - type: "SET_PROJECT_SCRIPTS", - projectId: activeProject.id, - scripts: activeProject.scripts, - }); - throw error; - } }, - [activeProject, api, dispatch, queryClient], + [activeProject, persistProjectScripts], ); const updateProjectScript = useCallback( async (scriptId: string, input: NewProjectScriptInput) => { @@ -841,61 +862,16 @@ export default function ChatView() { : script, ); - dispatch({ - type: "SET_PROJECT_SCRIPTS", + await persistProjectScripts({ projectId: activeProject.id, - scripts: nextScripts, + projectCwd: activeProject.cwd, + previousScripts: activeProject.scripts, + nextScripts, + keybinding: input.keybinding, + keybindingCommand: commandForProjectScript(scriptId), }); - - if (!isElectron || !api) return; - let scriptsPersisted = false; - try { - const updated = await api.projects.updateScripts({ - id: activeProject.id, - scripts: nextScripts, - }); - scriptsPersisted = true; - - if (input.keybinding) { - const keybindingUpdate = await api.server.upsertKeybinding({ - key: input.keybinding, - command: commandForProjectScript(scriptId), - }); - queryClient.setQueryData( - serverQueryKeys.config(), - (current: { cwd: string; keybindings: ResolvedKeybindingsConfig } | undefined) => - current - ? { ...current, keybindings: keybindingUpdate.keybindings } - : { - cwd: activeProject.cwd, - keybindings: keybindingUpdate.keybindings, - }, - ); - } - - dispatch({ - type: "SET_PROJECT_SCRIPTS", - projectId: updated.project.id, - scripts: updated.project.scripts, - }); - } catch (error) { - if (scriptsPersisted) { - await api.projects - .updateScripts({ - id: activeProject.id, - scripts: activeProject.scripts, - }) - .catch(() => undefined); - } - dispatch({ - type: "SET_PROJECT_SCRIPTS", - projectId: activeProject.id, - scripts: activeProject.scripts, - }); - throw error; - } }, - [activeProject, api, dispatch, queryClient], + [activeProject, persistProjectScripts], ); const handleRuntimeModeChange = async (mode: "approval-required" | "full-access") => { -- 2.54.0