import { join } from "node:path"; import { BrowserWindow, globalShortcut, ipcMain, shell, Notification } from "electron"; import { isLinux, isMac, isWin } from "../utils"; import { destroyTray } from "./trayManage"; import { getStore } from "./storeManage"; import { getIsForceQuit } from "./appManage"; import { registerShortcuts, unregisterShortcuts } from "./shortcutManage"; interface NotificationData { title: string; body: string; } const url = process.env.VITE_DEV_SERVER_URL; let mainWindow: BrowserWindow | null = null; let splashWindow: BrowserWindow | null = null; const store = getStore(); function createSplashWindow() { splashWindow = new BrowserWindow({ frame: false, width: 200, height: 200, resizable: false, transparent: true, }); splashWindow.loadFile(global.pathConfig.splashHtml); splashWindow.on("closed", () => { splashWindow = null; }); } export function createMainWindow() { createSplashWindow(); mainWindow = new BrowserWindow({ title: "OpenIM", icon: join(global.pathConfig.publicPath, "favicon.ico"), frame: false, show: false, minWidth: 680, minHeight: 550, titleBarStyle: "hiddenInset", webPreferences: { preload: global.pathConfig.preload, // Warning: Enable nodeIntegration and disable contextIsolation is not secure in production // Consider using contextBridge.exposeInMainWorld // Read more on https://www.electronjs.org/docs/latest/tutorial/context-isolation nodeIntegration: false, contextIsolation: true, sandbox: false, devTools: true, webSecurity: false, }, }); if (process.env.VITE_DEV_SERVER_URL) { // Open devTool if the app is not packaged mainWindow.loadURL(url); // mainWindow.webContents.openDevTools() } else { mainWindow.loadFile(global.pathConfig.indexHtml); } // // Make all links open with the browser, not with the application mainWindow.webContents.setWindowOpenHandler(({ url }) => { if (url.startsWith("https:")) shell.openExternal(url); return { action: "deny" }; }); mainWindow.on("focus", () => { mainWindow?.flashFrame(false); registerShortcuts(); }); mainWindow.on("blur", () => { unregisterShortcuts(); }); mainWindow.on("close", (e) => { if ( getIsForceQuit() || !mainWindow.isVisible() || store.get("closeAction") === "quit" ) { mainWindow = null; destroyTray(); } else { e.preventDefault(); if (isMac && mainWindow.isFullScreen()) { mainWindow.setFullScreen(false); } mainWindow?.hide(); } }); // globalShortcut.register('CommandOrControl+shift+l', () => { // mainWindow.webContents.openDevTools() // }) ipcMain.handle('show-notification', (event, { title, body }: NotificationData) => { const notification = new Notification({ title, body }); notification.show(); }); return mainWindow; } export function splashEnd() { splashWindow?.close(); mainWindow?.show(); } // utils export const isExistMainWindow = (): boolean => !!mainWindow && !mainWindow?.isDestroyed(); export const isShowMainWindow = (): boolean => { if (!mainWindow) return false; return mainWindow.isVisible() && (isWin ? true : mainWindow.isFocused()); }; export const closeWindow = () => { if (!mainWindow) return; mainWindow.close(); }; export const sendEvent = (name: string, ...args: any[]) => { if (!mainWindow) return; mainWindow.webContents.send(name, ...args); }; export const minimize = () => { if (!mainWindow) return; mainWindow.minimize(); }; export const updateMaximize = () => { if (!mainWindow) return; if (mainWindow.isMaximized()) { mainWindow.unmaximize(); } else { mainWindow.maximize(); } }; export const toggleHide = () => { if (!mainWindow) return; mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); }; export const toggleMinimize = () => { if (!mainWindow) return; if (mainWindow.isMinimized()) { if (!mainWindow.isVisible()) { mainWindow.show(); } mainWindow.restore(); mainWindow.focus(); } else { mainWindow.minimize(); } }; export const showWindow = () => { if (!mainWindow) return; if (mainWindow.isMinimized()) { mainWindow.restore(); } if (mainWindow.isVisible()) { mainWindow.focus(); } else { mainWindow.show(); } }; export const hideWindow = () => { if (!mainWindow) return; mainWindow.hide(); }; export const setFullScreen = (isFullscreen: boolean): boolean => { if (!mainWindow) return false; if (isLinux) { // linux It needs to be resizable before it can be full screen if (isFullscreen) { mainWindow.setResizable(isFullscreen); mainWindow.setFullScreen(isFullscreen); } else { mainWindow.setFullScreen(isFullscreen); mainWindow.setResizable(isFullscreen); } } else { mainWindow.setFullScreen(isFullscreen); } return isFullscreen; }; export const getWebContents = (): Electron.WebContents => { if (!mainWindow) throw new Error("main window is undefined"); return mainWindow.webContents; }; export const toggleDevTools = () => { if (!mainWindow) return; if (mainWindow.webContents.isDevToolsOpened()) { mainWindow.webContents.closeDevTools(); } else { mainWindow.webContents.openDevTools({ mode: "detach", }); } };