RenaiApp/src/main/modules/app-window/app-window.ts

109 lines
2.7 KiB
TypeScript

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<void> {
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<void>;
}