import { app, BrowserWindow, Event, LoadFileOptions, LoadURLOptions, NewWindowWebContentsEvent } from 'electron'; import os from 'os'; import path from 'path'; import { isDev } from '../../core/env'; import type { SessionHelperInterface } from '../session/session-helper-interface'; import type { AppWindowInterface } from './app-window-interface'; import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions; let defaultOptions: BrowserWindowConstructorOptions = { width: 1600, height: 900, webPreferences: { enableRemoteModule: false, nodeIntegration: false, contextIsolation: true, devTools: isDev(), }, }; switch (os.platform()) { case 'win32': defaultOptions = { ...defaultOptions, ...{ icon: path.resolve(app.getAppPath(), 'resources', 'icon.ico'), }, }; break; default: break; } export abstract class AppWindow implements AppWindowInterface { protected static default = {}; protected _window: BrowserWindow | null = null; protected readonly sessionHelper: SessionHelperInterface; protected options: BrowserWindowConstructorOptions; protected uri: string; protected abstract loadOptions: LoadFileOptions | LoadURLOptions; protected constructor( sessionHelper: SessionHelperInterface, uri: string, options: BrowserWindowConstructorOptions = {} ) { this.sessionHelper = sessionHelper; this.options = { ...defaultOptions, ...options }; this.uri = uri; } public get window(): BrowserWindow | null { return this._window; } public open(): Promise { this._window = new BrowserWindow(this.options); this.sessionHelper.setCsp(this._window, this.getCsp()); this._window.on('closed', () => { this.onClosed(); this._window = null; }); if (isDev()) { this._window.webContents.openDevTools(); } this._window.webContents.on('will-navigate', this.onWillNavigate); this._window.webContents.on('new-window', this.onNewWindow); return this.load(this._window); } public close(force: boolean = false): void { if (force) { this._window?.destroy(); } else { this._window?.close(); } } public isClosed(): boolean { return !this._window; } protected getCsp(): Session.ContentSecurityPolicy { return {}; } // eslint-disable-next-line @typescript-eslint/no-unused-vars -- it is used in child classes protected onWillNavigate(event: Event, navigationUrl: string): void { event.preventDefault(); } protected onNewWindow(event: NewWindowWebContentsEvent): void { event.preventDefault(); } protected onClosed(): void {} protected abstract load(window: BrowserWindow): Promise; }