UNPKG

backsplash-app

Version:
231 lines (201 loc) 6.75 kB
import { app, BrowserWindow, nativeImage, Tray } from "electron"; import path from "path"; import { registerMenuIpc } from "src/ipc/menuIPC"; import { registerServerIpc } from "src/ipc/serverIPC"; import { registerStoreIpc } from "src/ipc/storeIPC"; import { registerWallpaperIpc } from "src/ipc/wallpaperIPC"; import { registerLicenseIpc } from "src/ipc/licenseIPC"; import { registerWindowStateChangedEvents } from "src/windowState"; import { WallpaperService } from "./ipc/services/wallpaperService"; import { storeServiceInstance } from "./main"; import { registerAutoLaunchHandlers, cleanupAutoLaunchHandlers } from "./ipc/handlers/autoLaunchHandlers"; let appWindow: BrowserWindow; let appTray: Tray | null = null; // Manage tray at module level /** * Clean up the tray icon */ export const cleanupTray = () => { if (appTray && !appTray.isDestroyed()) { try { console.log("[AppWindow] Cleaning up tray icon"); appTray.destroy(); appTray = null; } catch (error) { console.error("[AppWindow] Error cleaning up tray:", error); } } }; /** * Configure auto-launch settings for the application */ function configureAutoLaunch() { const launchAtLogin = storeServiceInstance.get("launchAtLogin") as boolean | undefined; if (launchAtLogin !== undefined) { app.setLoginItemSettings({ openAtLogin: launchAtLogin, openAsHidden: true, // Start minimized }); } } /** * Create Application Window * @returns { BrowserWindow } Application Window Instance */ export function createAppWindow(wallpaperService: WallpaperService): BrowserWindow { const width = 375; const height = 415; // Configure auto-launch settings configureAutoLaunch(); const windowOptions: Electron.BrowserWindowConstructorOptions = { show: false, frame: false, width, height, resizable: false, fullscreenable: false, transparent: true, skipTaskbar: true, backgroundColor: "#1a1a1a", ...(process.platform === "darwin" && { type: "panel" }), webPreferences: { nodeIntegration: false, contextIsolation: true, nodeIntegrationInWorker: false, nodeIntegrationInSubFrames: false, preload: path.join(__dirname, "preload.js"), }, }; // Clean up any existing tray before creating a new one cleanupTray(); // Determine appropriate icon path let iconPath; if (app.isPackaged) { // In production, use path relative to the app's resource directory iconPath = path.join(process.resourcesPath, "assets", "icons", "16x16.png"); } else { // In development, use path relative to the project root iconPath = path.join(app.getAppPath(), "assets", "icons", "16x16.png"); } // Create the tray icon using nativeImage const trayIcon = nativeImage.createFromPath(iconPath); appTray = new Tray(trayIcon); try { // Set tooltip for the tray appTray.setToolTip("Backsplash"); } catch (error) { console.error("Failed to create tray icon:", error); } // Create new window instance appWindow = new BrowserWindow(windowOptions); // Set visibility properties for macOS upfront if (process.platform === "darwin") { appWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true }); appWindow.setFullScreenable(false); } // Load the index.html of the app window. if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { appWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL); } else { appWindow.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)); } const showWindow = () => { if (!appWindow || !appTray) return; // Get the tray position and window bounds const trayPos = appTray.getBounds(); const windowPos = appWindow.getBounds(); let x = 0; let y = 0; switch (process.platform) { case "win32": x = Math.round(trayPos.x + trayPos.width / 2 - windowPos.width / 2); y = Math.round(trayPos.y - height); break; case "darwin": x = Math.round(trayPos.x + trayPos.width / 2 - windowPos.width / 2); y = Math.round(trayPos.y + trayPos.height); break; case "freebsd": case "linux": case "sunos": default: x = screen.width - width - 10; y = 10; break; } // Position and show the window appWindow.setPosition(x, y, false); // Show the window (panel type handles activation policy) appWindow.show(); // if (!app.isPackaged) { // appWindow.webContents.openDevTools({ mode: "detach" }); // } }; const toggleWindow = () => { if (!appWindow) return; if (appWindow.isVisible()) { appWindow.hide(); } else { showWindow(); } }; // Register Inter Process Communication for main process registerMainIPC(wallpaperService); // Toggle showing the window when the tray item is clicked if (appTray) { appTray.on("click", toggleWindow); } // Close all windows when main window is closed appWindow.on("close", () => { cleanupTray(); // Clean up auto-launch handlers that are tied to the window if (appWindow) { cleanupAutoLaunchHandlers(appWindow); } appWindow = null; // Don't call app.quit() here to avoid circular calls with before-quit }); // Hide the window when it loses focus (clicked outside) appWindow.on("blur", () => { if (process.env.NODE_ENV === "development") { return; } // Check if the window still exists and is visible before hiding if (appWindow && !appWindow.isDestroyed() && appWindow.isVisible()) { appWindow.hide(); } }); return appWindow; } /** * Register Inter Process Communication */ function registerMainIPC(wallpaperService: WallpaperService) { /** * Here you can assign IPC related codes for the application window * to Communicate asynchronously from the main process to renderer processes. */ registerWindowStateChangedEvents(appWindow); registerMenuIpc(appWindow); registerWallpaperIpc(wallpaperService); registerStoreIpc(storeServiceInstance); registerServerIpc(storeServiceInstance); registerLicenseIpc(storeServiceInstance); // Make sure auto-launch handlers are registered try { registerAutoLaunchHandlers(appWindow); } catch (error) { console.error("Failed to register auto-launch handlers:", error); } } // In your main process app.on("before-quit", () => { // Clean up resources, close connections // Don't call window.close() here as it can cause circular calls // The windows will be destroyed automatically when the app quits }); // Make sure child windows are properly closed app.on("window-all-closed", () => { if (process.platform !== "darwin") { app.quit(); } });