store-sync-fixes, part 1

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman committed 2020-07-15 01:07:18 +03:00
1 parent 67377af52e
commit c06c322ca9
5 files changed
+39 -26

No files matched your search

+16 -18
View File
@@ -1,14 +1,13 @@
import path from "path"
import Config from "conf"
import { Options as ConfOptions } from "conf/dist/source/types"
import produce from "immer";
import { app, ipcMain, ipcRenderer, remote } from "electron"
import { action, observable, reaction, toJS, when } from "mobx";
import Singleton from "./utils/singleton";
import isEqual from "lodash/isEqual"
import { getAppVersion } from "./utils/app-version";
import logger from "../main/logger";
import { broadcastMessage } from "./ipc-helpers";
import isEqual from "lodash/isEqual";
export interface BaseStoreParams<T = any> extends ConfOptions<T> {
autoLoad?: boolean;
@@ -63,25 +62,33 @@ export class BaseStore<T = any> extends Singleton {
});
const storeModel = Object.assign({}, this.storeConfig.store);
Reflect.deleteProperty(storeModel, "__internal__"); // fixme: avoid "external-internals"
logger.info(`[STORE]: loaded ${this.storeConfig.path}`);
logger.info(`[STORE]: LOADED from ${this.storeConfig.path}`);
this.fromStore(storeModel);
this.isLoaded = true;
}
protected async save(model: T) {
logger.info(`[STORE]: SAVING ${this.name}`);
// fixme: https://github.com/sindresorhus/conf/issues/114
Object.entries(model).forEach(([key, value]) => {
this.storeConfig.set(key, value); // save update to config file
});
}
enableSync() {
this.syncDisposers.push(
reaction(() => this.toJSON(), this.onModelChange.bind(this)),
reaction(() => this.toJSON(), model => this.onModelChange(model)),
);
if (ipcMain) {
ipcMain.on(this.syncEvent, (event, model: T) => {
logger.debug(`[STORE]: ${this.name} sync update from renderer`, model);
logger.info(`[STORE]: SYNC ${this.name} from renderer`);
this.onSync(model);
});
this.syncDisposers.push(() => ipcMain.removeAllListeners(this.syncEvent));
}
if (ipcRenderer) {
ipcRenderer.on(this.syncEvent, (event, model: T) => {
logger.debug(`[STORE]: ${this.name} sync update from main`, model);
logger.info(`[STORE]: SYNC ${this.name} from main`);
this.onSync(model);
});
this.syncDisposers.push(() => ipcRenderer.removeAllListeners(this.syncEvent));
@@ -101,14 +108,10 @@ export class BaseStore<T = any> extends Singleton {
protected async onModelChange(model: T) {
if (ipcMain) {
broadcastMessage(this.syncEvent, model); // send updates to renderer views
// fixme: https://github.com/sindresorhus/conf/issues/114
Object.entries(model).forEach(([key, value]) => {
this.storeConfig.set(key, value); // save update to config file
});
this.save(model); // save to config file
broadcastMessage({ channel: this.syncEvent }, model); // broadcast to renderer views
}
// sends "update-request" event to main-process
// send "update-request" to main-process
if (ipcRenderer) {
ipcRenderer.send(this.syncEvent, model);
}
@@ -119,11 +122,6 @@ export class BaseStore<T = any> extends Singleton {
this.data = data;
}
@action
merge(updater: (modelDraft: T) => void) {
this.data = produce(this.data, updater);
}
// todo: use "serializr" ?
toJSON(): T {
return toJS(this.data, {
+12 -3
View File
@@ -2,7 +2,7 @@
// https://www.electronjs.org/docs/api/ipc-main
// https://www.electronjs.org/docs/api/ipc-renderer
import { ipcMain, ipcRenderer, webContents } from "electron"
import { ipcMain, ipcRenderer, WebContents, webContents } from "electron"
import logger from "../main/logger";
export type IpcChannel = string;
@@ -15,8 +15,17 @@ export interface IpcMessageHandler<T extends any[] = any> {
(...args: T): any;
}
export function broadcastMessage(channel: IpcChannel, ...args: any[]) {
webContents.getAllWebContents().forEach(webContent => {
export interface IpcBroadcastOpts {
channel: IpcChannel
filter?: (webContent: WebContents) => boolean
}
export function broadcastMessage({ channel, filter }: IpcBroadcastOpts, ...args: any[]) {
let webContentsList = webContents.getAllWebContents();
if (filter) {
webContentsList = webContentsList.filter(filter);
}
webContentsList.forEach(webContent => {
webContent.send(channel, ...args);
})
}