UNPKG

electron-event-flux

Version:

Redux store which synchronizes between instances in multiple process

139 lines (121 loc) 4.34 kB
import buildRendererAppStore, { RendererAppStore } from './RendererAppStore'; import { Emitter } from 'event-kit'; import IExtendStoreBase from './IExtendStoreBase'; import IStoresDeclarer, { IStoresObjDeclarer } from './IStoresDeclarer'; import { Logger } from './utils/loggerApply'; function getQuery() { let query: { [key: string]: string } = {}; window.location.search.slice(1).split('&').forEach(item => { let [key, val] = item.split('='); query[key] = decodeURIComponent(val); }); return query; } class ChildWindowProxy { emitter = new Emitter(); store: RendererAppStore; messages: any[] = []; childId: any; constructor(store: RendererAppStore, createPromise: Promise<string>) { this.emitter = new Emitter(); this.store = store; this.messages = []; createPromise.then(childId => { this.childId = childId; this.messages.forEach((message) => { this.send(message); }); }); (this.store as any).onDidWinMessage(this.handleWinMessage.bind(this)); } send(message: any) { if (!this.childId) { this.messages.push(message); } else { (this.store as any).sendWindowMessage(this.childId, message); } } handleWinMessage({ senderId, message }: { senderId: string, message: string }) { if (senderId === this.childId) { this.emitter.emit('message', message); } } onDidReceiveMsg(callback: (message: any) => void) { return this.emitter.on('message', callback); } } class ParentWindowProxy { store: RendererAppStore; parentId: string; emitter: Emitter; constructor(store: RendererAppStore, parentId: string) { this.store = store; this.parentId = parentId; this.emitter = new Emitter(); this.store.onDidWinMessage(this.handleWinMessage.bind(this)); } send(message: any) { this.store.sendWindowMessage(this.parentId, message); } handleWinMessage({ senderId, message }: { senderId: string, message: any }) { if (senderId === this.parentId) { this.emitter.emit('message', message); } } onDidReceiveMsg(callback: (message: any) => void) { return this.emitter.on('message', callback); } } interface RenderOptions { renderHandler?: any; actionHandler?: any; }; export default function rendererInit(rendererStores: IStoresObjDeclarer, options: RenderOptions = {}, logger: Logger) { let query = getQuery(); (window as any)['clientId'] = query['clientId'] || 'mainClient'; (window as any)['parentId'] = query['parentId']; // if (!window['clientId']) { // Not a renderer window // return; // } function getAction() { if ((window as any)['process']) return query['url'] || '/'; return window.location.pathname + window.location.search + window.location.hash; } (window as any)['action'] = getAction(); const store = buildRendererAppStore(rendererStores, options.renderHandler, logger); const genProxy = (store: RendererAppStore, multiWinStore: IExtendStoreBase) => { return new Proxy(multiWinStore, { get: function(target: any, propName: string) { if (!propName) return; if (propName === 'createWin') { return function(url: string, params: any) { return new ChildWindowProxy(store, target[propName](url, (window as any)['clientId'], params)); } } else { return target[propName]; } } }) } logger("rendererInitializer", "start async init", query); return store.asyncInit().then((state) => { store.stores['multiWinStore'] = genProxy(store, store.stores['multiWinStore']); if ((window as any)['parentId']) { (window as any)['parentWin'] = new ParentWindowProxy(store, (window as any)['parentId']); } store.observeInitWindow((message) => { // console.log('message', message); let { url, parentId } = message; // change-props (window as any)['action'] = url; (window as any)['parentId'] = parentId; if (!(window as any)['parentWin']) { (window as any)['parentWin'] = new ParentWindowProxy(store, (window as any)['parentId']); } else { (window as any)['parentWin']['parentId'] = parentId; } options.actionHandler && options.actionHandler((window as any)['action'], (window as any)['parentWin']); }); return store; }); }