mirror of
				https://github.com/flynx/ImageGrid.git
				synced 2025-10-31 03:10:07 +00:00 
			
		
		
		
	reworked localStorage/sessionStorage store backend, still not content with the HL API...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
		
							parent
							
								
									dacdb01bbe
								
							
						
					
					
						commit
						2f14d723b2
					
				| @ -113,8 +113,8 @@ module.ConfigStore = core.ImageGridFeatures.Feature({ | ||||
| 		// XXX need to update rather than rewrite things...
 | ||||
| 		['prepareStoreToSave',  | ||||
| 			function(res){ | ||||
| 				//var ls_path = '/${ROOT_PATH}/config'
 | ||||
| 				var ls_path = 'config' | ||||
| 				var ls_path = '${INSTANCE}/config' | ||||
| 				//var ls_path = 'config'
 | ||||
| 
 | ||||
| 				// localStorage...
 | ||||
| 				// NOTE: we do not need to clone anything here as this 
 | ||||
| @ -135,8 +135,7 @@ module.ConfigStore = core.ImageGridFeatures.Feature({ | ||||
| 		['storeDataLoaded', | ||||
| 			function(data){ | ||||
| 				var base = this.__base_config = this.__base_config || this.config | ||||
| 				//var ls_path = '/${ROOT_PATH}/config'
 | ||||
| 				var ls_path = 'config' | ||||
| 				var ls_path = '${INSTANCE}/config' | ||||
| 
 | ||||
| 				// XXX sort out load priority/logic...
 | ||||
| 				// 		- one or the other or both?
 | ||||
|  | ||||
| @ -670,6 +670,8 @@ var CacheActions = actions.Actions({ | ||||
| 		NOTE: both "modes" of doing a pre-cache run in the main thread, | ||||
| 			the difference is that the "async" version lets JS run frames | ||||
| 			between processing sync chunks... | ||||
| 		NOTE: this will not drop the existing cache, to do this run  | ||||
| 			.clearCache() first or run .reCache(..). | ||||
| 		`,
 | ||||
| 		function(t){ | ||||
| 			if(this.config.cache){ | ||||
| @ -719,6 +721,13 @@ var CacheActions = actions.Actions({ | ||||
| 				delete this.__cache | ||||
| 			} | ||||
| 		}], | ||||
| 
 | ||||
| 	// XXX do we need this...
 | ||||
| 	reCache: ['System/Re-cache', | ||||
| 		function(t){ | ||||
| 			this | ||||
| 				.clearCache() | ||||
| 				.preCache(t) }], | ||||
| }) | ||||
| 
 | ||||
| var Cache =  | ||||
|  | ||||
| @ -84,7 +84,7 @@ var StoreActions = actions.Actions({ | ||||
| 		})], | ||||
| 
 | ||||
| 
 | ||||
| 	// XXX do we need to parse date here???
 | ||||
| 	// base API...
 | ||||
| 	parseStoreQuery: ['- Store/', | ||||
| 		core.doc` | ||||
| 
 | ||||
| @ -145,7 +145,6 @@ var StoreActions = actions.Actions({ | ||||
| 			} | ||||
| 		}], | ||||
| 
 | ||||
| 	// base API...
 | ||||
| 	prepareStoreToSave: ['- Store/', | ||||
| 		core.doc` | ||||
| 
 | ||||
| @ -328,140 +327,116 @@ module.Store = core.ImageGridFeatures.Feature({ | ||||
| 
 | ||||
| // NOTE: the doc is reused for both localStorage and sessionStorage with 
 | ||||
| // 		appropriate automated changes...
 | ||||
| // XXX Q: do we save to ROOT_PATH by default???
 | ||||
| var __storageHandler_doc =  | ||||
| 	core.doc`Handle localStorage store data...
 | ||||
| 		 | ||||
| 		Write data to key... | ||||
| 		.localStorageDataHandler(key, data) | ||||
| 		 | ||||
| 		Get data from key... | ||||
| 		.localStorageDataHandler(key) | ||||
| 			-> value | ||||
| 		 | ||||
| 		Remove key... | ||||
| 		.localStorageDataHandler(key, null) | ||||
| 		.localStorageDataHandler([key, ..], null) | ||||
| 		 | ||||
| 
 | ||||
| 		Get localStorage data... | ||||
| 
 | ||||
| 		Get stored keys... | ||||
| 		.localStorageDataHandler('?') | ||||
| 			-> keys | ||||
| 		 | ||||
| 		.localStorageDataHandler() | ||||
| 		.localStorageDataHandler('??') | ||||
| 			-> data | ||||
| 		 | ||||
| 		.localStorageDataHandler([key, ..], '??') | ||||
| 			-> data | ||||
| 
 | ||||
| 		Save data set to localStorage... | ||||
| 		Expand data to store... | ||||
| 		.localStorageDataHandler(data) | ||||
| 			-> this | ||||
| 
 | ||||
| 		Save data to key in localStorage... | ||||
| 		.localStorageDataHandler(data, key) | ||||
| 			-> this | ||||
| 
 | ||||
| 		Delete all data from localStorage... | ||||
| 		 | ||||
| 		Remove all data... | ||||
| 		.localStorageDataHandler(null) | ||||
| 			-> this | ||||
| 
 | ||||
| 
 | ||||
| 	NOTE: load resolves to the same keys as were passed to load, while | ||||
| 		localStorage stores the expanded keys... | ||||
| 			'/$\{ROOT_PATH}/path'  | ||||
| 				--(store)--> this.config['store-root-key'] +'/path' | ||||
| 				--(load)--> '/$\{ROOT_PATH}/path'  | ||||
| 
 | ||||
| 
 | ||||
| 	Root keys of data partially support path syntax: | ||||
| 		'/key' or '../key'		 | ||||
| 			stored in localStorage[key] | ||||
| 		'./key' or 'key' | ||||
| 			stored as-is in localStorage[this.config['store-root-key']] | ||||
| 
 | ||||
| 
 | ||||
| 	Path variables: | ||||
| 		$\{ROOT_PATH}	- resolves to .config['store-root-key'] | ||||
| 							NOTE: './key' and $\{ROOT_PATH}/key are  | ||||
| 								not the same, the former will be stored in: | ||||
| 									localStorage[this.config['store-root-key']][key] | ||||
| 								while the later is stored in: | ||||
| 									localStorage[this.config['store-root-key/' + key] | ||||
| 								XXX not yet sure this is the right way to go... | ||||
| 
 | ||||
| 	HOTE: other path syntax is ignored and the key will be saved as-is. | ||||
| 		 | ||||
| 		 | ||||
| 	NOTE: when handling key expansion the unexpanded key should be used  | ||||
| 		to access data, e.g. if writing '\${INSTANCE}/xyz' the same string | ||||
| 		is returned via .localStorageDataHandler('??') and should be used  | ||||
| 		to get the value, i.e.  | ||||
| 			.localStorageDataHandler('\${INSTANCE}/xyz') | ||||
| 	` | ||||
| function makeStorageHandler(storage, alias){ | ||||
| 	var func = function(data, key){ | ||||
| 		alias = alias || storage | ||||
| function makeStorageHandler(storage){ | ||||
| 	var func = function(a, b){ | ||||
| 		storage = typeof(storage) == typeof('str') ? window[storage] : storage | ||||
| 
 | ||||
| 		var root_pattern = /^(\.\.)?[\\\/]/ | ||||
| 		var root = this.config['store-root-key']  | ||||
| 
 | ||||
| 		var instance = this.config['store-instance-key']  | ||||
| 		var resolvePath = function(p){ | ||||
| 			return p | ||||
| 				.replace('${ROOT_PATH}', root) | ||||
| 				.replace(root_pattern, '') } | ||||
| 
 | ||||
| 		// clear...
 | ||||
| 		if(data === null){ | ||||
| 			// remove specific key...
 | ||||
| 			if(key){ | ||||
| 				var data = func.call(this) | ||||
| 				data[key] = undefined | ||||
| 				func.call(this, data) | ||||
| 
 | ||||
| 			// clear all...
 | ||||
| 			} else { | ||||
| 				var d = storage[root] | ||||
| 				d = d != undefined ? JSON.parse(d) : {} | ||||
| 				;(d.__root_paths__ || []) | ||||
| 					.forEach(function(p){ | ||||
| 						var key = resolvePath(p) | ||||
| 						delete storage[key] }) | ||||
| 				delete storage[root] | ||||
| 			} | ||||
| 
 | ||||
| 		// set...
 | ||||
| 		// NOTE: this will update existing data set...
 | ||||
| 		// NOTE: attrs explicitly set to undefined are removed...
 | ||||
| 		} else if(data){ | ||||
| 			if(key){ | ||||
| 				data = { [key]: data } | ||||
| 			} | ||||
| 
 | ||||
| 			// update existing data...
 | ||||
| 			var old = func.call(this) | ||||
| 			Object.keys(data).forEach(function(k){ | ||||
| 				if(data[k] === undefined){ | ||||
| 					delete old[k] | ||||
| 					delete data[k] | ||||
| 				} | ||||
| 			}) | ||||
| 			data = Object.assign(old, data) | ||||
| 
 | ||||
| 			var root_data = {} | ||||
| 			var root_paths = [] | ||||
| 
 | ||||
| 			// handle root paths...
 | ||||
| 			Object.keys(data) | ||||
| 				.forEach(function(p){ | ||||
| 					if(root_pattern.test(p)){ | ||||
| 						var key = resolvePath(p) | ||||
| 						root_paths.push(p) | ||||
| 						root_data[key] = JSON.stringify(data[p]) | ||||
| 						delete data[p] | ||||
| 					} | ||||
| 				}) | ||||
| 			data.__root_paths__ = root_paths | ||||
| 
 | ||||
| 			storage[root] = JSON.stringify(data) | ||||
| 
 | ||||
| 			// store root stuff...
 | ||||
| 			Object.assign(storage, root_data) | ||||
| 
 | ||||
| 		// get...
 | ||||
| 		} else { | ||||
| 			var d = storage[root] | ||||
| 			d = d != undefined ? JSON.parse(d) : {} | ||||
| 
 | ||||
| 			// load root paths...
 | ||||
| 			;(d.__root_paths__ || []) | ||||
| 				.forEach(function(p){ | ||||
| 					var key = resolvePath(p) | ||||
| 					var o = storage[key] | ||||
| 					o = o != undefined ? JSON.parse(o) : o | ||||
| 
 | ||||
| 					d[p] = o  | ||||
| 				}) | ||||
| 			delete d.__root_paths__ | ||||
| 
 | ||||
| 			return d | ||||
| 				.replace('${INSTANCE}', instance)  | ||||
| 		} | ||||
| 
 | ||||
| 		// XXX should this be all keys by default???
 | ||||
| 		var keys = Object.keys(storage) | ||||
| 
 | ||||
| 		var dict_key = '${INSTANCE}/__dict__' | ||||
| 		var k = resolvePath(dict_key) | ||||
| 		var dict = JSON.parse(storage[k] || '{}') | ||||
| 		dict[k] = dict_key | ||||
| 
 | ||||
| 		// get list of keys...
 | ||||
| 		if(a == '?'){ | ||||
| 			return keys | ||||
| 				.map(function(key){ return dict[key] || key }) | ||||
| 
 | ||||
| 		// get store contents...
 | ||||
| 		} else if(a == '??'  | ||||
| 				|| arguments.length == 0  | ||||
| 				|| (a instanceof Array && (b == '??' || arguments.length == 1))){ | ||||
| 			var res = {} | ||||
| 			var keys = a instanceof Array ? a : keys | ||||
| 			keys.forEach(function(key){ | ||||
| 				res[dict[key] || key] = JSON.parse(storage[key]) }) | ||||
| 			return res | ||||
| 
 | ||||
| 		// remove all keys...
 | ||||
| 		} else if(a === null || (a instanceof Array && b === null)){ | ||||
| 			;(a || keys) | ||||
| 				.forEach(function(key){ | ||||
| 					delete storage[key] }) | ||||
| 			dict = {} | ||||
| 
 | ||||
| 		// expand data to store...
 | ||||
| 		} else if(typeof(a) != typeof('str')){ | ||||
| 			Object.keys(a).forEach(function(key){ | ||||
| 				var k = resolvePath(key) | ||||
| 				k != key | ||||
| 					&& (dict[k] = key) | ||||
| 				storage[k] = JSON.stringify(a[key]) }) | ||||
| 
 | ||||
| 		// remove key...
 | ||||
| 		} else if(b === null){ | ||||
| 			var k = resolvePath(a) | ||||
| 			delete dict[k] | ||||
| 			delete storage[k] | ||||
| 
 | ||||
| 		// get key...
 | ||||
| 		} else if(b === undefined){ | ||||
| 			var k = resolvePath(a) | ||||
| 			return k in storage ?  | ||||
| 				JSON.parse(storage[k])  | ||||
| 				: actions.UNDEFINED | ||||
| 
 | ||||
| 		// write key...
 | ||||
| 		} else { | ||||
| 			var k = resolvePath(a) | ||||
| 			k != a | ||||
| 				&& (dict[k] = a) | ||||
| 			storage[k] = JSON.stringify(b) | ||||
| 		} | ||||
| 
 | ||||
| 		storage[resolvePath('${INSTANCE}/__dict__')] = JSON.stringify(dict) | ||||
| 	} | ||||
| 
 | ||||
| 	if(typeof(storage) == typeof('str')){ | ||||
| @ -478,16 +453,16 @@ function makeStorageHandler(storage, alias){ | ||||
| // 		load the store... (???)
 | ||||
| var StoreLocalStorageActions = actions.Actions({ | ||||
| 	config: { | ||||
| 		'store-root-key': 'ImageGrid.Viewer.main', | ||||
| 		'store-instance-key': 'ImageGrid.Viewer.main', | ||||
| 	}, | ||||
| 
 | ||||
| 	// NOTE: for docs see __storageHandler_doc...
 | ||||
| 	localStorageDataHandler: ['- Store/', | ||||
| 		{handle_data_store: 'storage',}, | ||||
| 		makeStorageHandler('localStorage', 'storage')], | ||||
| 		makeStorageHandler('localStorage')], | ||||
| 	sessionStorageDataHandler: ['- Store/', | ||||
| 		{handle_data_store: 'session',}, | ||||
| 		makeStorageHandler('sessionStorage', 'session')], | ||||
| 		makeStorageHandler('sessionStorage')], | ||||
| }) | ||||
| 
 | ||||
| var StoreLocalStorage =  | ||||
|  | ||||
							
								
								
									
										8
									
								
								ui (gen4)/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								ui (gen4)/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1058,9 +1058,9 @@ | ||||
|       "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" | ||||
|     }, | ||||
|     "ig-actions": { | ||||
|       "version": "3.16.0", | ||||
|       "resolved": "https://registry.npmjs.org/ig-actions/-/ig-actions-3.16.0.tgz", | ||||
|       "integrity": "sha512-4ibmH2vMNYxzac63ibCS5vwSr6C+NO+IJLwft9eEorAxyi74es+QRgyPPyZVqHOB9GouUZM9kWQVDxcZYrGp+w==", | ||||
|       "version": "3.18.0", | ||||
|       "resolved": "https://registry.npmjs.org/ig-actions/-/ig-actions-3.18.0.tgz", | ||||
|       "integrity": "sha512-wiN7pjt5CfklD/XNiehJnxrAn6/K7/dorUAYG0zTItYTCtp3iqyPCDtFiAF/PAFMbWjbiQxA2w8oIrZNV1QECQ==", | ||||
|       "requires": { | ||||
|         "ig-object": "1.0.2" | ||||
|       } | ||||
| @ -1070,7 +1070,7 @@ | ||||
|       "resolved": "https://registry.npmjs.org/ig-features/-/ig-features-3.3.4.tgz", | ||||
|       "integrity": "sha512-nJmMDfY6JiyQ2mQj31oMOmw/HOY4zbN6yyPEFu61ySXU/f3+CC/GZjdaYFemVbnZThC7hcxYfmj62eSjt7oT+Q==", | ||||
|       "requires": { | ||||
|         "ig-actions": "3.16.0", | ||||
|         "ig-actions": "3.18.0", | ||||
|         "ig-object": "1.0.2" | ||||
|       } | ||||
|     }, | ||||
|  | ||||
| @ -26,7 +26,7 @@ | ||||
|     "fs-walk": "^0.0.1", | ||||
|     "glob": "^4.0.6", | ||||
|     "guarantee-events": "^1.0.0", | ||||
|     "ig-actions": "^3.16.0", | ||||
|     "ig-actions": "^3.18.0", | ||||
|     "ig-features": "^3.3.4", | ||||
|     "ig-object": "^1.0.2", | ||||
|     "moment": "^2.20.1", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user