Skip to content
Snippets Groups Projects
Commit ecc4f3d1 authored by Loïc Correnson's avatar Loïc Correnson
Browse files

[ivette/states] sync state & value hooks

parent 95df169f
No related branches found
No related tags found
No related merge requests found
...@@ -30,7 +30,7 @@ export const PROJECT = 'frama-c.project' ; ...@@ -30,7 +30,7 @@ export const PROJECT = 'frama-c.project' ;
@summary State Notification Events. @summary State Notification Events.
@description @description
Event `'frama-c.state.<id>'` for project `<id>`. Event `'frama-c.state.<id>'` for project `<id>`.
The prefix `'frama-c-state.'` is exported as `States.STATE` in public API. The prefix `'frama-c.state.'` is exported as `States.STATE` in public API.
*/ */
export const STATE = 'frama-c.state.' ; export const STATE = 'frama-c.state.' ;
...@@ -39,6 +39,8 @@ export const STATE = 'frama-c.state.' ; ...@@ -39,6 +39,8 @@ export const STATE = 'frama-c.state.' ;
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
var currentProject = undefined ; var currentProject = undefined ;
var globalStates = {} ;
var globalSync = {} ;
Server.onReady(() => { Server.onReady(() => {
Server.sendGET('kernel.project.getCurrent') Server.sendGET('kernel.project.getCurrent')
...@@ -51,6 +53,7 @@ Server.onReady(() => { ...@@ -51,6 +53,7 @@ Server.onReady(() => {
Server.onShutdown(() => { Server.onShutdown(() => {
currentProject = undefined ; currentProject = undefined ;
globalStates = {} ; globalStates = {} ;
globalSync = {} ;
Dome.emit(PROJECT); Dome.emit(PROJECT);
}); });
...@@ -77,36 +80,32 @@ export function useProject() ...@@ -77,36 +80,32 @@ export function useProject()
*/ */
export function setProject(project) export function setProject(project)
{ {
Server.sendSET( 'kernel.project.setCurrent' , project ); if (Server.isRunning()) {
currentProject = project ; Server.sendSET( 'kernel.project.setCurrent' , project );
Dome.emit(PROJECT); currentProject = project ;
} Dome.emit(PROJECT);
}
/**
@summary Clear Project Cache.
@param {string} [project] - the project identifier, defaults to current
@description
Remove all projectified values for the specified project
Emits `PROJECT`.
*/
export function clearCache(project)
{
const theProject = project || currentProject ;
if (theProject)
_.unset( globalStates , [theProject] );
Dome.emit(PROJECT);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// --- Projectified State // --- Projectified State
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
var globalStates = {} ; function getValue(id,project) {
if (!project) return undefined;
return _.get( globalStates, [project,id] );
}
function setValue(id,project,value) {
const theProject = project || currentProject ;
if (!theProject) return ;
_.set( globalStates, [project,id], value );
Dome.emit( STATE + id , value );
}
/** /**
@summary Projectified State (Custom React Hook). @summary Projectified State (Custom React Hook).
@param {string} id - the state identifier (mandatory) @param {string} id - the state identifier (mandatory)
@param {string} [project] - the project identifier, defaults to current
@return {array} `[state,setState]` for the specified project @return {array} `[state,setState]` for the specified project
@description @description
Returns a getter and a setter for the specified state Returns a getter and a setter for the specified state
...@@ -116,23 +115,112 @@ var globalStates = {} ; ...@@ -116,23 +115,112 @@ var globalStates = {} ;
Each state is associated to a specific event `frama-c-state.<id>` which is Each state is associated to a specific event `frama-c-state.<id>` which is
is used to notify updates. The hook also updates on `PROJECT` notifications. is used to notify updates. The hook also updates on `PROJECT` notifications.
*/ */
export function useState(id,project) export function useState(id)
{ {
const theEvent = STATE + id ; Dome.useUpdate( PROJECT, STATE + id );
Dome.useUpdate( PROJECT, theEvent ); const project = currentProject ;
const theProject = project || currentProject ; const value = getValue(id,project);
if (!theProject) return NONE; return [ value , (v) => setValue(id,project,v) ];
const thePath = [theProject,id] ; }
const theValue = _.get( globalStates, thePath );
const setValue = (v) => { // --------------------------------------------------------------------------
_.set( globalStates, thePath, v ); // --- Synchronized States
Dome.emit(theEvent,v); // --------------------------------------------------------------------------
};
return [ theValue, setValue ]; class Synchro {
constructor(id) {
this.id = id ;
this.UPDATE = STATE + id ;
this.signal = id + '.sig' ;
this.get_rq = id + '.get' ;
this.set_rq = id + '.set' ;
this.insync = false ;
this.value = undefined ;
this.update = this.update.bind(this);
this.effect = this.effect.bind(this);
this.setValue = this.setValue.bind(this);
Dome.on( PROJECT , this.update );
}
value() {
if (!this.insync && Server.isRunning())
this.update();
return this.value ;
}
setValue(v) {
this.insync = true ;
this.value = v ;
Server.sendSET( this.set_rq , v );
Dome.emit( this.UPDATE );
}
update() {
const project = currentProject ;
this.insync = true ;
Server.sendGET( this.get_rq ).then((v) => {
this.value = v ;
Dome.emit( this.UPDATE );
});
}
}
const synchros = {} ;
function synchro(id) {
let s = synchros[id] ;
if (!s) s = synchros[id] = new Synchro(id);
return s ;
}
Server.onReady(() => _.forEach( synchros , (s) => {
if (!s.insync) s.update();
}));
/**
@summary Use Synchronized State (Custom React Hook).
@parameter {string} id - name of the server state
@return {Array} `[ value , setValue ]` of the synchronized state
@description
Synchronization with some (projectified) server state:
- sends a `<id>.get` request to obtain the current value of the state;
- sends a `<id>.set` request to update the value of the state;
- listens to `<id>.sig` signal to stay in sync with server updates.
*/
export function useSyncState(id)
{
let s = synchro(id) ;
Dome.useUpdate( s.UPDATE );
Server.useSignal( s.signal , s.update );
return [ s.value() , s.setValue ];
}
/**
@summary Use Synchronized Value (Custom React Hook).
@parameter {string} id - name of the server state
@return {any} current `value` of the state
@description
Synchronization with some (projectified) server value:
- sends a `<id>.get` request to obtain the current value of the state;
- listens to `<id>.sig` signal to stay in sync with server updates.
*/
export function useSyncValue(id)
{
let s = synchro(id) ;
Dome.useUpdate( s.update );
React.useEffect( s.effect );
return s.value();
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
export default { useProject, setProject, useState, PROJECT }; export default {
useProject, setProject,
useState,
useSyncState,
useSyncValue,
PROJECT, STATE
};
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment