mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 02:10:08 +00:00
started refactoring config API...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
9fdd3d373e
commit
1f8723a0b7
@ -17,6 +17,7 @@ require('features/tags')
|
||||
require('features/marks')
|
||||
require('features/location')
|
||||
require('features/recover')
|
||||
require('features/config')
|
||||
require('features/history')
|
||||
require('features/app')
|
||||
require('features/peer')
|
||||
|
||||
293
ui (gen4)/features/config.js
Executable file
293
ui (gen4)/features/config.js
Executable file
@ -0,0 +1,293 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
* 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 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: [
|
||||
],
|
||||
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(){
|
||||
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,
|
||||
})
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// XXX store config locations:
|
||||
// - app
|
||||
// - home
|
||||
// XXX config override location/filename to support portable apps...
|
||||
|
||||
var ConfigFS = actions.Actions({
|
||||
config: {
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
|
||||
var ConfigLocalStorage =
|
||||
module.ConfigLocalStorage = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'fs-config',
|
||||
depends: [
|
||||
'config-local-storage',
|
||||
'fs',
|
||||
],
|
||||
|
||||
actions: ConfigFS,
|
||||
|
||||
handlers: [
|
||||
// NOTE: considering that allot depends on this it must be
|
||||
// first to run...
|
||||
['loadConfig',
|
||||
function(){
|
||||
}],
|
||||
['storeConfig',
|
||||
function(){
|
||||
}],
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* vim:set ts=4 sw=4 : */ return module })
|
||||
@ -135,7 +135,7 @@ core.ImageGridFeatures.Feature('imagegrid-testing', [
|
||||
// ...this is best included by direct feature dependency.
|
||||
'index-format',
|
||||
|
||||
'config-local-storage',
|
||||
'config',
|
||||
'ui-url-hash',
|
||||
|
||||
'fail-safe-devtools',
|
||||
|
||||
@ -5,8 +5,6 @@
|
||||
* Features:
|
||||
* - ui
|
||||
* implements basic ui actions...
|
||||
* - config-local-storage
|
||||
* maintain configuration state in local storage
|
||||
* - ui-url-hash
|
||||
* handle .location.hash
|
||||
* - ui-cursor
|
||||
@ -785,182 +783,6 @@ module.Viewer = core.ImageGridFeatures.Feature({
|
||||
/*********************************************************************/
|
||||
// Utilities and Services...
|
||||
|
||||
var ConfigLocalStorageActions = actions.Actions({
|
||||
config: {
|
||||
'config-local-storage-key': 'config',
|
||||
|
||||
// NOTE: this is in seconds...
|
||||
// NOTE: if this is null or 0 the timer will not start...
|
||||
'config-auto-save-local-storage-interval': 3*60,
|
||||
|
||||
// XXX not sure what should be the default...
|
||||
'config-local-storage-save-diff': true,
|
||||
},
|
||||
|
||||
// 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-local-storage-key'] = null
|
||||
}
|
||||
}],
|
||||
|
||||
storeConfig: ['File/Store configuration',
|
||||
function(key){
|
||||
var key = key || this.config['config-local-storage-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)
|
||||
}
|
||||
}],
|
||||
loadStoredConfig: ['File/Load stored configuration',
|
||||
function(key){
|
||||
key = key || this.config['config-local-storage-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
|
||||
}
|
||||
}],
|
||||
// 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-local-storage-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-local-storage-interval']
|
||||
if(!interval){
|
||||
delete that.__auto_save_config_timer
|
||||
return
|
||||
}
|
||||
interval *= 1000
|
||||
|
||||
that.__auto_save_config_timer = setTimeout(runner, interval)
|
||||
}
|
||||
|
||||
runner()
|
||||
}
|
||||
}
|
||||
},
|
||||
'running')],
|
||||
})
|
||||
|
||||
var ConfigLocalStorage =
|
||||
module.ConfigLocalStorage = core.ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'config-local-storage',
|
||||
depends: [
|
||||
'ui',
|
||||
],
|
||||
priority: 80,
|
||||
|
||||
isApplicable: function(){
|
||||
return typeof(localStorage) != 'undefined'
|
||||
&& localStorage != null },
|
||||
|
||||
actions: ConfigLocalStorageActions,
|
||||
|
||||
handlers: [
|
||||
// NOTE: considering that allot depends on this it must be
|
||||
// first to run...
|
||||
['start.pre',
|
||||
function(){
|
||||
this.logger && this.logger
|
||||
.push('Startup')
|
||||
.emit('loaded', 'config')
|
||||
this
|
||||
.loadStoredConfig()
|
||||
.toggleAutoStoreConfig('on')
|
||||
}],
|
||||
['stop.pre',
|
||||
function(){
|
||||
this.logger && this.logger
|
||||
.push('Shutdown')
|
||||
.emit('stored', 'config')
|
||||
this
|
||||
.storeConfig()
|
||||
.toggleAutoStoreConfig('off')
|
||||
}],
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// XXX make this work for external links in a stable manner...
|
||||
// ...a bit unpredictable when working in combination with history
|
||||
// feature -- need to stop them from competing...
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user