diff --git a/src/components/SetupBanner.tsx b/src/components/SetupBanner.tsx index 7185891..445cc2e 100644 --- a/src/components/SetupBanner.tsx +++ b/src/components/SetupBanner.tsx @@ -21,6 +21,12 @@ import { import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; import { NodeSystemInfo } from "@/ipc/ipc_types"; + +type NodeInstallStep = + | "install" + | "waiting-for-continue" + | "continue-processing"; + export function SetupBanner() { const navigate = useNavigate(); const { isAnyProviderSetup, loading } = useSettings(); @@ -28,7 +34,8 @@ export function SetupBanner() { null ); const [nodeCheckError, setNodeCheckError] = useState(false); - const [nodeInstallLoading, setNodeInstallLoading] = useState(false); + const [nodeInstallStep, setNodeInstallStep] = + useState("install"); const checkNode = useCallback(async () => { try { setNodeCheckError(false); @@ -52,14 +59,16 @@ export function SetupBanner() { }); }; - const handleNodeInstallClick = async () => { - setNodeInstallLoading(true); + const handleNodeInstallClick = useCallback(async () => { + setNodeInstallStep("waiting-for-continue"); IpcClient.getInstance().openExternalUrl(nodeSystemInfo!.nodeDownloadUrl); - }; + }, [nodeSystemInfo, setNodeInstallStep]); - const finishNodeInstallAndRestart = () => { - IpcClient.getInstance().reloadDyad(); - }; + const finishNodeInstall = useCallback(async () => { + setNodeInstallStep("continue-processing"); + await IpcClient.getInstance().reloadEnvPath(); + await checkNode(); + }, [checkNode, setNodeInstallStep]); const isNodeSetupComplete = Boolean( nodeSystemInfo?.nodeVersion && nodeSystemInfo?.pnpmVersion @@ -123,7 +132,7 @@ export function SetupBanner() {
{getStatusIcon(isNodeSetupComplete, nodeCheckError)} - 1. Install Node.js + 1. Install Node.js (App Runtime)
@@ -146,17 +155,37 @@ export function SetupBanner() { ) : (

Node.js is required to run apps locally.

-

- After you have installed node.js, click "Finish setup" to - restart Dyad. -

- {nodeInstallLoading ? ( - ) : ( - )}
diff --git a/src/ipc/handlers/node_handlers.ts b/src/ipc/handlers/node_handlers.ts index 0732e00..d72d24c 100644 --- a/src/ipc/handlers/node_handlers.ts +++ b/src/ipc/handlers/node_handlers.ts @@ -1,7 +1,8 @@ import { ipcMain, app } from "electron"; -import { spawn } from "child_process"; +import { exec, execSync, spawn } from "child_process"; import { platform, arch } from "os"; import { NodeSystemInfo } from "../ipc_types"; +import fixPath from "fix-path"; function checkCommandExists(command: string): Promise { return new Promise((resolve) => { @@ -68,8 +69,16 @@ export function registerNodeHandlers() { return { nodeVersion, pnpmVersion, nodeDownloadUrl }; }); - ipcMain.handle("reload-dyad", async (): Promise => { - app.relaunch(); - app.exit(0); + ipcMain.handle("reload-env-path", async (): Promise => { + console.debug("Reloading env path, previously:", process.env.PATH); + if (platform() === "win32") { + const newPath = execSync("cmd /c echo %PATH%", { + encoding: "utf8", + }).trim(); + process.env.PATH = newPath; + } else { + fixPath(); + } + console.debug("Reloaded env path, now:", process.env.PATH); }); } diff --git a/src/ipc/ipc_client.ts b/src/ipc/ipc_client.ts index b163626..f5ffb13 100644 --- a/src/ipc/ipc_client.ts +++ b/src/ipc/ipc_client.ts @@ -131,8 +131,8 @@ export class IpcClient { return IpcClient.instance; } - public async reloadDyad(): Promise { - await this.ipcRenderer.invoke("reload-dyad"); + public async reloadEnvPath(): Promise { + await this.ipcRenderer.invoke("reload-env-path"); } // Create a new app with an initial chat diff --git a/src/preload.ts b/src/preload.ts index 249a37c..3fca189 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -37,7 +37,7 @@ const validInvokeChannels = [ "github:create-repo", "github:push", "get-app-version", - "reload-dyad", + "reload-env-path", ] as const; // Add valid receive channels