summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/main/ipc-event-channel.ts44
-rw-r--r--gui/src/main/user-interface.ts4
-rw-r--r--gui/src/shared/ipc-helpers.ts29
3 files changed, 25 insertions, 52 deletions
diff --git a/gui/src/main/ipc-event-channel.ts b/gui/src/main/ipc-event-channel.ts
index bae499910d..80fed8a034 100644
--- a/gui/src/main/ipc-event-channel.ts
+++ b/gui/src/main/ipc-event-channel.ts
@@ -1,48 +1,12 @@
import { ipcMain, WebContents } from 'electron';
-import { createIpcMain, IpcMain, Notifier, Schema } from '../shared/ipc-helpers';
+import { createIpcMain } from '../shared/ipc-helpers';
import { ipcSchema } from '../shared/ipc-schema';
-// Type where the notify functions have been replaced with either `undefined` if no `WebContents` is
-// available, or with the function curried with the `WebContents`.
-type IpcMainBootstrappedWithWebContents<S extends Schema> = {
- [GK in keyof IpcMain<S>]: {
- [CK in keyof IpcMain<S>[GK]]: IpcMain<S>[GK][CK] extends Notifier<infer T>
- ? undefined | ((arg: T) => ReturnType<IpcMain<S>[GK][CK]>)
- : IpcMain<S>[GK][CK];
- };
-};
-
-const ipcMainFromSchema = createIpcMain(ipcSchema, ipcMain);
// eslint-disable-next-line @typescript-eslint/naming-convention
-export let IpcMainEventChannel = bootstrapIpcMainWithWebContents();
-
-// Curries all notify functions with `WebContents` if it's not `undefined`. If it is `undefined`
-// then the whole function will be replaced with `undefined`.
-function bootstrapIpcMainWithWebContents(
- webContents?: WebContents,
-): IpcMainBootstrappedWithWebContents<typeof ipcSchema> {
- return Object.fromEntries(
- Object.entries(ipcMainFromSchema).map(([groupKey, group]) => {
- const newGroup = Object.fromEntries(
- Object.entries(group).map(([callKey, call]) => {
- if (callKey.startsWith('notify')) {
- const newCall = webContents
- ? (arg: Parameters<typeof call>[1]) => call(webContents, arg)
- : undefined;
- return [callKey, newCall];
- } else {
- return [callKey, call];
- }
- }),
- );
-
- return [groupKey, newGroup];
- }),
- ) as IpcMainBootstrappedWithWebContents<typeof ipcSchema>;
-}
+export let IpcMainEventChannel = createIpcMain(ipcSchema, ipcMain, undefined);
// Change the `IpcMainEventChannel` for a new one with a new `WebContents`.
-export function changeIpcWebContents(webContents?: WebContents) {
- IpcMainEventChannel = bootstrapIpcMainWithWebContents(webContents);
+export function changeIpcWebContents(webContents: WebContents | undefined) {
+ IpcMainEventChannel = createIpcMain(ipcSchema, ipcMain, webContents);
}
diff --git a/gui/src/main/user-interface.ts b/gui/src/main/user-interface.ts
index 4d56d95eac..ae9e9c8592 100644
--- a/gui/src/main/user-interface.ts
+++ b/gui/src/main/user-interface.ts
@@ -48,7 +48,11 @@ export default class UserInterface implements WindowControllerDelegate {
private navigationResetDisabled: boolean,
) {
const window = this.createWindow();
+
changeIpcWebContents(window.webContents);
+ window.webContents.on('destroyed', () => {
+ changeIpcWebContents(undefined);
+ });
this.windowController = this.createWindowController(window);
this.tray = this.createTray();
diff --git a/gui/src/shared/ipc-helpers.ts b/gui/src/shared/ipc-helpers.ts
index fda5c2d3b5..27ad17e22a 100644
--- a/gui/src/shared/ipc-helpers.ts
+++ b/gui/src/shared/ipc-helpers.ts
@@ -5,14 +5,12 @@ import { capitalize } from './string-helpers';
type Handler<T, R> = (callback: (arg: T) => R) => void;
type Sender<T, R> = (arg: T) => R;
-// Remove export after upgrading to Electron 21+ and removal of code to curry notifiers with
-// webContents in ../main/ipc-event-channel.ts.
-export type Notifier<T> = (webContents: WebContents | undefined, arg: T) => void;
+type Notifier<T> = ((arg: T) => void) | undefined;
type Listener<T> = (callback: (arg: T) => void) => void;
interface MainToRenderer<T> {
direction: 'main-to-renderer';
- send: (event: string, ipcMain: EIpcMain) => Notifier<T>;
+ send: (event: string, webContents: WebContents) => Notifier<T>;
receive: (event: string, ipcRenderer: EIpcRenderer) => Listener<T>;
}
@@ -64,15 +62,22 @@ export type IpcRenderer<S extends Schema> = {
};
// Preforms the transformation of the main event channel in accordance with the above types.
-export function createIpcMain<S extends Schema>(schema: S, ipcMain: EIpcMain): IpcMain<S> {
+export function createIpcMain<S extends Schema>(
+ schema: S,
+ ipcMain: EIpcMain,
+ webContents: WebContents | undefined,
+): IpcMain<S> {
return createIpc(schema, (event, key, spec) => {
const capitalizedKey = capitalize(key);
const newKey =
spec.direction === 'main-to-renderer' ? `notify${capitalizedKey}` : `handle${capitalizedKey}`;
- const newValue =
- spec.direction === 'main-to-renderer'
- ? spec.send(event, ipcMain)
- : spec.receive(event, ipcMain);
+
+ let newValue;
+ if (spec.direction === 'main-to-renderer') {
+ newValue = webContents ? spec.send(event, webContents) : undefined;
+ } else {
+ newValue = spec.receive(event, ipcMain);
+ }
return [newKey, newValue];
});
@@ -154,9 +159,9 @@ export function notifyRenderer<T>(): MainToRenderer<T> {
};
}
-function notifyRendererImpl<T>(event: string, _ipcMain: EIpcMain): Notifier<T> {
- return (webContents, value) => {
- if (webContents === undefined) {
+function notifyRendererImpl<T>(event: string, webContents: WebContents): Notifier<T> {
+ return (value) => {
+ if (webContents === undefined || webContents.isDestroyed() || webContents.isCrashed()) {
log.error(`sender(${event}): webContents is already destroyed!`);
} else {
webContents.send(event, value);