From 3fb308ec0fc858302a767967a964435e29b28b66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Loi=CC=88c=20Correnson?= <loic.correnson@cea.fr> Date: Wed, 10 Jun 2020 19:33:06 +0200 Subject: [PATCH] [dome] change settings policy --- ivette/.gitignore | 1 + ivette/src/dome/src/main/dome.js | 366 +++++++++++------- .../dome/src/renderer/controls/buttons.tsx | 2 - ivette/src/dome/src/renderer/data/states.ts | 6 +- ivette/src/dome/src/renderer/dome.js | 132 ++++--- .../src/dome/src/renderer/frame/sidebars.js | 2 +- ivette/src/frama-c/LabViews.tsx | 1 - 7 files changed, 295 insertions(+), 215 deletions(-) diff --git a/ivette/.gitignore b/ivette/.gitignore index da037a9e2fa..194fc7ea7ce 100644 --- a/ivette/.gitignore +++ b/ivette/.gitignore @@ -2,6 +2,7 @@ # --- Template .gitignore file for Dome # -------------------------------------------------------------------------- +.ivette .dome-*.stamp .dome-*.back node_modules diff --git a/ivette/src/dome/src/main/dome.js b/ivette/src/dome/src/main/dome.js index 1385eb6bc5e..07d0d620e05 100644 --- a/ivette/src/dome/src/main/dome.js +++ b/ivette/src/dome/src/main/dome.js @@ -50,83 +50,136 @@ export const platform = System.platform ; // --- Settings // -------------------------------------------------------------------------- -const APP_DIR = app.getPath('userData'); -const APP_SETTINGS = path.join( APP_DIR , 'Settings.json' ); - -var s_frames = {} ; -var s_globals = {} ; -var s_application = {} ; -var s_preferences = {} ; +function loadSettings( file ) { + try { + if (!fstat(file)) + return {}; + const text = fs.readFileSync(file, { encoding: 'utf8' } ); + return Object.assign({}, JSON.parse(text)); + } catch(err) { + console.error("[Dome] Can not load settings", file, err); + return {}; + } +} -function loadSettings() { +function saveSettings( file, data={} ) { try { - if (!fstat( APP_SETTINGS )) return; - const content = fs.readFileSync( APP_SETTINGS, { encoding: 'utf8' } ); - const loaded = JSON.parse( content ); - const MERGE = (store,field) => _.merge( store , _.get( loaded , field )); - s_frames = MERGE( s_frames , 'frames' ); - s_globals = MERGE( s_globals, 'globals' ); - s_application = MERGE( s_application, 'application' ); - s_preferences = MERGE( s_preferences, 'preferences' ); + const text = JSON.stringify( data, undefined, DEVEL ? 2 : 0 ); + fs.writeFileSync( file, text, { encoding: 'utf8' }, (err) => { throw(err); } ); } catch(err) { - console.error("[Dome] Can not load application settings\n" + err); + console.error("[Dome] Can not save settings", file, err); } } -function saveSettings() { +// -------------------------------------------------------------------------- +// --- Global Settings +// -------------------------------------------------------------------------- + +var GlobalSettings; // Current Dictionnary + +const APP_DIR = app.getPath('userData'); +const PATH_WINDOW_SETTINGS = path.join( APP_DIR, 'WindowSettings.json' ); +const PATH_GLOBAL_SETTINGS = path.join( APP_DIR, 'GlobalSettings.json' ); + +function saveGlobalSettings() { try { if (!fstat( APP_DIR )) fs.mkdirSync( APP_DIR ); - const saved = { - globals: s_globals, - application: s_application, - preferences: s_preferences, - frames: s_frames - }; - const content = JSON.stringify( saved, undefined, DEVEL ? 2 : 0 ); - fs.writeFileSync( APP_SETTINGS, content, { encoding: 'utf8' }, errorSettings ); + saveSettings( PATH_GLOBAL_SETTINGS, GlobalSettings ); } catch(err) { - errorSettings(err); + console.error("[Dome] Can not save global settings", err); } } -const fireSaveSettings = _.debounce( saveSettings , 50 ); +function obtainGlobalSettings() { + if (!GlobalSettings) { + GlobalSettings = loadSettings( PATH_GLOBAL_SETTINGS ); + } + return GlobalSettings; +} + +// -------------------------------------------------------------------------- +// --- Window Settings & Frames +// -------------------------------------------------------------------------- -function errorSettings(err) { - if (err) console.error("[Dome] Can not save application settings\n" + err); +/* Window Handle: + { + window: BrowserWindow ; // Also prevents Gc + config: path; // Path to config file + frame: { x,y,w,h }; // Frame position + settings: object; // Current settings + reload: boolean; // Reloaded window + } + */ + +const WindowHandles = {}; // Indexed by *webContents* id + +function saveWindowConfig(handle) { + const settings = { + frame: handle.frame, + settings: handle.settings, + devtools: handle.devtools + }; + saveSettings( handle.config, settings ); } -function remoteSyncSettings(event) -{ - const isSetting = windowSettings && windowSettings.id === event.frameId ; +function windowSyncSettings(event) { + const handle = WindowHandles[event.sender.id]; event.returnValue = { - globals: s_globals, - settings: isSetting ? s_preferences : s_application + globals: obtainGlobalSettings(), + settings: handle && handle.settings }; } -function remoteSaveWindowSettings(event,patches) -{ - const isSetting = windowSettings && windowSettings.id === event.frameId ; - _.merge( isSetting ? s_preferences : s_application , patches ); - saveSettings(); +ipcMain.on('dome.ipc.settings.sync', windowSyncSettings ); + +// -------------------------------------------------------------------------- +// --- Patching Settings +// -------------------------------------------------------------------------- + +function applyPatches( data, args ) { + args.forEach(({ key, value }) => { + if (value === null) { + delete data[key]; + } else { + data[key] = value; + } + }); } -function remoteSaveGlobalSettings(event,patches) -{ - _.merge( s_globals , patches ); - saveSettings(); - BrowserWindow.getAllWindows().forEach((win) => { - if (win.id !== event.frameId) - win.send('dome.ipc.settings.update',patches); +function applyWindowSettings(event,args) { + const handle = WindowHandles[event.sender.id]; + if (handle) { + applyPatches( handle.settings, args ); + if (DEVEL) saveWindowConfig( handle ); + } +} + +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); + } }); + if (DEVEL) saveGlobalSettings(); } -ipcMain.on('dome.ipc.settings.sync', remoteSyncSettings ); -ipcMain.on('dome.ipc.settings.window', remoteSaveWindowSettings ); -ipcMain.on('dome.ipc.settings.global', remoteSaveGlobalSettings ); +ipcMain.on('dome.ipc.settings.window', applyWindowSettings ); +ipcMain.on('dome.ipc.settings.global', applyGlobalSettings ); // -------------------------------------------------------------------------- -// --- Active Windows +// --- Renderer-Process Communication +// -------------------------------------------------------------------------- + +function broadcast( event, ...args ) +{ + BrowserWindow.getAllWindows().forEach((w) => { + w.send( event, ...args ); + }); +} + +// -------------------------------------------------------------------------- +// --- Window Activities // -------------------------------------------------------------------------- var appName = 'Dome' ; @@ -141,21 +194,24 @@ export function setName(title) { } function setTitle(event,title) { - let w = BrowserWindow.fromId( event.frameId ); - w.setTitle( title || appName ); + let handle = WindowHandles[event.sender.id]; + handle && handle.setTitle( title || appName ); } function setModified(event,modified) { - let w = BrowserWindow.frameId( event.frameId ); - if (platform == 'macos') - w.setDocumentEdited( modified ); - else { - let title = w.getTitle(); - if (title.startsWith(MODIFIED)) - title = title.substring(MODIFIED.length); - if (modified) - title = MODIFIED + title ; - w.setTitle(title); + let handle = WindowHandles[event.sender.id]; + if (handle) { + const w = handle.window; + if (platform == 'macos') + w.setDocumentEdited( modified ); + else { + let title = w.getTitle(); + if (title.startsWith(MODIFIED)) + title = title.substring(MODIFIED.length); + if (modified) + title = MODIFIED + title ; + w.setTitle(title); + } } } @@ -192,34 +248,55 @@ function navigateURL( event , url ) { } // -------------------------------------------------------------------------- -// --- Browser Window SetUp +// --- Lookup for config file // -------------------------------------------------------------------------- -const windowsHandle = {} ; // Prevent live windows to be garbage collected -const windowsReload = {} ; // Reloaded windows +function lookupConfig(wdir) { + let cwd = wdir = path.resolve(wdir); + let cfg = '.' + appName.toLowerCase(); + for(;;) { + const here = path.join(cwd,cfg); + if (fstat(here)) return here; + let up = path.dirname(cwd); + if (up === cwd) break; + cwd = up; + } + const home = path.resolve(app.getPath('home')); + const user = wdir.startsWith(home) ? wdir : home ; + return path.join( user, cfg ); +} + +// -------------------------------------------------------------------------- +// --- Browser Window SetUp +// -------------------------------------------------------------------------- -function createBrowserWindow( config, isMain=true ) +function createBrowserWindow( config, argv, wdir ) { - const argv = isMain + const isAppWindow = (argv !== undefined && wdir !== undefined); + + const browserArguments = isAppWindow ? SYS.WINDOW_APPLICATION_ARGV : SYS.WINDOW_PREFERENCES_ARGV ; - const options = _.merge( + const options = Object.assign( { show: false, backgroundColor: '#f0f0f0', webPreferences: { nodeIntegration:true, - additionalArguments: [ argv ] + additionalArguments: [ browserArguments ] } - } - , config ); + }, + config + ); - const frameId = isMain ? 'application' : 'preferences' ; - const frame = _.get( s_frames, frameId ); - const getInt = (v) => v && _.toSafeInteger(v); + const configFile = isAppWindow ? lookupConfig( wdir ) : PATH_WINDOW_SETTINGS ; + const configData = loadSettings( configFile ); + + const { frame, devtools, settings={} } = configData; if (frame) { + const getInt = (v) => v && _.toSafeInteger(v); options.x = getInt(frame.x); options.y = getInt(frame.y); options.width = getInt(frame.width); @@ -227,8 +304,25 @@ function createBrowserWindow( config, isMain=true ) } const theWindow = new BrowserWindow( options ); - const wid = theWindow.id; - + const wid = theWindow.webContents.id; + + const handle = { + window: theWindow, + config: configFile, + frame, settings, devtools, + reload: false + }; + + // Keep the window reference (prevent garbage collection) + WindowHandles[wid] = handle; + + // Emitted when the window is closed. + theWindow.on('closed', () => { + saveWindowConfig(handle); + // Dereference the window object (allow garbage collection) + delete WindowHandles[wid] ; + }); + // Load the index.html of the app. if (DEVEL || LOCAL) process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'; @@ -239,7 +333,7 @@ function createBrowserWindow( config, isMain=true ) theWindow.once('ready-to-show' , () => { if (DEVEL || LOCAL) process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'false'; - if (DEVEL) + if (DEVEL && devtools) theWindow.openDevTools(); theWindow.show(); }); @@ -251,57 +345,44 @@ function createBrowserWindow( config, isMain=true ) // URL Navigation theWindow.webContents.on('will-navigate', navigateURL ); theWindow.webContents.on('did-navigate-in-page', navigateURL ); + + // Application Startup theWindow.webContents.on('did-finish-load', () => { - const isLoaded = windowsReload[wid]; - if (!isLoaded) { - windowsReload[wid] = true; + if (!handle.reload) { + handle.reload = true; } else { broadcast('dome.ipc.reload'); } + theWindow.send('dome.ipc.command',argv,wdir); }); // Emitted when the window want's to close. theWindow.on('close', (evt) => { + handle.frame = theWindow.getBounds(); + handle.devtools = theWindow.isDevToolsOpened(); theWindow.send('dome.ipc.closing'); - const frame = theWindow.getBounds(); - _.set( s_frames, frameId , frame ); }); // Keep track of frame positions (in DEVEL) if (DEVEL) { - const reframe = _.debounce( (evt) => { - const frame = theWindow.getBounds(); - _.set( s_frames, frameId , frame ); - saveSettings(); + const saveFrame = _.debounce( (evt) => { + handle.frame = theWindow.getBounds(); + handle.devtools = theWindow.isDevToolsOpened(); + saveWindowConfig(handle); } , 300); - theWindow.on('resize',reframe); - theWindow.on('moved',reframe); + theWindow.on('resize',saveFrame); + theWindow.on('moved',saveFrame); } - // Keep the window reference to prevent destruction - windowsHandle[ wid ] = theWindow ; - - // Emitted when the window is closed. - theWindow.on('closed', () => { - // Dereference the window object to actually destroy it - delete windowsHandle[ wid ] ; - }); - return theWindow ; } // -------------------------------------------------------------------------- -// --- Application Window(s) +// --- Application Window(s) & Command Line // -------------------------------------------------------------------------- -function filterArgv( argv ) { - return argv.slice( DEVEL ? 3 : (LOCAL ? 2 : 1) ).filter((p) => p); -} - -function sendCommand( win, argv, wdir ) { - win.webContents.on('did-finish-load', () => { - win.webContents.send('dome.ipc.command',argv,wdir); - }); +function stripElectronArgv( argv ) { + return argv.slice( DEVEL ? 3 : (LOCAL ? 2 : 1) ).filter((p) => !!p); } function createPrimaryWindow() @@ -309,31 +390,28 @@ function createPrimaryWindow() // Initialize Menubar Menubar.install(); - // Initialize Settings - loadSettings(); - // React Developper Tools if (DEVEL) installExtension(REACT_DEVELOPER_TOOLS,true); - - const primary = createBrowserWindow({ title: appName } , true); - const wdir = process.cwd() === '/' ? app.getPath('home') : process.cwd() ; - sendCommand( primary , filterArgv(process.argv) , wdir ); + const cwd = process.cwd(); + const wdir = cwd === '/' ? app.getPath('home') : cwd ; + const argv = stripElectronArgv(process.argv); + createBrowserWindow({ title: appName } , argv, wdir ); } var appCount = 1; -function createSecondaryWindow(_event,argv,wdir) +function createSecondaryWindow(_event,process_argv,wdir) { - const secondary = createBrowserWindow({ title: `${appName} #${++appCount}` }, true); - sendCommand( secondary, filterArgv(argv), wdir ); + const argv = stripElectronArgv(process_argv); + createBrowserWindow({ title: `${appName} #${++appCount}` }, argv, wdir); } function createDesktopWindow() { const instance = appCount++ ; - const secondary = createBrowserWindow({ title: `${appName} #${++appCount}` }, true); - sendCommand( secondary , [] , app.getPath('home') ); + const wdir = app.getPath('home'); + createBrowserWindow({ title: `${appName} #${++appCount}` }, [], wdir); } // -------------------------------------------------------------------------- @@ -361,31 +439,35 @@ function activateWindows() { // --- Settings Window // -------------------------------------------------------------------------- -var windowSettings = undefined ; // Preference Window +var PreferenceWindow = undefined ; // Preference Window function showSettingsWindow() { - if (!windowSettings) - windowSettings = createBrowserWindow({ + if (!PreferenceWindow) + PreferenceWindow = createBrowserWindow({ title: appName + ' Settings', width: 256, height: 248, fullscreen: false, maximizable: false, minimizable: false - }, false); - windowSettings.show(); - windowSettings.on('closed',() => windowSettings = undefined); + }); + PreferenceWindow.show(); + PreferenceWindow.on('closed',() => PreferenceWindow = undefined); } function restoreDefaultSettings() { - s_globals = {} ; - s_preferences = {} ; - s_application = {} ; - s_frames = {} ; - fireSaveSettings(); - fireSaveSettings.flush(); + GlobalSettings = {}; + if (DEVEL) saveGlobalSettings(); + + _.forEach( WindowHandles, (handle) => { + // Keep frame for user comfort + handle.settings = {}; + handle.devtools = handle.window.isDevToolsOpened(); + if (DEVEL) saveWindowConfig(handle); + }); + broadcast( 'dome.ipc.settings.defaults' ); } @@ -402,22 +484,21 @@ export function start() { // Change default locale app.commandLine.appendSwitch('lang','en'); - // Listen to window events + // Listen to application events app.on( 'ready', createPrimaryWindow ); // Wait for Electron init app.on( 'activate', activateWindows ); // Mac OSX response to dock app.on( 'second-instance', createSecondaryWindow ); app.on( 'dome.menu.settings', showSettingsWindow ); app.on( 'dome.menu.defaults', restoreDefaultSettings ); - // Performing on-exit callbacks + // At-exit callbacks app.on( 'will-quit' , () => { + saveGlobalSettings(); System.doExit() ; - fireSaveSettings(); - fireSaveSettings.flush(); }); - // On OS X menu bar stay active until the user quits explicitly from menu. - // On other systems, quit when all windows are closed. + // On macOS the menu bar stays active until the user explicitly quits. + // On other systems, automatically quit when all windows are closed. // Warning: when no event handler is registered, the app automatically // quit when all windows are closed. app.on( 'window-all-closed', () => { @@ -426,17 +507,6 @@ export function start() { } -// -------------------------------------------------------------------------- -// --- Renderer-Process Communication -// -------------------------------------------------------------------------- - -function broadcast( event, ...args ) -{ - BrowserWindow.getAllWindows().forEach((w) => { - w.send( event, ...args ); - }); -} - // -------------------------------------------------------------------------- // --- MenuBar Management // -------------------------------------------------------------------------- diff --git a/ivette/src/dome/src/renderer/controls/buttons.tsx b/ivette/src/dome/src/renderer/controls/buttons.tsx index da254148990..0789962f9c9 100644 --- a/ivette/src/dome/src/renderer/controls/buttons.tsx +++ b/ivette/src/dome/src/renderer/controls/buttons.tsx @@ -161,8 +161,6 @@ export function Button(props: ButtonProps) { + (display ? '' : ' dome-control-erased') + (className ? ' ' + className : ''); const nofocus = focusable ? undefined : true; - console.log('ICON', Icon); - console.log('LABEL', LABEL); return ( <button type='button' className={theClass} diff --git a/ivette/src/dome/src/renderer/data/states.ts b/ivette/src/dome/src/renderer/data/states.ts index 5fbf00dc837..73c8d4e8475 100644 --- a/ivette/src/dome/src/renderer/data/states.ts +++ b/ivette/src/dome/src/renderer/data/states.ts @@ -200,7 +200,7 @@ abstract class Settings<A> { abstract saveData(key: string, data: JSON.json): void; /** @internal */ - abstract event: symbol; + abstract event: string; /** Returns the current setting value for the provided data key. You shall only use validated keys otherwise you might fallback to default values. */ @@ -273,7 +273,7 @@ export class WindowSettingsData<A> extends Settings<A> { super(role, decoder, encoder, fallback); } - event = Symbol('dome.settings'); + event = 'dome.defaults'; loadData(key: string) { return Dome.getWindowSetting(key) as JSON.json; } saveData(key: string, data: JSON.json) { Dome.setWindowSetting(key, data); } @@ -293,7 +293,7 @@ export class GlobalSettingsData<A> extends Settings<A> { super(role, decoder, encoder, fallback); } - event = Symbol('dome.globals'); + event = 'dome.settings'; loadData(key: string) { return Dome.getGlobalSetting(key) as JSON.json; } saveData(key: string, data: JSON.json) { Dome.setGlobalSetting(key, data); } diff --git a/ivette/src/dome/src/renderer/dome.js b/ivette/src/dome/src/renderer/dome.js index 8b24c8deda9..a87d7c78f66 100644 --- a/ivette/src/dome/src/renderer/dome.js +++ b/ivette/src/dome/src/renderer/dome.js @@ -148,10 +148,6 @@ ipcRenderer.on('dome.ipc.command', (_event,argv,wdir) => { emitter.emit('dome.command',argv,wdir); }); -// -------------------------------------------------------------------------- -// --- Main-Process Communication -// -------------------------------------------------------------------------- - // -------------------------------------------------------------------------- // --- Window Management // -------------------------------------------------------------------------- @@ -395,55 +391,69 @@ export function popupMenu( items, callback ) // --- Settings // -------------------------------------------------------------------------- -var globals = {} ; -var globalPatches = {} ; +var globalSettings = new Map(); +var globalPatches = new Map(); -var settings = {} ; -var settingsPatches = {} ; +var windowSettings = new Map(); +var windowPatches = new Map(); + +const initSetting = + (m, data) => _.forEach(data,(value,key) => m.set(key,value)); // initial values => synchronized event -function syncSettings() { +const syncSettings = () => { const fullSettings = ipcRenderer.sendSync('dome.ipc.settings.sync'); - globals = fullSettings.globals ; - settings = fullSettings.settings ; -} + initSetting( globalSettings, fullSettings.globals ); + initSetting( windowSettings, fullSettings.settings ); +}; const readSetting = ( local, key, defaultValue ) => { - const value = _.get( local ? settings : globals , key ); + const store = local ? windowSettings : globalSettings; + const value = store.get(key); return value === undefined ? defaultValue : value ; }; const writeSetting = ( local, key, value ) => { - if (key) { - const theValue = value===undefined ? null : value ; - const store = local ? settings : globals ; - const patches = local ? settingsPatches : globalPatches ; - _.set( store, key, theValue ); - _.set( patches, key, theValue ); + const store = local ? windowSettings : globalSettings; + const patches = local ? windowPatches : globalPatches; + if (value === undefined) { + store.delete(key); + patches.set(key,null); + } else { + store.set(key,value); + patches.set(key,value); + } + if (local) { + if (DEVEL) fireSaveSettings(); + } else { emitter.emit('dome.settings'); - if (local) { - if (DEVEL) fireSaveSettings(); - } else { - fireSaveGlobals(); - } + fireSaveGlobals(); } }; +const flushPatches = (m) => { + if (m.size > 0) { + const args = []; + m.forEach((value,key) => { + args.push({ key, value }); + }); + m.clear(); + return args; + } + return undefined; +}; + const fireSaveSettings = _.debounce( () => { - if (!_.isEmpty(settingsPatches)) { - ipcRenderer.send( 'dome.ipc.settings.window', settingsPatches ) ; - settingsPatches = {} ; - } + const args = flushPatches(windowPatches); + args && ipcRenderer.send( 'dome.ipc.settings.window', args ) ; }, 100 ); const fireSaveGlobals = _.debounce( () => { - if (!_.isEmpty(globalPatches)) { - ipcRenderer.send( 'dome.ipc.settings.global', globalPatches ) ; - globalPatches = {} ; - } + const args = flushPatches(globalPatches); + args && ipcRenderer.send( 'dome.ipc.settings.global', args ) ; }, 100 ); @@ -456,25 +466,32 @@ ipcRenderer.on('dome.ipc.closing', (_evt) => { }); /** @event 'dome.settings' - @description Emitted when the settings have been updated. */ + @description Emitted when the global settings have been updated. */ /** @event 'dome.defaults' - @description Emitted when the settings have been reset to default. */ + @description Emitted when the window settings have re-initialized. */ ipcRenderer.on('dome.ipc.settings.defaults',(sender) => { fireSaveSettings.cancel(); fireSaveGlobals.cancel(); - settingsPatches = {}; - globalPatches = {}; - settings = {}; - globals = {}; - emitter.emit('dome.defaults'); + windowPatches.clear(); + globalPatches.clear(); + windowSettings.clear(); + globalSettings.clear(); emitter.emit('dome.settings'); + emitter.emit('dome.defaults'); }); ipcRenderer.on('dome.ipc.settings.update',(sender,patches) => { - // Don't cancel local updates - _.merge( globals , patches , globalPatches ); + patches.forEach(({ key, value }) => { + // Don't cancel local updates + if (!globalPatches.has(key)) { + if (value === null) + globalSettings.delete(key); + else + globalSettings.set(key,value); + } + }); emitter.emit('dome.settings'); }); @@ -524,7 +541,8 @@ export function getGlobalSetting( key, defaultValue ) { @description These settings are global to the current window, but persistently saved in the user's home directory. Updated values are broadcasted - in batch to all other windows, which in turn receive a `'dome.settings'` + in batch to all other windows, + which in turn receive a `'dome.settings'` event for synchronizing.<br/> For local window settings, use `set()` instead. */ @@ -684,25 +702,21 @@ export function useCommand() { function useSettings( local, settings, defaultValue ) { - const [ value, setValue ] = React.useState(() => readSetting( local, settings, defaultValue )); + const [ value, setValue ] = + React.useState(() => readSetting( local, settings, defaultValue )); React.useEffect(() => { - if (settings) { - let callback = () => { - let v = readSetting( local, settings , defaultValue ); - setValue(v); - }; - emitter.on('dome.settings',callback); - return () => emitter.off( 'dome.settings', callback ); - } else { - let callback = () => setValue(defaultValue); - emitter.on('dome.defaults',callback); - return () => emitter.off( 'dome.defaults', callback ); - } + let callback = () => { + let v = readSetting( local, settings , defaultValue ); + setValue(v); + }; + const event = local ? 'dome.defaults' : 'dome.settings' ; + emitter.on(event,callback); + return () => emitter.off(event, callback); }); const doUpdate = (upd) => { const theValue = typeof(upd)==='function' ? upd(value) : upd ; if (settings) writeSetting( local, settings, theValue ); - else setValue(theValue); + if (local) setValue(theValue); }; return [ value, doUpdate ]; } @@ -715,8 +729,7 @@ function useSettings( local, settings, defaultValue ) @description Similar to `React.useState()` with persistent _window_ settings. When the settings key is undefined, it simply uses a local React state. - Also responds to `'dome.settings'` to update the state and `'dome.defaults'` - to restore the default value. + Also responds to `'dome.defaults'`. The `setValue` callback accepts either a value, or a function to be applied on current value. @@ -750,8 +763,7 @@ export function useSwitch( settings, defaultValue=false ) @description Similar to `React.useState()` with persistent _global_ settings. When the settings key is undefined, it simply uses a local React state. - Also responds to `'dome.settings'` to update the state and `'dome.defaults'` - to restore the default value. + Also responds to `'dome.settings'` to update the state. The `setValue` callback accepts either a value, or a function to be applied on current value. diff --git a/ivette/src/dome/src/renderer/frame/sidebars.js b/ivette/src/dome/src/renderer/frame/sidebars.js index e8c5da03242..6a9f76d2cc8 100644 --- a/ivette/src/dome/src/renderer/frame/sidebars.js +++ b/ivette/src/dome/src/renderer/frame/sidebars.js @@ -108,7 +108,7 @@ export function Section(props) { const context = React.useContext( SideBarContext ); const [ state=true, setState ] = Dome.useState( - makeSettings(context,props), + makeSettings(context.settings,props), props.defaultUnfold ); const { enabled=true, disabled=false, unfold, children } = props ; diff --git a/ivette/src/frama-c/LabViews.tsx b/ivette/src/frama-c/LabViews.tsx index d41a4bc67b3..52bc3151cac 100644 --- a/ivette/src/frama-c/LabViews.tsx +++ b/ivette/src/frama-c/LabViews.tsx @@ -355,7 +355,6 @@ function CustomViews({ settings, shape, setShape, views: libViews }: any) { const [edited, setEdited]: any = React.useState(); const triggerDefault = React.useRef(); const { current, shapes = {} } = local; - const theViews: any = {}; _.forEach(libViews, (view) => { -- GitLab