import { app, BrowserWindow, Tray, Menu, globalShortcut, nativeImage, } from "electron"; import { createRequire } from "node:module"; import { fileURLToPath } from "node:url"; import path from "node:path"; import registerIpcMainHandlers from "./ipcMainHandlers"; import PythonManager from "./core/PythonManager"; import { createDatabase } from "./core/db"; import { getMachineId, mid } from "./core/auth"; const require = createRequire(import.meta.url); const __dirname = path.dirname(fileURLToPath(import.meta.url)); process.env.APP_ROOT = path.join(__dirname, ".."); export const VITE_DEV_SERVER_URL = process.env["VITE_DEV_SERVER_URL"]; export const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron"); export const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist"); process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT, "public") : RENDERER_DIST; let win: BrowserWindow | null; let tray: Tray | null = null; let pythonManager: PythonManager | null; const theme: "dark" | "light" = "light"; const themeTitleBarStyles = { dark: { color: "rgb(32,32,32)", symbolColor: "#fff" }, light: {}, }; function createWindow() { win = new BrowserWindow({ width: 1280, height: 800, show: false, // 先隐藏。等待渲染完成,防止闪烁 icon: path.join(process.env.VITE_PUBLIC, "AI.png"), // frame: false, titleBarStyle: "hidden", // customButtonsOnHover || hidden || hiddenInset titleBarOverlay: { height: 36, ...themeTitleBarStyles[theme] }, // 渲染进程发消息动态改变这个 webPreferences: { preload: path.join(__dirname, "preload.mjs"), nodeIntegration: true, }, }); // Test active push message to Renderer-process. win.webContents.on("did-finish-load", () => { win?.webContents.send("main-process-message", { platform: process.platform === "darwin" ? "macos" : "windows", theme, }); }); if (VITE_DEV_SERVER_URL) { win.loadURL(VITE_DEV_SERVER_URL); } else { win.loadFile(path.join(RENDERER_DIST, "index.html")); } pythonManager = new PythonManager(win, "http://127.0.0.1:15001", 3000); registerIpcMainHandlers(win, pythonManager); } function createTray() { if (tray) tray.destroy(); const iconPath = path.join(process.env.VITE_PUBLIC, "AI.png"); // 使用 PNG 图标 const icon = nativeImage .createFromPath(iconPath) .resize({ width: 20, height: 20 }); tray = new Tray(icon); const contextMenu = Menu.buildFromTemplate([ { label: "Show App", click: function () { if (win) { win.show(); } }, }, { label: "Quit", click: function () { app.quit(); }, }, ]); tray.setToolTip("My Electron App"); tray.setContextMenu(contextMenu); tray.on("click", () => { if (win) { win.isVisible() ? win.hide() : win.show(); } }); } function registerGlobalShortcuts() { // 注册全局快捷键 'CommandOrControl+Shift+S' 来显示应用窗口 globalShortcut.register("Option+N", () => { if (win) { win.isVisible() ? win.hide() : win.show(); } }); } app.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); win = null; } }); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); app.on("before-quit", () => { if (pythonManager?.flaskProcess) pythonManager?.stopFlask(); }); app.whenReady().then(() => { getMachineId(); createWindow(); createTray(); registerGlobalShortcuts(); createDatabase({ name: "cvpilot.json" }); console.log(path.join(app.getPath("userData"))); // 设置 Dock 图标 if (process.platform === "darwin") { const dockIconPath = path.join(process.env.VITE_PUBLIC, "girl.png"); const dockIcon = nativeImage.createFromPath(dockIconPath); app.dock.setIcon(dockIcon); } }); // 注销全局快捷键,当应用退出时 app.on("will-quit", () => { globalShortcut.unregisterAll(); });