import { join } from "node:path"; import { BrowserWindow, shell, ipcMain } 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"; const url = process.env.VITE_DEV_SERVER_URL; let mainWindow: BrowserWindow | null = null; let splashWindow: BrowserWindow | null = null; let callingWindow: 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); } 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(); } }); ipcMain.on('calling-window', createCallingWindow) return mainWindow; } export function createCallingWindow(event, msg) { if (callingWindow) { return } callingWindow = new BrowserWindow({ title: "OpenIM calling -----", icon: join(global.pathConfig.publicPath, "favicon.ico"), modal: true, titleBarStyle: "default", webPreferences: { preload: global.pathConfig.preload, }, }); if (process.env.VITE_DEV_SERVER_URL) { // Open devTool if the app is not packaged callingWindow.loadURL(`${url}/#/calling`); } else { callingWindow.loadFile(global.pathConfig.callingHtml); } callingWindow.on('close',()=>{ callingWindow = null }) return callingWindow; } 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", }); } };