electron-reactive-ipc
Version:
rxjs based electron IPC channel wrapper
103 lines (90 loc) • 3.3 kB
text/typescript
import { ipcRenderer } from "electron";
import { DuplexChannel } from "./channel";
import { ElectronIPC } from "./electron-ipc";
import { ControlFlags, SignalData } from "./types";
export interface ExposedIPCRenderer {
getChannel: (name: string) => DuplexChannel<unknown>,
addChannel: (name: string, data: any) => DuplexChannel<unknown>,
}
export class ElectronIPCRenderer extends ElectronIPC {
private constructor() {
super();
this.initRenderer();
}
public static initialize(): ElectronIPCRenderer {
if (!this._instance) this._instance = new ElectronIPCRenderer();
return this._instance as ElectronIPCRenderer;
}
public get<T>(channelName: string) {
return <DuplexChannel<T>>this._channels[0]?.[channelName];
}
public addChanel<T>(name: string, data: T): DuplexChannel<unknown> {
return super.addChanel(name, data);
}
/**
* For exposing functions using Electron's contextBridge api
*/
public get asExposed() {
return {
getChannel: (name: string) => this.get(name),
addChannel: (name: string, initialData: any) => this.addChanel(name, initialData)
} as ExposedIPCRenderer;
}
private initRenderer() {
console.log('init renderer')
ipcRenderer.once(ControlFlags.INIT, (event) => {
console.log('init main')
this.resetChannels();
this.isInitialized = true;
this.que[0]?.forEach(subjectName => {
ipcRenderer.send(ControlFlags.CREATE,
{
channel: subjectName,
data: this._channels[0][subjectName]?.localValue,
} as SignalData<unknown>);
});
this.que[0] = [];
})
ipcRenderer.on(ControlFlags.CREATE, (event, data: SignalData<unknown>) => {
this.setDataIncoming(data);
});
ipcRenderer.on(ControlFlags.CLOSE, (event, data: SignalData<unknown>) => {
const channel = this._channels[0][data.channel];
if (channel) {
channel.close();
delete this._channels[0][data.channel];
}
});
ipcRenderer.on(ControlFlags.DATA, (event, data: SignalData<unknown>) => {
this.setDataIncoming(data);
});
ipcRenderer.once(ControlFlags.QUIT, (event) => {
this.resetChannels();
this.isInitialized = false;
this.loadQue();
});
this.pingMain();
window.onbeforeunload = () => {
console.log('reloading')
ipcRenderer.send(ControlFlags.RELOAD);
}
}
private pingMain() {
ipcRenderer.send(ControlFlags.INIT);
let i = 0;
let timer: NodeJS.Timeout;
timer = setInterval(() => {
if (this.isInitialized) {
clearInterval(timer);
return;
}
if (i > 3) {
clearInterval(timer);
throw new Error('IPC Handshake Failed');
}
console.log(`No response from main, reconnecting. Attermpt: ${i + 2}`)
ipcRenderer.send(ControlFlags.INIT);
i++;
}, 3000)
}
}