Alex A. Naanou 35a7a16539 moved to new store for config...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2018-02-14 16:49:44 +03:00

380 lines
9.5 KiB
JavaScript
Executable File

/**********************************************************************
*
* Features:
* - config
* general config API
* - localstorage-config
* maintain configuration state in localStorage
* - fs-config
* maintain configuration state in file system
*
* XXX this module need refactoring...
*
*
**********************************************************************/
((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define)
(function(require){ var module={} // make module AMD/node compatible...
/*********************************************************************/
var toggler = require('lib/toggler')
var actions = require('lib/actions')
var features = require('lib/features')
var core = require('features/core')
/*********************************************************************/
// XXX might be a good idea to add a .configLoaded(..) and .configChanged(..)
// events thought it's not clear how are we going to track changes...
var ConfigStoreActions = actions.Actions({
config: {
// XXX should this include path???
// ...there should be modes:
// - 'read-only' -- don't save...
// - 'portable' -- use APP dir
// - 'normal' -- use $HOME
'config-fs-filename': '.ImageGrid.json',
'config-auto-save-interval': 1000*5,
},
__base_config: null,
// XXX
storeConfig: ['File/Store configuration',
function(key){
// XXX
}],
// XXX
loadConfig: ['File/Load stored configuration',
function(key){
// XXX
}],
// XXX should this also reload???
resetConfig: ['- Config/',
function(){
var base = this.__base_config = this.__base_config || this.config
this.config = Object.create(base)
}],
// XXX use timer events... (???)
// XXX this needs a working .storeConfig(..)
toggleAutoStoreConfig: ['File/Store configuration',
toggler.Toggler(null,
function(_, state){
var timer = 'config-auto-save-timer'
if(state == null){
return this.isPersistentInterval(timer) || 'none'
} else {
var that = this
var interval = this.config['config-auto-save-interval']
// no timer interval set...
if(!interval){
return false
}
// start/restart...
if(state == 'running' && interval){
this.setPersistentInterval(timer, 'storeConfig', interval*1000)
// stop...
} else {
this.clearPersistentInterval(timer)
}
}
},
'running')],
})
var ConfigStore =
module.ConfigStore = core.ImageGridFeatures.Feature({
title: '',
doc: '',
tag: 'store-config',
priority: 80,
depends: [
'timers',
'store-localstorage',
],
suggested: [
'store-fs-json-sync',
],
actions: ConfigStoreActions,
handlers: [
['prepareStoreToSave',
function(res){
// localStorage...
// NOTE: we do not need to clone anything here as this
// will be done by the localStorage handler...
res.store.localStorage.config = this.config
// XXX sync fs store...
// XXX get better tag...
if(res.store.fsJSONSync){
// XXX should this include path???
res.store.fsJSONSync[this.config['config-fs-filename'] || '.ImageGrid.json'] = this.config
}
}],
// NOTE: this is sync for sync stores...
['storeDataLoaded',
function(store){
if((store.localStorage || {}).config){
console.log('--- PRE LOAD CONFIG (test)')
var base = this.__base_config = this.__base_config || this.config
var config = store.localStorage.config || {}
config.__proto__ = base
this.config = config
}
// XXX sync fs store...
// XXX get better tag...
// XXX where do we write???
if((store.fsJSONSync || {}).config){
// XXX
}
// auto-start auto-save...
this.config['config-auto-save-interval'] > 0
&& this.toggleAutoStoreConfig('?') == 'off'
&& this.toggleAutoStoreConfig()
}],
],
})
/*********************************************************************/
/*/ XXX LEGACY...
//
// XXX might be a good idea to add an external payload mechanism for
// other data to be saved to avoid re-implementing the same logic
// ...like is done in features/history.js
var ConfigActions = actions.Actions({
config: {
'config-store-key': 'config',
// NOTE: this is in seconds...
// NOTE: if this is null or 0 the timer will not start...
'config-auto-save-interval': 3*60,
},
// XXX should we store this in something like .default_config and
// clone it???
// ...do not think so, as the __base_config should always be set
// to the values set in code... (check this!)
__base_config: null,
__config_loaded: null,
__auto_save_config_timer: null,
// Disable localStorage in child, preventing two viewers from messing
// things up in one store...
clone: [function(){
return function(res){
res.config['config-store-key'] = null
}
}],
// XXX make this a protocol to support multiple sources...
// ...load only one, by priority/order
// might be good to make this similar to collections loading...
storeConfig: ['File/Store configuration',
function(key){
// XXX
}],
loadConfig: ['File/Load stored configuration',
function(key){
// XXX
}],
// XXX need to load the reset config, and not just set it...
resetConfig: ['File/Reset settings',
function(){
this.config = this.__base_config || this.config
}],
toggleAutoStoreConfig: ['File/Store configuration',
toggler.Toggler(null,
function(_, state){
if(state == null){
return this.__auto_save_config_timer || 'none'
} else {
var that = this
var interval = this.config['config-auto-save-interval']
// no timer interval set...
if(!interval){
return false
}
// this cleans up before 'on' and fully handles 'off' action...
if(this.__auto_save_config_timer != null){
clearTimeout(this.__auto_save_config_timer)
delete this.__auto_save_config_timer
}
if(state == 'running'
&& interval
&& this.__auto_save_config_timer == null){
var runner = function(){
clearTimeout(that.__auto_save_config_timer)
//that.logger && that.logger.emit('config', 'saving to local storage...')
that.storeConfig()
var interval = that.config['config-auto-save-interval']
if(!interval){
delete that.__auto_save_config_timer
return
}
interval *= 1000
that.__auto_save_config_timer = setTimeout(runner, interval)
}
runner()
}
}
},
'running')],
})
var Config =
module.Config = core.ImageGridFeatures.Feature({
title: '',
doc: '',
tag: 'config',
depends: [
'store',
],
priority: 80,
suggested: [
'localstorage-config',
'fs-config',
],
actions: ConfigActions,
handlers: [
// NOTE: considering that allot depends on this it must be
// first to run...
['start.pre',
function(){
console.log('--- PRE LOAD CONFIG')
this.logger && this.logger
.push('Startup')
.emit('loaded', 'config')
this
.loadConfig()
.toggleAutoStoreConfig('on')
}],
['stop.pre',
function(){
this.logger && this.logger
.push('Shutdown')
.emit('stored', 'config')
this
.storeConfig()
.toggleAutoStoreConfig('off')
}],
],
})
//---------------------------------------------------------------------
var ConfigLocalStorageActions = actions.Actions({
config: {
// XXX not sure what should be the default...
'config-local-storage-save-diff': true,
},
storeConfig: ['File/Store configuration',
function(key){
var key = key || this.config['config-store-key']
if(key != null){
// build a diff...
if(this.config['config-local-storage-save-diff']){
var base = this.__base_config || {}
var cur = this.config
var config = {}
Object.keys(cur)
.forEach(function(e){
if(cur.hasOwnProperty(e)
&& base[e] != cur[e]
// NOTE: this may go wrong for objects
// if key order is different...
// ...this is no big deal as false
// positives are not lost data...
|| JSON.stringify(base[e]) != JSON.stringify(cur[e])){
config[e] = cur[e]
}
})
// full save...
} else {
var config = this.config
}
// store...
localStorage[key] = JSON.stringify(config)
}
}],
loadConfig: ['File/Load stored configuration',
function(key){
key = key || this.config['config-store-key']
if(key && localStorage[key]){
// get the original (default) config and keep it for
// reference...
// NOTE: this is here so as to avoid creating 'endless'
// config inheritance chains...
base = this.__base_config = this.__base_config || this.config
var loaded = JSON.parse(localStorage[key])
loaded.__proto__ = base
this.config = loaded
}
}],
})
var ConfigLocalStorage =
module.ConfigLocalStorage = core.ImageGridFeatures.Feature({
title: '',
doc: '',
// XXX rename???
tag: 'localstorage-config',
depends: [
'config',
'ui',
],
priority: 80,
isApplicable: function(){
return typeof(localStorage) != 'undefined'
&& localStorage != null },
actions: ConfigLocalStorageActions,
})
//*/
/**********************************************************************
* vim:set ts=4 sw=4 : */ return module })