| 
									
										
										
										
											2018-01-17 06:28:09 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * 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...
 | 
					
						
							| 
									
										
										
										
											2018-01-18 05:04:42 +03:00
										 |  |  | // XXX comment support in json (preferably both reading and writing...)
 | 
					
						
							| 
									
										
										
										
											2018-01-17 06:28:09 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 03:24:19 +03:00
										 |  |  | var ConfigFSActions = actions.Actions({ | 
					
						
							| 
									
										
										
										
											2018-01-17 06:28:09 +03:00
										 |  |  | 	config: { | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 03:24:19 +03:00
										 |  |  | var ConfigFS =  | 
					
						
							|  |  |  | module.ConfigFS = core.ImageGridFeatures.Feature({ | 
					
						
							| 
									
										
										
										
											2018-01-17 06:28:09 +03:00
										 |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'fs-config', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							| 
									
										
										
										
											2018-01-28 03:24:19 +03:00
										 |  |  | 		'localstorage-config', | 
					
						
							| 
									
										
										
										
											2018-01-17 06:28:09 +03:00
										 |  |  | 		'fs', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-28 03:24:19 +03:00
										 |  |  | 	actions: ConfigFSActions, | 
					
						
							| 
									
										
										
										
											2018-01-17 06:28:09 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	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 }) |