mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-11-03 04:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			250 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			6.6 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 "sandbox" mode -- i.e. all settings 
 | 
						|
// 		are saved to sessionStorage and a re-open will load the old settings...
 | 
						|
// 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,
 | 
						|
 | 
						|
		'config-load-sequence': [
 | 
						|
			// localStorage...
 | 
						|
			'storage:${INSTANCE}/config',
 | 
						|
 | 
						|
			// FS...
 | 
						|
			// XXX should we load both or just one???
 | 
						|
			'fileSync:${APP}/.ImageGrid.json',
 | 
						|
			'fileSync:${HOME}/.ImageGrid.json',
 | 
						|
 | 
						|
			// temporary config...
 | 
						|
			// NOTE: this is active until we re-open the app...
 | 
						|
			'session:${INSTANCE}/config',
 | 
						|
		],
 | 
						|
	},
 | 
						|
 | 
						|
	__config_base: null,
 | 
						|
	__config_loaded_from: null,
 | 
						|
 | 
						|
	// XXX handle save order -- need to save to one location only...
 | 
						|
	// 		...use: .__config_loaded_from in reverse order (stop on session:..)
 | 
						|
	// XXX keep record of what we loaded...
 | 
						|
	// XXX should we only support sync stores??? (current state)
 | 
						|
	loadConfig: ['File/Load configuration',
 | 
						|
		core.doc`
 | 
						|
 | 
						|
		NOTE: might need to reload after this.
 | 
						|
		`,
 | 
						|
		function(query){
 | 
						|
			// store loaded...
 | 
						|
			var loaded = this.__config_loaded_from = []
 | 
						|
 | 
						|
			this.resetConfig()
 | 
						|
 | 
						|
			// do the load...
 | 
						|
			;(query ? 
 | 
						|
					(query instanceof Array ? query : [query])
 | 
						|
					: (this.config['config-load-sequence'] || ['storage:config']))
 | 
						|
				.forEach(function(query){
 | 
						|
					query = this.parseStoreQuery(query)
 | 
						|
					var cfg = this.loadStore(query)
 | 
						|
 | 
						|
					// select store...
 | 
						|
					cfg = query.store
 | 
						|
						.map(function(store){ return cfg[store] })
 | 
						|
						.filter(function(cfg){ return Object.keys(cfg).length > 0 })
 | 
						|
						.shift() || {}
 | 
						|
					// select key...
 | 
						|
					cfg = query.key
 | 
						|
						.map(function(key){ return cfg[key] })
 | 
						|
						.filter(function(cfg){ return !!cfg })
 | 
						|
						.shift()
 | 
						|
 | 
						|
					// merge the config...
 | 
						|
					cfg 
 | 
						|
						&& Object.assign(this.config, cfg)
 | 
						|
						&& loaded.push(query.query)
 | 
						|
				}.bind(this))
 | 
						|
		}],
 | 
						|
	storeConfig: ['File/Save configuration',
 | 
						|
		function(query){
 | 
						|
			// XXX
 | 
						|
			this.saveStore(query || 'storage:${INSTANCE}/config') 
 | 
						|
		}],
 | 
						|
	// XXX this needs to be confirmed...
 | 
						|
	resetConfig: ['File/Reset configuration',
 | 
						|
		core.doc`
 | 
						|
 | 
						|
		NOTE: might need to reload after this.
 | 
						|
		`,
 | 
						|
		function(){
 | 
						|
			var base = this.__config_base = this.__config_base || this.config
 | 
						|
			this.config = Object.create(base)
 | 
						|
		}],
 | 
						|
 | 
						|
	// XXX use timer events... (???)
 | 
						|
	toggleConfigAutoStore: ['File/Auto-save 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')],
 | 
						|
	
 | 
						|
 | 
						|
	// XXX does not work yet... 
 | 
						|
	toggleConfigSandbox: ['- File/',
 | 
						|
		toggler.Toggler(null, 
 | 
						|
			function(_, state){ 
 | 
						|
 | 
						|
				if(state == null){
 | 
						|
					return Object.keys(this.store('session:${INSTANCE}/config').session).length > 0 || 'none'
 | 
						|
 | 
						|
				} else if(state == 'sandboxed'){
 | 
						|
					this.store('session:${INSTANCE}/config', undefined)
 | 
						|
 | 
						|
				} else {
 | 
						|
					this.storeConfig('session:${INSTANCE}/config')
 | 
						|
				}
 | 
						|
			},
 | 
						|
			'sandboxed')],
 | 
						|
})
 | 
						|
 | 
						|
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: [
 | 
						|
		// XXX need to update rather than rewrite things...
 | 
						|
		['prepareStoreToSave', 
 | 
						|
			function(res, query, data){
 | 
						|
				var ls_path = '${INSTANCE}/config'
 | 
						|
				//var ls_path = 'config'
 | 
						|
				query = this.parseStoreQuery(query)
 | 
						|
				
 | 
						|
				// config not requested...
 | 
						|
				if(query.key != '*' 
 | 
						|
						&& query.key.indexOf('config')
 | 
						|
						&& query.key.indexOf(ls_path)){
 | 
						|
					return
 | 
						|
				}
 | 
						|
 | 
						|
				// localStorage...
 | 
						|
				// NOTE: we do not need to clone anything here as this 
 | 
						|
				// 		will be done by the localStorage handler...
 | 
						|
				if(query.store.indexOf('storage') >= 0){
 | 
						|
					//res.data.storage[ls_path] = this.config
 | 
						|
					res.data.storage[ls_path] = data || this.config
 | 
						|
				}
 | 
						|
 | 
						|
				if(query.store.indexOf('fileSync') >= 0){
 | 
						|
					// XXX should this include path???
 | 
						|
					//res.data.fileSync[this.config['config-fs-filename'] || '.ImageGrid.json'] = this.config
 | 
						|
					res.data.fileSync[this.config['config-fs-filename'] || '.ImageGrid.json'] = data || this.config
 | 
						|
				}
 | 
						|
			}],
 | 
						|
		//['prepareIndexForLoad',
 | 
						|
		//	function(){
 | 
						|
		//	}],
 | 
						|
		// NOTE: this is sync for sync stores...
 | 
						|
		['storeDataLoaded',
 | 
						|
			function(_, store, data){
 | 
						|
				var base = this.__config_base = this.__config_base || this.config
 | 
						|
				var ls_path = '${INSTANCE}/config'
 | 
						|
 | 
						|
				// XXX sort out load priority/logic...
 | 
						|
				// 		- one or the other or both?
 | 
						|
				// 		- what order?
 | 
						|
 | 
						|
				if((data.storage || {})[ls_path]){
 | 
						|
					var config = data.storage[ls_path] || {}
 | 
						|
					config.__proto__ = base
 | 
						|
					this.config = config
 | 
						|
				}
 | 
						|
 | 
						|
				if((data.fsJSONSync || {}).config){
 | 
						|
					var config = data.fsJSONSync.config || {}
 | 
						|
					config.__proto__ = base
 | 
						|
					this.config = config
 | 
						|
				}
 | 
						|
 | 
						|
				// auto-start auto-save...
 | 
						|
				this.config['config-auto-save-interval'] > 0 
 | 
						|
					&& this.toggleConfigAutoStore('?') == 'off'
 | 
						|
					&& this.toggleConfigAutoStore()
 | 
						|
			}],
 | 
						|
	],
 | 
						|
})
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
* vim:set ts=4 sw=4 :                               */ return module })
 |