hyper/app/rpc.ts

77 lines
2 KiB
TypeScript
Raw Normal View History

2019-11-28 05:17:01 -09:00
import {EventEmitter} from 'events';
import {ipcMain, BrowserWindow} from 'electron';
import {v4 as uuidv4} from 'uuid';
2023-06-25 05:26:16 -08:00
import {TypedEmitter, MainEvents, RendererEvents, FilterNever} from '../common';
2016-06-30 22:01:04 -08:00
2023-06-25 05:26:16 -08:00
export class Server {
emitter: TypedEmitter<MainEvents>;
destroyed = false;
win: BrowserWindow;
id!: string;
2023-06-25 05:26:16 -08:00
constructor(win: BrowserWindow) {
2023-06-25 05:26:16 -08:00
this.emitter = new EventEmitter();
2016-06-30 22:01:04 -08:00
this.win = win;
2023-06-25 05:26:16 -08:00
this.emit = this.emit.bind(this);
2016-07-25 10:01:01 -08:00
if (this.destroyed) {
return;
}
2016-07-25 10:01:01 -08:00
const uid = uuidv4();
2016-07-25 10:01:01 -08:00
this.id = uid;
ipcMain.on(uid, this.ipcListener);
// we intentionally subscribe to `on` instead of `once`
// to support reloading the window and re-initializing
// the channel
this.wc.on('did-finish-load', () => {
this.wc.send('init', uid);
2016-06-30 22:01:04 -08:00
});
}
get wc() {
2016-06-30 22:01:04 -08:00
return this.win.webContents;
}
2023-06-25 05:26:16 -08:00
ipcListener = (event: any, {ev, data}: {ev: keyof MainEvents; data: any}) => this.emitter.emit(ev, data);
on = <U extends keyof MainEvents>(ev: U, fn: (arg0: MainEvents[U]) => void) => {
this.emitter.on(ev, fn);
return this;
};
once = <U extends keyof MainEvents>(ev: U, fn: (arg0: MainEvents[U]) => void) => {
this.emitter.once(ev, fn);
return this;
};
2016-06-30 22:01:04 -08:00
2023-06-25 05:26:16 -08:00
emit<U extends Exclude<keyof RendererEvents, FilterNever<RendererEvents>>>(ch: U): boolean;
emit<U extends FilterNever<RendererEvents>>(ch: U, data: RendererEvents[U]): boolean;
emit<U extends keyof RendererEvents>(ch: U, data?: RendererEvents[U]) {
// This check is needed because data-batching can cause extra data to be
// emitted after the window has already closed
if (!this.win.isDestroyed()) {
this.wc.send(this.id, {ch, data});
2023-06-25 05:26:16 -08:00
return true;
}
2023-06-25 05:26:16 -08:00
return false;
2016-06-30 22:01:04 -08:00
}
destroy() {
2023-06-25 05:26:16 -08:00
this.emitter.removeAllListeners();
2016-06-30 22:01:04 -08:00
this.wc.removeAllListeners();
if (this.id) {
ipcMain.removeListener(this.id, this.ipcListener);
} else {
// mark for `genUid` in constructor
this.destroyed = true;
}
}
}
export default (win: BrowserWindow) => {
2016-06-30 22:01:04 -08:00
return new Server(win);
};