Update flow.toml to start web and desktop dev servers with port management and cleanup logic; enhance desktop preload and main process to resolve preload path, set web URLs, and expose shell functions; improve README with load fallback info and environment variables; add external logs configuration to worker package.

This commit is contained in:
Nikita
2025-12-28 12:15:13 -08:00
parent c073fe6ee0
commit 3f2d571592
9 changed files with 240 additions and 31 deletions

View File

@@ -4,6 +4,8 @@ import { fileURLToPath } from "node:url";
import { readdir, stat } from "node:fs/promises";
import { app, BrowserWindow, dialog, ipcMain, shell } from "electron";
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = "true";
const __dirname = dirname(fileURLToPath(import.meta.url));
interface GitRepo {
@@ -50,13 +52,24 @@ async function findGitRepos(dir: string, maxDepth = 4): Promise<GitRepo[]> {
return repos;
}
function resolvePreload() {
const candidates = [
join(__dirname, "../preload/index.js"),
join(__dirname, "../preload/index.cjs"),
join(__dirname, "../preload/index.mjs"),
];
return candidates.find((path) => existsSync(path));
}
function createWindow() {
const preloadJs = join(__dirname, "../preload/index.js");
const preloadCjs = join(__dirname, "../preload/index.cjs");
const preloadMjs = join(__dirname, "../preload/index.mjs");
const preloadPath = [preloadJs, preloadCjs, preloadMjs].find((p) =>
existsSync(p),
);
const preloadPath = resolvePreload();
const webDevUrl =
process.env.WEB_DEV_URL ??
process.env.VITE_WEB_DEV_URL ??
"http://localhost:5625";
const webProdUrl = process.env.WEB_URL ?? process.env.VITE_WEB_URL;
const targetUrl = webProdUrl ?? webDevUrl;
const mainWindow = new BrowserWindow({
width: 1000,
@@ -79,16 +92,22 @@ function createWindow() {
return { action: "deny" };
});
if (process.env.ELECTRON_RENDERER_URL) {
mainWindow.loadURL(process.env.ELECTRON_RENDERER_URL);
mainWindow.webContents.openDevTools();
} else {
mainWindow.loadFile(join(__dirname, "../renderer/index.html"));
mainWindow
.loadURL(targetUrl)
.catch(() => mainWindow.loadFile(join(__dirname, "../renderer/index.html")));
if (!webProdUrl) {
mainWindow.webContents.openDevTools({ mode: "bottom" });
}
return mainWindow;
}
ipcMain.handle("shell:open-external", async (_event, url: string) => {
if (!url) return;
await shell.openExternal(url);
});
ipcMain.handle("dialog:pick-folder", async (): Promise<string | null> => {
const result = await dialog.showOpenDialog({
title: "Select code folder",
@@ -102,6 +121,8 @@ ipcMain.handle("dialog:pick-folder", async (): Promise<string | null> => {
return result.filePaths[0];
});
ipcMain.handle("app:get-version", () => app.getVersion());
ipcMain.handle("repos:scan", async (_event, folders: string[]): Promise<GitRepo[]> => {
const allRepos: GitRepo[] = [];
@@ -121,15 +142,23 @@ ipcMain.handle("repos:scan", async (_event, folders: string[]): Promise<GitRepo[
});
ipcMain.handle("shell:show-in-folder", async (_event, path: string) => {
if (!path) return;
shell.showItemInFolder(path);
});
ipcMain.handle("shell:show-path", async (_event, path: string) => {
if (!path) return;
shell.showItemInFolder(path);
});
ipcMain.handle("shell:open-in-editor", async (_event, path: string) => {
if (!path) return;
const { exec } = await import("node:child_process");
exec(`code "${path}"`);
});
ipcMain.handle("shell:open-in-terminal", async (_event, path: string) => {
if (!path) return;
const { exec } = await import("node:child_process");
if (process.platform === "darwin") {
exec(`open -a Terminal "${path}"`);

View File

@@ -6,10 +6,24 @@ export interface GitRepo {
lastModified: number;
}
export interface DesktopAPI {
openExternal: (url: string) => Promise<void>;
showPath: (path: string) => Promise<void>;
showInFolder: (path: string) => Promise<void>;
pickFolder: () => Promise<string | null>;
getVersion: () => Promise<string>;
scanRepos: (folders: string[]) => Promise<GitRepo[]>;
openInEditor: (path: string) => Promise<void>;
openInTerminal: (path: string) => Promise<void>;
}
contextBridge.exposeInMainWorld("electronAPI", {
pickFolder: () => ipcRenderer.invoke("dialog:pick-folder") as Promise<string | null>,
scanRepos: (folders: string[]) => ipcRenderer.invoke("repos:scan", folders) as Promise<GitRepo[]>,
openExternal: (url: string) => ipcRenderer.invoke("shell:open-external", url),
showPath: (path: string) => ipcRenderer.invoke("shell:show-path", path),
showInFolder: (path: string) => ipcRenderer.invoke("shell:show-in-folder", path),
pickFolder: () => ipcRenderer.invoke("dialog:pick-folder") as Promise<string | null>,
getVersion: () => ipcRenderer.invoke("app:get-version") as Promise<string>,
scanRepos: (folders: string[]) => ipcRenderer.invoke("repos:scan", folders) as Promise<GitRepo[]>,
openInEditor: (path: string) => ipcRenderer.invoke("shell:open-in-editor", path),
openInTerminal: (path: string) => ipcRenderer.invoke("shell:open-in-terminal", path),
});
} satisfies DesktopAPI);

View File

@@ -1,20 +1,8 @@
interface GitRepo {
name: string;
path: string;
lastModified: number;
}
interface ElectronAPI {
pickFolder: () => Promise<string | null>;
scanRepos: (folders: string[]) => Promise<GitRepo[]>;
showInFolder: (path: string) => Promise<void>;
openInEditor: (path: string) => Promise<void>;
openInTerminal: (path: string) => Promise<void>;
}
import type { DesktopAPI } from "../preload";
declare global {
interface Window {
electronAPI: ElectronAPI;
electronAPI: DesktopAPI;
}
}