import { app, BrowserWindow, ipcMain } from 'electron'; import { join } from 'path'; import { URL } from 'url'; import { disableMediaKeys, enableMediaKeys } from './features/core/media-keys'; import { store } from './features/core/settings'; import electronLocalShortcut from 'electron-localshortcut'; import './features'; const isDevelopment = process.env.NODE_ENV === 'development'; const installExtensions = async () => { const installer = require('electron-devtools-installer'); const forceDownload = !!process.env.UPGRADE_EXTENSIONS; const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS']; return installer .default( extensions.map((name) => installer[name]), forceDownload, ) .catch(console.log); }; let browserWindow: BrowserWindow | null = null; async function createWindow() { if (isDevelopment) { await installExtensions(); } browserWindow = new BrowserWindow({ show: false, // Use the 'ready-to-show' event to show the instantiated BrowserWindow. frame: false, minWidth: 640, minHeight: 600, height: 900, width: 1440, webPreferences: { nodeIntegration: false, contextIsolation: true, sandbox: false, // Sandbox disabled because the demo of preload script depend on the Node.js api webviewTag: false, // The webview tag is not recommended. Consider alternatives like an iframe or Electron's BrowserView. @see https://www.electronjs.org/docs/latest/api/webview-tag#warning preload: join(app.getAppPath(), 'packages/preload/dist/index.cjs'), backgroundThrottling: false, }, }); /** * If the 'show' property of the BrowserWindow's constructor is omitted from the initialization options, * it then defaults to 'true'. This can cause flickering as the window loads the html content, * and it also has show problematic behaviour with the closing of the window. * Use `show: false` and listen to the `ready-to-show` event to show the window. * * @see https://github.com/electron/electron/issues/25012 for the afford mentioned issue. */ browserWindow.on('ready-to-show', () => { browserWindow?.show(); if (import.meta.env.DEV) { browserWindow?.webContents.openDevTools(); } }); ipcMain.on('window-maximize', () => { browserWindow?.maximize(); }); ipcMain.on('window-unmaximize', () => { browserWindow?.unmaximize(); }); ipcMain.on('window-minimize', () => { browserWindow?.minimize(); }); ipcMain.on('window-close', () => { browserWindow?.close(); }); electronLocalShortcut.register(browserWindow, 'Ctrl+Shift+I', () => { browserWindow?.webContents.openDevTools(); }); const globalMediaKeysEnabled = store.get('global_media_hotkeys') as boolean; if (globalMediaKeysEnabled) { enableMediaKeys(browserWindow); } ipcMain.on('global-media-keys-enable', () => { enableMediaKeys(browserWindow); }); ipcMain.on('global-media-keys-disable', () => { disableMediaKeys(); }); /** * URL for main window. * Vite dev server for development. * `file://../renderer/index.html` for production and test. */ const pageUrl = import.meta.env.DEV && import.meta.env.VITE_DEV_SERVER_URL !== undefined ? import.meta.env.VITE_DEV_SERVER_URL : new URL('../renderer/dist/index.html', 'file://' + __dirname).toString(); await browserWindow.loadURL(pageUrl); return browserWindow; } /** * Restore an existing BrowserWindow or Create a new BrowserWindow. */ export async function restoreOrCreateWindow() { let window = BrowserWindow.getAllWindows().find((w) => !w.isDestroyed()); if (window === undefined) { window = await createWindow(); } if (window.isMinimized()) { window.restore(); } window.focus(); } ipcMain.on('app-restart', () => { app.relaunch(); app.exit(0); }); export const getBrowserWindow = () => { return browserWindow; };