tabs/src/Window.ts
2021-03-06 18:45:37 +01:00

100 lines
3.1 KiB
TypeScript

import {BrowserWindow, BrowserWindowConstructorOptions, ipcMain, IpcMainEvent} from "electron";
import Application from "./Application";
import Config from "./Config";
export default abstract class Window {
private readonly listeners: {
[channel: string]: ((event: IpcMainEvent, ...args: unknown[]) => void)[] | undefined
} = {};
private readonly onCloseListeners: (() => void)[] = [];
protected readonly application: Application;
protected readonly config: Config;
protected readonly parent?: Window;
protected window?: BrowserWindow;
protected constructor(application: Application, parent?: Window) {
this.application = application;
this.parent = parent;
this.config = this.application.getConfig();
}
public setup(options: BrowserWindowConstructorOptions): void {
console.log('Creating window', this.constructor.name);
if (this.parent) {
options.parent = this.parent.getWindow();
}
this.window = new BrowserWindow(options);
this.window.on('close', () => {
this.teardown();
this.window = undefined;
});
this.onIpc('close-window', (
event,
constructorName: string,
) => {
if (constructorName === this.constructor.name) {
console.log('Closing', this.constructor.name);
const window = this.getWindow();
if (window.closable) {
window.close();
}
}
});
}
public teardown(): void {
console.log('Tearing down window', this.constructor.name);
for (const listener of this.onCloseListeners) {
listener();
}
for (const channel in this.listeners) {
const listeners = this.listeners[channel];
if (!listeners) continue;
for (const listener of listeners) {
ipcMain.removeListener(channel, listener);
}
}
this.window = undefined;
}
// This is the spec of ipcMain.on()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
protected onIpc(channel: string, listener: (event: IpcMainEvent, ...args: any[]) => void): this {
ipcMain.on(channel, listener);
if (!this.listeners[channel]) this.listeners[channel] = [];
this.listeners[channel]?.push(listener);
return this;
}
public onClose(listener: () => void): void {
this.onCloseListeners.push(listener);
}
public toggle(): void {
if (this.window) {
if (!this.window.isFocused()) {
console.log('Showing window', this.constructor.name);
this.window.show();
} else {
console.log('Hiding window', this.constructor.name);
this.window.hide();
}
}
}
public getWindow(): BrowserWindow {
if (!this.window) throw Error('Window not initialized.');
else if (this.window.isDestroyed()) throw Error('Window destroyed.');
return this.window;
}
}