Reload env path instead of restarting dyad app after node.js install
This commit is contained in:
@@ -21,6 +21,12 @@ import {
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { NodeSystemInfo } from "@/ipc/ipc_types";
|
import { NodeSystemInfo } from "@/ipc/ipc_types";
|
||||||
|
|
||||||
|
type NodeInstallStep =
|
||||||
|
| "install"
|
||||||
|
| "waiting-for-continue"
|
||||||
|
| "continue-processing";
|
||||||
|
|
||||||
export function SetupBanner() {
|
export function SetupBanner() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isAnyProviderSetup, loading } = useSettings();
|
const { isAnyProviderSetup, loading } = useSettings();
|
||||||
@@ -28,7 +34,8 @@ export function SetupBanner() {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [nodeCheckError, setNodeCheckError] = useState<boolean>(false);
|
const [nodeCheckError, setNodeCheckError] = useState<boolean>(false);
|
||||||
const [nodeInstallLoading, setNodeInstallLoading] = useState<boolean>(false);
|
const [nodeInstallStep, setNodeInstallStep] =
|
||||||
|
useState<NodeInstallStep>("install");
|
||||||
const checkNode = useCallback(async () => {
|
const checkNode = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setNodeCheckError(false);
|
setNodeCheckError(false);
|
||||||
@@ -52,14 +59,16 @@ export function SetupBanner() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleNodeInstallClick = async () => {
|
const handleNodeInstallClick = useCallback(async () => {
|
||||||
setNodeInstallLoading(true);
|
setNodeInstallStep("waiting-for-continue");
|
||||||
IpcClient.getInstance().openExternalUrl(nodeSystemInfo!.nodeDownloadUrl);
|
IpcClient.getInstance().openExternalUrl(nodeSystemInfo!.nodeDownloadUrl);
|
||||||
};
|
}, [nodeSystemInfo, setNodeInstallStep]);
|
||||||
|
|
||||||
const finishNodeInstallAndRestart = () => {
|
const finishNodeInstall = useCallback(async () => {
|
||||||
IpcClient.getInstance().reloadDyad();
|
setNodeInstallStep("continue-processing");
|
||||||
};
|
await IpcClient.getInstance().reloadEnvPath();
|
||||||
|
await checkNode();
|
||||||
|
}, [checkNode, setNodeInstallStep]);
|
||||||
|
|
||||||
const isNodeSetupComplete = Boolean(
|
const isNodeSetupComplete = Boolean(
|
||||||
nodeSystemInfo?.nodeVersion && nodeSystemInfo?.pnpmVersion
|
nodeSystemInfo?.nodeVersion && nodeSystemInfo?.pnpmVersion
|
||||||
@@ -123,7 +132,7 @@ export function SetupBanner() {
|
|||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{getStatusIcon(isNodeSetupComplete, nodeCheckError)}
|
{getStatusIcon(isNodeSetupComplete, nodeCheckError)}
|
||||||
<span className="font-medium text-sm">
|
<span className="font-medium text-sm">
|
||||||
1. Install Node.js
|
1. Install Node.js (App Runtime)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -146,17 +155,37 @@ export function SetupBanner() {
|
|||||||
) : (
|
) : (
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
<p>Node.js is required to run apps locally.</p>
|
<p>Node.js is required to run apps locally.</p>
|
||||||
<p className="mb-3">
|
{nodeInstallStep === "waiting-for-continue" && (
|
||||||
After you have installed node.js, click "Finish setup" to
|
<p className="mt-1">
|
||||||
restart Dyad.
|
After you have installed Node.js, click "Continue". If the
|
||||||
</p>
|
installer didn't work, try{" "}
|
||||||
{nodeInstallLoading ? (
|
<a
|
||||||
<Button onClick={finishNodeInstallAndRestart}>
|
className="text-blue-500 dark:text-blue-400 hover:underline"
|
||||||
Finish setup and restart Dyad
|
onClick={() => {
|
||||||
|
IpcClient.getInstance().openExternalUrl(
|
||||||
|
"https://nodejs.org/en/download"
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
more download options
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
{nodeInstallStep === "install" ? (
|
||||||
|
<Button className="mt-3" onClick={handleNodeInstallClick}>
|
||||||
|
Install Node.js Runtime
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button onClick={handleNodeInstallClick}>
|
<Button className="mt-3" onClick={finishNodeInstall}>
|
||||||
Install Node.js Runtime
|
{nodeInstallStep === "continue-processing" ? (
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Loader2 className="h-4 w-4 animate-spin" />
|
||||||
|
Checking Node.js setup...
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
"Continue | I installed Node.js"
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { ipcMain, app } from "electron";
|
import { ipcMain, app } from "electron";
|
||||||
import { spawn } from "child_process";
|
import { exec, execSync, spawn } from "child_process";
|
||||||
import { platform, arch } from "os";
|
import { platform, arch } from "os";
|
||||||
import { NodeSystemInfo } from "../ipc_types";
|
import { NodeSystemInfo } from "../ipc_types";
|
||||||
|
import fixPath from "fix-path";
|
||||||
|
|
||||||
function checkCommandExists(command: string): Promise<string | null> {
|
function checkCommandExists(command: string): Promise<string | null> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@@ -68,8 +69,16 @@ export function registerNodeHandlers() {
|
|||||||
return { nodeVersion, pnpmVersion, nodeDownloadUrl };
|
return { nodeVersion, pnpmVersion, nodeDownloadUrl };
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle("reload-dyad", async (): Promise<void> => {
|
ipcMain.handle("reload-env-path", async (): Promise<void> => {
|
||||||
app.relaunch();
|
console.debug("Reloading env path, previously:", process.env.PATH);
|
||||||
app.exit(0);
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ export class IpcClient {
|
|||||||
return IpcClient.instance;
|
return IpcClient.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async reloadDyad(): Promise<void> {
|
public async reloadEnvPath(): Promise<void> {
|
||||||
await this.ipcRenderer.invoke("reload-dyad");
|
await this.ipcRenderer.invoke("reload-env-path");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new app with an initial chat
|
// Create a new app with an initial chat
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ const validInvokeChannels = [
|
|||||||
"github:create-repo",
|
"github:create-repo",
|
||||||
"github:push",
|
"github:push",
|
||||||
"get-app-version",
|
"get-app-version",
|
||||||
"reload-dyad",
|
"reload-env-path",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// Add valid receive channels
|
// Add valid receive channels
|
||||||
|
|||||||
Reference in New Issue
Block a user