| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | /********************************************************************** | 
					
						
							|  |  |  | *  | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | * | 
					
						
							|  |  |  | **********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-08-21 02:19:24 +03:00
										 |  |  | ((typeof define)[0]=='u'?function(f){module.exports=f(require)}:define) | 
					
						
							|  |  |  | (function(require){ var module={} // make module AMD/node compatible...
 | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // XXX this should not be imported!!!
 | 
					
						
							|  |  |  | // 		...something wrong with requirejs(..)
 | 
					
						
							| 
									
										
										
										
											2015-12-31 10:37:21 +03:00
										 |  |  | if(typeof(process) != 'undefined'){ | 
					
						
							| 
									
										
										
										
											2016-06-06 01:10:36 +03:00
										 |  |  | 	var child_process = requirejs('child_process') | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	var fse = requirejs('fs-extra') | 
					
						
							|  |  |  | 	var pathlib = requirejs('path') | 
					
						
							|  |  |  | 	var glob = requirejs('glob') | 
					
						
							| 
									
										
										
										
											2017-02-07 18:58:37 +03:00
										 |  |  | 	var wglob = requirejs('wildglob') | 
					
						
							| 
									
										
										
										
											2016-05-28 16:29:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-01 16:12:10 +03:00
										 |  |  | 	var file = require('imagegrid/file') | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-01 16:12:10 +03:00
										 |  |  | var data = require('imagegrid/data') | 
					
						
							|  |  |  | var images = require('imagegrid/images') | 
					
						
							| 
									
										
										
										
											2015-12-29 01:40:10 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | var util = require('lib/util') | 
					
						
							|  |  |  | var actions = require('lib/actions') | 
					
						
							|  |  |  | var features = require('lib/features') | 
					
						
							| 
									
										
										
										
											2016-05-03 01:43:43 +03:00
										 |  |  | var keyboard = require('lib/keyboard') | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var core = require('features/core') | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | var widgets = require('features/ui-widgets') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | var overlay = require('lib/widget/overlay') | 
					
						
							|  |  |  | var browse = require('lib/widget/browse') | 
					
						
							| 
									
										
										
										
											2016-01-09 04:59:57 +03:00
										 |  |  | var browseWalk = require('lib/widget/browse-walk') | 
					
						
							| 
									
										
										
										
											2015-12-17 09:14:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if(typeof(process) != 'undefined'){ | 
					
						
							|  |  |  | 	var copy = file.denodeify(fse.copy) | 
					
						
							|  |  |  | 	var ensureDir = file.denodeify(fse.ensureDir) | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 	var outputFile = file.denodeify(fse.outputFile) | 
					
						
							|  |  |  | 	var createFile = file.denodeify(fse.createFile) | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 06:33:37 +03:00
										 |  |  | var IndexFormatActions = actions.Actions({ | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 	config: { | 
					
						
							|  |  |  | 		'index-dir': '.ImageGrid', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'preview-sizes': [ | 
					
						
							|  |  |  | 			75, | 
					
						
							|  |  |  | 			150, | 
					
						
							|  |  |  | 			350, | 
					
						
							|  |  |  | 			900, | 
					
						
							|  |  |  | 			1000, | 
					
						
							|  |  |  | 			1280, | 
					
						
							|  |  |  | 			1920, | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Supported fields:
 | 
					
						
							|  |  |  | 		// 	$INDEX			- index directory name
 | 
					
						
							|  |  |  | 		// 	$RESOLUTION		- preview resolution
 | 
					
						
							|  |  |  | 		// 	$GID			- image GID
 | 
					
						
							|  |  |  | 		// 	$NAME			- image name
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// XXX make this used in loader too...
 | 
					
						
							|  |  |  | 		'preview-path-template': '${INDEX}/${RESOLUTION}px/${GID} - ${NAME}.jpg', | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-01 03:36:04 +03:00
										 |  |  | 	// XXX might be a good idea to replace 'full' with changes to 
 | 
					
						
							|  |  |  | 	// 		override .changes...
 | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 	prepareIndexForWrite: ['- File/Prepare index for writing', | 
					
						
							| 
									
										
										
										
											2017-02-16 06:39:23 +03:00
										 |  |  | 		core.doc`Convert json index to a format compatible with file.writeIndex(..)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Prepare current state... | 
					
						
							|  |  |  | 			.prepareIndexForWrite() | 
					
						
							|  |  |  | 				-> data | 
					
						
							|  |  |  | 				NOTE: this will account for .changes  | 
					
						
							|  |  |  | 					(see: core.Changes.markChanged(..)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Prepare a specific state... | 
					
						
							|  |  |  | 			.prepareIndexForWrite(json) | 
					
						
							|  |  |  | 				-> data | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-01 15:44:18 +03:00
										 |  |  | 			Prepare a state overwriting changes... | 
					
						
							|  |  |  | 			.prepareIndexForWrite(null, changes) | 
					
						
							|  |  |  | 			.prepareIndexForWrite(json, changes) | 
					
						
							| 
									
										
										
										
											2017-02-16 06:39:23 +03:00
										 |  |  | 				-> data | 
					
						
							|  |  |  | 				NOTE: this will disregard .changes | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		This is here so as other features can participate in index | 
					
						
							|  |  |  | 		preparation... | 
					
						
							|  |  |  | 		This is done in two stages: | 
					
						
							|  |  |  | 			1) .json(..) action | 
					
						
							|  |  |  | 				- serialise the state in a consistent manner, | 
					
						
							|  |  |  | 				- compatible with .load(..) action | 
					
						
							|  |  |  | 				- defines the global high level serialization format | 
					
						
							|  |  |  | 			2) .prepareIndexForWrite(..) action | 
					
						
							|  |  |  | 				- takes the output of .json(..) and converts to a format  | 
					
						
							|  |  |  | 					ready for writing/serialization... | 
					
						
							| 
									
										
										
										
											2018-02-04 06:23:31 +03:00
										 |  |  | 				- compatible with .prepareIndexForLoad(..) | 
					
						
							| 
									
										
										
										
											2017-02-16 06:39:23 +03:00
										 |  |  | 				- this directly affects the index structure  | 
					
						
							|  |  |  | 					(see: file.writeIndex(..)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		This will get the base index, ignoring the cropped state. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Returns: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				// Timestamp...
 | 
					
						
							|  |  |  | 				// NOTE: this is the timestamp used to write the index.
 | 
					
						
							|  |  |  | 				date: <timestamp>, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// normalized changes...
 | 
					
						
							|  |  |  | 				// 	- true			- everything changed
 | 
					
						
							|  |  |  | 				//	- false			- nothing changes/disabled
 | 
					
						
							|  |  |  | 				/	- <object>		- specific changes | 
					
						
							|  |  |  | 				changes: <changes>, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// This is the original json object, either the one passed as
 | 
					
						
							|  |  |  | 				// an argument or the one returned by .json('base')
 | 
					
						
							|  |  |  | 				raw: <original-json>, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// this is the prepared index object, the one that is going to be
 | 
					
						
							|  |  |  | 				// saved.
 | 
					
						
							|  |  |  | 				index: <index-json>, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				... | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		The format for the <prapared-json> is as follows: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				<keyword>: <data>, | 
					
						
							|  |  |  | 				... | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		The <index-json> is written out to a fs index in the following | 
					
						
							|  |  |  | 		way: | 
					
						
							|  |  |  | 				<index-dir>/<timestamp>-<keyword>.json | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			<index-dir>		- taken from .config['index-dir'] (default: '.ImageGrid') | 
					
						
							|  |  |  | 			<timestamp>		- as returned by Date.timeStamp() (see: jli) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-10-01 15:44:18 +03:00
										 |  |  | 		function(json, changes){ | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 			json = json || this.json('base') | 
					
						
							| 
									
										
										
										
											2017-10-01 15:44:18 +03:00
										 |  |  | 			changes = changes !== undefined ? changes | 
					
						
							| 
									
										
										
										
											2017-10-02 01:35:09 +03:00
										 |  |  | 				: json.changes | 
					
						
							|  |  |  | 				//: this.hasOwnProperty('changes') ? this.changes
 | 
					
						
							|  |  |  | 				//: null
 | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 			changes = changes === null ? true : changes | 
					
						
							|  |  |  | 			return { | 
					
						
							| 
									
										
										
										
											2017-09-30 01:00:11 +03:00
										 |  |  | 				date: json.date || Date.timeStamp(), | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 				changes: changes, | 
					
						
							|  |  |  | 				raw: json, | 
					
						
							|  |  |  | 				index: {}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	// XXX should this return {} or json???
 | 
					
						
							| 
									
										
										
										
											2018-02-04 06:23:31 +03:00
										 |  |  | 	prepareIndexForLoad: ['- File/Prepare JSON for loading', | 
					
						
							| 
									
										
										
										
											2017-02-16 06:39:23 +03:00
										 |  |  | 		core.doc`Prepare JSON for loading...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 06:23:31 +03:00
										 |  |  | 			.prepareIndexForLoad(json) | 
					
						
							|  |  |  | 			.prepareIndexForLoad(json, base_path) | 
					
						
							| 
									
										
										
										
											2017-02-16 06:39:23 +03:00
										 |  |  | 				-> data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Prepare the loaded JSON data to be loaded via the .load(..) action. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		It is the participating action's responsibility to transfer the  | 
					
						
							|  |  |  | 		data from the input json to the result object. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: this is a symmetrical function to .prepareIndexForWrite(..), | 
					
						
							|  |  |  | 			see it for more info. | 
					
						
							|  |  |  | 		NOTE: also see: file.loadIndex(..) and file.loadIndex(..) | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 		function(json, base_path){ return {} }], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 06:33:37 +03:00
										 |  |  | var IndexFormat =  | 
					
						
							|  |  |  | module.IndexFormat = core.ImageGridFeatures.Feature({ | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 	title: '', | 
					
						
							| 
									
										
										
										
											2017-02-17 06:33:37 +03:00
										 |  |  | 	doc: '', | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 06:33:37 +03:00
										 |  |  | 	tag: 'index-format', | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-17 06:33:37 +03:00
										 |  |  | 	actions: IndexFormatActions, | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemInfoActions = actions.Actions({ | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemInfo =  | 
					
						
							|  |  |  | module.FileSystemInfo = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'fs-info', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'location', | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 		'index-format', | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: FileSystemInfoActions, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-04 08:08:40 +03:00
										 |  |  | 	isApplicable: function(){ return this.runtime.node }, | 
					
						
							| 
									
										
										
										
											2016-05-22 21:10:37 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | /*********************************************************************/ | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // Loader... 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // NOTE: this will also manage .location.from
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | var FileSystemLoaderActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							| 
									
										
										
										
											2017-11-17 02:50:05 +03:00
										 |  |  | 		// NOTE: this will not match "dot filenames", this is done 
 | 
					
						
							|  |  |  | 		// 		intentionally to avoid the previews MAC computers 
 | 
					
						
							|  |  |  | 		// 		generate all over the place...
 | 
					
						
							| 
									
										
										
										
											2020-04-05 22:26:17 +03:00
										 |  |  | 		'image-file-pattern': '*.@(jpg|jpeg|png|svg|JPG|JPEG|PNG|SVG)', | 
					
						
							| 
									
										
										
										
											2016-03-30 15:24:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-20 03:56:19 +03:00
										 |  |  | 		'image-file-read-stat': true, | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 		'image-file-skip-previews': false, | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 03:46:24 +03:00
										 |  |  | 		'default-load-method': 'loadIndex', | 
					
						
							|  |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// XXX is this a hack???
 | 
					
						
							|  |  |  | 	// XXX need a more generic form...
 | 
					
						
							|  |  |  | 	checkPath: ['- File/', | 
					
						
							|  |  |  | 		function(path){ return fse.existsSync(path) }], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 19:14:02 +03:00
										 |  |  | 	// Load index...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-06-05 02:10:42 +03:00
										 |  |  | 	// 	.loadIndex(path)
 | 
					
						
							|  |  |  | 	// 		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-05-07 02:02:42 +03:00
										 |  |  | 	// This maintains:
 | 
					
						
							|  |  |  | 	// 	.location.loaded		- list of loaded URLs...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// NOTE: when passed no path this will not do anything...
 | 
					
						
							| 
									
										
										
										
											2016-05-04 18:01:19 +03:00
										 |  |  | 	// NOTE: this will add a .from field to .location, this will indicate
 | 
					
						
							|  |  |  | 	// 		the date starting from which saves are loaded.
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// XXX look inside...
 | 
					
						
							|  |  |  | 	loadIndex: ['- File/Load index', | 
					
						
							| 
									
										
										
										
											2016-05-03 19:14:46 +03:00
										 |  |  | 		function(path, from_date, logger){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-02-11 04:40:22 +03:00
										 |  |  | 			var index_dir = util.normalizePath(this.config['index-dir']) | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 			// XXX get a logger...
 | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							| 
									
										
										
										
											2016-11-04 23:00:34 +03:00
										 |  |  | 			logger = logger && logger.push('Load') | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if(path == null){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 			path = util.normalizePath(path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-03 19:14:46 +03:00
										 |  |  | 			if(from_date && from_date.emit != null){ | 
					
						
							|  |  |  | 				logger = from_date | 
					
						
							|  |  |  | 				from_date = null | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// XXX make this load incrementally (i.e. and EventEmitter
 | 
					
						
							|  |  |  | 			// 		a-la glob)....
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 			//file.loadIndex(path, this.config['index-dir'], logger)
 | 
					
						
							| 
									
										
										
										
											2017-02-11 04:40:22 +03:00
										 |  |  | 			return file.loadIndex(path, index_dir, from_date, logger) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				.then(function(res){ | 
					
						
							| 
									
										
										
										
											2018-12-06 00:59:05 +03:00
										 |  |  | 					var force_full_save = false | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					// XXX if res is empty load raw...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// XXX use the logger...
 | 
					
						
							|  |  |  | 					//console.log('FOUND INDEXES:', Object.keys(res).length)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// skip nested paths...
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 					//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					// XXX make this optional...
 | 
					
						
							|  |  |  | 					// XXX this is best done BEFORE we load all the 
 | 
					
						
							|  |  |  | 					// 		indexes, e.g. in .loadIndex(..)
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 					var skipped = new Set() | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					var paths = Object.keys(res) | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 					paths | 
					
						
							|  |  |  | 						.sort() | 
					
						
							|  |  |  | 						.forEach(function(p){ | 
					
						
							|  |  |  | 							// already removed...
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 							if(skipped.has(p) >= 0){ | 
					
						
							|  |  |  | 								return } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 							paths | 
					
						
							|  |  |  | 								// get all paths that fully contain p...
 | 
					
						
							|  |  |  | 								.filter(function(o){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 									return o != p  | 
					
						
							|  |  |  | 										&& o.indexOf(p) == 0 }) | 
					
						
							|  |  |  | 								// drop all nested (longer) paths...
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 								.forEach(function(e){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 									skipped.add(e) | 
					
						
							|  |  |  | 									delete res[e] }) }) | 
					
						
							|  |  |  | 					// keep only the valid paths...
 | 
					
						
							|  |  |  | 					paths = Object.keys(res) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					//console.log('SKIPPING NESTED:', skipped.length)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var index | 
					
						
							|  |  |  | 					var base_path | 
					
						
							|  |  |  | 					var loaded = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// NOTE: res may contain multiple indexes...
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 					//for(var k in res){
 | 
					
						
							|  |  |  | 					for(var i=0; i < paths.length; i++){ | 
					
						
							|  |  |  | 						var k = paths[i] | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						// skip empty indexes...
 | 
					
						
							| 
									
										
										
										
											2017-03-08 19:34:49 +03:00
										 |  |  | 						// XXX should we rebuild or list here???
 | 
					
						
							|  |  |  | 						if(res[k].data == null && res[k].images == null){ | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 							continue } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 19:34:49 +03:00
										 |  |  | 						// build the data from images...
 | 
					
						
							|  |  |  | 						if(res[k].data == null){ | 
					
						
							|  |  |  | 							res[k].data = { | 
					
						
							|  |  |  | 								order: Object.keys(res[k].images), | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 							} } | 
					
						
							| 
									
										
										
										
											2017-03-08 19:34:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-06 00:59:05 +03:00
										 |  |  | 						// prepare to do a full save if format version updated...
 | 
					
						
							|  |  |  | 						if(res[k].data.version != that.data.version){ | 
					
						
							| 
									
										
										
										
											2018-12-09 08:44:10 +03:00
										 |  |  | 							// compensate for a typo that was discovered in v3.1
 | 
					
						
							|  |  |  | 							var v = res[k].data.version || res[k].data.varsion | 
					
						
							|  |  |  | 							logger && logger.emit('Data version changed:', | 
					
						
							|  |  |  | 								v, '->', that.data.version) | 
					
						
							| 
									
										
										
										
											2018-12-06 00:59:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 							force_full_save = true } | 
					
						
							| 
									
										
										
										
											2018-12-06 00:59:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 06:23:31 +03:00
										 |  |  | 						var part = that.prepareIndexForLoad(res[k], k) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						// load the first index...
 | 
					
						
							|  |  |  | 						if(index == null){ | 
					
						
							|  |  |  | 							logger && logger.emit('base index', k, res) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							index = part | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// merge indexes...
 | 
					
						
							|  |  |  | 						// XXX need to skip sub-indexes in the same sub-tree...
 | 
					
						
							|  |  |  | 						// 		...skip any path that fully contains an 
 | 
					
						
							|  |  |  | 						// 		already loaded path..
 | 
					
						
							|  |  |  | 						// XXX load data in chunks rather than merge...
 | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							//console.log('MERGING:', k, part)
 | 
					
						
							|  |  |  | 							logger && logger.emit('merge index', k, res) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// merge...
 | 
					
						
							|  |  |  | 							index.data.join(part.data) | 
					
						
							|  |  |  | 							index.images.join(part.images) | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						loaded.push(k) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					logger && logger.emit('load index', index) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 02:24:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// XXX BUG?: some times we reach this point with index
 | 
					
						
							|  |  |  | 					// 		equaling null
 | 
					
						
							|  |  |  | 					// 		...we are not fixing this here as the cause of 
 | 
					
						
							|  |  |  | 					// 		this issue is likely someplace else and that 
 | 
					
						
							|  |  |  | 					// 		needs investigating...
 | 
					
						
							|  |  |  | 					// XXX REMOVE WHEN ISSUE FIXED...
 | 
					
						
							|  |  |  | 					!index | 
					
						
							|  |  |  | 						&& console.error('Failed to load index from:', paths) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 					// prepare the location data...
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 					index.location =  | 
					
						
							|  |  |  | 						Object.assign( | 
					
						
							|  |  |  | 							index.location || {}, | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								path: path, | 
					
						
							|  |  |  | 								loaded: loaded, | 
					
						
							|  |  |  | 								load: 'loadIndex', | 
					
						
							|  |  |  | 							}) | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 					from_date | 
					
						
							|  |  |  | 						&& (index.location.from = from_date) | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// this is the critical section, after this point we
 | 
					
						
							|  |  |  | 					// are doing the actual loading....
 | 
					
						
							| 
									
										
										
										
											2016-06-05 03:46:24 +03:00
										 |  |  | 					that.loadOrRecover(index)  | 
					
						
							| 
									
										
										
										
											2018-12-06 00:59:05 +03:00
										 |  |  | 						.then(function(){ | 
					
						
							|  |  |  | 							force_full_save | 
					
						
							| 
									
										
										
										
											2018-12-06 16:10:20 +03:00
										 |  |  | 								// XXX remove as soon as merged index save is done...
 | 
					
						
							|  |  |  | 								&& loaded.length == 1 | 
					
						
							| 
									
										
										
										
											2020-07-10 18:58:22 +03:00
										 |  |  | 								&& that.markChanged('all') }) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				}) | 
					
						
							|  |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 	// Get image(s) previews...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Load current image previews...
 | 
					
						
							|  |  |  | 	//	.getPreviews()
 | 
					
						
							|  |  |  | 	//	.getPreviews('current')
 | 
					
						
							|  |  |  | 	//		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Load previews for specific image...
 | 
					
						
							|  |  |  | 	//	.getPreviews(gid)
 | 
					
						
							|  |  |  | 	//		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Load all image previews...
 | 
					
						
							|  |  |  | 	//	.getPreviews('*')
 | 
					
						
							|  |  |  | 	//	.getPreviews('all')
 | 
					
						
							|  |  |  | 	//		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	Load previews that match glob pattern...
 | 
					
						
							|  |  |  | 	//	.getPreviews(pattern)
 | 
					
						
							|  |  |  | 	//		-> promise
 | 
					
						
							|  |  |  | 	//		NOTE: this is useful for finding previews for example by 
 | 
					
						
							|  |  |  | 	//			image name, e.g. .getPreviews('*' + ig.image[gid].name)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 	// NOTE: this will override image .preview and may change .path and
 | 
					
						
							|  |  |  | 	// 		.base_path...
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 	// NOTE: if multiple sets of previews are located this will use the 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 	// 		last found and set image .base_path and .path accordingly...
 | 
					
						
							| 
									
										
										
										
											2016-06-03 19:14:02 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX should this accept a list of gids???
 | 
					
						
							|  |  |  | 	// XXX revise image .base_path and .path handling: should .base_path 
 | 
					
						
							|  |  |  | 	// 		and .path be set relative to .located.path or relative to 
 | 
					
						
							|  |  |  | 	// 		given path???
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 	getPreviews: ['- File/', | 
					
						
							|  |  |  | 		function(pattern, path, images){ | 
					
						
							|  |  |  | 			images = images || this.images | 
					
						
							|  |  |  | 			pattern = pattern == 'current' ? this.current + '*' | 
					
						
							|  |  |  | 				: pattern == 'all' ? '*' | 
					
						
							|  |  |  | 				// explicit gid...
 | 
					
						
							|  |  |  | 				: pattern in images ? pattern + '*' | 
					
						
							|  |  |  | 				// other pattern...
 | 
					
						
							|  |  |  | 				: pattern != null ? pattern | 
					
						
							|  |  |  | 				// default...
 | 
					
						
							|  |  |  | 				: this.current + '*' | 
					
						
							|  |  |  | 			path = path || this.location.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var index_dir = this.config['index-dir'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return file.loadPreviews(path, pattern, null, index_dir) | 
					
						
							|  |  |  | 				.then(function(previews){ | 
					
						
							|  |  |  | 					for(var l in previews){ | 
					
						
							|  |  |  | 						var p = previews[l] | 
					
						
							|  |  |  | 						p && Object.keys(p).forEach(function(gid){ | 
					
						
							|  |  |  | 							if(gid in images){ | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 								var base = pathlib.basename(l) == index_dir ?  | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 									pathlib.dirname(l)  | 
					
						
							|  |  |  | 									: l | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 								// update .path and .base_path if they change...
 | 
					
						
							|  |  |  | 								if(images[gid].base_path != base){ | 
					
						
							|  |  |  | 									// XXX
 | 
					
						
							|  |  |  | 									console.warn('getPreviews(..): changing .base_path of image:', gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									var rel = pathlib.relative(images[gid].base_path, base) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									images[gid].path = pathlib.join(rel, images[gid].path)  | 
					
						
							|  |  |  | 									images[gid].base_path = base | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 								images[gid].preview = p[gid].preview | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					return images | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-31 23:19:24 +03:00
										 |  |  | 	// Get images in path...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 	// This will:
 | 
					
						
							|  |  |  | 	// 	- get images from path
 | 
					
						
							|  |  |  | 	// 	- get basic stat data
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 	// 	- get previews from path if they exist (.getPreviews(..))
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-05-31 23:19:24 +03:00
										 |  |  | 	// Returns: Images object
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 	// XXX revise logging...
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 	getImagesInPath: ['- File/', | 
					
						
							|  |  |  | 		function(path, read_stat, skip_preview_search, logger){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			if(path == null){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 			read_stat = read_stat == null ? | 
					
						
							|  |  |  | 				this.config['image-file-read-stat'] | 
					
						
							|  |  |  | 				: read_stat | 
					
						
							|  |  |  | 			skip_preview_search = skip_preview_search == null ? | 
					
						
							|  |  |  | 				this.config['image-file-skip-previews'] | 
					
						
							|  |  |  | 				: skip_preview_search | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			logger = logger || this.logger | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			path = util.normalizePath(path) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 			// progress...
 | 
					
						
							|  |  |  | 			// XXX this does not appear to run while glob(..) is running...
 | 
					
						
							|  |  |  | 			var found = [] | 
					
						
							|  |  |  | 			var update_interval | 
					
						
							|  |  |  | 			if(logger){ | 
					
						
							|  |  |  | 				that.showProgress  | 
					
						
							|  |  |  | 					&& that.showProgress(logger.path) | 
					
						
							|  |  |  | 				update_interval = setInterval(function(){ | 
					
						
							|  |  |  | 					found.length > 0 | 
					
						
							|  |  |  | 						&& logger.emit('found', found)  | 
					
						
							|  |  |  | 						&& (found = []) }, 150) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			// get the image list...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 			return new Promise(function(resolve, reject){ | 
					
						
							| 
									
										
										
										
											2019-05-22 23:28:38 +03:00
										 |  |  | 				glob(path + '/'+ that.config['image-file-pattern'], { | 
					
						
							|  |  |  | 						stat: !!read_stat, | 
					
						
							|  |  |  | 						strict: false, | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					.on('match', function(e){ found.push(e) }) | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 					.on('error', function(err){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 						update_interval | 
					
						
							|  |  |  | 							&& clearInterval(update_interval) | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 						console.error(err) | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 						reject(err) }) | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 					.on('end', function(lst){  | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 						update_interval | 
					
						
							|  |  |  | 							&& clearInterval(update_interval) | 
					
						
							|  |  |  | 						logger && found.length > 0 | 
					
						
							|  |  |  | 							&& logger.emit('found', found) | 
					
						
							|  |  |  | 							&& (found = []) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-29 05:27:31 +03:00
										 |  |  | 						// XXX might be a good idea to make image paths relative to path...
 | 
					
						
							|  |  |  | 						//lst = lst.map(function(p){ return pathlib.relative(base, p) })
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 						// XXX do we need to normalize paths after we get them from glob??
 | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 						//lst = lst.map(function(p){ return util.normalizePath(p) }), path)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 						var imgs = images.Images.fromArray(lst, path) | 
					
						
							| 
									
										
										
										
											2016-04-20 03:56:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 						if(!!read_stat){ | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 							var stats = this.statCache | 
					
						
							|  |  |  | 							var p = pathlib.posix | 
					
						
							| 
									
										
										
										
											2016-04-20 03:56:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 							imgs.forEach(function(gid, img){ | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 								var stat = stats[p.join(img.base_path, img.path)] | 
					
						
							| 
									
										
										
										
											2016-04-20 03:56:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 								img.atime = stat.atime | 
					
						
							|  |  |  | 								img.mtime = stat.mtime | 
					
						
							|  |  |  | 								img.ctime = stat.ctime | 
					
						
							|  |  |  | 								img.birthtime = stat.birthtime | 
					
						
							| 
									
										
										
										
											2016-04-20 16:17:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 								img.size = stat.size | 
					
						
							| 
									
										
										
										
											2016-04-20 03:56:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 								// XXX do we need anything else???
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 							}) } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 						// pass on the result...
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 						resolve(imgs) | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 					}) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			// load previews if they exist...
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 			.then(function(imgs){ | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 				var index_dir = that.config['index-dir'] | 
					
						
							|  |  |  | 				var index_path = path +'/'+ index_dir | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-03 04:46:51 +03:00
										 |  |  | 				return !skip_preview_search ?  | 
					
						
							|  |  |  | 					//that.getPreviews('all', path, imgs)
 | 
					
						
							|  |  |  | 					that.getPreviews('all', index_path, imgs) | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					: imgs }) }], | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Load images...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-06-05 02:10:42 +03:00
										 |  |  | 	// 	.loadImages(path)
 | 
					
						
							|  |  |  | 	// 		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if path is not given this will do nothing.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 	// XXX use the logger...
 | 
					
						
							|  |  |  | 	// XXX add a recursive option...
 | 
					
						
							|  |  |  | 	// 		...might also be nice to add sub-dirs to ribbons...
 | 
					
						
							| 
									
										
										
										
											2016-05-31 23:19:24 +03:00
										 |  |  | 	// XXX add option to preserve/update .data (???)
 | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 	// XXX make image pattern more generic...
 | 
					
						
							|  |  |  | 	loadImages: ['- File/Load images', | 
					
						
							|  |  |  | 		function(path, logger){ | 
					
						
							|  |  |  | 			if(path == null){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							| 
									
										
										
										
											2016-11-04 23:00:34 +03:00
										 |  |  | 			logger = logger && logger.push('Load images') | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			path = util.normalizePath(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// get the image list...
 | 
					
						
							|  |  |  | 			return this.getImagesInPath( | 
					
						
							|  |  |  | 					path,  | 
					
						
							|  |  |  | 					that.config['image-file-read-stat'], | 
					
						
							|  |  |  | 					that.config['image-file-skip-previews'], | 
					
						
							|  |  |  | 					logger) | 
					
						
							|  |  |  | 				// load the data...
 | 
					
						
							|  |  |  | 				.then(function(imgs){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					logger && logger.emit('loaded', imgs.keys())  | 
					
						
							| 
									
										
										
										
											2017-12-02 18:33:37 +03:00
										 |  |  | 					return that.loadOrRecover({ | 
					
						
							| 
									
										
										
										
											2017-03-08 20:05:49 +03:00
										 |  |  | 							images: imgs, | 
					
						
							|  |  |  | 							data: data.Data.fromArray(imgs.keys()), | 
					
						
							| 
									
										
										
										
											2016-05-30 02:23:55 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-08 20:05:49 +03:00
										 |  |  | 							location: { | 
					
						
							|  |  |  | 								path: path, | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 								load: 'loadImages', | 
					
						
							|  |  |  | 								sync: 'syncIndexWithDir', | 
					
						
							| 
									
										
										
										
											2017-03-08 20:05:49 +03:00
										 |  |  | 							} | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 						.then(function(){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 							that.markChanged('none') }) }) }], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-25 18:17:04 +03:00
										 |  |  | 	// Load images to new ribbon...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 	//	.loadImagesAsRibbon(path[, logger])
 | 
					
						
							|  |  |  | 	//		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//	.loadImagesAsRibbon(path, 'above'[, logger])
 | 
					
						
							|  |  |  | 	//	.loadImagesAsRibbon(path, 'below'[, logger])
 | 
					
						
							|  |  |  | 	//		-> promise
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2017-01-25 18:17:04 +03:00
										 |  |  | 	// NOTE: this will clear .location
 | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	// XXX should this be usable only in crops???
 | 
					
						
							|  |  |  | 	// 		....also would be a good idea to add things like .removeRibbon(..)...
 | 
					
						
							| 
									
										
										
										
											2017-01-25 18:17:04 +03:00
										 |  |  | 	// XXX should this be a crop???
 | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 	loadImagesAsRibbon: ['- File/Load images into ribbon', | 
					
						
							|  |  |  | 		function(path, direction, logger){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			if(path == null){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(logger === undefined  | 
					
						
							|  |  |  | 					&& direction  | 
					
						
							|  |  |  | 					&& typeof(direction) != typeof('str')){ | 
					
						
							|  |  |  | 				logger = direction | 
					
						
							|  |  |  | 				direction = null | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			direction = direction || 'below' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							|  |  |  | 			logger = logger && logger.push('Load images to ribbon') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return this.getImagesInPath( | 
					
						
							|  |  |  | 					path,  | 
					
						
							|  |  |  | 					that.config['image-file-read-stat'], | 
					
						
							|  |  |  | 					that.config['image-file-skip-previews'], | 
					
						
							|  |  |  | 					logger) | 
					
						
							|  |  |  | 				// load the data...
 | 
					
						
							|  |  |  | 				.then(function(imgs){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					logger && logger.emit('loaded', imgs.keys())  | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 					that.clearLoaction() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var d = that.data | 
					
						
							|  |  |  | 					var nd = data.Data.fromArray(imgs.keys()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var r = d.getRibbon() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// splice the order...
 | 
					
						
							|  |  |  | 					d.order.splice.apply(d.order,  | 
					
						
							|  |  |  | 						[d.order.indexOf(d.current)+1, 0] | 
					
						
							|  |  |  | 							.concat(nd.order)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// new ribbon and data...
 | 
					
						
							|  |  |  | 					var n = d.newRibbon(r, direction) | 
					
						
							|  |  |  | 					d.ribbons[n] = nd.ribbons[nd.ribbon_order[0]] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// sort elements within the new ribbon...
 | 
					
						
							|  |  |  | 					d.updateImagePositions() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// join images...
 | 
					
						
							|  |  |  | 					that.images.join(imgs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					that.reload(true) | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// XXX revise logger...
 | 
					
						
							| 
									
										
										
										
											2016-06-03 19:14:02 +03:00
										 |  |  | 	// XXX revise alignment...
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 	loadNewImages: ['File/Load new images to index', | 
					
						
							| 
									
										
										
										
											2020-05-20 02:49:26 +03:00
										 |  |  | 		core.doc`Load new images...
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Load new images from current path... | 
					
						
							|  |  |  | 			.loadNewImages() | 
					
						
							|  |  |  | 				-> promise | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 			Load new images from path... | 
					
						
							|  |  |  | 			.loadNewImages(path) | 
					
						
							|  |  |  | 				-> promise | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		This will prepend images in path (default .location.path) that  | 
					
						
							|  |  |  | 		were not loaded in index... | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		NOTE: this will not load images that are already loaded. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 		{ locationSync: true, | 
					
						
							|  |  |  | 			mode: function(){  | 
					
						
							|  |  |  | 				return ['loadIndex', 'loadImages'].includes(this.location.load)  | 
					
						
							|  |  |  | 					|| 'disabled' }, }, | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		function(path, logger){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			path = path || this.location.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(path == null){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 			logger = logger || this.logger | 
					
						
							| 
									
										
										
										
											2016-11-04 23:00:34 +03:00
										 |  |  | 			logger = logger && logger.push('Load new images') | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			path = util.normalizePath(path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			// cache the loaded images...
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 			var loaded = new Set(this.images.map(function(gid, img){ return img.path })) | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 			//var base_pattern = RegExp('^'+path)
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 			return this.getImagesInPath( | 
					
						
							|  |  |  | 					path,  | 
					
						
							|  |  |  | 					that.config['image-file-read-stat'], | 
					
						
							|  |  |  | 					that.config['image-file-skip-previews'], | 
					
						
							|  |  |  | 					logger) | 
					
						
							|  |  |  | 				// load the data...
 | 
					
						
							|  |  |  | 				.then(function(imgs){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					var added = [] | 
					
						
							|  |  |  | 					var skipped = [] | 
					
						
							|  |  |  | 					var progress = function(){ | 
					
						
							|  |  |  | 						skipped.length > 0 | 
					
						
							|  |  |  | 							&& logger.emit('skipped', skipped) | 
					
						
							|  |  |  | 							&& (skipped = []) | 
					
						
							|  |  |  | 						added.length > 0 | 
					
						
							|  |  |  | 							&& logger.emit('done', added) | 
					
						
							|  |  |  | 							&& (added = []) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 					// remove the images we already have loaded...
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					var t = Date.now() | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 					imgs.forEach(function(gid, img){ | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 						// XXX this does not let the browser update progress...
 | 
					
						
							|  |  |  | 						Date.now() - t > 200 | 
					
						
							|  |  |  | 							&& (t = Date.now()) | 
					
						
							|  |  |  | 							&& progress() | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 						// NOTE: we do not need to normalize anything as
 | 
					
						
							|  |  |  | 						// 		both the current path and loaded paths 
 | 
					
						
							|  |  |  | 						// 		came from the same code...
 | 
					
						
							|  |  |  | 						// XXX is this good enough???
 | 
					
						
							|  |  |  | 						// 		...might be a good idea to compare absolute
 | 
					
						
							|  |  |  | 						// 		paths...
 | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 						if(loaded.has(img.path)){ | 
					
						
							|  |  |  | 							delete imgs[gid]  | 
					
						
							|  |  |  | 							skipped.push(gid) | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							added.push(gid) } }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// finalize progress...
 | 
					
						
							|  |  |  | 					if(logger){ | 
					
						
							|  |  |  | 						skipped.length > 0 | 
					
						
							|  |  |  | 							&& logger.emit('skipped', skipped) | 
					
						
							|  |  |  | 						added.length > 0 | 
					
						
							|  |  |  | 							&& logger.emit('done', added) } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// nothing new...
 | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 					if(imgs.length == 0){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 						// XXX
 | 
					
						
							|  |  |  | 						logger && logger.emit('loaded', []) | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 						return imgs } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// XXX
 | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 					logger && logger.emit('queued', imgs) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 					var gids = imgs.keys() | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					var new_data = that.data.constructor.fromArray(gids) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// merge with index...
 | 
					
						
							|  |  |  | 					// NOTE: we are prepending new images to the start...
 | 
					
						
							|  |  |  | 					// NOTE: all ribbon gids will change here...
 | 
					
						
							|  |  |  | 					var cur = that.data.current | 
					
						
							| 
									
										
										
										
											2018-03-26 19:54:02 +03:00
										 |  |  | 					that.data = new_data.join(that.data) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					that.data.current = cur | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-30 03:15:05 +03:00
										 |  |  | 					that.images.join(imgs) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					that.reload() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// XXX report that we are done...
 | 
					
						
							| 
									
										
										
										
											2016-06-03 05:12:29 +03:00
										 |  |  | 					logger && logger.emit('loaded', imgs) | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					return imgs | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				}) | 
					
						
							|  |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX update index for removed images...
 | 
					
						
							|  |  |  | 	// 		- remove non-existing previews from index
 | 
					
						
							|  |  |  | 	// 		- replace non-existing originals with the largest preview (in index)
 | 
					
						
							|  |  |  | 	// 		...do not touch the fs
 | 
					
						
							| 
									
										
										
										
											2019-01-07 09:34:49 +03:00
										 |  |  | 	// XXX this does not give the logger to render... can't seem to make this
 | 
					
						
							|  |  |  | 	// 		not block the browser render...
 | 
					
						
							| 
									
										
										
										
											2020-05-21 04:29:44 +03:00
										 |  |  | 	// XXX trigger this on .ribbons.imageLoadErrorCallback ...
 | 
					
						
							|  |  |  | 	// 		this.ribbos.imageLoadErrorCallback = function(){
 | 
					
						
							|  |  |  | 	// 			// XXX prevent calling too often...
 | 
					
						
							|  |  |  | 	// 			// XXX
 | 
					
						
							|  |  |  | 	// 			that.checkIndex() }
 | 
					
						
							| 
									
										
										
										
											2019-01-07 09:34:49 +03:00
										 |  |  | 	checkIndex: ['File/Check index consistency', | 
					
						
							| 
									
										
										
										
											2019-01-09 08:29:53 +03:00
										 |  |  | 		core.doc`Check index consistency...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 		Check currently loaded index for missing references and fix them | 
					
						
							|  |  |  | 		if found. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-09 08:29:53 +03:00
										 |  |  | 		This will: | 
					
						
							|  |  |  | 			- remove references to non-existing preview images (image.preview) | 
					
						
							|  |  |  | 			- remove references to non-existing .path (image.path) | 
					
						
							|  |  |  | 			- if .path removed, set to largest available preview | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: currently this is disabled for merged indexes, need to load | 
					
						
							|  |  |  | 			and check individually... | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 		`,
 | 
					
						
							|  |  |  | 		function(logger){ | 
					
						
							| 
									
										
										
										
											2019-01-07 09:34:49 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 			logger = logger || this.logger | 
					
						
							|  |  |  | 			logger = logger && logger.push('Checking index') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 			// no index loaded...
 | 
					
						
							|  |  |  | 			if(!this.location.loaded){ | 
					
						
							|  |  |  | 				logger.emit('no index to fix.') | 
					
						
							|  |  |  | 				return Promise.resolve([]) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 			// XXX can we remove this restriction...
 | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 			if(this.location.loaded.length > 1){ | 
					
						
							|  |  |  | 				throw new Error('.fixIndex(): combined indexes not supported.') } | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 09:34:49 +03:00
										 |  |  | 			logger  | 
					
						
							|  |  |  | 				&& this.images | 
					
						
							|  |  |  | 					.forEach(function(gid){  | 
					
						
							|  |  |  | 						logger.emit('queued', gid)}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 			// XXX get this from config...
 | 
					
						
							| 
									
										
										
										
											2019-01-11 04:17:47 +03:00
										 |  |  | 			//var chunk_size = 50
 | 
					
						
							|  |  |  | 			var chunk_size = '100C' | 
					
						
							| 
									
										
										
										
											2019-01-07 09:34:49 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 			return this.images | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 				.map(function(gid, image){  | 
					
						
							|  |  |  | 					return [gid, image] }) | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 				.mapChunks(chunk_size, function([gid, image]){ | 
					
						
							| 
									
										
										
										
											2019-01-07 08:02:02 +03:00
										 |  |  | 					var updated = false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					var previews = image.preview || {} | 
					
						
							|  |  |  | 					Object.entries(previews) | 
					
						
							|  |  |  | 						.forEach(function(p){ | 
					
						
							|  |  |  | 							!fse.existsSync(image.base_path +'/'+ p[1]) | 
					
						
							|  |  |  | 								&& (updated = true) | 
					
						
							|  |  |  | 								&& (delete previews[p[0]]) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					!fse.existsSync(image.base_path +'/'+ image.path) | 
					
						
							|  |  |  | 						&& (updated = true) | 
					
						
							|  |  |  | 						&& (delete image.path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					logger && logger.emit('done', gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return updated ? gid : [] | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2019-01-10 06:15:35 +03:00
										 |  |  | 				.then(function(res){ | 
					
						
							|  |  |  | 					return res.flat() }) | 
					
						
							| 
									
										
										
										
											2019-01-07 09:34:49 +03:00
										 |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 02:49:26 +03:00
										 |  |  | 	// XXX should this take a path argument???
 | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 	// XXX not yet sure about this...
 | 
					
						
							|  |  |  | 	removeMissingImages: ['File/Remove missing images from index', | 
					
						
							|  |  |  | 		core.doc`Remove missing images from index
 | 
					
						
							| 
									
										
										
										
											2020-05-20 02:49:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			.removeMissingImages() | 
					
						
							|  |  |  | 				-> promise | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 		 | 
					
						
							|  |  |  | 		This will remove images that are not found via their original  | 
					
						
							|  |  |  | 		path/name from the index. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: no actual data is removed. | 
					
						
							|  |  |  | 		NOTE: this will not remove generated previews from index. | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 		{ locationSync: true, | 
					
						
							|  |  |  | 			mode: 'loadNewImages', }, | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 		function(logger){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							|  |  |  | 			rem_logger = logger && logger.push('Remove missing') | 
					
						
							|  |  |  | 			logger = logger && logger.push('Check missing') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			logger  | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 				&& logger.emit('queued', this.images.keys()) | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var chunk_size = '100C' | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 			var removed = [] | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return this.images | 
					
						
							|  |  |  | 				.map(function(gid, image){  | 
					
						
							|  |  |  | 					return [gid, image] }) | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 				.mapChunks(chunk_size, [ | 
					
						
							|  |  |  | 					function([gid, image]){ | 
					
						
							|  |  |  | 						var updated = false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						image.path  | 
					
						
							|  |  |  | 							&& !fse.existsSync(image.base_path +'/'+ image.path) | 
					
						
							|  |  |  | 							&& (updated = true) | 
					
						
							|  |  |  | 							&& logger  | 
					
						
							|  |  |  | 								&& removed.push(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						return updated ? gid : [] }, | 
					
						
							|  |  |  | 					// do the logging per chunk...
 | 
					
						
							|  |  |  | 					function(chunk, res){ | 
					
						
							|  |  |  | 						logger  | 
					
						
							|  |  |  | 							&& logger.emit('done', chunk.map(function([gid]){ return gid }))  | 
					
						
							|  |  |  | 							&& rem_logger.emit('queued', removed) | 
					
						
							|  |  |  | 							&& (removed = []) }]) | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 				.then(function(res){ | 
					
						
							|  |  |  | 					res = res.flat() | 
					
						
							| 
									
										
										
										
											2020-07-09 02:19:43 +03:00
										 |  |  | 					return res.length > 0 ? | 
					
						
							|  |  |  | 						res | 
					
						
							|  |  |  | 							.mapChunks(chunk_size, [ | 
					
						
							|  |  |  | 								// clear images...
 | 
					
						
							|  |  |  | 								function(gid){ | 
					
						
							|  |  |  | 									delete that.images[gid] },  | 
					
						
							|  |  |  | 								// log...
 | 
					
						
							|  |  |  | 								function(chunk){ | 
					
						
							|  |  |  | 									logger && rem_logger.emit('done', chunk) }]) | 
					
						
							|  |  |  | 							// clear data...
 | 
					
						
							|  |  |  | 							.then(function(){ | 
					
						
							|  |  |  | 								that.data.clear(res)  | 
					
						
							|  |  |  | 								return res }) | 
					
						
							| 
									
										
										
										
											2020-07-10 04:07:45 +03:00
										 |  |  | 						: res }) | 
					
						
							|  |  |  | 				// clear out progress...
 | 
					
						
							|  |  |  | 				.then(function(res){ | 
					
						
							|  |  |  | 					logger && rem_logger.emit('done') | 
					
						
							|  |  |  | 					return res }) }], | 
					
						
							| 
									
										
										
										
											2020-05-20 02:49:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX EXPERIMENTAL...
 | 
					
						
							|  |  |  | 	// shorthand...
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 	syncIndexWithDir: ['File/Synchronize index to path', | 
					
						
							| 
									
										
										
										
											2020-05-20 02:49:26 +03:00
										 |  |  | 		core.doc`Load new and remove deleted images...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			.syncIndexWithDir() | 
					
						
							|  |  |  | 				-> promise | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		This will call: | 
					
						
							|  |  |  | 			.loadNewImages() | 
					
						
							|  |  |  | 			.removeMissingImages() | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 		{ locationSync: true, | 
					
						
							|  |  |  | 			mode: 'loadNewImages', }, | 
					
						
							| 
									
										
										
										
											2020-05-20 02:49:26 +03:00
										 |  |  | 		function(logger){ | 
					
						
							|  |  |  | 			return Promise.all([ | 
					
						
							|  |  |  | 				this.loadNewImages(), | 
					
						
							|  |  |  | 				this.removeMissingImages(), ]) }], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemLoader =  | 
					
						
							|  |  |  | module.FileSystemLoader = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'fs-loader', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							| 
									
										
										
										
											2017-05-14 02:29:47 +03:00
										 |  |  | 		'base', | 
					
						
							|  |  |  | 		'edit', | 
					
						
							| 
									
										
										
										
											2017-02-17 06:33:37 +03:00
										 |  |  | 		'index-format', | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		'location', | 
					
						
							| 
									
										
										
										
											2016-06-05 04:11:20 +03:00
										 |  |  | 		'recover', | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 		'fs-info', | 
					
						
							| 
									
										
										
										
											2016-04-27 08:59:13 +03:00
										 |  |  | 		'tasks', | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'ui-fs-loader', | 
					
						
							|  |  |  | 		'fs-url-history', | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 		'fs-save-history', | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	actions: FileSystemLoaderActions, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-04 08:08:40 +03:00
										 |  |  | 	isApplicable: function(){ return this.runtime.node }, | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		// clear changes when loading an index...
 | 
					
						
							|  |  |  | 		['loadIndex', | 
					
						
							|  |  |  | 			function(res, path){ | 
					
						
							|  |  |  | 				if(path){ | 
					
						
							|  |  |  | 					var that = this | 
					
						
							| 
									
										
										
										
											2017-10-03 04:34:19 +03:00
										 |  |  | 					res.then(function(){  | 
					
						
							|  |  |  | 						that.markChanged('none') }) | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2017-10-03 04:34:19 +03:00
										 |  |  | 		// mark everything changed when loading images...
 | 
					
						
							|  |  |  | 		['loadImages', | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				res.then(function(){  | 
					
						
							|  |  |  | 					that.markChanged('all') }) | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 		// add new images to changes...
 | 
					
						
							|  |  |  | 		['loadNewImages', | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				res.then(function(imgs){ | 
					
						
							|  |  |  | 					imgs  | 
					
						
							|  |  |  | 						&& imgs.length > 0  | 
					
						
							|  |  |  | 						&& that | 
					
						
							|  |  |  | 							.markChanged('data') | 
					
						
							| 
									
										
										
										
											2018-03-26 20:24:12 +03:00
										 |  |  | 							.markChanged('images', imgs.keys()) }) | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2019-01-07 09:41:37 +03:00
										 |  |  | 		['checkIndex', | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				res.then(function(gids){ | 
					
						
							|  |  |  | 					gids.length > 0 | 
					
						
							|  |  |  | 						&& that.markChanged('images', gids) }) }], | 
					
						
							| 
									
										
										
										
											2020-05-17 22:47:01 +03:00
										 |  |  | 		['removeMissingImages', | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				res.then(function(gids){ | 
					
						
							|  |  |  | 					gids.length > 0 | 
					
						
							|  |  |  | 						&& that | 
					
						
							|  |  |  | 							.markChanged('data') | 
					
						
							|  |  |  | 							.markChanged('images')  | 
					
						
							|  |  |  | 							.reload(true) }) }], | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // Loader UI...
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // XXX would need to delay the original action while the user is 
 | 
					
						
							|  |  |  | // 		browsing...
 | 
					
						
							|  |  |  | var makeBrowseProxy = function(action, callback){ | 
					
						
							| 
									
										
										
										
											2016-04-30 16:58:00 +03:00
										 |  |  | 	return widgets.uiDialog(function(path, logger){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		var that = this | 
					
						
							|  |  |  | 		path = path || this.location.path | 
					
						
							|  |  |  | 		// XXX should we set a start path here to current???
 | 
					
						
							|  |  |  | 		return this.browsePath(path,  | 
					
						
							|  |  |  | 			function(path){  | 
					
						
							|  |  |  | 				var res = that[action](path, logger)  | 
					
						
							|  |  |  | 				callback && callback.call(that, path) | 
					
						
							|  |  |  | 				return res | 
					
						
							| 
									
										
										
										
											2018-12-10 17:56:20 +03:00
										 |  |  | 			}) }) } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | // XXX show list of indexes when more than one are found....
 | 
					
						
							|  |  |  | // 		Ex:
 | 
					
						
							|  |  |  | // 			- <index-1>		x 	- 'x' will strike out the element...
 | 
					
						
							|  |  |  | // 			- <index-2>		x
 | 
					
						
							|  |  |  | // 			- ...
 | 
					
						
							|  |  |  | // 			- load all			- load all non striked out elements
 | 
					
						
							|  |  |  | // 		...would be nice to add either ability to sort manually or some 
 | 
					
						
							|  |  |  | // 		modes of auto-sorting, or both...
 | 
					
						
							|  |  |  | // 		...might be a good idea to add root images with an option to 
 | 
					
						
							|  |  |  | // 		load them...
 | 
					
						
							|  |  |  | // 			...do not think that recursively searching for images is a 
 | 
					
						
							|  |  |  | // 			good idea...
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | var FileSystemLoaderUIActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							|  |  |  | 		// list of loaders to complete .browsePath(..) action
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 		// The loader can be action name or a keyboard.parseActionCall(..) 
 | 
					
						
							|  |  |  | 		// compatible syntax.
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// If an argument string containing "$PATH" is passed then it 
 | 
					
						
							|  |  |  | 		// will be replaces by the selected path...
 | 
					
						
							|  |  |  | 		// 	Example:
 | 
					
						
							|  |  |  | 		// 		'someAction: "$PATH" -- doc'
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		// NOTE: these will be displayed in the same order as they appear
 | 
					
						
							|  |  |  | 		// 		in the list.
 | 
					
						
							|  |  |  | 		// NOTE: the first one is auto-selected.
 | 
					
						
							|  |  |  | 		'path-loaders': [ | 
					
						
							| 
									
										
										
										
											2017-01-31 02:51:06 +03:00
										 |  |  | 			'loadIndex: "$PATH"', | 
					
						
							|  |  |  | 			'loadImages: "$PATH"', | 
					
						
							|  |  |  | 			//'loadPath: "$PATH"',
 | 
					
						
							| 
									
										
										
										
											2017-01-23 20:49:05 +03:00
										 |  |  | 			'---', | 
					
						
							|  |  |  | 			'loadImagesAsRibbon: "$PATH" "above" -- Load images to new ribbon above', | 
					
						
							|  |  |  | 			'loadImagesAsRibbon: "$PATH" "below" -- Load images to new ribbon below', | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		'file-browser-settings': { | 
					
						
							|  |  |  | 			disableFiles: true, | 
					
						
							|  |  |  | 			showNonTraversable: true, | 
					
						
							|  |  |  | 			showDisabled: true, | 
					
						
							| 
									
										
										
										
											2017-01-04 19:05:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-05 19:47:26 +03:00
										 |  |  | 			disableDotFiles: 'on', | 
					
						
							|  |  |  | 			//disableHiddenFiles: false,
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 05:35:19 +03:00
										 |  |  | 			//actionButton: '⋯', 		// "..."
 | 
					
						
							| 
									
										
										
										
											2017-01-04 19:39:04 +03:00
										 |  |  | 			//actionButton: '⮠', 	// down then left arrow (long)
 | 
					
						
							|  |  |  | 			//actionButton: '▹',		// right-pointing white triangle
 | 
					
						
							|  |  |  | 			//actionButton: '◹',		// ne white triangle
 | 
					
						
							|  |  |  | 			//actionButton: '↗',		// ne arrow
 | 
					
						
							|  |  |  | 			//actionButton: '⮣', 	// up then right arrow
 | 
					
						
							|  |  |  | 			//actionButton: '»',			// right-pointing double angle
 | 
					
						
							|  |  |  | 											// quotation mark
 | 
					
						
							| 
									
										
										
										
											2017-01-04 19:05:19 +03:00
										 |  |  | 			// XXX not sure about this...
 | 
					
						
							| 
									
										
										
										
											2017-01-04 19:39:04 +03:00
										 |  |  | 			//actionButton: '📂',	// folder icon (color)
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 	// FS browser...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// XXX should the loader list be nested or open in overlay (as-is now)???
 | 
					
						
							|  |  |  | 	browsePath: ['File/Browse file system...', | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 		widgets.makeUIDialog(function(base, callback){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2017-01-04 19:05:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var cfg = Object.create(this.config['file-browser-settings']) | 
					
						
							|  |  |  | 			cfg.cls = 'file-browser' | 
					
						
							| 
									
										
										
										
											2019-01-05 19:47:26 +03:00
										 |  |  | 			// normalize...
 | 
					
						
							|  |  |  | 			cfg.disableDotFiles = cfg.disableDotFiles == 'on' | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			base = base || this.location.path || '/' | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			base = util.normalizePath(base) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 19:05:19 +03:00
										 |  |  | 			var o = browseWalk.makeWalk(null,  | 
					
						
							|  |  |  | 						base,  | 
					
						
							|  |  |  | 						this.config['image-file-pattern'], | 
					
						
							|  |  |  | 						cfg) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					// path selected...
 | 
					
						
							|  |  |  | 					.open(function(evt, path){  | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 						var item = o.selected | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						// single loader...
 | 
					
						
							|  |  |  | 						if(callback && callback.constructor === Function){ | 
					
						
							|  |  |  | 							// close self and parent...
 | 
					
						
							| 
									
										
										
										
											2017-01-24 00:14:31 +03:00
										 |  |  | 							o.close()  | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							callback(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// list of loaders...
 | 
					
						
							|  |  |  | 						} else { | 
					
						
							| 
									
										
										
										
											2017-01-24 00:14:31 +03:00
										 |  |  | 							// show user the loader list...
 | 
					
						
							| 
									
										
										
										
											2017-01-31 02:51:06 +03:00
										 |  |  | 							var so = that.showActionList( | 
					
						
							|  |  |  | 									callback  | 
					
						
							|  |  |  | 										|| that.config['path-loaders'], | 
					
						
							|  |  |  | 									{ | 
					
						
							|  |  |  | 										path: 0, | 
					
						
							|  |  |  | 										args_dict: { '$PATH': path }, | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2017-01-22 01:39:46 +03:00
										 |  |  | 								// close self and parent...
 | 
					
						
							|  |  |  | 								.open(function(){ | 
					
						
							|  |  |  | 									so.close() | 
					
						
							| 
									
										
										
										
											2017-01-24 00:14:31 +03:00
										 |  |  | 									o.close()  | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 								}) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							return so | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					// we closed the browser -- save settings to .config...
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 					.on('close', function(){ | 
					
						
							| 
									
										
										
										
											2019-01-05 19:47:26 +03:00
										 |  |  | 						var config =  | 
					
						
							|  |  |  | 							that.config['file-browser-settings'] =  | 
					
						
							|  |  |  | 							that.config['file-browser-settings'] || {} | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 						config.disableFiles = o.options.disableFiles | 
					
						
							|  |  |  | 						config.showDisabled = o.options.showDisabled | 
					
						
							|  |  |  | 						config.showNonTraversable = o.options.showNonTraversable | 
					
						
							| 
									
										
										
										
											2019-01-05 19:47:26 +03:00
										 |  |  | 						// normalize...
 | 
					
						
							|  |  |  | 						config.disableDotFiles = o.options.disableDotFiles ? 'on' : 'off' | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2016-12-30 21:24:16 +03:00
										 |  |  | 					 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			return o | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 		})], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 	// Browse indexes/images...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// NOTE: if no path is passed (null) these behave just like .browsePath(..)
 | 
					
						
							|  |  |  | 	// 		with the appropriate callback otherwise it will just load 
 | 
					
						
							|  |  |  | 	// 		the given path (no UI) while .browsePath(..) will load the 
 | 
					
						
							|  |  |  | 	// 		UI in all cases but will treat the given path as a base path 
 | 
					
						
							|  |  |  | 	// 		to start from.
 | 
					
						
							| 
									
										
										
										
											2018-01-23 05:56:02 +03:00
										 |  |  | 	browseIndex: ['- File/Load index...', makeBrowseProxy('loadIndex')], | 
					
						
							|  |  |  | 	browseImages: ['- File/Load images...', makeBrowseProxy('loadImages')], | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 	browseSubIndexes: ['File/List sub-indexes...', | 
					
						
							|  |  |  | 		widgets.makeUIDialog(function(){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 			var index_dir = this.config['index-dir'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var o = browse.makeLister(null, function(path, make){ | 
					
						
							|  |  |  | 				var dialog = this | 
					
						
							|  |  |  | 				var path = that.location.path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 				if(that.location.load != 'loadIndex'){ | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 					make('No indexes loaded...', null, true) | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// indicate that we are working...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 01:17:18 +03:00
										 |  |  | 				var spinner = make('...') | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// XXX we do not need to actually read anything....
 | 
					
						
							|  |  |  | 				//file.loadIndex(path, that.config['index-dir'], this.logger)
 | 
					
						
							|  |  |  | 				// XXX we need to prune the indexes -- avoid loading nested indexes...
 | 
					
						
							|  |  |  | 				file.listIndexes(path, index_dir) | 
					
						
							| 
									
										
										
										
											2016-05-05 01:32:47 +03:00
										 |  |  | 					.on('error', function(err){ | 
					
						
							|  |  |  | 						console.error(err) | 
					
						
							|  |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 					.on('end', function(res){ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						// we got the data, we can now remove the spinner...
 | 
					
						
							|  |  |  | 						spinner.remove() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						res.forEach(function(p){ | 
					
						
							|  |  |  | 							// trim local paths and keep external paths as-is...
 | 
					
						
							|  |  |  | 							p = p.split(index_dir)[0] | 
					
						
							|  |  |  | 							var txt = p.split(path).pop() | 
					
						
							|  |  |  | 							txt = txt != p ? './'+pathlib.join('.', txt) : txt | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							make(txt) | 
					
						
							|  |  |  | 								.on('open', function(){ | 
					
						
							|  |  |  | 									that.loadIndex(p) | 
					
						
							|  |  |  | 								}) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 			.on('open', function(){ | 
					
						
							| 
									
										
										
										
											2017-01-24 00:14:31 +03:00
										 |  |  | 				o.close() | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return o | 
					
						
							|  |  |  | 		})], | 
					
						
							| 
									
										
										
										
											2019-01-05 19:47:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	toggleDotFileDrawing: ['Interface/File browser/Hide dot files', | 
					
						
							|  |  |  | 		core.makeConfigToggler( | 
					
						
							|  |  |  | 			'file-browser-settings.disableDotFiles', | 
					
						
							|  |  |  | 			['on', 'off'])], | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX is this a good name???
 | 
					
						
							|  |  |  | var FileSystemLoaderUI =  | 
					
						
							|  |  |  | module.FileSystemLoaderUI = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'ui-fs-loader', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui', | 
					
						
							|  |  |  | 		'fs-loader' | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: FileSystemLoaderUIActions, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Save History...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemSaveHistoryActions = actions.Actions({ | 
					
						
							|  |  |  | 	// Save comments...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 	// 	.comments.save = {
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	// 		// comment staged for next .saveIndex(..)...
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 	// 		//
 | 
					
						
							|  |  |  | 	// 		// NOTE: 'current' will get replaced with save timestamp...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	// 		'current': <comment>,
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 		<timestamp>: <comment>,
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// NOTE: if comments are not loaded yet this will break...
 | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 	getSaveComment: ['- File/', | 
					
						
							|  |  |  | 		function(save){ | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 			this.comments == null  | 
					
						
							|  |  |  | 				&& console.error('Comments do not appear to be loaded yet...') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 			return (this.comments.save && this.comments.save[save || 'current']) || '' }], | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	// Comment a save...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Comment current save...
 | 
					
						
							|  |  |  | 	// 	.setSaveComment(comment)
 | 
					
						
							|  |  |  | 	// 		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Reset current save comment...
 | 
					
						
							|  |  |  | 	// 	.setSaveComment(null)
 | 
					
						
							|  |  |  | 	// 		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Comment specific save...
 | 
					
						
							|  |  |  | 	// 	.setSaveComment(save, comment)
 | 
					
						
							|  |  |  | 	// 		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// 	Reset specific save comment...
 | 
					
						
							|  |  |  | 	// 	.setSaveComment(save, null)
 | 
					
						
							|  |  |  | 	// 		-> actions
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: "save" is the save format as returned by file.groupByDate(..),
 | 
					
						
							|  |  |  | 	// 		or .loadSaveHistoryList(..)
 | 
					
						
							|  |  |  | 	// 		...normally it is Date.timeStamp() compatible string.
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 	// NOTE: if comments are not loaded yet this will break...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	setSaveComment: ['- File/Comment a save', | 
					
						
							|  |  |  | 		function(save, comment){ | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 			this.comments == null  | 
					
						
							|  |  |  | 				&& console.error('Comments do not appear to be loaded yet...') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 			var comments = this.comments.save = this.comments.save || {} | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// no explicit save given -- stage a comment for next save...
 | 
					
						
							|  |  |  | 			if(comment === undefined){ | 
					
						
							|  |  |  | 				comment = save | 
					
						
							|  |  |  | 				save = 'current' | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(comment === undefined){ | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else if(comment == null){ | 
					
						
							|  |  |  | 				delete comments[save] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				comments[save] = comment | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 			this.markChanged('comments') | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 		}], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	loadSaveHistoryList: ['- File/', | 
					
						
							|  |  |  | 		function(path){ | 
					
						
							| 
									
										
										
										
											2018-12-07 02:28:33 +03:00
										 |  |  | 			var index_dir = this.config['index-dir'] | 
					
						
							|  |  |  | 			path = path || this.location.loaded | 
					
						
							|  |  |  | 			path = path instanceof Array ? path : [path] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var res = {} | 
					
						
							|  |  |  | 			return Promise | 
					
						
							|  |  |  | 				.all(this.location.loaded | 
					
						
							|  |  |  | 					.map(function(path){ | 
					
						
							|  |  |  | 						return file.loadSaveHistoryList(path +'/'+ index_dir) | 
					
						
							|  |  |  | 							.then(function(data){ | 
					
						
							|  |  |  | 								res[path] = data }) })) | 
					
						
							|  |  |  | 				.then(function(){ | 
					
						
							|  |  |  | 					return res }) | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 		}], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemSaveHistory =  | 
					
						
							|  |  |  | module.FileSystemSaveHistory = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'fs-save-history', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 		'fs-loader', | 
					
						
							|  |  |  | 		'fs-comments', | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'ui-fs-save-history', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: FileSystemSaveHistoryActions, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		// Prepare comments for writing...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 		// These will replace .comments.save['current'] with .location.from...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 		// NOTE: defining this here enables us to actually post-bind to
 | 
					
						
							|  |  |  | 		// 		an action that is defined later or may not even be 
 | 
					
						
							|  |  |  | 		// 		available.
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 		// NOTE: 'loadIndex' will also drop any unsaved changes...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 		['prepareIndexForWrite', | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var changed = res.changes === true || res.changes.comments | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-15 23:20:06 +03:00
										 |  |  | 				if(changed){ | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 					var comments = res.raw.comments && res.raw.comments.save || {} | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// set the 'current' comment to the correct date...
 | 
					
						
							|  |  |  | 					if(comments.current){ | 
					
						
							|  |  |  | 						comments[res.date] = comments.current | 
					
						
							|  |  |  | 						delete comments.current | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}], | 
					
						
							|  |  |  | 		['saveIndex', | 
					
						
							|  |  |  | 			function(res){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							| 
									
										
										
										
											2017-05-15 17:26:30 +03:00
										 |  |  | 				var comments = this.comments && this.comments.save | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				if(comments && comments.current){ | 
					
						
							|  |  |  | 					res | 
					
						
							| 
									
										
										
										
											2016-06-14 03:06:35 +03:00
										 |  |  | 						.then(function(res){ | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 							comments[that.location.from] = comments.current | 
					
						
							|  |  |  | 							delete comments.current | 
					
						
							| 
									
										
										
										
											2016-06-14 03:06:35 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							return res | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 						}) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 				// drop unsaved changes...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 				delete this.unsaved_index | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2016-06-14 03:06:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 		// merge save comments...
 | 
					
						
							|  |  |  | 		['loadComments', | 
					
						
							| 
									
										
										
										
											2016-06-14 03:06:35 +03:00
										 |  |  | 			function(res){ | 
					
						
							| 
									
										
										
										
											2016-06-14 17:39:26 +03:00
										 |  |  | 				var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				res.then(function(){ | 
					
						
							|  |  |  | 					// NOTE: if we loaded just one index the comments 
 | 
					
						
							|  |  |  | 					// 		are already loaded and we do not need to do
 | 
					
						
							|  |  |  | 					// 		anything...
 | 
					
						
							|  |  |  | 					if(that.location.loaded.length > 1){ | 
					
						
							|  |  |  | 						var comments = that.comments | 
					
						
							|  |  |  | 						var raw = comments.raw | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						comments.save = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						Object.keys(raw).forEach(function(path){ | 
					
						
							|  |  |  | 							raw[path] && Object.keys(raw[path].save || {}).forEach(function(date){ | 
					
						
							|  |  |  | 								comments.save[date] = raw[path].save[date] | 
					
						
							|  |  |  | 							}) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2016-06-14 03:06:35 +03:00
										 |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	] | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 03:06:35 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | // Save History UI...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX add comment editing...
 | 
					
						
							|  |  |  | // XXX should this also list journal stuff or have the ability for extending???
 | 
					
						
							|  |  |  | var FileSystemSaveHistoryUIActions = actions.Actions({ | 
					
						
							|  |  |  | 	// Saved original index state before loading a state from history...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	unsaved_index: null, | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 	// List save history dialog...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	//	.location.from			- set to timestamp of save state when 
 | 
					
						
							|  |  |  | 	//								selecting a non-top state.
 | 
					
						
							|  |  |  | 	//								NOTE: this may be set to last save 
 | 
					
						
							|  |  |  | 	//									state.
 | 
					
						
							|  |  |  | 	// 	.location.historic		- set to true when at a non-top state.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// For multiple indexes this will show the combined history and 
 | 
					
						
							|  |  |  | 	// selecting a postion will load all the participating indexes to 
 | 
					
						
							|  |  |  | 	// that specific date or closest earlier state.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Unsaved changes will be saved to .unsaved_index when switching 
 | 
					
						
							|  |  |  | 	// from current to a historic state.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 	// NOTE: this will show no history if .location.load is not 'loadIndex'..
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	// NOTE: this will set changes to all when loading a historic state
 | 
					
						
							| 
									
										
										
										
											2016-05-05 01:32:47 +03:00
										 |  |  | 	// 		that the latest and to non otherwise....
 | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-05-05 14:40:58 +03:00
										 |  |  | 	// XXX add comment editing...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	// XXX might be a good idea to show a diff of some kind or at least
 | 
					
						
							|  |  |  | 	// 		what .changed when writing a save...
 | 
					
						
							| 
									
										
										
										
											2017-01-11 20:03:33 +03:00
										 |  |  | 	listSaveHistory: ['File/Edit history...', | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 		widgets.makeUIDialog(function(){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 			var _makeTitle = function(title, date, a){ | 
					
						
							|  |  |  | 				title = [title] | 
					
						
							|  |  |  | 				date = date || 'current' | 
					
						
							|  |  |  | 				a = a || that | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 				var comment = a.comments.save && a.comments.save[date]  | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 				//title.push(comment || '')
 | 
					
						
							|  |  |  | 				comment && title.push(comment) | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 				// XXX is this the best format???
 | 
					
						
							|  |  |  | 				return title.join(' - ') | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 			var o = browse.makeLister(null, function(path, make){ | 
					
						
							|  |  |  | 				var dialog = this | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 				var from = that.location.from | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 				if(that.changes !== false){ | 
					
						
							|  |  |  | 					make(_makeTitle('Current state (unsaved)', 'current'))	 | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-05 01:32:47 +03:00
										 |  |  | 					make('---') | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 				// only search for history if we have an index loaded...
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 				if(that.location.load != 'loadIndex'){ | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 					make('No history...', {disabled: true})	 | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// select the 'Unsaved' item...
 | 
					
						
							|  |  |  | 					dialog.select() | 
					
						
							|  |  |  | 						.addClass('highlighted') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					return | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 				// indicate that we are working...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 01:17:18 +03:00
										 |  |  | 				var spinner = make('...') | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 				that.loadSaveHistoryList() | 
					
						
							|  |  |  | 					.catch(function(err){ | 
					
						
							|  |  |  | 						// XXX
 | 
					
						
							|  |  |  | 						console.error(err) | 
					
						
							|  |  |  | 					}) | 
					
						
							|  |  |  | 					.then(function(data){ | 
					
						
							|  |  |  | 						var list = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 						// got the data, remove the spinner...
 | 
					
						
							|  |  |  | 						spinner.remove() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 						Object.keys(data).forEach(function(path){ | 
					
						
							|  |  |  | 							Object.keys(data[path]).forEach(function(d){ | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 								list.push(d) }) }) | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						list | 
					
						
							|  |  |  | 							.sort() | 
					
						
							|  |  |  | 							.reverse() | 
					
						
							| 
									
										
										
										
											2016-05-05 01:32:47 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 						// Special case: unsaved state...
 | 
					
						
							|  |  |  | 						if(that.unsaved_index){ | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 							var unsaved = that.unsaved_index | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 							make(_makeTitle('Original state (unsaved)', 'current', unsaved))	 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 								.on('open', function(){ | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 									that.load(unsaved) | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 									delete that.unsaved_index }) | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 						// Special case: top save state is the default, 
 | 
					
						
							|  |  |  | 						// no need to mark anything for change, but only
 | 
					
						
							|  |  |  | 						// if nothing changed...
 | 
					
						
							|  |  |  | 						} else if(that.changes === false){ | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 							var first = list.shift() | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 							first && make(_makeTitle(Date.fromTimeStamp(first).toShortDate(), first))	 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 								.on('open', function(){ | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 									that.loadIndex(that.location.path, first) }) } | 
					
						
							| 
									
										
										
										
											2016-05-05 01:32:47 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 						list | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 							.forEach(function(d){ | 
					
						
							|  |  |  | 								var txt = Date.fromTimeStamp(d).toShortDate() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 								make(_makeTitle(Date.fromTimeStamp(d).toShortDate(), d))	 | 
					
						
							| 
									
										
										
										
											2016-05-05 14:40:58 +03:00
										 |  |  | 									.attr('timestamp', d) | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 									.on('open', function(){ | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 										// auto save...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 										if(that.changes !== false | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 												&& !that.location.historic){ | 
					
						
							|  |  |  | 											that.unsaved_index = that.json() | 
					
						
							|  |  |  | 										} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 										that.loadIndex(that.location.path, d) | 
					
						
							| 
									
										
										
										
											2016-05-05 01:32:47 +03:00
										 |  |  | 											.then(function(){ | 
					
						
							|  |  |  | 												that.markChanged('all') | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 19:17:14 +03:00
										 |  |  | 												that.location.historic = true | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 												// remove 'current' comments
 | 
					
						
							|  |  |  | 												// from loaded state...
 | 
					
						
							|  |  |  | 												//
 | 
					
						
							|  |  |  | 												// NOTE: the original 'current'
 | 
					
						
							|  |  |  | 												// 		comment is saved to
 | 
					
						
							|  |  |  | 												// 		.unsaved_index
 | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 												delete that.comments.save.current }) }) | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 									// mark the current loaded position...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 									.addClass(d == from ? 'selected highlighted' : '') }) | 
					
						
							| 
									
										
										
										
											2016-05-04 18:01:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 19:26:26 +03:00
										 |  |  | 						make.done() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-04 18:01:19 +03:00
										 |  |  | 						// NOTE: here we will select 'Latest' if nothing
 | 
					
						
							|  |  |  | 						// 		was selected...
 | 
					
						
							| 
									
										
										
										
											2016-05-04 21:28:46 +03:00
										 |  |  | 						dialog.select() | 
					
						
							| 
									
										
										
										
											2016-05-04 18:01:19 +03:00
										 |  |  | 							.addClass('highlighted') | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2017-07-02 04:36:39 +03:00
										 |  |  | 			}, { | 
					
						
							|  |  |  | 				cls: 'save-history', | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 			.on('open', function(){ | 
					
						
							| 
									
										
										
										
											2017-01-24 00:14:31 +03:00
										 |  |  | 				o.close() | 
					
						
							| 
									
										
										
										
											2016-05-04 17:25:15 +03:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return o | 
					
						
							|  |  |  | 		})], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | var FileSystemSaveHistoryUI =  | 
					
						
							|  |  |  | module.FileSystemSaveHistoryUI = core.ImageGridFeatures.Feature({ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	tag: 'ui-fs-save-history', | 
					
						
							| 
									
										
										
										
											2016-04-20 00:43:20 +03:00
										 |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui', | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 		'fs-save-history', | 
					
						
							| 
									
										
										
										
											2016-04-20 00:43:20 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 	actions: FileSystemSaveHistoryUIActions, | 
					
						
							| 
									
										
										
										
											2016-05-05 18:19:24 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 		['saveIndex', | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 			function(res){ | 
					
						
							|  |  |  | 				delete this.unsaved_index | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2016-05-05 18:19:24 +03:00
										 |  |  | 	] | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // URL History...
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var pushToHistory = function(action, to_top, checker){ | 
					
						
							|  |  |  | 	return [action,  | 
					
						
							|  |  |  | 		function(_, path){  | 
					
						
							|  |  |  | 			path = util.normalizePath(path) | 
					
						
							|  |  |  | 			if(path){ | 
					
						
							|  |  |  | 				this.pushURLToHistory( | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 					path,  | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					action,  | 
					
						
							|  |  |  | 					checker || 'checkPath')  | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if(to_top){ | 
					
						
							|  |  |  | 				this.setTopURLHistory(path) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-01-20 03:55:28 +03:00
										 |  |  | 		}] } | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | var FileSystemURLHistory =  | 
					
						
							|  |  |  | module.FileSystemLoaderURLHistory = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'fs-url-history', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'fs-loader', | 
					
						
							|  |  |  | 		'url-history', | 
					
						
							|  |  |  | 	], | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'ui-fs-url-history', | 
					
						
							|  |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		pushToHistory('loadImages'),  | 
					
						
							|  |  |  | 		pushToHistory('loadIndex'),  | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // URL History UI...
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Opening the url via .browsePath(..) if url is in history will move 
 | 
					
						
							|  |  |  | // it to top of list...
 | 
					
						
							|  |  |  | var FileSystemURLHistoryUI =  | 
					
						
							|  |  |  | module.FileSystemLoaderURLHistoryUI = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'ui-fs-url-history', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							|  |  |  | 		'ui-fs-loader', | 
					
						
							|  |  |  | 		'fs-url-history', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		['browsePath',  | 
					
						
							|  |  |  | 			function(res){  | 
					
						
							|  |  |  | 				var that = this | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 				res.open(function(_, path){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					that.setTopURLHistory(path)  | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			}], | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // Writer...
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | var EXPORT_PREVIEW_NAME = '%(fav)l%n%(-%c)c' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-30 05:02:28 +03:00
										 |  |  | // XXX rename: 'clean-target' -> 'merge-to-target'
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | var FileSystemWriterActions = actions.Actions({ | 
					
						
							|  |  |  | 	config: { | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		// main settings...
 | 
					
						
							|  |  |  | 		'export-settings': { | 
					
						
							|  |  |  | 			'path': null, | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			'include-virtual': true, | 
					
						
							| 
									
										
										
										
											2020-09-30 05:02:28 +03:00
										 |  |  | 			// XXX rename to 'merge-to-target'
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			'clean-target': true, | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			// NOTE: file extension is added automatically...
 | 
					
						
							|  |  |  | 			// NOTE: see .formatImageName(..) for format docs...
 | 
					
						
							|  |  |  | 			'preview-name-pattern': '%(fav)l%n%(-%c)c', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX is this used???
 | 
					
						
							|  |  |  | 			//'level-directory-name': 'fav',
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX do we need both???
 | 
					
						
							|  |  |  | 			'preview-size': 1000, | 
					
						
							|  |  |  | 			'preview-size-limit': 'no limit', | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// history / presets...
 | 
					
						
							|  |  |  | 		'export-paths': [], | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 		'export-preview-name-patterns': [ | 
					
						
							| 
									
										
										
										
											2019-05-16 05:34:44 +03:00
										 |  |  | 			'%(fav)l%n%(-bookmarked)b%(-%c)c', | 
					
						
							|  |  |  | 			'%(fav)l%n%(-bookmarked)b%(-m)m%(-%c)c', | 
					
						
							|  |  |  | 			'%(fav)l%n%(-%c)c', | 
					
						
							|  |  |  | 			'%(fav)l%i-%n', | 
					
						
							|  |  |  | 			'%(fav)l%g-%n', | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 		], | 
					
						
							|  |  |  | 		// XXX add options to indicate:
 | 
					
						
							|  |  |  | 		// 		- long side
 | 
					
						
							|  |  |  | 		// 		- short side
 | 
					
						
							|  |  |  | 		// 		- vertical
 | 
					
						
							|  |  |  | 		// 		- horizontal
 | 
					
						
							|  |  |  | 		// 		- ...
 | 
					
						
							| 
									
										
										
										
											2016-05-23 03:42:53 +03:00
										 |  |  | 		// XXX this repeats sharp.SharpActions.config['preview-sizes']
 | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 		'export-preview-sizes': [ | 
					
						
							| 
									
										
										
										
											2016-04-18 03:05:48 +03:00
										 |  |  | 			'900', | 
					
						
							|  |  |  | 			'1000', | 
					
						
							|  |  |  | 			'1280', | 
					
						
							|  |  |  | 			'1920', | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 		], | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 		'export-preview-size-limits': [ | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 			'no limit', | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 			'900', | 
					
						
							|  |  |  | 			'1000', | 
					
						
							|  |  |  | 			'1280', | 
					
						
							|  |  |  | 			'1920', | 
					
						
							|  |  |  | 		], | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		'export-level-directory-names': [ | 
					
						
							|  |  |  | 			'fav', | 
					
						
							|  |  |  | 			'select', | 
					
						
							|  |  |  | 		], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//'index-filename-template': '${DATE}-${KEYWORD}.${EXT}',
 | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		// This is used in .exportIndex(..) to resolve name conflicts...
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// NOTE: this is applied ONLY if there is a naming conflict...
 | 
					
						
							|  |  |  | 		// NOTE: see .formatImageName(..) for format docs...
 | 
					
						
							|  |  |  | 		// XXX adding a %c is more human-readable but is unstable as
 | 
					
						
							|  |  |  | 		// 		depends on gid order, %g resolves this problem but is 
 | 
					
						
							|  |  |  | 		// 		not very intuitive...
 | 
					
						
							|  |  |  | 		// XXX is this used???
 | 
					
						
							|  |  |  | 		//'export-conflicting-image-name': '%n%(-%g)c',
 | 
					
						
							|  |  |  | 		'export-conflicting-image-name': '%n%(-%c)c', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* XXX LEGACY... | 
					
						
							|  |  |  | 		'export-path': null, | 
					
						
							|  |  |  | 		'export-include-virtual': true, | 
					
						
							|  |  |  | 		'export-clean-target': true, | 
					
						
							|  |  |  | 		'export-preview-name-pattern': '%(fav)l%n%(-%c)c', | 
					
						
							|  |  |  | 		'export-level-directory-name': 'fav', | 
					
						
							|  |  |  | 		'export-preview-size': 1000, | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 		'export-preview-size-limit': 'no limit', | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		//*/
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 	// XXX document data format...
 | 
					
						
							|  |  |  | 	// XXX should %T / %I be global or current crop???
 | 
					
						
							|  |  |  | 	// XXX add comments...
 | 
					
						
							|  |  |  | 	// 		%comment - add comment if present
 | 
					
						
							|  |  |  | 	// 		%(...%comment )comment - add comment if present
 | 
					
						
							|  |  |  | 	// 		...need a better name...
 | 
					
						
							|  |  |  | 	// XXX add tags/keywords... 
 | 
					
						
							|  |  |  | 	// 		%(tag|...)k - if image is tagged with tag add text
 | 
					
						
							|  |  |  | 	formatImageName: ['- File/', | 
					
						
							|  |  |  | 		core.doc`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Filename patterns: | 
					
						
							|  |  |  | 		 	%n		- name without extension | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 	%gid	- full image gid | 
					
						
							|  |  |  | 		 	%g		- short gid | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 	%i		- image index in ribbon | 
					
						
							|  |  |  | 		 	%I		- global image index | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			%r		- ribbon number | 
					
						
							|  |  |  | 			%R		- ribbon number counting from the bottom | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 	%t 		- total number of images in ribbon | 
					
						
							|  |  |  | 		 	%T		- total number of images | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 	%(...)m	- add text in braces if image marked | 
					
						
							|  |  |  | 		 	%(...)b	- add text in braces if image is bookmark | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		 	%(...)C	- add text in braces if there are name conflicts. | 
					
						
							|  |  |  | 						NOTE: this will be added to all images. | 
					
						
							|  |  |  | 		 	%(...)c	- add text in braces if there are name conflicts  | 
					
						
							|  |  |  | 						present, but only if the current image has a  | 
					
						
							|  |  |  | 						conflicting name. | 
					
						
							|  |  |  | 		 	%c		- number in set of conflicting names (default: 0). | 
					
						
							|  |  |  | 						NOTE: this is not stable and can change depending | 
					
						
							|  |  |  | 							on image order. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			%(...)l	- image level path, level depth corresponds to ribbon  | 
					
						
							|  |  |  | 						number counting from the bottom | 
					
						
							|  |  |  | 						NOTE: if level is 0 this resolves to '/' | 
					
						
							|  |  |  | 						Example: '%(x)lz.jop' will resolve to '/z.jpg' for bottom  | 
					
						
							|  |  |  | 							ribbon and to 'x/x/x/z.jpg' for ribbon #3 from the | 
					
						
							|  |  |  | 							bottom. | 
					
						
							|  |  |  | 			%(...)L	- image level path, level depth corresponds to ribbon  | 
					
						
							|  |  |  | 						number counting from the top | 
					
						
							|  |  |  | 						NOTE: if level is 0 this resolves to '/' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: file extension is added automatically. | 
					
						
							|  |  |  | 		NOTE: all group patterns (i.e. '%(..)x') can include other patterns. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Examples: | 
					
						
							|  |  |  | 			These examples are for image 123.jpg at position 2 of 10 (15th | 
					
						
							|  |  |  | 			of 100 total), bookmarked but not marked, in ribbon 1 in a  | 
					
						
							|  |  |  | 			set of 3 ribbons. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			'%(fav)l%i-%n'		-> 'fav/02-123.jpg' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			'%(other)L/%I-John-Smith-%n%(-b)b%(-m)m' | 
					
						
							|  |  |  | 								-> '/10-John-Smith-123-b.jpg' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			'%(best)b/%i of %t - J. Smith - %n' | 
					
						
							|  |  |  | 								-> 'best/02 of 10 - J. Smith - 123.jpg' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		`,
 | 
					
						
							|  |  |  | 		function(pattern, name, data){ | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 			pattern = pattern  | 
					
						
							|  |  |  | 				|| EXPORT_PREVIEW_NAME | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			data = data || {} | 
					
						
							|  |  |  | 			var gid = data.gid | 
					
						
							|  |  |  | 			if(!gid && name in this.images){ | 
					
						
							|  |  |  | 				gid = name | 
					
						
							|  |  |  | 				name = null | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			gid = gid || this.current | 
					
						
							|  |  |  | 			var ribbon = this.data.getRibbon(gid) | 
					
						
							|  |  |  | 			data = Object.assign({},  | 
					
						
							|  |  |  | 				this.images[gid] || {},  | 
					
						
							|  |  |  | 				data) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			name = name  | 
					
						
							|  |  |  | 				|| pathlib.basename( | 
					
						
							|  |  |  | 					data.path || ((data.name || '') + (data.ext || ''))) | 
					
						
							|  |  |  | 			name = name == '' ?  | 
					
						
							|  |  |  | 				gid  | 
					
						
							|  |  |  | 				: name | 
					
						
							|  |  |  | 			var ext = pathlib.extname(name) | 
					
						
							|  |  |  | 			var to_ext = data.ext  | 
					
						
							|  |  |  | 				|| ext | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var tags = data.tags || this.data.getTags(gid) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// XXX revise defaults...
 | 
					
						
							|  |  |  | 			var len = data.len || this.data.ribbons[ribbon].len | 
					
						
							|  |  |  | 			var total_len = data.total_len || this.data.length | 
					
						
							|  |  |  | 			var r_len = data.r_len || Object.keys(this.data.ribbons).length | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var i = data.i || this.data.getImageOrder('ribbon', gid) | 
					
						
							|  |  |  | 			var I = data.I || this.data.getImageOrder('loaded', gid) | 
					
						
							|  |  |  | 			var r = data.r || this.data.getRibbonOrder(gid) | 
					
						
							|  |  |  | 			var R = data.R || r_len - r - 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// pad with zeros...
 | 
					
						
							|  |  |  | 			i = (i+'').padStart((len + '').length, '0') | 
					
						
							|  |  |  | 			I = (I+'').padStart((total_len + '').length, '0') | 
					
						
							|  |  |  | 			r = (r+'').padStart((r_len + '').length, '0') | 
					
						
							|  |  |  | 			R = (R+'').padStart((r_len + '').length, '0') | 
					
						
							|  |  |  | 			//i = ((('1e'+(len+'').length)*1 + i) + '').slice(1)
 | 
					
						
							|  |  |  | 			//I = ((('1e'+(total_len+'').length)*1 + I) + '').slice(1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			var conflicts = data.conflicts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			return pattern | 
					
						
							|  |  |  | 				// file name...
 | 
					
						
							|  |  |  | 				.replace(/%n/, name.replace(ext, '')) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// gid...
 | 
					
						
							|  |  |  | 				.replace(/%gid/, gid) | 
					
						
							|  |  |  | 				// XXX get the correct short gid length...
 | 
					
						
							|  |  |  | 				.replace(/%g/, gid.slice(-6)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// order...
 | 
					
						
							|  |  |  | 				.replace(/%i/, i) | 
					
						
							|  |  |  | 				.replace(/%I/, I) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// ribbon order...
 | 
					
						
							|  |  |  | 				.replace(/%r/, r) | 
					
						
							|  |  |  | 				.replace(/%r/, R) | 
					
						
							|  |  |  | 				 | 
					
						
							|  |  |  | 				// totals...
 | 
					
						
							|  |  |  | 				.replace(/%t/, len) | 
					
						
							|  |  |  | 				.replace(/%T/, total_len) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// conflict count...
 | 
					
						
							|  |  |  | 				.replace(/%c/, (conflicts && conflicts[gid]) ?  | 
					
						
							|  |  |  | 					conflicts[gid].indexOf(gid)  | 
					
						
							|  |  |  | 					: 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// metadata...
 | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Group patterns...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// tags...
 | 
					
						
							|  |  |  | 				// XXX test: %n%(b)b%(m)m%e
 | 
					
						
							|  |  |  | 				.replace( | 
					
						
							|  |  |  | 					/%\(([^)]*)\)m/, tags.indexOf('marked') >= 0 ? '$1' : '') | 
					
						
							|  |  |  | 				.replace( | 
					
						
							|  |  |  | 					/%\(([^)]*)\)b/, tags.indexOf('bookmark') >= 0 ? '$1' : '') | 
					
						
							|  |  |  | 				// XXX
 | 
					
						
							|  |  |  | 				//.replace(
 | 
					
						
							|  |  |  | 				//	/%\(([^)]*)\)k/, tags.indexOf('bookmark') >= 0 ? '$1' : '')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// conflicts...
 | 
					
						
							|  |  |  | 				.replace( | 
					
						
							|  |  |  | 					/%\(([^)]*)\)C/, conflicts ? '$1' : '') | 
					
						
							|  |  |  | 				.replace( | 
					
						
							|  |  |  | 					/%\(([^)]*)\)c/, (conflicts || {})[gid] ? '$1' : '') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// level...
 | 
					
						
							|  |  |  | 				.replace( | 
					
						
							|  |  |  | 					/%\(([^)]*)\)L/,  | 
					
						
							|  |  |  | 					function(match, level, offset, str){ | 
					
						
							|  |  |  | 						return (offset == 0 ? '' : '/')  | 
					
						
							|  |  |  | 							+(new Array(r*1)).fill(level).join('/') | 
					
						
							|  |  |  | 							+(match.length + offset == str.length ? '' : '/') }) | 
					
						
							|  |  |  | 				.replace( | 
					
						
							|  |  |  | 					/%\(([^)]*)\)l/, | 
					
						
							|  |  |  | 					function(match, level, offset, str){ | 
					
						
							|  |  |  | 						return (offset == 0 ? '' : '/')  | 
					
						
							|  |  |  | 							+(new Array(r_len - r*1 - 1)).fill(level).join('/') | 
					
						
							|  |  |  | 							+(match.length + offset == str.length ? '' : '/') }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				+ to_ext | 
					
						
							|  |  |  | 		}], | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 	// XXX should this be sync???
 | 
					
						
							|  |  |  | 	backupDir: ['- File/', | 
					
						
							|  |  |  | 		function(path, logger){ | 
					
						
							|  |  |  | 			// XXX get a logger...
 | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							|  |  |  | 			logger = logger && logger.push('Backup') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 17:44:03 +03:00
										 |  |  | 			do { | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 				var d = Date.timeStamp() | 
					
						
							|  |  |  | 				var backup_dir = `${pathlib.dirname(path)}/.${pathlib.basename(path)}.${d}` | 
					
						
							|  |  |  | 			} while(fse.existsSync(backup_dir)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			logger && logger.emit(backup_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			fse.moveSync(path, backup_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			typeof(process) != 'undefined'  | 
					
						
							|  |  |  | 				&& (process.platform == 'win32'  | 
					
						
							|  |  |  | 					|| process.platform == 'win64') | 
					
						
							|  |  |  | 				&& child_process | 
					
						
							|  |  |  | 					.spawn('attrib', ['+h', backup_dir]) }], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 	// Save index...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Returns:
 | 
					
						
							|  |  |  | 	// 	a promise, when resolved will get the location object as argument.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// NOTE: with no arguments this will save index to .location.path
 | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 	// XXX should this return a promise??? ...a clean promise???
 | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 	// XXX BUG: after .loadImages(..) and without arguments this produces
 | 
					
						
							|  |  |  | 	// 		a result that is not loaded....
 | 
					
						
							| 
									
										
										
										
											2016-04-19 03:12:57 +03:00
										 |  |  | 	saveIndex: ['- File/', | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		function(path, logger){ | 
					
						
							|  |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 			// XXX get a logger...
 | 
					
						
							|  |  |  | 			logger = logger || this.logger | 
					
						
							| 
									
										
										
										
											2016-11-04 23:00:34 +03:00
										 |  |  | 			logger = logger && logger.push('Save') | 
					
						
							| 
									
										
										
										
											2016-05-07 02:02:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-04 05:15:56 +03:00
										 |  |  | 			path = path  | 
					
						
							|  |  |  | 				|| this.location.loaded  | 
					
						
							|  |  |  | 				|| this.location.path | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 			path = path && path.length == 1 ? path[0] : path  | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			path = util.normalizePath(path) | 
					
						
							| 
									
										
										
										
											2016-05-07 02:02:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 			// merged index...
 | 
					
						
							| 
									
										
										
										
											2016-05-07 02:02:42 +03:00
										 |  |  | 			// XXX
 | 
					
						
							|  |  |  | 			if(path instanceof Array){ | 
					
						
							|  |  |  | 				console.error('saving to merged indexes not yet supported...') | 
					
						
							|  |  |  | 				return | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 			// XXX
 | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 			if(path == null && this.location.load != 'loadIndex'){ | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 				path = this.location.path | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 			// resolve relative paths...
 | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 			if(/^(\.\.?[\\\/]|[^\\\/])/.test(path)  | 
					
						
							|  |  |  | 					// and skip windows drives...
 | 
					
						
							|  |  |  | 					&& !/^[a-z]:[\\\/]/i.test(path)){ | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 				// XXX do we need to normalize???
 | 
					
						
							|  |  |  | 				path = this.location.path +'/'+ path | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			// XXX get real base path...
 | 
					
						
							|  |  |  | 			//path = path || this.location.path +'/'+ this.config['index-dir']
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 			// NOTE: this will prevent us from overwriting the location
 | 
					
						
							|  |  |  | 			// 		after we have loaded something else...
 | 
					
						
							|  |  |  | 			var location = this.location | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 			var index = this.prepareIndexForWrite() | 
					
						
							| 
									
										
										
										
											2016-05-06 18:32:00 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 17:39:19 +03:00
										 |  |  | 			var full_path = path +'/'+ this.config['index-dir'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 			return file.writeIndex( | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 					index.index,  | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					// XXX should we check if index dir is present in path???
 | 
					
						
							|  |  |  | 					//path, 
 | 
					
						
							| 
									
										
										
										
											2016-06-05 17:39:19 +03:00
										 |  |  | 					full_path, | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 					index.date, | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 					this.config['index-filename-template'],  | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 					logger) | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 				// set hidden file attribute on Windows...
 | 
					
						
							| 
									
										
										
										
											2016-06-05 17:39:19 +03:00
										 |  |  | 				.then(function(){ | 
					
						
							| 
									
										
										
										
											2016-06-06 01:10:36 +03:00
										 |  |  | 					typeof(process) != 'undefined'  | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 						&& (process.platform == 'win32'  | 
					
						
							|  |  |  | 							|| process.platform == 'win64') | 
					
						
							| 
									
										
										
										
											2016-06-06 01:10:36 +03:00
										 |  |  | 						&& child_process | 
					
						
							|  |  |  | 							.spawn('attrib', ['+h', full_path]) | 
					
						
							| 
									
										
										
										
											2016-06-05 17:39:19 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				.then(function(){ | 
					
						
							| 
									
										
										
										
											2020-05-20 20:31:19 +03:00
										 |  |  | 					location.load = 'loadIndex' | 
					
						
							| 
									
										
										
										
											2016-06-04 20:50:37 +03:00
										 |  |  | 					location.from = index.date | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-14 00:04:53 +03:00
										 |  |  | 					//return location
 | 
					
						
							|  |  |  | 					return index | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				}) | 
					
						
							|  |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 	// XXX add name conflict resolution strategies (pattern)...
 | 
					
						
							|  |  |  | 	// 		...use the same strategy as for .exportDirs(..)
 | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 	// XXX ways to treat a collection:
 | 
					
						
							|  |  |  | 	// 		- crop data
 | 
					
						
							|  |  |  | 	// 		- independent index
 | 
					
						
							|  |  |  | 	// XXX save to: .ImageGrid/collections/<title>/
 | 
					
						
							|  |  |  | 	// XXX move to a feature???
 | 
					
						
							|  |  |  | 	// XXX API: save/load/list/remove
 | 
					
						
							|  |  |  | 	// 		...need to track save location (not the save as the index)...
 | 
					
						
							|  |  |  | 	// XXX
 | 
					
						
							|  |  |  | 	saveCollection: ['- File/Save collection', | 
					
						
							|  |  |  | 		function(title){ | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							|  |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 	// Export current state as a full loadable index
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: if max_size is given the base image in the target path will
 | 
					
						
							|  |  |  | 	// 		be replaced with the largest preview under max_size.
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-04-18 02:22:12 +03:00
										 |  |  | 	// XXX resolve env variables in path...
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 	// XXX what should happen if no path is given???
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 	// XXX handle .image.path and other stack files...
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	// XXX local collections???
 | 
					
						
							| 
									
										
										
										
											2019-11-02 04:05:32 +03:00
										 |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX BUG: this does not remove previews correctly...
 | 
					
						
							|  |  |  | 	// 		to reproduce:
 | 
					
						
							|  |  |  | 	// 			open: L:\media\img\my\2019
 | 
					
						
							|  |  |  | 	// 			exportIndex: with max_size=400
 | 
					
						
							|  |  |  | 	// 				-> main preview is not replaced
 | 
					
						
							|  |  |  | 	// 				-> preivew size 350px not copied but kept in index...
 | 
					
						
							| 
									
										
										
										
											2019-11-03 18:32:49 +03:00
										 |  |  | 	// 		temporary workaround:
 | 
					
						
							|  |  |  | 	//			ig.getPreviews('*')
 | 
					
						
							|  |  |  | 	//				.then(function(){
 | 
					
						
							|  |  |  | 	//					ig.markChanged('images')
 | 
					
						
							|  |  |  | 	//					console.log('done.') })
 | 
					
						
							| 
									
										
										
										
											2019-11-05 14:56:19 +03:00
										 |  |  | 	// XXX when no previews present this should create at least one file
 | 
					
						
							|  |  |  | 	// 		of max_size...
 | 
					
						
							| 
									
										
										
										
											2020-04-06 23:53:57 +03:00
										 |  |  | 	// XXX log gid count instead of file count...
 | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 	exportIndex: ['- File/Export/Export index', | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		core.doc`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			.exportIndex(path) | 
					
						
							|  |  |  | 			.exportIndex(settings) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 		function(path, max_size, include_orig, clean_target_dir, logger){ | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			var settings | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			logger = logger || this.logger | 
					
						
							| 
									
										
										
										
											2016-11-04 23:00:34 +03:00
										 |  |  | 			logger = logger && logger.push('Export index') | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 			if(path && typeof(path) != typeof('str')){ | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				settings = path | 
					
						
							|  |  |  | 				path = settings.path } | 
					
						
							|  |  |  | 			settings = this.config['export-settings'] || {} | 
					
						
							| 
									
										
										
										
											2016-04-18 02:22:12 +03:00
										 |  |  | 			// XXX resolve env variables in path...
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 			// 		...also add ImageGrid specifics: $IG_INDEX, ...
 | 
					
						
							| 
									
										
										
										
											2016-04-18 02:22:12 +03:00
										 |  |  | 			// XXX
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			path = path || './exported' | 
					
						
							|  |  |  | 			path = util.normalizePath(path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			max_size = parseInt(max_size || settings['preview-size-limit']) || null | 
					
						
							|  |  |  | 			// XXX make this dependant on max_size....
 | 
					
						
							|  |  |  | 			include_orig = include_orig || true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 			// clear/backup target...
 | 
					
						
							|  |  |  | 			clean_target_dir = clean_target_dir === undefined ?  | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				settings['clean-target']  | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 				: clean_target_dir | 
					
						
							|  |  |  | 			clean_target_dir | 
					
						
							|  |  |  | 				&& fse.existsSync(path) | 
					
						
							|  |  |  | 				&& this.backupDir(path, logger) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 02:22:12 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 			// resolve relative paths...
 | 
					
						
							| 
									
										
										
										
											2016-04-18 01:52:09 +03:00
										 |  |  | 			if(/^(\.\.?[\\\/]|[^\\\/])/.test(path)  | 
					
						
							|  |  |  | 					// and skip windows drives...
 | 
					
						
							|  |  |  | 					&& !/^[a-z]:[\\\/]/i.test(path)){ | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 				// XXX do we need to normalize???
 | 
					
						
							|  |  |  | 				path = this.location.path +'/'+ path | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			var json = this.json() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// get all loaded gids...
 | 
					
						
							|  |  |  | 			var gids = [] | 
					
						
							|  |  |  | 			for(var r in json.data.ribbons){ | 
					
						
							|  |  |  | 				this.data.makeSparseImages(json.data.ribbons[r], gids) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			gids = gids.compact() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// build .images with loaded images...
 | 
					
						
							|  |  |  | 			var images = {} | 
					
						
							|  |  |  | 			gids.forEach(function(gid){ | 
					
						
							|  |  |  | 				var img = json.images[gid] | 
					
						
							|  |  |  | 				if(img){ | 
					
						
							|  |  |  | 					images[gid] = json.images[gid] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// prepare and save index to target path...
 | 
					
						
							|  |  |  | 			json.data.order = gids | 
					
						
							|  |  |  | 			json.images = images | 
					
						
							|  |  |  | 			// XXX should we check if index dir is present in path???
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			var index_path = path +'/'+ this.config['index-dir'] | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// copy previews for the loaded images...
 | 
					
						
							|  |  |  | 			// XXX should also optionally populate the base dir and nested favs...
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			var base_dir = this.location.path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// check if we have naming conflicts...
 | 
					
						
							|  |  |  | 			var conflicts = this.imageNameConflicts() | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var pattern = this.config['export-conflicting-image-name'] || '%n%(-%g)c%e' | 
					
						
							|  |  |  | 			var total_len = this.data.length | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 			var queue = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			gids.map(function(gid){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				var img = json.images[gid] | 
					
						
							|  |  |  | 				var img_base = img.base_path | 
					
						
							|  |  |  | 				var previews = img.preview | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 				var from_path = img.path | 
					
						
							|  |  |  | 				var to_path = img.path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// resolve name conflicts...
 | 
					
						
							|  |  |  | 				if(conflicts){ | 
					
						
							|  |  |  | 					var base = pathlib.dirname(img.path || '') | 
					
						
							|  |  |  | 					var name = pathlib.basename(img.path || (img.name + img.ext)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// update name via pattern...
 | 
					
						
							|  |  |  | 					name = that.formatImageName(pattern,  | 
					
						
							|  |  |  | 						gid,  | 
					
						
							|  |  |  | 						{ | 
					
						
							|  |  |  | 							total_len: total_len, | 
					
						
							|  |  |  | 							conflicts: conflicts.conflicts, | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// update name...
 | 
					
						
							|  |  |  | 					if(img.name){ | 
					
						
							|  |  |  | 						img.name = img.name == img.path ?  | 
					
						
							|  |  |  | 								pathlib.join(base, name) | 
					
						
							|  |  |  | 							// name without extension...
 | 
					
						
							|  |  |  | 							: img.path == (img.name + img.ext) ?  | 
					
						
							|  |  |  | 								pathlib.join(base, name) | 
					
						
							|  |  |  | 									.split(/\./g) | 
					
						
							|  |  |  | 									.slice(0, -1) | 
					
						
							|  |  |  | 									.join('.') | 
					
						
							|  |  |  | 							// other name...
 | 
					
						
							| 
									
										
										
										
											2019-11-02 04:05:32 +03:00
										 |  |  | 							: img.name } | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					// update path...
 | 
					
						
							|  |  |  | 					to_path = img.path = pathlib.join(base, name) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// update previews...
 | 
					
						
							|  |  |  | 					// NOTE: this is needed if some of the previews are the 
 | 
					
						
							|  |  |  | 					// 		same as .path
 | 
					
						
							|  |  |  | 					Object.keys(img.preview) | 
					
						
							|  |  |  | 						.forEach(function(s){  | 
					
						
							|  |  |  | 							var p = img.preview[s] | 
					
						
							|  |  |  | 							img.preview[s] = p == from_path ? to_path : p | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 				// NOTE: we are copying everything to one place so no 
 | 
					
						
							|  |  |  | 				// 		need for a base path...
 | 
					
						
							|  |  |  | 				delete img.base_path | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 				if(previews || img.path){ | 
					
						
							| 
									
										
										
										
											2019-04-11 02:52:16 +03:00
										 |  |  | 					var seen = new Set() | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 					var max | 
					
						
							|  |  |  | 					var replace_orig = false | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 					Object.keys(previews || {}) | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 						// limit preview size...
 | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 						// NOTE: also remove the preview resolution if 
 | 
					
						
							|  |  |  | 						// 		it's smaller...
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 						.filter(function(res){  | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 							// no size limit or match...
 | 
					
						
							|  |  |  | 							if(!max_size || parseInt(res) <= max_size){ | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 								// get the biggest remaining preview...
 | 
					
						
							| 
									
										
										
										
											2019-11-02 04:05:32 +03:00
										 |  |  | 								max = (max == null  | 
					
						
							|  |  |  | 										|| parseInt(res) > parseInt(max)) ? | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 									res | 
					
						
							|  |  |  | 									: max | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 								return true | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							// skip and remove...
 | 
					
						
							| 
									
										
										
										
											2019-11-02 04:05:32 +03:00
										 |  |  | 							delete previews[res] | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 							replace_orig = true | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 						// get paths...
 | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 						.map(function(res){  | 
					
						
							|  |  |  | 							return res != max ? | 
					
						
							|  |  |  | 								decodeURI(previews[res])  | 
					
						
							|  |  |  | 								// NOTE: we will skip including the preview 
 | 
					
						
							|  |  |  | 								// 		we are using as the primary image to
 | 
					
						
							|  |  |  | 								// 		save space...
 | 
					
						
							|  |  |  | 								: null }) | 
					
						
							|  |  |  | 						// add primary image...
 | 
					
						
							|  |  |  | 						.concat(include_orig && img.path ?  | 
					
						
							|  |  |  | 							[[ | 
					
						
							|  |  |  | 								(replace_orig && max != null) ?  | 
					
						
							|  |  |  | 									// replace the base image with the 
 | 
					
						
							|  |  |  | 									// largest available preview...
 | 
					
						
							|  |  |  | 									previews[max] | 
					
						
							|  |  |  | 									: from_path,  | 
					
						
							|  |  |  | 								img.path | 
					
						
							|  |  |  | 							]]  | 
					
						
							|  |  |  | 							: null) | 
					
						
							|  |  |  | 						// build the from/to paths...
 | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 						.forEach(function(preview_path){ | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 							var to | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 							if(preview_path == null){ | 
					
						
							|  |  |  | 								return | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 							if(preview_path instanceof Array){ | 
					
						
							|  |  |  | 								to = preview_path[1] | 
					
						
							|  |  |  | 								preview_path = preview_path[0] | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// we got a preview that is the same image as .path
 | 
					
						
							|  |  |  | 							if(preview_path == to_path){ | 
					
						
							|  |  |  | 								to = to_path | 
					
						
							|  |  |  | 								preview_path = from_path	 | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 							var from = (img_base || base_dir) +'/'+ preview_path | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 							to = path +'/'+ (to || preview_path) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 03:26:26 +03:00
										 |  |  | 							// we do not need to report repeats...
 | 
					
						
							|  |  |  | 							// NOTE: these can occur because the same image can
 | 
					
						
							|  |  |  | 							// 		be included as a preview and as .path...
 | 
					
						
							| 
									
										
										
										
											2019-04-11 02:52:16 +03:00
										 |  |  | 							if(seen.has(to)){ | 
					
						
							|  |  |  | 								return | 
					
						
							|  |  |  | 							} | 
					
						
							|  |  |  | 							seen.add(to) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 18:29:33 +03:00
										 |  |  | 							// XXX use queue for progress reporting...
 | 
					
						
							|  |  |  | 							logger && logger.emit('queued', to) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 20:11:37 +03:00
										 |  |  | 							// destination exists...
 | 
					
						
							| 
									
										
										
										
											2017-07-25 12:00:48 +03:00
										 |  |  | 							if(fse.existsSync(to)){ | 
					
						
							| 
									
										
										
										
											2016-11-15 20:11:37 +03:00
										 |  |  | 								logger && logger.emit('skipping', to) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// copy...
 | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								// XXX do we queue these or let the OS handle it???
 | 
					
						
							|  |  |  | 								// 		...needs testing, if node's fs queues the io
 | 
					
						
							|  |  |  | 								// 		internally then we do not need to bother...
 | 
					
						
							|  |  |  | 								queue.push(copy(from, to) | 
					
						
							|  |  |  | 									.then(function(){ | 
					
						
							|  |  |  | 										logger && logger.emit('done', to) }) | 
					
						
							|  |  |  | 									.catch(function(err){ | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 										logger && logger.emit('error', err) })) | 
					
						
							| 
									
										
										
										
											2016-11-15 20:11:37 +03:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2016-04-18 04:06:37 +03:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 			// prep the index...
 | 
					
						
							|  |  |  | 			var index = this.prepareIndexForWrite(json, true) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			// NOTE: if we are to use .saveIndex(..) here, do not forget
 | 
					
						
							|  |  |  | 			// 		to reset .changes
 | 
					
						
							| 
									
										
										
										
											2019-11-02 04:05:32 +03:00
										 |  |  | 			queue.push( | 
					
						
							|  |  |  | 					file.writeIndex( | 
					
						
							|  |  |  | 						index.index, | 
					
						
							|  |  |  | 						index_path,  | 
					
						
							|  |  |  | 						index.date, | 
					
						
							|  |  |  | 						this.config['index-filename-template'],  | 
					
						
							|  |  |  | 						logger) | 
					
						
							|  |  |  | 						//logger || this.logger)
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 				// set hidden file attribute on Windows...
 | 
					
						
							| 
									
										
										
										
											2016-06-05 17:39:19 +03:00
										 |  |  | 				.then(function(){ | 
					
						
							| 
									
										
										
										
											2016-06-06 01:10:36 +03:00
										 |  |  | 					typeof(process) != 'undefined'  | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 						&& (process.platform == 'win32'  | 
					
						
							|  |  |  | 							|| process.platform == 'win64') | 
					
						
							| 
									
										
										
										
											2016-06-06 01:10:36 +03:00
										 |  |  | 						&& child_process | 
					
						
							| 
									
										
										
										
											2019-11-02 04:05:32 +03:00
										 |  |  | 							.spawn('attrib', ['+h', index_path]) })) | 
					
						
							| 
									
										
										
										
											2016-06-05 17:39:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return Promise.all(queue) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		}], | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 	// XXX might also be good to save/load the export options to .ImageGrid-export.json
 | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 	// XXX resolve env variables in path... (???)
 | 
					
						
							|  |  |  | 	// XXX make custom previews (option)...
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 	// 		...should this be a function of .images.getBestPreview(..)???
 | 
					
						
							| 
									
										
										
										
											2016-04-18 17:27:34 +03:00
										 |  |  | 	// XXX report errors...
 | 
					
						
							|  |  |  | 	// XXX stop the process on errors...
 | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 	// XXX use tasks...
 | 
					
						
							| 
									
										
										
										
											2016-09-26 22:21:27 +03:00
										 |  |  | 	// XXX check global index ('%I') in crop...
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 	// XXX add option to "clean" destination...
 | 
					
						
							|  |  |  | 	// 		...i.e. if destination exists then move it to .removed/<date>/
 | 
					
						
							| 
									
										
										
										
											2019-10-14 22:46:10 +03:00
										 |  |  | 	// XXX make clean_target more error tolerant...
 | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 	exportDirs: ['- File/Export/Export ribbons as directories', | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 		core.doc`Export ribbons as directories
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 			.exportDirs(path) | 
					
						
							|  |  |  | 			.exportDirs(settings) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-11 01:11:11 +03:00
										 |  |  | 		NOTE: see .formatImageName(..) for pattern syntax details. | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 		function(path, pattern, level_dir, size, include_virtual, clean_target_dir, logger){ | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			logger = logger || this.logger | 
					
						
							| 
									
										
										
										
											2016-11-04 23:00:34 +03:00
										 |  |  | 			logger = logger && logger.push('Export dirs') | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			var that = this | 
					
						
							|  |  |  | 			var base_dir = this.location.path | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 			if(path && typeof(path) != typeof('str')){ | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				settings = path | 
					
						
							|  |  |  | 				path = settings.path } | 
					
						
							|  |  |  | 			settings = this.config['export-settings'] || {} | 
					
						
							|  |  |  | 			// XXX resolve env variables in path...
 | 
					
						
							|  |  |  | 			// 		...also add ImageGrid specifics: $IG_INDEX, ...
 | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							|  |  |  | 			path = path || './exported-dirs' | 
					
						
							| 
									
										
										
										
											2016-05-29 23:49:01 +03:00
										 |  |  | 			path = util.normalizePath(path) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 02:22:12 +03:00
										 |  |  | 			// XXX resolve env variables in path...
 | 
					
						
							|  |  |  | 			// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 			// resolve relative paths...
 | 
					
						
							| 
									
										
										
										
											2016-04-18 01:52:09 +03:00
										 |  |  | 			if(/^(\.\.?[\\\/]|[^\\\/])/.test(path)  | 
					
						
							|  |  |  | 					// and skip windows drives...
 | 
					
						
							|  |  |  | 					&& !/^[a-z]:[\\\/]/i.test(path)){ | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 				// XXX do we need to normalize???
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				path = this.location.path +'/'+ path } | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 			var to_dir = path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// get/set the config data...
 | 
					
						
							|  |  |  | 			// XXX should this store the last set???
 | 
					
						
							| 
									
										
										
										
											2019-05-16 05:00:15 +03:00
										 |  |  | 			level_dir = level_dir === undefined ? | 
					
						
							|  |  |  | 				level_dir  | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				: (level_dir  | 
					
						
							|  |  |  | 					|| settings['level-directory-name']  | 
					
						
							|  |  |  | 						|| 'fav') | 
					
						
							|  |  |  | 			size = size  | 
					
						
							|  |  |  | 				|| settings['preview-size']  | 
					
						
							|  |  |  | 				|| 1000 | 
					
						
							|  |  |  | 			pattern = pattern  | 
					
						
							|  |  |  | 				|| settings['preview-name-pattern']  | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 				|| EXPORT_PREVIEW_NAME | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 			include_virtual = include_virtual === undefined ? | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				settings['include-virtual'] | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 				: include_virtual | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// clear/backup target...
 | 
					
						
							|  |  |  | 			clean_target_dir = clean_target_dir === undefined ?  | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 				settings['clean-target']  | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 				: clean_target_dir | 
					
						
							|  |  |  | 			clean_target_dir | 
					
						
							|  |  |  | 				&& fse.existsSync(to_dir) | 
					
						
							|  |  |  | 				&& this.backupDir(to_dir, logger) | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 			// check if we have naming conflicts...
 | 
					
						
							|  |  |  | 			var conflicts = this.imageNameConflicts() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-18 17:27:34 +03:00
										 |  |  | 			// XXX need to abort on fatal errors...
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 			return Promise.all(this.data.ribbon_order | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 				.slice() | 
					
						
							|  |  |  | 				.reverse() | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 				.map(function(ribbon){ | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 					// NOTE: this is here to keep the specific path local to 
 | 
					
						
							|  |  |  | 					// 		this scope...
 | 
					
						
							|  |  |  | 					var img_dir = to_dir | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 					var res = ensureDir(pathlib.dirname(img_dir)) | 
					
						
							|  |  |  | 						// XXX do we need error handling here???
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 						.catch(function(err){ | 
					
						
							| 
									
										
										
										
											2016-04-18 02:22:12 +03:00
										 |  |  | 							logger && logger.emit('error', err) }) | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 						.then(function(){ | 
					
						
							| 
									
										
										
										
											2016-09-26 22:21:27 +03:00
										 |  |  | 							// XXX revise...
 | 
					
						
							|  |  |  | 							var len = that.data.ribbons[ribbon].len | 
					
						
							|  |  |  | 							var total_len = that.data.length | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 							that.data.ribbons[ribbon].forEach(function(gid){ | 
					
						
							|  |  |  | 								var img = that.images[gid] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								// XXX get/form image name... 
 | 
					
						
							|  |  |  | 								// XXX might be a good idea to connect this to the info framework...
 | 
					
						
							| 
									
										
										
										
											2017-11-10 22:39:20 +03:00
										 |  |  | 								var name = that.formatImageName(pattern,  | 
					
						
							|  |  |  | 									gid,  | 
					
						
							|  |  |  | 									{ | 
					
						
							|  |  |  | 										len: len, | 
					
						
							|  |  |  | 										total_len: total_len, | 
					
						
							|  |  |  | 										conflicts: conflicts.conflicts, | 
					
						
							|  |  |  | 									}) | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 								// handle virtual blocks...
 | 
					
						
							|  |  |  | 								if(img.type == 'virtual'){ | 
					
						
							| 
									
										
										
										
											2019-10-13 13:37:45 +03:00
										 |  |  | 									name = (img.ext || pathlib.extname(name) != '') ?  | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 										name  | 
					
						
							|  |  |  | 										: name +'.txt' | 
					
						
							|  |  |  | 									to = img_dir +'/'+ name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									logger && logger.emit('queued', to) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									var res = include_virtual  | 
					
						
							|  |  |  | 										&& !fse.existsSync(to) | 
					
						
							|  |  |  | 										&& outputFile(to, img.text || '') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								// normal images...
 | 
					
						
							|  |  |  | 								} else { | 
					
						
							|  |  |  | 									// NOTE: we are intentionally losing image dir 
 | 
					
						
							|  |  |  | 									// 		name here -- we do not need to preserve 
 | 
					
						
							|  |  |  | 									// 		topology when exporting...
 | 
					
						
							|  |  |  | 									var img_name = pathlib.basename(img.path || (img.name + img.ext)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									// get best preview...
 | 
					
						
							|  |  |  | 									var from = (img.base_path || base_dir)  | 
					
						
							|  |  |  | 											+'/' | 
					
						
							|  |  |  | 											+ that.images.getBestPreview(gid, size).url | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 									// XXX see if we need to make a preview (sharp)
 | 
					
						
							|  |  |  | 									// XXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									var to = img_dir +'/'+ name | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									logger && logger.emit('queued', to) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									var res = !fse.existsSync(to) | 
					
						
							|  |  |  | 										&& copy(from, to) | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2016-11-14 17:10:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-15 20:11:37 +03:00
										 |  |  | 								// destination exists...
 | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 								if(!res){ | 
					
						
							| 
									
										
										
										
											2016-11-15 20:11:37 +03:00
										 |  |  | 									logger && logger.emit('skipping', to) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 								} else { | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 									return res  | 
					
						
							| 
									
										
										
										
											2016-11-15 20:11:37 +03:00
										 |  |  | 										.then(function(){ | 
					
						
							|  |  |  | 											logger && logger.emit('done', to) }) | 
					
						
							|  |  |  | 										.catch(function(err){ | 
					
						
							|  |  |  | 											logger && logger.emit('error', err) }) | 
					
						
							|  |  |  | 								} | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 							}) | 
					
						
							|  |  |  | 						}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 05:00:15 +03:00
										 |  |  | 					to_dir += level_dir != null ?  | 
					
						
							|  |  |  | 						'/'+level_dir | 
					
						
							|  |  |  | 						: '' | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					return res | 
					
						
							|  |  |  | 				})) | 
					
						
							| 
									
										
										
										
											2016-04-15 23:32:33 +03:00
										 |  |  | 		}] | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemWriter =  | 
					
						
							|  |  |  | module.FileSystemWriter = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'fs-writer', | 
					
						
							|  |  |  | 	// NOTE: this is mostly because of the base path handling...
 | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | 	depends: [ | 
					
						
							| 
									
										
										
										
											2016-05-26 05:36:28 +03:00
										 |  |  | 		'fs-loader', | 
					
						
							|  |  |  | 		'index-format', | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'ui-fs-writer', | 
					
						
							|  |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	actions: FileSystemWriterActions, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-04 08:08:40 +03:00
										 |  |  | 	isApplicable: function(){ return this.runtime.node }, | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// monitor changes...
 | 
					
						
							|  |  |  | 	// XXX should we use .load(..) to trigger changes instead of .loadURLs(..)???
 | 
					
						
							|  |  |  | 	// 		...the motivation is that .crop(..) may also trigger loads...
 | 
					
						
							|  |  |  | 	// 		....needs more thought...
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							|  |  |  | 		// clear changes...
 | 
					
						
							|  |  |  | 		// XXX currently if no args are passed then nothing is 
 | 
					
						
							|  |  |  | 		// 		done here, this might change...
 | 
					
						
							|  |  |  | 		['saveIndex', | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 			function(res, path){ | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				// NOTE: if saving to a different path than loaded do not
 | 
					
						
							|  |  |  | 				// 		drop the .changes flags...
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 				if(!path || path == this.location.path){ | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 					//this.markChanged('none')
 | 
					
						
							|  |  |  | 					var that = this | 
					
						
							|  |  |  | 					res.then(function(){ | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 						that.markChanged('none') | 
					
						
							| 
									
										
										
										
											2016-04-01 18:42:45 +03:00
										 |  |  | 					}) | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			}], | 
					
						
							| 
									
										
										
										
											2016-07-03 03:47:12 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | // Writer UI...
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-04 01:45:51 +03:00
										 |  |  | var object = require('lib/object') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX move this to browse2 and use it as an option/basis for list...
 | 
					
						
							|  |  |  | // XXX BUG: UniqueKeyMap([['a', 123], ...]) breaks...
 | 
					
						
							|  |  |  | var UniqueKeyMap = object.Constructor('UniqueKeyMap', Map, { | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	Map([
 | 
					
						
							|  |  |  | 	// 		[ <elem>, <original-name> ],
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	])
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// XXX make this a non-enumerable prop...
 | 
					
						
							|  |  |  | 	__names: null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__name_pattern__: '$NAME ($COUNT)', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX problem: non unique elems will override each other in .__names...
 | 
					
						
							|  |  |  | 	set: function(key, elem){ | 
					
						
							|  |  |  | 		// elem already in index -> rename...
 | 
					
						
							|  |  |  | 		// XXX should we have the restriction of requiring unique elements??? 
 | 
					
						
							|  |  |  | 		if(this.__names.has(elem)){ | 
					
						
							|  |  |  | 			return this.rename(this.__names.get(elem), key) } | 
					
						
							|  |  |  | 		this.__names[elem] = key | 
					
						
							|  |  |  | 		var n = key | 
					
						
							|  |  |  | 		var i = 0 | 
					
						
							|  |  |  | 		while(this.has(n)){ | 
					
						
							|  |  |  | 			i++ | 
					
						
							|  |  |  | 			n = this.__name_pattern__ | 
					
						
							|  |  |  | 				.replace(/\$NAME/, key) | 
					
						
							|  |  |  | 				.replace(/\$COUNT/, i) } | 
					
						
							|  |  |  | 		return object.parentCall(UniqueKeyMap.prototype, 'set', this, n, elem) }, | 
					
						
							|  |  |  | 	delete: function(key){ | 
					
						
							|  |  |  | 		delete this.__names[this.get(key)] | 
					
						
							|  |  |  | 		return object.parentCall(UniqueKeyMap.prototype, 'delete', this, key) }, | 
					
						
							|  |  |  | 	rename: function(from, to){ | 
					
						
							|  |  |  | 		var e = this.get(from) | 
					
						
							|  |  |  | 		this.delete(from) | 
					
						
							|  |  |  | 		return this.set(to, e) }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	__init__: function(){ | 
					
						
							|  |  |  | 		this.__names = new Map() }, | 
					
						
							|  |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | // XXX add writer UI feature...
 | 
					
						
							|  |  |  | // 		- save as.. (browser)
 | 
					
						
							|  |  |  | // 		- save if not base path present (browser)
 | 
					
						
							|  |  |  | var FileSystemWriterUIActions = actions.Actions({ | 
					
						
							| 
									
										
										
										
											2016-04-16 04:17:34 +03:00
										 |  |  | 	config: { | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		// NOTE: for more docs on export settings see FileSystemWriter.config...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 04:17:34 +03:00
										 |  |  | 		'export-dialog-modes': { | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 			// XXX is this the right title???
 | 
					
						
							|  |  |  | 			// XXX this is not yet working...
 | 
					
						
							|  |  |  | 			'Save index to current location': { | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 				alias: 'save', | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 				action: 'saveIndexHere', | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 				data: [ | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 					'comment' | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 				], | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 			'Current state as index': { | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 				alias: 'index', | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 				action: 'exportIndex', | 
					
						
							|  |  |  | 				data: [ | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 					//'name',
 | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 					'base_path', | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 					'target_dir', | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 					'clean_target_dir', | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 					// XXX need to add options to size: 'none',
 | 
					
						
							|  |  |  | 					// XXX use closest preview instead of hi-res when 
 | 
					
						
							|  |  |  | 					// 		this is set...
 | 
					
						
							| 
									
										
										
										
											2016-06-07 04:03:56 +03:00
										 |  |  | 					// XXX need to add option to save full index...
 | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 					'size_limit', | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 					// XXX might be a good idea to include source data links
 | 
					
						
							|  |  |  | 					//'include_source_url', // bool
 | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 					'comment', | 
					
						
							|  |  |  | 				], | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			'Images only': { | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 				alias: 'images', | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 				action: 'exportDirs', | 
					
						
							|  |  |  | 				data: [ | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 					//'name',
 | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 					'pattern', | 
					
						
							|  |  |  | 					'size', | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 					'include_virtual', | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 					'base_path', | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 					'target_dir', | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 					'clean_target_dir', | 
					
						
							| 
									
										
										
										
											2019-05-16 05:00:15 +03:00
										 |  |  | 					// XXX add option to disable this...
 | 
					
						
							|  |  |  | 					//'level_dir',
 | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 				], | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2016-04-16 04:17:34 +03:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-10-19 00:39:50 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		//
 | 
					
						
							|  |  |  | 		// Format:
 | 
					
						
							|  |  |  | 		// 	{
 | 
					
						
							|  |  |  | 		//		// NOTE: this is set/used by .exportDialog(..)
 | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 		//		// XXX replace this with action...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		//		'mode': 'Images only',
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		//		// NOTE: for more info see FileSystemWriter.config['export-settings']...
 | 
					
						
							|  |  |  | 		//		...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		// 	}
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// XXX this will accumulate settings from all export modes, is this correct???
 | 
					
						
							|  |  |  | 		// XXX this is not yet used by the actual export actions, only for the UI...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 21:32:06 +03:00
										 |  |  | 		//'export-settings': {},
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		//
 | 
					
						
							|  |  |  | 		// Format:
 | 
					
						
							| 
									
										
										
										
											2019-10-19 00:39:50 +03:00
										 |  |  | 		// 	[
 | 
					
						
							|  |  |  | 		// 		{
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		// 			// preset name (optional)...
 | 
					
						
							|  |  |  | 		// 			name: ...,
 | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		// 			// see: 'export-settings' for more settings...
 | 
					
						
							| 
									
										
										
										
											2019-10-19 00:39:50 +03:00
										 |  |  | 		// 			...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		// 		},
 | 
					
						
							|  |  |  | 		// 		...
 | 
					
						
							| 
									
										
										
										
											2019-10-19 00:39:50 +03:00
										 |  |  | 		// 	]
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		//
 | 
					
						
							| 
									
										
										
										
											2019-10-19 00:39:50 +03:00
										 |  |  | 		// XXX should this be a dict or a list???
 | 
					
						
							|  |  |  | 		// 		...a dict would require keys (gid/title??)
 | 
					
						
							|  |  |  | 		// XXX should this api be accessible from outside the ui???
 | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 		'export-presets': [ | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 				'name': './select (ribbons to "./fav/..")', | 
					
						
							|  |  |  | 				'mode': 'Images only', | 
					
						
							|  |  |  | 				'path': './select', | 
					
						
							|  |  |  | 				'include-virtual': true, | 
					
						
							|  |  |  | 				'clean-target': true, | 
					
						
							|  |  |  | 				'preview-name-pattern': '%(fav)l%n%(-%c)c', | 
					
						
							|  |  |  | 				'preview-size': 1000, | 
					
						
							|  |  |  | 				'preview-size-limit': 'no limit', | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 				'mode': 'Images only', | 
					
						
							|  |  |  | 				'path': 'L:/tmp/test/export-test/images-only/', | 
					
						
							|  |  |  | 				'include-virtual': true, | 
					
						
							|  |  |  | 				'clean-target': true, | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 				'preview-name-pattern': '%n%(-b)b%(-%c)c', | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 				'preview-size': 1000, | 
					
						
							|  |  |  | 				'preview-size-limit': 'no limit', | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 		], | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 		'export-history-length': 50, | 
					
						
							| 
									
										
										
										
											2020-09-29 03:19:15 +03:00
										 |  |  | 		// XXX should this be stored here or like file history in session???
 | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 		'export-history': [], | 
					
						
							| 
									
										
										
										
											2016-04-16 04:17:34 +03:00
										 |  |  | 	}, | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 	// XXX rename???
 | 
					
						
							|  |  |  | 	// XXX should this be here or in FileSystemWriter???
 | 
					
						
							|  |  |  | 	// 		...FileSystemWriter does not define .mode for this to work correctly...
 | 
					
						
							|  |  |  | 	exportAs: ['- File/', | 
					
						
							|  |  |  | 		function(settings){ | 
					
						
							|  |  |  | 			settings = settings  | 
					
						
							|  |  |  | 				|| this.config['export-settings'] | 
					
						
							|  |  |  | 			var action = this.config['export-dialog-modes'][settings.mode].action | 
					
						
							|  |  |  | 			return this[action](settings) }], | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-01 19:02:28 +03:00
										 |  |  | 	// XXX this needs feedback...
 | 
					
						
							| 
									
										
										
										
											2016-04-07 16:09:29 +03:00
										 |  |  | 	// XXX should this return a promise???
 | 
					
						
							| 
									
										
										
										
											2017-08-26 23:58:52 +03:00
										 |  |  | 	saveIndexHere: ['File/$Save', | 
					
						
							| 
									
										
										
										
											2019-12-31 19:47:25 +03:00
										 |  |  | 		core.doc`Save changes...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: if .location is empty this will prompt user for save path by  | 
					
						
							| 
									
										
										
										
											2019-12-31 19:52:32 +03:00
										 |  |  | 			launching .exportIndexDialog(..) | 
					
						
							| 
									
										
										
										
											2019-12-31 19:47:25 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		function(){  | 
					
						
							| 
									
										
										
										
											2019-12-31 19:47:25 +03:00
										 |  |  | 			this.location.path ?  | 
					
						
							| 
									
										
										
										
											2016-04-19 02:42:21 +03:00
										 |  |  | 				this.saveIndex()  | 
					
						
							| 
									
										
										
										
											2019-12-31 19:52:32 +03:00
										 |  |  | 				: this.exportIndexDialog() }], | 
					
						
							| 
									
										
										
										
											2016-04-19 03:12:57 +03:00
										 |  |  | 	// XXX should this be a UI action???
 | 
					
						
							|  |  |  | 	// 		...at this point this depends on .saveIndexHere(..), thus 
 | 
					
						
							|  |  |  | 	// 		it is here...
 | 
					
						
							| 
									
										
										
										
											2016-04-07 16:09:29 +03:00
										 |  |  | 	// XXX should this return a promise???
 | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 	saveFullIndex: ['File/Save ($full)', | 
					
						
							| 
									
										
										
										
											2019-12-31 19:47:25 +03:00
										 |  |  | 		core.doc`Save full state...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: for more info see: .saveIndexHere(..)`,
 | 
					
						
							| 
									
										
										
										
											2016-04-19 03:12:57 +03:00
										 |  |  | 		function(){ | 
					
						
							|  |  |  | 			return this | 
					
						
							|  |  |  | 				.markChanged('all') | 
					
						
							|  |  |  | 				.saveIndexHere()}], | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 	saveWithCommentDialog: ['File/Save with $comment...',  | 
					
						
							| 
									
										
										
										
											2019-12-31 19:47:25 +03:00
										 |  |  | 		'exportDialog: "save" -- Save full state with a comment...'], | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Export dialog...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-04-17 00:58:21 +03:00
										 |  |  | 	// Export <mode> is set by:
 | 
					
						
							|  |  |  | 	// 		.config['export-mode']
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 	// The fields used and their order is set by:
 | 
					
						
							| 
									
										
										
										
											2016-04-17 00:58:21 +03:00
										 |  |  | 	// 		.config['export-modes'][<mode>].data	(list)
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 	// The action used to export is set by:
 | 
					
						
							| 
									
										
										
										
											2016-04-17 00:58:21 +03:00
										 |  |  | 	// 		.config['export-modes'][<mode>].action
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Dialog fields...
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// Format:
 | 
					
						
							|  |  |  | 	// 	{
 | 
					
						
							|  |  |  | 	// 		// Arguments:
 | 
					
						
							|  |  |  | 	// 		//	actions		- the actions object
 | 
					
						
							|  |  |  | 	// 		//	make		- browse item constructor 
 | 
					
						
							|  |  |  | 	// 		//					(see: browse.Browser.update(..) for more info)
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 	// 		//	parent		- the parent dialog
 | 
					
						
							| 
									
										
										
										
											2016-04-17 00:58:21 +03:00
										 |  |  | 	// 		<key>: function(actions, make, overlay){ ... },
 | 
					
						
							|  |  |  | 	// 		...
 | 
					
						
							|  |  |  | 	// 	}
 | 
					
						
							|  |  |  | 	//
 | 
					
						
							|  |  |  | 	// NOTE: .__export_dialog_fields__ can be defined both in the feature
 | 
					
						
							|  |  |  | 	// 		as well as in the instance.
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 	// NOTE: the export action should get all of its arguments from config
 | 
					
						
							|  |  |  | 	// 		except for the export path...
 | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 	__export_dialog_fields__: { | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		'pattern': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 			var img = actions.current | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 			var pattern =  | 
					
						
							|  |  |  | 				settings['preview-name-pattern'] = | 
					
						
							|  |  |  | 					settings['preview-name-pattern']  | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 					|| EXPORT_PREVIEW_NAME | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			var showExaples = function(pattern, img){ | 
					
						
							|  |  |  | 				img = img || actions.current | 
					
						
							|  |  |  | 				return actions.showList([ | 
					
						
							|  |  |  | 					// current...
 | 
					
						
							|  |  |  | 					['Current:',  | 
					
						
							|  |  |  | 						actions.formatImageName(pattern, img)], | 
					
						
							|  |  |  | 					['Marked:',  | 
					
						
							|  |  |  | 						actions.formatImageName(pattern,  | 
					
						
							|  |  |  | 							img,  | 
					
						
							| 
									
										
										
										
											2018-11-08 21:10:58 +03:00
										 |  |  | 							{tags: ['marked']})], | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 					['Bookmarked:',  | 
					
						
							|  |  |  | 						actions.formatImageName(pattern,  | 
					
						
							|  |  |  | 							img,  | 
					
						
							|  |  |  | 							{tags: ['bookmark']})], | 
					
						
							|  |  |  | 					['Repeating:',  | 
					
						
							|  |  |  | 						actions.formatImageName(pattern,  | 
					
						
							|  |  |  | 							img,  | 
					
						
							|  |  |  | 							{conflicts: {[actions.current]: ['', actions.current], }} )], | 
					
						
							|  |  |  | 					['All:',  | 
					
						
							|  |  |  | 						actions.formatImageName(pattern,  | 
					
						
							|  |  |  | 							img,  | 
					
						
							|  |  |  | 							{ | 
					
						
							|  |  |  | 								tags: [ | 
					
						
							| 
									
										
										
										
											2018-11-08 21:10:58 +03:00
										 |  |  | 									'marked', | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 									'bookmark', | 
					
						
							|  |  |  | 								], | 
					
						
							|  |  |  | 								conflicts: { | 
					
						
							|  |  |  | 									[img]: ['', img], | 
					
						
							|  |  |  | 								} | 
					
						
							|  |  |  | 							} )], | 
					
						
							|  |  |  | 				], { | 
					
						
							|  |  |  | 					cls: 'table-view', | 
					
						
							|  |  |  | 				}) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-15 01:11:18 +03:00
										 |  |  | 			// XXX make this a dialog...
 | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 			var res = make(['Filename $pattern: ', pattern], { | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 				open: widgets.makeNestedConfigListEditor(actions, parent, | 
					
						
							|  |  |  | 					'export-preview-name-patterns', | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					'export-settings.preview-name-pattern', { | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 						length_limit: 10, | 
					
						
							|  |  |  | 						events: { | 
					
						
							|  |  |  | 							menu: function(_, p){ showExaples(p) }, | 
					
						
							|  |  |  | 						}, | 
					
						
							|  |  |  | 						buttons: [ | 
					
						
							|  |  |  | 							['i', function(p){ showExaples(p) }], | 
					
						
							|  |  |  | 						], | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 					}, function(){ | 
					
						
							|  |  |  | 						this.showExaples = function(){ showExaples(this.selected) } | 
					
						
							|  |  |  | 						this.keyboard.handler('General', 'i', 'showExaples') | 
					
						
							|  |  |  | 						this.showDoc = function(){ actions.showDoc('formatImageName') } | 
					
						
							|  |  |  | 						this.keyboard.handler('General', '?', 'showDoc') | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 					}), | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 				buttons: [ | 
					
						
							|  |  |  | 					['?', function(){ | 
					
						
							|  |  |  | 						actions.showDoc('formatImageName') | 
					
						
							|  |  |  | 					}], | 
					
						
							|  |  |  | 				], | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// show example generated names...
 | 
					
						
							|  |  |  | 			make(['Filename:',  | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 				function(){ return actions.formatImageName(pattern, img) }], | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					open: function(){  | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 						showExaples(settings['preview-name-pattern']  | 
					
						
							|  |  |  | 							|| EXPORT_PREVIEW_NAME) }, }) | 
					
						
							| 
									
										
										
										
											2017-11-13 23:38:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 			return res }, | 
					
						
							| 
									
										
										
										
											2019-05-16 05:00:15 +03:00
										 |  |  | 		// XXX add option not to create level dirs...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		'level_dir': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 			return make(['$Level directory: ',  | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 					function(){  | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 						return settings['level-directory-name'] || 'fav' }]) | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 				.on('open',  | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 					widgets.makeNestedConfigListEditor(actions, parent, | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 						'export-level-directory-names',  | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 						'export-settings.level-directory-name', { | 
					
						
							| 
									
										
										
										
											2017-01-25 22:22:33 +03:00
										 |  |  | 							length_limit: 10, | 
					
						
							| 
									
										
										
										
											2019-05-16 05:00:15 +03:00
										 |  |  | 						})) }, | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 		// XXX should we merge this with 'size_limit'????
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		'size': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 			return make(['Image $size: ',  | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 					function(){  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 						return (settings['preview-size'] =  | 
					
						
							|  |  |  | 							settings['preview-size']  | 
					
						
							|  |  |  | 							|| 1000) }]) | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 				.on('open',  | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 					widgets.makeNestedConfigListEditor(actions, parent, | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 						'export-preview-sizes', | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 						'export-settings.preview-size', | 
					
						
							| 
									
										
										
										
											2016-04-18 03:05:48 +03:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2017-01-25 22:22:33 +03:00
										 |  |  | 							length_limit: 10, | 
					
						
							| 
									
										
										
										
											2016-04-18 03:05:48 +03:00
										 |  |  | 							sort: function(a, b){ return parseInt(a) - parseInt(b) }, | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 							check: function(e){ | 
					
						
							|  |  |  | 								return !!parseInt(e) }, | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 						})) }, | 
					
						
							|  |  |  | 		'size_limit': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 			return make(['Limit image $size: ',  | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 					function(){  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 						return (settings['preview-size-limit'] = | 
					
						
							|  |  |  | 							settings['preview-size-limit']  | 
					
						
							|  |  |  | 							|| 'no limit') }], | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 					{ buttons: [ | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 						['clear', function(p){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 							settings['preview-size-limit'] = 'no limit' | 
					
						
							|  |  |  | 							parent.update() }], | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 					] }) | 
					
						
							|  |  |  | 				.on('open',  | 
					
						
							|  |  |  | 					widgets.makeNestedConfigListEditor(actions, parent, | 
					
						
							|  |  |  | 						'export-preview-size-limits', | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 						'export-settings.preview-size-limit', | 
					
						
							| 
									
										
										
										
											2016-06-08 18:10:39 +03:00
										 |  |  | 						{ | 
					
						
							| 
									
										
										
										
											2017-01-25 22:22:33 +03:00
										 |  |  | 							length_limit: 10, | 
					
						
							| 
									
										
										
										
											2019-04-15 15:44:28 +03:00
										 |  |  | 							// sort ascending + keep 'no limit' at top...
 | 
					
						
							|  |  |  | 							sort: function(a, b){  | 
					
						
							|  |  |  | 								return a == 'no limit' ? | 
					
						
							|  |  |  | 										-1 | 
					
						
							|  |  |  | 									: b == 'no limit' ? | 
					
						
							|  |  |  | 										1 | 
					
						
							|  |  |  | 									: parseInt(a) - parseInt(b) }, | 
					
						
							|  |  |  | 							check: function(e){ | 
					
						
							|  |  |  | 								return e == 'no limit'  | 
					
						
							|  |  |  | 									|| !!parseInt(e) }, | 
					
						
							|  |  |  | 							remove: function(e){ | 
					
						
							|  |  |  | 								return e != 'no limit' }, | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 						})) }, | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 		// XXX should this be editable???
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		'base_path': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 			var elem = make(['Current path: ', this.location.path],  | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-04-17 01:36:05 +03:00
										 |  |  | 					select: function(){ | 
					
						
							|  |  |  | 						elem.find('.text').last().selectText() }, | 
					
						
							|  |  |  | 					deselect: function(){ | 
					
						
							|  |  |  | 						elem.find('.text').last().selectText(null) }, | 
					
						
							|  |  |  | 				}) }, | 
					
						
							| 
									
										
										
										
											2016-04-17 01:56:52 +03:00
										 |  |  | 		// XXX BUG: history closing errors -- non-critical...
 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		'target_dir': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 			var elem = make(['$To: ',  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 				function(){  | 
					
						
							|  |  |  | 					return (settings['path'] =  | 
					
						
							|  |  |  | 						settings['path']  | 
					
						
							|  |  |  | 						|| './') }],  | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 				{  | 
					
						
							|  |  |  | 					buttons: [ | 
					
						
							|  |  |  | 						['browse', function(p){ | 
					
						
							|  |  |  | 							var e = this.filter('"'+p+'"', false) | 
					
						
							|  |  |  | 							var path = e.find('.text').last().text() | 
					
						
							|  |  |  | 							var txt = e.find('.text').first().text() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 							// XXX add new dir global button...
 | 
					
						
							|  |  |  | 							return actions.browsePath(path,  | 
					
						
							|  |  |  | 								function(path){  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 									settings['path'] = path | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 									actions.config['export-paths'].splice(0, 0, path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									parent.update() | 
					
						
							|  |  |  | 									parent.select(txt) | 
					
						
							|  |  |  | 								}) | 
					
						
							|  |  |  | 						}], | 
					
						
							|  |  |  | 						// XXX BUG: closing this breaks on parant.focus()...
 | 
					
						
							| 
									
										
										
										
											2020-07-07 16:35:43 +03:00
										 |  |  | 						['history', widgets.makeNestedConfigListEditor(actions, parent, | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 							'export-paths', | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 							'export-settings.path', | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 							{ | 
					
						
							|  |  |  | 								length_limit: 10, | 
					
						
							|  |  |  | 								new_item: false, | 
					
						
							|  |  |  | 							})], | 
					
						
							|  |  |  | 					], | 
					
						
							|  |  |  | 					// XXX make this editable???
 | 
					
						
							|  |  |  | 					open: function(){ | 
					
						
							|  |  |  | 						event.preventDefault() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						var path = elem.find('.text').last() | 
					
						
							|  |  |  | 							.makeEditable({ | 
					
						
							|  |  |  | 								activate: true, | 
					
						
							|  |  |  | 								clear_on_edit: false, | 
					
						
							|  |  |  | 								abort_keys: [ | 
					
						
							|  |  |  | 									'Esc', | 
					
						
							|  |  |  | 								], | 
					
						
							|  |  |  | 							}) | 
					
						
							|  |  |  | 							.on('edit-commit', function(_, path){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 								settings['path'] = path | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 								actions.config['export-paths'].indexOf(path) < 0 | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 									&& actions.config['export-paths'].splice(0, 0, path) }) | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 							.on('edit-abort edit-commit', function(evt, path){ | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 								parent.update() | 
					
						
							| 
									
										
										
										
											2019-04-16 19:47:27 +03:00
										 |  |  | 									.then(function(){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 										parent.select(path) }) }) }, | 
					
						
							|  |  |  | 				}) }, | 
					
						
							|  |  |  | 		'comment': function(actions, make, parent, settings){ | 
					
						
							| 
									
										
										
										
											2017-11-14 00:13:47 +03:00
										 |  |  | 			var elem = make(['$Comment: ',  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					// XXX get staged comment???
 | 
					
						
							|  |  |  | 					function(){ return actions.getSaveComment() }]) | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 				.on('open', function(){ | 
					
						
							|  |  |  | 					event.preventDefault() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					// XXX multiline???
 | 
					
						
							|  |  |  | 					var path = elem.find('.text').last() | 
					
						
							|  |  |  | 						.makeEditable({ | 
					
						
							| 
									
										
										
										
											2016-06-07 06:03:16 +03:00
										 |  |  | 							activate: true, | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 							multiline: true, | 
					
						
							|  |  |  | 							clear_on_edit: false, | 
					
						
							|  |  |  | 							abort_keys: [ | 
					
						
							|  |  |  | 								'Esc', | 
					
						
							|  |  |  | 							], | 
					
						
							|  |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2017-01-25 22:22:33 +03:00
										 |  |  | 						.on('edit-commit', function(_, text){ | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 							actions.setSaveComment(text) | 
					
						
							|  |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2017-01-25 22:22:33 +03:00
										 |  |  | 						.on('edit-abort edit-commit', function(evt, text){ | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 							parent.update() | 
					
						
							|  |  |  | 								.then(function(){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 									parent.select(text) }) }) }) }, | 
					
						
							|  |  |  | 		'include_virtual': function(actions, make, parent, settings){ | 
					
						
							|  |  |  | 			settings['include-virtual'] = !!settings['include-virtual'] | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 			var elem = make([ | 
					
						
							|  |  |  | 					'Include $virtual: ',  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					settings['include-virtual'] ? | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 						'yes'  | 
					
						
							|  |  |  | 						: 'no'],  | 
					
						
							|  |  |  | 				{ open: function(){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					var v = settings['include-virtual'] =  | 
					
						
							|  |  |  | 						!settings['include-virtual']  | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 					elem.find('.text').last() | 
					
						
							|  |  |  | 						.text(v ? 'yes' : 'no') }, }) }, | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		'clean_target_dir': function(actions, make, parent, settings){ | 
					
						
							|  |  |  | 			settings['clean-target'] = !!settings['clean-target'] | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 			var elem = make([ | 
					
						
							|  |  |  | 					'$Clean target: ',  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					settings['clean-target'] ? | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 						'yes'  | 
					
						
							|  |  |  | 						: 'no'],  | 
					
						
							|  |  |  | 				{ open: function(){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					var v = settings['clean-target'] =  | 
					
						
							|  |  |  | 						!settings['clean-target']  | 
					
						
							| 
									
										
										
										
											2019-10-13 04:33:36 +03:00
										 |  |  | 					elem.find('.text').last() | 
					
						
							|  |  |  | 						.text(v ? 'yes' : 'no') }, }) }, | 
					
						
							| 
									
										
										
										
											2016-04-16 05:19:31 +03:00
										 |  |  | 	}, | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 	// XXX update export state: index, crop, image...
 | 
					
						
							|  |  |  | 	// XXX should this be visible directly???
 | 
					
						
							| 
									
										
										
										
											2019-04-17 02:32:41 +03:00
										 |  |  | 	exportDialog: ['- File/Export...', | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		core.doc`
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			.exportDialog() | 
					
						
							|  |  |  | 			.exportDialog(mode) | 
					
						
							|  |  |  | 			.exportDialog(settings) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		NOTE: when saving a preset the dialog will trigger a 'save-preset' event. | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 		widgets.makeUIDialog(function(mode){ | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 			var settings | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// explicitly passed settings... 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 			if(mode && typeof(mode) != typeof('str')){ | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 				settings = mode | 
					
						
							|  |  |  | 				mode = settings['mode'] } | 
					
						
							|  |  |  | 			settings = settings | 
					
						
							|  |  |  | 				|| (this.config['export-settings'] =  | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 					this.config['export-settings'] || {}) | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 			// mode aliases...
 | 
					
						
							|  |  |  | 			var mode_aliases = Object.entries(that.config['export-dialog-modes'] || {}) | 
					
						
							|  |  |  | 				.reduce(function(res, [key, value]){ | 
					
						
							|  |  |  | 					res[value.alias || key] = key | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 					return res }, {}) | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 			var show_mode = mode_aliases[mode] || mode | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 			var o = browse.makeLister(null, function(path, make){ | 
					
						
							|  |  |  | 				var dialog = this | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 				mode =  | 
					
						
							|  |  |  | 					settings['mode'] = | 
					
						
							|  |  |  | 						show_mode  | 
					
						
							|  |  |  | 						|| settings['mode'] | 
					
						
							|  |  |  | 						|| 'Images only' | 
					
						
							| 
									
										
										
										
											2016-05-11 06:59:56 +03:00
										 |  |  | 				// if invalid mode get the first...
 | 
					
						
							|  |  |  | 				mode = !that.config['export-dialog-modes'][mode] ? | 
					
						
							|  |  |  | 					Object.keys(that.config['export-dialog-modes']).shift() | 
					
						
							|  |  |  | 					: mode | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 				var data = that.config['export-dialog-modes'][mode].data | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// mode selector...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 				// NOTE: this is only visible if no mode/settings are given...
 | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 				!show_mode | 
					
						
							|  |  |  | 					&& make(['Export $mode: ',  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 							function(){ return mode }],  | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 						{ | 
					
						
							|  |  |  | 							// XXX for some reason o is initially undefined when
 | 
					
						
							|  |  |  | 							// 		it should be set to the dialog...
 | 
					
						
							|  |  |  | 							//widgets.makeNestedConfigListEditor(that, o,
 | 
					
						
							|  |  |  | 							open: widgets.makeNestedConfigListEditor(that, make.dialog, | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 								'export-dialog-modes', | 
					
						
							| 
									
										
										
										
											2020-09-27 02:49:10 +03:00
										 |  |  | 								'export-settings.mode', | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 								{ | 
					
						
							|  |  |  | 									length_limit: 10, | 
					
						
							|  |  |  | 									new_item: false, | 
					
						
							|  |  |  | 									itemButtons: [], | 
					
						
							|  |  |  | 								}), | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 						}) | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// get the root and user fields...
 | 
					
						
							|  |  |  | 				var fields = that.__export_dialog_fields__ || {} | 
					
						
							|  |  |  | 				var base_fields = FileSystemWriterUIActions.__export_dialog_fields__ || {} | 
					
						
							|  |  |  | 				// build the fields...
 | 
					
						
							|  |  |  | 				data.forEach(function(k){ | 
					
						
							|  |  |  | 					(fields[k]  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 							&& fields[k].call(that, that, make, dialog, settings)) | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 						|| (base_fields[k]  | 
					
						
							| 
									
										
										
										
											2020-09-26 20:58:06 +03:00
										 |  |  | 								&& base_fields[k].call(that, that, make, dialog, settings)) }) | 
					
						
							| 
									
										
										
										
											2016-04-16 04:17:34 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-06 18:46:23 +03:00
										 |  |  | 				// Start action...
 | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 				make([function(){ | 
					
						
							|  |  |  | 						// XXX indicate export state: index, crop, image...
 | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 						return mode == mode_aliases['save'] ?  | 
					
						
							|  |  |  | 							'$Save'  | 
					
						
							| 
									
										
										
										
											2019-05-02 04:25:58 +03:00
										 |  |  | 							: '$Export' }],  | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 					{ | 
					
						
							|  |  |  | 						cls: 'selected', | 
					
						
							|  |  |  | 						open: function(){ | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 							that.exportAs(settings) | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 							dialog.close() }, | 
					
						
							|  |  |  | 						buttons: [ | 
					
						
							|  |  |  | 							['<i><small>Save preset</small></i>', | 
					
						
							|  |  |  | 								function(_, elem){ | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 									that.exportPresetSave(settings) | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 									// button press feedback...
 | 
					
						
							|  |  |  | 									var e = elem.find('.button small') | 
					
						
							|  |  |  | 									var text = e.text() | 
					
						
							|  |  |  | 									var reset = function(){ | 
					
						
							|  |  |  | 										e.text(text) } | 
					
						
							|  |  |  | 									e.text('Saved.') | 
					
						
							|  |  |  | 									e.one('mouseout', reset) | 
					
						
							|  |  |  | 									setTimeout(reset, 2000) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 									make.dialog.trigger('save-preset') | 
					
						
							|  |  |  | 								}] ], | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 					})  | 
					
						
							| 
									
										
										
										
											2016-05-04 19:26:26 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				make.done() | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-05-14 00:06:55 +03:00
										 |  |  | 			o.dom.addClass('table-view tail-action') | 
					
						
							| 
									
										
										
										
											2016-04-16 03:41:45 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return o | 
					
						
							| 
									
										
										
										
											2016-04-30 05:25:43 +03:00
										 |  |  | 		})], | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// aliases...
 | 
					
						
							|  |  |  | 	// NOTE: .saveWithCommentDialog(..) is another alias (see above)...
 | 
					
						
							| 
									
										
										
										
											2019-04-17 02:32:41 +03:00
										 |  |  | 	exportIndexDialog: ['File/$Export index...',  | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 		'exportDialog: "index"'], | 
					
						
							| 
									
										
										
										
											2019-04-17 02:32:41 +03:00
										 |  |  | 	exportImagesDialog: ['File/Export $images...',  | 
					
						
							| 
									
										
										
										
											2019-04-16 19:03:42 +03:00
										 |  |  | 		'exportDialog: "images"'], | 
					
						
							| 
									
										
										
										
											2019-10-17 14:02:23 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-02 17:45:39 +03:00
										 |  |  | 	// XXX ASAP BUG: affecting preset name will delete on dialog close...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 	// 		to reproduce:
 | 
					
						
							|  |  |  | 	// 			- open dialog
 | 
					
						
							|  |  |  | 	// 			- edit preset changing path
 | 
					
						
							|  |  |  | 	// 			- close
 | 
					
						
							|  |  |  | 	// 		result:
 | 
					
						
							|  |  |  | 	// 			.config['export-presets'] will contain undefined instead 
 | 
					
						
							|  |  |  | 	// 			of last preset
 | 
					
						
							|  |  |  | 	// 		likely cause:
 | 
					
						
							|  |  |  | 	// 			- inconsistent keys and on .close(..) we can't get the 
 | 
					
						
							|  |  |  | 	// 				correct preset...
 | 
					
						
							| 
									
										
										
										
											2020-10-02 17:45:39 +03:00
										 |  |  | 	// XXX ASAP BUG: running a preset from the editor will use the default 
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 	// 		settings and not the loaded preset...
 | 
					
						
							|  |  |  | 	// 		...can't reproduce... (revise)
 | 
					
						
							|  |  |  | 	// XXX ASAP handle presets with repeating titles...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 	// XXX UI:
 | 
					
						
							|  |  |  | 	// 		- element format:
 | 
					
						
							|  |  |  | 	// 			TITLE
 | 
					
						
							|  |  |  | 	// 			mode / destination / format
 | 
					
						
							|  |  |  | 	// 		- revise buttons and icons...
 | 
					
						
							|  |  |  | 	// 		- button shortcuts...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 	// XXX add a 'name' field to the exportDialog(..) (???)
 | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 	// XXX would be nice to mark/title sections -- presets / history... (???)
 | 
					
						
							| 
									
										
										
										
											2020-09-29 03:19:15 +03:00
										 |  |  | 	exportPresets: ['- File/Export presets and history...', | 
					
						
							| 
									
										
										
										
											2020-10-01 22:38:12 +03:00
										 |  |  | 		core.doc`
 | 
					
						
							|  |  |  | 		`,
 | 
					
						
							| 
									
										
										
										
											2019-10-17 14:02:23 +03:00
										 |  |  | 		widgets.makeUIDialog(function(mode){ | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 			var that = this | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 			var logger = this.logger && this.logger.push('exportPresets') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 			// XXX need a way for index to support unique names and to do it
 | 
					
						
							|  |  |  | 			// 		in a stable manner:
 | 
					
						
							|  |  |  | 			// 			- getName(..) must generate the same title for 
 | 
					
						
							|  |  |  | 			// 				the same item, i.e. 'abc' -> 'abc (3)' -> 'abc (3)' ...
 | 
					
						
							|  |  |  | 			// 				...this may be done like this:
 | 
					
						
							|  |  |  | 			// 					- index format (buildIndex(..)):
 | 
					
						
							|  |  |  | 			// 						{
 | 
					
						
							|  |  |  | 			// 							<title>: [ <index>, ... ],
 | 
					
						
							|  |  |  | 			// 							...
 | 
					
						
							|  |  |  | 			// 						}
 | 
					
						
							|  |  |  | 			// 					- title format (used by getPreset(..)):
 | 
					
						
							|  |  |  | 			// 						"<title>"				-> index = 0
 | 
					
						
							|  |  |  | 			// 						"<title> (<index>)"		-> index = <index>
 | 
					
						
							|  |  |  | 			// 					- cache name with index in a Map(..) with preset as key
 | 
					
						
							|  |  |  | 			//
 | 
					
						
							|  |  |  | 			// Format:
 | 
					
						
							|  |  |  | 			// 	Map([
 | 
					
						
							|  |  |  | 			// 		[<preset>, {
 | 
					
						
							|  |  |  | 			// 			base: <base-name>, 
 | 
					
						
							|  |  |  | 			// 			index: <index>,
 | 
					
						
							|  |  |  | 			// 			name: "<base-name> (<index>)", 
 | 
					
						
							|  |  |  | 			// 		}],
 | 
					
						
							|  |  |  | 			// 		...
 | 
					
						
							|  |  |  | 			// 	])
 | 
					
						
							| 
									
										
										
										
											2020-10-03 22:13:15 +03:00
										 |  |  | 			var getName = function(elem, index){ | 
					
						
							| 
									
										
										
										
											2020-10-04 01:45:51 +03:00
										 |  |  | 				// add to index...
 | 
					
						
							| 
									
										
										
										
											2020-10-03 22:13:15 +03:00
										 |  |  | 				if(index){ | 
					
						
							|  |  |  | 					var data = index.get(elem) || {} | 
					
						
							|  |  |  | 					index.has(elem) | 
					
						
							|  |  |  | 						|| index.set(elem, data) } | 
					
						
							| 
									
										
										
										
											2020-10-04 01:45:51 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// generate base name...
 | 
					
						
							|  |  |  | 				// NOTE: we always do this unconditionally so as not to 
 | 
					
						
							|  |  |  | 				// 		mess with keeping things in sync...
 | 
					
						
							|  |  |  | 				var date = preset.date | 
					
						
							|  |  |  | 					&& Date.fromTimeStamp(preset.date).toShortDate() | 
					
						
							|  |  |  | 				date = date ?  | 
					
						
							|  |  |  | 					date + ' - ' | 
					
						
							|  |  |  | 					: '' | 
					
						
							|  |  |  | 				var clean = preset['clean-target'] ?  | 
					
						
							|  |  |  | 					''  | 
					
						
							|  |  |  | 					: ' (merge)' | 
					
						
							|  |  |  | 				var base = data.base =  | 
					
						
							|  |  |  | 					date | 
					
						
							|  |  |  | 						+ (preset.name | 
					
						
							|  |  |  | 							|| ( preset.mode == 'Images only' ? | 
					
						
							|  |  |  | 								// XXX might be a good idea to move name patterns to .config
 | 
					
						
							|  |  |  | 								`${ preset.mode }: ` | 
					
						
							|  |  |  | 									+`"${ preset['preview-name-pattern'] }" → "${ preset.path }"${ clean }` | 
					
						
							|  |  |  | 								: `${ preset.mode }: → "${ preset.path }"${ clean }`)) | 
					
						
							|  |  |  | 				// generate a unique name...
 | 
					
						
							|  |  |  | 				var name = base | 
					
						
							|  |  |  | 				var i = 0 | 
					
						
							|  |  |  | 				while(name in index.names){ | 
					
						
							|  |  |  | 					data.index = ++i | 
					
						
							|  |  |  | 					// XXX might be a good idea to move name patterns to .config
 | 
					
						
							|  |  |  | 					name = `${ base } (${ i })` } | 
					
						
							|  |  |  | 				data.name = name | 
					
						
							|  |  |  | 				index.names[name] = elem | 
					
						
							|  |  |  | 				return name } | 
					
						
							|  |  |  | 			var getElem = function(title, index){ | 
					
						
							|  |  |  | 				return index.names[title] } | 
					
						
							|  |  |  | 			var delElem = function(title, index){ | 
					
						
							|  |  |  | 				var e = index.names[title] | 
					
						
							|  |  |  | 				delete index.names[title] | 
					
						
							|  |  |  | 				index.delete(e) | 
					
						
							|  |  |  | 				return index } | 
					
						
							|  |  |  | 			var renameElem = function(from, to, index){ | 
					
						
							|  |  |  | 				var e = getElem(from, index) | 
					
						
							|  |  |  | 				if(to.trim() == ''){ | 
					
						
							|  |  |  | 					delete e.name | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					e.name = to.trim() } | 
					
						
							|  |  |  | 				delete index.names[from] | 
					
						
							|  |  |  | 				getName(e, index) | 
					
						
							|  |  |  | 				return index } | 
					
						
							| 
									
										
										
										
											2020-10-03 22:13:15 +03:00
										 |  |  | 			var buildCache = function(list){ | 
					
						
							| 
									
										
										
										
											2020-10-04 01:45:51 +03:00
										 |  |  | 				//var index = new Map()
 | 
					
						
							|  |  |  | 				//var index.names = {}
 | 
					
						
							| 
									
										
										
										
											2020-10-03 22:13:15 +03:00
										 |  |  | 				// populate the index...
 | 
					
						
							|  |  |  | 				list | 
					
						
							| 
									
										
										
										
											2020-10-04 01:45:51 +03:00
										 |  |  | 					.forEach(function(e){ getName(e, index) }) | 
					
						
							|  |  |  | 				return index } | 
					
						
							| 
									
										
										
										
											2020-10-03 22:13:15 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 			var getName = function(preset){ | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 				var date = preset.date | 
					
						
							|  |  |  | 					&& Date.fromTimeStamp(preset.date).toShortDate() | 
					
						
							|  |  |  | 				date = date ?  | 
					
						
							|  |  |  | 					date + ' - ' | 
					
						
							|  |  |  | 					: '' | 
					
						
							| 
									
										
										
										
											2020-09-30 05:02:28 +03:00
										 |  |  | 				var clean = preset['clean-target'] ?  | 
					
						
							|  |  |  | 					''  | 
					
						
							|  |  |  | 					: ' (merge)' | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 				return date | 
					
						
							|  |  |  | 					+ (preset.name | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 						|| ( preset.mode == 'Images only' ? | 
					
						
							|  |  |  | 							`${ preset.mode }: ` | 
					
						
							| 
									
										
										
										
											2020-09-30 05:02:28 +03:00
										 |  |  | 								+`"${ preset['preview-name-pattern'] }" → "${ preset.path }"${ clean }` | 
					
						
							|  |  |  | 							: `${ preset.mode }: → "${ preset.path }"${ clean }`)) } | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 			var buildIndex = function(presets){ | 
					
						
							|  |  |  | 				var index | 
					
						
							|  |  |  | 				return [ | 
					
						
							|  |  |  | 					// index...
 | 
					
						
							|  |  |  | 					(index = presets | 
					
						
							|  |  |  | 						.reduce(function(res, e, i){ | 
					
						
							|  |  |  | 							res[getName(e)] = i  | 
					
						
							|  |  |  | 							return res }, {})), | 
					
						
							|  |  |  | 					// keys...
 | 
					
						
							|  |  |  | 					Object.keys(index), ] } | 
					
						
							|  |  |  | 			var getPreset = function(title, presets, index){ | 
					
						
							|  |  |  | 				return presets[index[title]] } | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 			// presets...
 | 
					
						
							| 
									
										
										
										
											2020-09-24 20:36:09 +03:00
										 |  |  | 			var presets = that.config['export-presets'] || [] | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 			var [index, keys] = buildIndex(presets) | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 			var updateIndex = function(){ | 
					
						
							|  |  |  | 				var [idx, k] = buildIndex(presets) | 
					
						
							|  |  |  | 				index = idx | 
					
						
							|  |  |  | 				// NOTE: keys must be updated in-place...
 | 
					
						
							|  |  |  | 				keys.splice(0, keys.length, ...k) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 			// history...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 			// NOTE: history is reversed in view...
 | 
					
						
							|  |  |  | 			var history = (that.config['export-history'] || []) | 
					
						
							|  |  |  | 				.slice() | 
					
						
							|  |  |  | 				.reverse() | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 			var [history_index, history_keys] = buildIndex(history) | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 			return browse.makeLister(null, function(path, make){ | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 				// preset list...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 				keys.length > 0 | 
					
						
							|  |  |  | 					&& make.EditableList(keys, { | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 						list_id: 'presets', | 
					
						
							|  |  |  | 						sortable: true, | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 						update_merge: 'live', | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 						new_item: false, | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 						// saving an empty string on item edit will clear .name...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 						allow_empty: true, | 
					
						
							|  |  |  | 						itemedit: function(evt, from, to){ | 
					
						
							|  |  |  | 							var preset = getPreset(from, presets, index) | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 							// reset...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 							if(to.trim() == ''){ | 
					
						
							|  |  |  | 								delete preset.name | 
					
						
							|  |  |  | 								to = keys[keys.indexOf(from)] = getName(preset) | 
					
						
							|  |  |  | 							// set...
 | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								to = preset.name = to.trim() } | 
					
						
							|  |  |  | 							// update index...
 | 
					
						
							|  |  |  | 							index[to] = index[from] | 
					
						
							|  |  |  | 							delete index[from]  | 
					
						
							|  |  |  | 							// select item...
 | 
					
						
							|  |  |  | 							// NOTE: this is not done automatically because 
 | 
					
						
							|  |  |  | 							// 		we are changing the title .EditableList(..)
 | 
					
						
							|  |  |  | 							// 		is expecting...
 | 
					
						
							|  |  |  | 							make.dialog.one('update',  | 
					
						
							|  |  |  | 								function(){ | 
					
						
							|  |  |  | 									make.dialog.select(to) }) }, | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 						buttons: [ | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 							// edit...
 | 
					
						
							|  |  |  | 							['<small class="show-on-hover">edit</small>',  | 
					
						
							|  |  |  | 								function(title){ | 
					
						
							|  |  |  | 									var preset = getPreset(title, presets, index) | 
					
						
							|  |  |  | 									that.exportDialog(preset) | 
					
						
							|  |  |  | 										.close(function(){ | 
					
						
							|  |  |  | 											var n = getName(preset) | 
					
						
							|  |  |  | 											// update the list if name is affected...
 | 
					
						
							|  |  |  | 											if(n != title){ | 
					
						
							|  |  |  | 												keys[keys.indexOf(title)] = n | 
					
						
							|  |  |  | 												index[n] = index[title] | 
					
						
							|  |  |  | 												delete index[title] | 
					
						
							|  |  |  | 												make.dialog.select(n)  | 
					
						
							|  |  |  | 												make.dialog.update() } })}], | 
					
						
							|  |  |  | 							// duplicate...
 | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 							//['<span class="show-on-hover">❏</span>', 
 | 
					
						
							|  |  |  | 							['<small class="show-on-hover">clone</small>',  | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 								function(title){ | 
					
						
							|  |  |  | 									var preset = JSON.parse( | 
					
						
							|  |  |  | 										JSON.stringify( | 
					
						
							|  |  |  | 											getPreset(title, presets, index) )) | 
					
						
							|  |  |  | 									preset.name = title + ' (copy)' | 
					
						
							|  |  |  | 									// place preset in list...
 | 
					
						
							|  |  |  | 									var i = index[preset.name] = index[title]+1 | 
					
						
							|  |  |  | 									presets.splice(i, 0, preset) | 
					
						
							|  |  |  | 									keys.splice(keys.indexOf(title)+1, 0, preset.name) | 
					
						
							|  |  |  | 									make.dialog.update() }], | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 							['♦', 'TO_TOP'], | 
					
						
							|  |  |  | 							'REMOVE'], | 
					
						
							|  |  |  | 						// export...
 | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 						open: function(evt, title){ | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 							var preset = getPreset(title, presets, index) | 
					
						
							|  |  |  | 							// export only if we get a good preset...
 | 
					
						
							|  |  |  | 							if(preset && getName(preset) == title){ | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 								console.log('>>>>>>>>>', preset) | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 								that.exportAs(preset) | 
					
						
							|  |  |  | 								return make.dialog.close() } | 
					
						
							|  |  |  | 							// error...
 | 
					
						
							|  |  |  | 							logger  | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 								&& logger.emit('error', `preset not found: "${ title }"`) }, }) | 
					
						
							| 
									
										
										
										
											2020-09-21 20:06:38 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 				// export dialog...
 | 
					
						
							|  |  |  | 				make.Separator({ style: { opacity: '0.1' } }) | 
					
						
							|  |  |  | 				make('E$xport...', { | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 					open: function(){ | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 						that.exportDialog() | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 							// new preset saved...
 | 
					
						
							|  |  |  | 							.on('save-preset', function(){ | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 								updateIndex() | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 								make.dialog.update() }) | 
					
						
							|  |  |  | 							// close dialog on export...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 							.close(function(evt, reason){ | 
					
						
							|  |  |  | 								reason != 'reject' | 
					
						
							|  |  |  | 									&& make.dialog.close() }) }, }) | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// history...
 | 
					
						
							|  |  |  | 				make.Separator() | 
					
						
							|  |  |  | 				history.length == 0 ? | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 					make.Empty('No export history...') | 
					
						
							| 
									
										
										
										
											2020-09-29 03:19:15 +03:00
										 |  |  | 					: make.EditableList(history_keys, { | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 						list_id: 'history', | 
					
						
							|  |  |  | 						sortable: false, | 
					
						
							|  |  |  | 						new_item: false, | 
					
						
							|  |  |  | 						editable_items: false, | 
					
						
							|  |  |  | 						buttons: [ | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 							// view...
 | 
					
						
							|  |  |  | 							['<small class="show-on-hover">view</small>',  | 
					
						
							|  |  |  | 								function(title){ | 
					
						
							|  |  |  | 									var preset = getPreset(title, history, history_index) | 
					
						
							|  |  |  | 									preset | 
					
						
							|  |  |  | 										&& that.exportDialog( | 
					
						
							|  |  |  | 												// prevent editing history...
 | 
					
						
							|  |  |  | 												JSON.parse(JSON.stringify( preset )) )  | 
					
						
							|  |  |  | 											// new preset saved...
 | 
					
						
							|  |  |  | 											.on('save-preset', function(){ | 
					
						
							|  |  |  | 												updateIndex() | 
					
						
							|  |  |  | 												make.dialog.update() }) | 
					
						
							|  |  |  | 											// close dialog on export...
 | 
					
						
							|  |  |  | 											.close(function(evt, reason){ | 
					
						
							|  |  |  | 												reason != 'reject' | 
					
						
							|  |  |  | 													&& make.dialog.close() }) }], | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 							// to preset...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 							['<small class="show-on-hover">save</small>',  | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 								 function(title){ | 
					
						
							|  |  |  | 									var preset = getPreset(title, history, history_index) | 
					
						
							|  |  |  | 									if(preset){ | 
					
						
							|  |  |  | 										that.exportPresetSave(preset)  | 
					
						
							|  |  |  | 										updateIndex() | 
					
						
							|  |  |  | 										make.dialog.update() } }], | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 							'REMOVE', | 
					
						
							|  |  |  | 						], | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 						// export...
 | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 						open: function(evt, title){ | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 							var preset = getPreset(title, history, history_index) | 
					
						
							|  |  |  | 							// export only if we get a good preset...
 | 
					
						
							|  |  |  | 							if(preset && getName(preset) == title){ | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 								console.log('>>>>>>>>>', preset) | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 								that.exportAs(preset) | 
					
						
							|  |  |  | 								return make.dialog.close() } | 
					
						
							|  |  |  | 							// error...
 | 
					
						
							|  |  |  | 							logger  | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 								&& logger.emit('error',  | 
					
						
							|  |  |  | 									`history item not found: "${ title }"`) }, }) | 
					
						
							| 
									
										
										
										
											2020-09-22 18:23:19 +03:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 			// keyboard...
 | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 			.run(function(){ | 
					
						
							|  |  |  | 				var that = this | 
					
						
							|  |  |  | 				this.keyboard.on('E', function(){ | 
					
						
							| 
									
										
										
										
											2020-09-30 05:02:28 +03:00
										 |  |  | 					// XXX trigger edit/view button...
 | 
					
						
							| 
									
										
										
										
											2020-09-28 17:42:19 +03:00
										 |  |  | 				}) | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 			// save things after we are done...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 			.close(function(){ | 
					
						
							|  |  |  | 				// update preset order and count...
 | 
					
						
							|  |  |  | 				that.config['export-presets'] = keys | 
					
						
							|  |  |  | 					.map(function(e){ | 
					
						
							|  |  |  | 						return getPreset(e, presets, index) }) | 
					
						
							|  |  |  | 				// handle history delete...
 | 
					
						
							|  |  |  | 				history.length != that.config['export-history'] | 
					
						
							| 
									
										
										
										
											2020-09-29 03:19:15 +03:00
										 |  |  | 					&& (that.config['export-history'] = history_keys | 
					
						
							| 
									
										
										
										
											2020-09-30 04:51:10 +03:00
										 |  |  | 						.reverse() | 
					
						
							| 
									
										
										
										
											2020-09-29 03:05:02 +03:00
										 |  |  | 						.map(function(e){ | 
					
						
							| 
									
										
										
										
											2020-09-29 03:19:15 +03:00
										 |  |  | 							return getPreset(e, history, history_index) })) }) })], | 
					
						
							| 
									
										
										
										
											2019-10-19 00:39:50 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// XXX these do note need the ui -- move to a separate feature...
 | 
					
						
							|  |  |  | 	// XXX these are essentially the same as the history API, make a 
 | 
					
						
							|  |  |  | 	// 		generic list manager???
 | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 	// XXX need to check preset uniqueness...
 | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 	exportPresetSave: ['- File/',  | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 		function(settings){ | 
					
						
							|  |  |  | 			settings = settings  | 
					
						
							|  |  |  | 				|| this.config['export-settings'] | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 			// no settings...
 | 
					
						
							|  |  |  | 			if(!settings){ | 
					
						
							|  |  |  | 				console.error('.exportPresets(..): no settings to save.') | 
					
						
							|  |  |  | 				return } | 
					
						
							|  |  |  | 			// isolate and cleanup...
 | 
					
						
							|  |  |  | 			settings = JSON.parse(JSON.stringify(settings)) | 
					
						
							|  |  |  | 			delete settings.date | 
					
						
							|  |  |  | 			// XXX check preset uniqueness...
 | 
					
						
							|  |  |  | 			;(this.config['export-presets'] =  | 
					
						
							|  |  |  | 					this.config['export-presets']  | 
					
						
							|  |  |  | 					|| []) | 
					
						
							|  |  |  | 				.push(settings) }], | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 	// XXX need to check item uniqueness???
 | 
					
						
							| 
									
										
										
										
											2020-09-27 03:41:22 +03:00
										 |  |  | 	exportHistoryPush: ['- File/',  | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 		function(settings){ | 
					
						
							|  |  |  | 			settings = settings  | 
					
						
							|  |  |  | 				|| this.config['export-settings'] | 
					
						
							|  |  |  | 			var l = this.config['export-history-length'] || 50 | 
					
						
							|  |  |  | 			var history =  | 
					
						
							|  |  |  | 				this.config['export-history'] =  | 
					
						
							|  |  |  | 					this.config['export-history'] || [] | 
					
						
							|  |  |  | 			// add...
 | 
					
						
							|  |  |  | 			settings  | 
					
						
							| 
									
										
										
										
											2020-09-29 05:18:53 +03:00
										 |  |  | 				&& history.push(Object.assign( | 
					
						
							|  |  |  | 					JSON.parse(JSON.stringify( settings )),  | 
					
						
							|  |  |  | 					{ | 
					
						
							|  |  |  | 						date: Date.timeStamp(true), | 
					
						
							|  |  |  | 					})) | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 			// trim the history...
 | 
					
						
							|  |  |  | 			history.length > l | 
					
						
							|  |  |  | 				&& history.splice(0, history.length - l) }], | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	clearExportHistory: ['- File/Clear export history', | 
					
						
							|  |  |  | 		function(){ | 
					
						
							|  |  |  | 			delete this.config['export-history'] }], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var FileSystemWriterUI =  | 
					
						
							|  |  |  | module.FileSystemWriterUI = core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	title: '', | 
					
						
							|  |  |  | 	doc: '', | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tag: 'ui-fs-writer', | 
					
						
							|  |  |  | 	depends: [ | 
					
						
							| 
									
										
										
										
											2019-11-09 03:37:13 +03:00
										 |  |  | 		'ui-editor', | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 		'ui-fs-loader', | 
					
						
							| 
									
										
										
										
											2017-05-21 00:21:32 +03:00
										 |  |  | 		'fs-writer',  | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 	], | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	actions: FileSystemWriterUIActions, | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	handlers: [ | 
					
						
							| 
									
										
										
										
											2020-09-30 01:25:38 +03:00
										 |  |  | 		// update export history...
 | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 		[[ | 
					
						
							|  |  |  | 			'exportIndex', | 
					
						
							|  |  |  | 			'exportDirs', | 
					
						
							| 
									
										
										
										
											2020-09-29 03:19:15 +03:00
										 |  |  | 		], function(_, settings){ | 
					
						
							|  |  |  | 			this.exportHistoryPush( | 
					
						
							|  |  |  | 				(!settings || typeof(settings) == typeof('str')) ? | 
					
						
							|  |  |  | 					this.config['export-settings'] | 
					
						
							|  |  |  | 					: settings) }] | 
					
						
							| 
									
										
										
										
											2020-09-29 00:54:39 +03:00
										 |  |  | 	], | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | //---------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-06 02:24:36 +03:00
										 |  |  | // NOTE: this is not a trivial meta-feature purely for aesthetic reasons,
 | 
					
						
							|  |  |  | // 		when the fs stuff is not applicable it's really confusing to see
 | 
					
						
							|  |  |  | // 		an 'fs' feature loaded in the feature list... at least to me ;)
 | 
					
						
							|  |  |  | // 		XXX should we do anything about this?
 | 
					
						
							| 
									
										
										
										
											2017-07-02 16:42:28 +03:00
										 |  |  | core.ImageGridFeatures.Feature({ | 
					
						
							|  |  |  | 	tag: 'fs',  | 
					
						
							|  |  |  | 	suggested: [ | 
					
						
							|  |  |  | 		'index-format', | 
					
						
							|  |  |  | 		'fs-info', | 
					
						
							|  |  |  | 		'fs-loader', | 
					
						
							|  |  |  | 		'fs-writer', | 
					
						
							|  |  |  | 	], | 
					
						
							|  |  |  | 	isApplicable: FileSystemInfo.isApplicable, | 
					
						
							|  |  |  | }) | 
					
						
							| 
									
										
										
										
											2016-04-02 19:30:48 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-05-06 21:17:54 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-22 16:11:17 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 03:34:20 +03:00
										 |  |  | /********************************************************************** | 
					
						
							| 
									
										
										
										
											2016-08-20 22:49:36 +03:00
										 |  |  | * vim:set ts=4 sw=4 :                               */ return module }) |