From 5dc3c546ca874e79929e16545b99020472cdf066 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr>
Date: Fri, 10 Jul 2020 15:44:45 +0200
Subject: [PATCH] [dome] refactor settings API

---
 ivette/src/dome/src/main/dome.js              |  2 +-
 ivette/src/dome/src/misc/system.js            |  9 +++
 ivette/src/dome/src/renderer/data/settings.ts | 74 +++++++++++++------
 ivette/src/dome/src/renderer/data/states.ts   |  2 +-
 4 files changed, 64 insertions(+), 23 deletions(-)

diff --git a/ivette/src/dome/src/main/dome.js b/ivette/src/dome/src/main/dome.js
index cd01363afb0..8fd188b09b6 100644
--- a/ivette/src/dome/src/main/dome.js
+++ b/ivette/src/dome/src/main/dome.js
@@ -158,7 +158,7 @@ function applyGlobalSettings(event,args) {
   applyPatches( obtainGlobalSettings(), args );
   BrowserWindow.getAllWindows().forEach((w) => {
     if (w.webContents.id !== event.sender.id) {
-      w.send('dome.ipc.settings.update',args);
+      w.send('dome.ipc.settings.broadcast',args);
     }
   });
   if (DEVEL) saveGlobalSettings();
diff --git a/ivette/src/dome/src/misc/system.js b/ivette/src/dome/src/misc/system.js
index 3a4deac841f..437b62d7227 100644
--- a/ivette/src/dome/src/misc/system.js
+++ b/ivette/src/dome/src/misc/system.js
@@ -57,6 +57,15 @@ export const platform = thePlatform ;
 /** Development mode flag */
 export const DEVEL = process.env.NODE_ENV !== 'production' ;
 
+// --------------------------------------------------------------------------
+// --- System Emitter
+// --------------------------------------------------------------------------
+
+export const emitter = new Emitter();
+{
+  emitter.setMaxListeners(250);
+}
+
 // --------------------------------------------------------------------------
 // --- At Exit
 // --------------------------------------------------------------------------
diff --git a/ivette/src/dome/src/renderer/data/settings.ts b/ivette/src/dome/src/renderer/data/settings.ts
index aeddf5c47c9..19e6730a157 100644
--- a/ivette/src/dome/src/renderer/data/settings.ts
+++ b/ivette/src/dome/src/renderer/data/settings.ts
@@ -11,9 +11,8 @@
 import React from 'react';
 import { ipcRenderer } from 'electron';
 import { debounce } from 'lodash';
-import * as Dome from 'dome';
 import isEqual from 'react-fast-compare';
-import { DEVEL } from 'dome/misc/system';
+import { DEVEL, emitter as SysEmitter } from 'dome/misc/system';
 import * as JSON from './json';
 import type { State } from './states';
 
@@ -130,29 +129,31 @@ class Driver {
         ipcRenderer.send(ipc, patches);
       }
     }, 100);
-    // --- Init Events
+    // --- Restore Defaults Events
     ipcRenderer.on('dome.ipc.settings.defaults', () => {
       this.fire.cancel();
       this.store.clear();
       this.diffs.clear();
-      Dome.emit(this.evt);
+      SysEmitter.emit(this.evt);
     });
     // --- Broadcast Events
     if (this.broadcast) {
-      ipcRenderer.on('dome.ipc.settings.update', (_sender, patches: patch[]) => {
-        const m = this.store;
-        const d = this.diffs;
-        patches.forEach(({ key, value }) => {
-          // Don't cancel local updates
-          if (!d.has(key)) {
-            if (value === null)
-              m.delete(key);
-            else
-              m.set(key, value);
-          }
+      ipcRenderer.on(
+        'dome.ipc.settings.broadcast',
+        (_sender, updates: patch[]) => {
+          const m = this.store;
+          const d = this.diffs;
+          updates.forEach(({ key, value }) => {
+            // Don't cancel local updates
+            if (!d.has(key)) {
+              if (value === null)
+                m.delete(key);
+              else
+                m.set(key, value);
+            }
+          });
+          SysEmitter.emit(this.evt);
         });
-        Dome.emit('dome.settings');
-      });
     }
     // --- Closing Events
     ipcRenderer.on('dome.ipc.closing', () => {
@@ -161,6 +162,19 @@ class Driver {
     });
   }
 
+  // --- Initial Data
+
+  sync(data: patch[]) {
+    this.fire.cancel();
+    this.store.clear();
+    this.diffs.clear();
+    const m = this.store;
+    data.forEach(({ key, value }) => {
+      m.set(key, value);
+    });
+    SysEmitter.emit(this.evt);
+  }
+
   // --- Load Data
 
   load(key: string | undefined): JSON.json {
@@ -178,7 +192,7 @@ class Driver {
       this.store.set(key, data);
       this.diffs.set(key, data);
     }
-    if (this.broadcast) Dome.emit(this.evt);
+    if (this.broadcast) SysEmitter.emit(this.evt);
     this.fire();
   }
 
@@ -216,8 +230,10 @@ function useSettings<A>(
   // Broadcast
   React.useEffect(() => {
     if (K) {
+      const event = D.evt;
       const callback = () => setValue(loader());
-      return () => Dome.off(D.evt, callback);
+      SysEmitter.on(event, callback);
+      return () => { SysEmitter.off(event, callback); }
     }
     return undefined;
   });
@@ -248,10 +264,10 @@ export function getWindowSettings<A>(
   key: string | undefined,
   decoder: JSON.Loose<A>,
   defaultValue: A,
-) {
+): A {
   return key ?
     JSON.jCatch(decoder, defaultValue)(WindowDriver.load(key))
-    : undefined;
+    : defaultValue;
 }
 
 /**
@@ -318,3 +334,19 @@ export function useGlobalSettings<A>(S: GlobalSettings<A>) {
 }
 
 // --------------------------------------------------------------------------
+// --- Settings Synchronization
+// --------------------------------------------------------------------------
+
+/*@ internal */
+export function synchronize() {
+  ipcRenderer.sendSync(
+    'dome.ipc.settings.sync',
+    (_event: string, data: any) => {
+      const globals: patch[] = data.globals ?? [];
+      GlobalDriver.sync(globals);
+      const settings: patch[] = data.settings ?? [];
+      WindowDriver.sync(settings);
+    });
+}
+
+// --------------------------------------------------------------------------
diff --git a/ivette/src/dome/src/renderer/data/states.ts b/ivette/src/dome/src/renderer/data/states.ts
index 84ff5d6a811..91f2fadde56 100644
--- a/ivette/src/dome/src/renderer/data/states.ts
+++ b/ivette/src/dome/src/renderer/data/states.ts
@@ -17,7 +17,7 @@ import isEqual from 'react-fast-compare';
 // --------------------------------------------------------------------------
 
 /** Alias to `[state,setState]` returned values*/
-export type State<A> = [A, (update: A) => void];
+export type State<A> = [A, (newValue: A) => void];
 
 /** State field of an object state. */
 export function key<A, K extends keyof A>(
-- 
GitLab