mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
reworked long action abort... the results still need some tweaking...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
da63da2f2c
commit
baa1b06dce
@ -1575,7 +1575,7 @@ module.CropActions = actions.Actions({
|
|||||||
return this.crop(list.slice(list.indexOf(image)), flatten) }],
|
return this.crop(list.slice(list.indexOf(image)), flatten) }],
|
||||||
|
|
||||||
// XXX not sure if we actually need this...
|
// XXX not sure if we actually need this...
|
||||||
cropFlatten: ['Crop/$Flatten',
|
cropFlatten: ['Crop|Ribbon/Crop $flatten',
|
||||||
{mode: function(){
|
{mode: function(){
|
||||||
return this.data.ribbon_order.length <= 1 && 'disabled' }},
|
return this.data.ribbon_order.length <= 1 && 'disabled' }},
|
||||||
function(list){ this.data.length > 0 && this.crop(list, true) }],
|
function(list){ this.data.length > 0 && this.crop(list, true) }],
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
* - introspection
|
* - introspection
|
||||||
* - lifecycle
|
* - lifecycle
|
||||||
* base life-cycle events (start/stop/..)
|
* base life-cycle events (start/stop/..)
|
||||||
|
* base abort api
|
||||||
* - serialization
|
* - serialization
|
||||||
* base methods to handle loading, serialization and cloning...
|
* base methods to handle loading, serialization and cloning...
|
||||||
* - cache
|
* - cache
|
||||||
@ -226,6 +227,8 @@ var LoggerActions = actions.Actions({
|
|||||||
Logger: object.Constructor('BaseLogger', {
|
Logger: object.Constructor('BaseLogger', {
|
||||||
doc: `Logger object constructor...`,
|
doc: `Logger object constructor...`,
|
||||||
|
|
||||||
|
quiet: false,
|
||||||
|
|
||||||
__context: null,
|
__context: null,
|
||||||
get context(){
|
get context(){
|
||||||
return this.__context || this.root.__context },
|
return this.__context || this.root.__context },
|
||||||
@ -324,11 +327,20 @@ var LoggerActions = actions.Actions({
|
|||||||
|
|
||||||
|
|
||||||
// main API...
|
// main API...
|
||||||
|
//
|
||||||
|
// .push(str, ...)
|
||||||
|
//
|
||||||
|
// .push(str, ..., attrs)
|
||||||
|
//
|
||||||
push: function(...msg){
|
push: function(...msg){
|
||||||
|
attrs = typeof(msg.last()) != typeof('str') ?
|
||||||
|
msg.pop()
|
||||||
|
: {}
|
||||||
return msg.length == 0 ?
|
return msg.length == 0 ?
|
||||||
this
|
this
|
||||||
: Object.assign(
|
: Object.assign(
|
||||||
this.constructor(),
|
this.constructor(),
|
||||||
|
attrs,
|
||||||
{
|
{
|
||||||
root: this.root,
|
root: this.root,
|
||||||
path: this.path.concat(msg),
|
path: this.path.concat(msg),
|
||||||
@ -359,7 +371,7 @@ var LoggerActions = actions.Actions({
|
|||||||
// call context log handler...
|
// call context log handler...
|
||||||
this.context
|
this.context
|
||||||
&& this.context.handleLogItem
|
&& this.context.handleLogItem
|
||||||
&& this.context.handleLogItem(this.path, status, ...rest)
|
&& this.context.handleLogItem(this, this.path, status, ...rest)
|
||||||
return this },
|
return this },
|
||||||
|
|
||||||
|
|
||||||
@ -379,15 +391,16 @@ var LoggerActions = actions.Actions({
|
|||||||
|
|
||||||
// XXX move this to console-logger???
|
// XXX move this to console-logger???
|
||||||
handleLogItem: ['- System/',
|
handleLogItem: ['- System/',
|
||||||
function(path, status, ...rest){
|
function(logger, path, status, ...rest){
|
||||||
console.log(
|
logger.quiet
|
||||||
path.join(': ') + (path.length > 0 ? ': ' : '')
|
|| console.log(
|
||||||
+ status
|
path.join(': ') + (path.length > 0 ? ': ' : '')
|
||||||
+ (rest.length > 1 ?
|
+ status
|
||||||
':\n\t'
|
+ (rest.length > 1 ?
|
||||||
: rest.length == 1 ?
|
':\n\t'
|
||||||
': '
|
: rest.length == 1 ?
|
||||||
: ''), ...rest) }],
|
': '
|
||||||
|
: ''), ...rest) }],
|
||||||
})
|
})
|
||||||
|
|
||||||
var Logger =
|
var Logger =
|
||||||
@ -583,6 +596,82 @@ module.Introspection = ImageGridFeatures.Feature({
|
|||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// System life-cycle...
|
// System life-cycle...
|
||||||
|
|
||||||
|
// XXX docs...
|
||||||
|
//
|
||||||
|
// action: ['Path/To/Action',
|
||||||
|
// abortablePromise('abort-id', function(abort, ...args){
|
||||||
|
//
|
||||||
|
// abort.cleanup(function(reason, res){
|
||||||
|
// if(reason == 'done'){
|
||||||
|
// // ...
|
||||||
|
// }
|
||||||
|
// if(reason == 'aborted'){
|
||||||
|
// // ...
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// return new Promise(function(resolve, reject){
|
||||||
|
// // ...
|
||||||
|
//
|
||||||
|
// if(abort.isAborted){
|
||||||
|
// // handle abort...
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // ...
|
||||||
|
// }) })],
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// NOTE: if the returned promise is not resolved .cleanup(..) will not
|
||||||
|
// be called even if the appropriate .abort(..) as called...
|
||||||
|
var abortablePromise =
|
||||||
|
module.abortablePromise =
|
||||||
|
function(title, func){
|
||||||
|
return Object.assign(
|
||||||
|
function(...args){
|
||||||
|
var that = this
|
||||||
|
|
||||||
|
var abort = object.mixinFlat(
|
||||||
|
this.abortable(title, function(){
|
||||||
|
that.clearAbortable(title, abort)
|
||||||
|
return abort }),
|
||||||
|
{
|
||||||
|
get isAborted(){
|
||||||
|
return !((that.__abortable || new Map())
|
||||||
|
.get(title) || new Set())
|
||||||
|
.has(this) },
|
||||||
|
|
||||||
|
__cleanup: null,
|
||||||
|
cleanup: function(func){
|
||||||
|
var args = [...arguments]
|
||||||
|
var reason = this.isAborted ?
|
||||||
|
'aborted'
|
||||||
|
: 'done'
|
||||||
|
typeof(func) == 'function' ?
|
||||||
|
// register handler...
|
||||||
|
(this.__cleanup = this.__cleanup
|
||||||
|
|| new Set()).add(func)
|
||||||
|
// call cleanup handlers...
|
||||||
|
: [...(this.__cleanup || [])]
|
||||||
|
.forEach(function(f){
|
||||||
|
f.call(that, reason, ...args) })
|
||||||
|
return this },
|
||||||
|
})
|
||||||
|
|
||||||
|
return func.call(this, abort, ...args)
|
||||||
|
.then(function(res){
|
||||||
|
abort.cleanup(res)()
|
||||||
|
return res })
|
||||||
|
.catch(function(res){
|
||||||
|
abort.cleanup(res)() }) },
|
||||||
|
{
|
||||||
|
toString: function(){
|
||||||
|
return `core.abortablePromise('${ title }', \n${ func.toString() })` },
|
||||||
|
}) }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
// XXX should his have state???
|
// XXX should his have state???
|
||||||
// ...if so, should this be a toggler???
|
// ...if so, should this be a toggler???
|
||||||
var LifeCycleActions = actions.Actions({
|
var LifeCycleActions = actions.Actions({
|
||||||
@ -966,6 +1055,98 @@ var LifeCycleActions = actions.Actions({
|
|||||||
.stop()
|
.stop()
|
||||||
.clear()
|
.clear()
|
||||||
.start() }],
|
.start() }],
|
||||||
|
|
||||||
|
|
||||||
|
// Abortable...
|
||||||
|
//
|
||||||
|
// Format:
|
||||||
|
// Map({
|
||||||
|
// title: Set([ func, ... ]),
|
||||||
|
// ...
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
__abortable: null,
|
||||||
|
|
||||||
|
abortable: ['- System/Register abort handler',
|
||||||
|
doc`Register abortable action
|
||||||
|
|
||||||
|
.abortable(title, func)
|
||||||
|
-> func
|
||||||
|
|
||||||
|
`,
|
||||||
|
function(title, callback){
|
||||||
|
// reserved titles...
|
||||||
|
if(title == 'all' || title == '*'){
|
||||||
|
throw new Error('.abortable(..): can not set reserved title: "'+ title +'".') }
|
||||||
|
|
||||||
|
var abortable = this.__abortable = this.__abortable || new Map()
|
||||||
|
var set = abortable.get(title) || new Set()
|
||||||
|
abortable.set(title, set)
|
||||||
|
set.add(callback)
|
||||||
|
|
||||||
|
return actions.ASIS(callback) }],
|
||||||
|
clearAbortable: ['- System/Clear abort handler(s)',
|
||||||
|
doc`Clear abort handler(s)
|
||||||
|
|
||||||
|
Clear abort handler...
|
||||||
|
.clearAbortable(title, callback)
|
||||||
|
|
||||||
|
Clear all abort handlers for title...
|
||||||
|
.clearAbortable(title)
|
||||||
|
.clearAbortable(title, 'all')
|
||||||
|
|
||||||
|
Clear all abort handlers...
|
||||||
|
.clearAbortable('all')
|
||||||
|
|
||||||
|
`,
|
||||||
|
function(title, callback){
|
||||||
|
callback = callback || '*'
|
||||||
|
|
||||||
|
// clear all...
|
||||||
|
if(title == '*' || title == 'all'){
|
||||||
|
delete this.__abortable }
|
||||||
|
|
||||||
|
var set = ((this.__abortable || new Map()).get(title) || new Set())
|
||||||
|
// clear specific handler...
|
||||||
|
callback != '*'
|
||||||
|
&& callback != 'all'
|
||||||
|
&& set.delete(callback)
|
||||||
|
// cleanup / clear title...
|
||||||
|
;(set.size == 0
|
||||||
|
|| callback == '*'
|
||||||
|
|| callback == 'all')
|
||||||
|
&& (this.__abortable || new Set()).delete(title)
|
||||||
|
// cleanup...
|
||||||
|
this.__abortable
|
||||||
|
&& this.__abortable.size == 0
|
||||||
|
&& (delete this.__abortable) }],
|
||||||
|
abort: ['- System/Run abort handler(s)',
|
||||||
|
doc`
|
||||||
|
|
||||||
|
.abort(title)
|
||||||
|
.abort([title, .. ])
|
||||||
|
|
||||||
|
.abort('all')
|
||||||
|
|
||||||
|
`,
|
||||||
|
function(title){
|
||||||
|
title = title == '*' || title == 'all' ?
|
||||||
|
[...(this.__abortable || new Map()).keys()]
|
||||||
|
: title instanceof Array ?
|
||||||
|
title
|
||||||
|
: [title]
|
||||||
|
|
||||||
|
this.__abortable
|
||||||
|
&& title
|
||||||
|
.forEach(function(title){
|
||||||
|
[...(this.__abortable || new Map()).get(title) || []]
|
||||||
|
.forEach(function(f){ f() })
|
||||||
|
this.__abortable
|
||||||
|
&& this.__abortable.delete(title) }.bind(this))
|
||||||
|
// cleanup...
|
||||||
|
this.__abortable
|
||||||
|
&& this.__abortable.size == 0
|
||||||
|
&& (delete this.__abortable) }],
|
||||||
})
|
})
|
||||||
|
|
||||||
var LifeCycle =
|
var LifeCycle =
|
||||||
|
|||||||
@ -106,7 +106,18 @@ var MetadataReaderActions = actions.Actions({
|
|||||||
// XXX this uses .markChanged(..) form filesystem.FileSystemWriter
|
// XXX this uses .markChanged(..) form filesystem.FileSystemWriter
|
||||||
// feature, but technically does not depend on it...
|
// feature, but technically does not depend on it...
|
||||||
// XXX should we store metadata in an image (current) or in fs???
|
// XXX should we store metadata in an image (current) or in fs???
|
||||||
|
// XXX should this set .orientation / .flipped if they are not set???
|
||||||
readMetadata: ['- Image/Get metadata data',
|
readMetadata: ['- Image/Get metadata data',
|
||||||
|
core.doc`
|
||||||
|
|
||||||
|
This will overwrite/update if:
|
||||||
|
- image .metadata is not set
|
||||||
|
- image .metadata.ImageGridMetadata is not 'full'
|
||||||
|
- force is true
|
||||||
|
|
||||||
|
|
||||||
|
NOTE: also see: .cacheMetadata(..)
|
||||||
|
`,
|
||||||
function(image, force){
|
function(image, force){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
@ -169,6 +180,7 @@ var MetadataReaderActions = actions.Actions({
|
|||||||
|
|
||||||
resolve(data) }) }) }) }],
|
resolve(data) }) }) }) }],
|
||||||
|
|
||||||
|
// XXX make this abortable...
|
||||||
// XXX STUB: add support for this to .readMetadata(..)
|
// XXX STUB: add support for this to .readMetadata(..)
|
||||||
readAllMetadata: ['File/Read all metadata',
|
readAllMetadata: ['File/Read all metadata',
|
||||||
function(){
|
function(){
|
||||||
@ -254,6 +266,12 @@ var MetadataReaderActions = actions.Actions({
|
|||||||
&& this.markChanged('data')
|
&& this.markChanged('data')
|
||||||
mode == 'crop'
|
mode == 'crop'
|
||||||
&& this.crop(data) }],
|
&& this.crop(data) }],
|
||||||
|
|
||||||
|
// shorthands...
|
||||||
|
cropRatingsAsRibbons: ['Ribbon|Crop/Crop ratings to ribbons',
|
||||||
|
'ratingToRibbons: "crop"'],
|
||||||
|
splitRatingsAsRibbons: ['Ribbon/Split ratings to ribbons (in-place)',
|
||||||
|
'ratingToRibbons: "in-place"'],
|
||||||
})
|
})
|
||||||
|
|
||||||
var MetadataReader =
|
var MetadataReader =
|
||||||
@ -705,13 +723,6 @@ var MetadataUIActions = actions.Actions({
|
|||||||
&& make.Separator() })
|
&& make.Separator() })
|
||||||
.forEach(function(e){
|
.forEach(function(e){
|
||||||
make(...e) }) })],
|
make(...e) }) })],
|
||||||
|
|
||||||
|
|
||||||
// shorthands...
|
|
||||||
cropRatingsAsRibbons: ['Ribbon|Crop/Split ratings to ribbons (crop)',
|
|
||||||
'ratingToRibbons: "crop"'],
|
|
||||||
splitRatingsAsRibbons: ['Ribbon/Split ratings to ribbons (in-place)',
|
|
||||||
'ratingToRibbons: "in-place"'],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
var MetadataUI =
|
var MetadataUI =
|
||||||
|
|||||||
@ -7,6 +7,8 @@
|
|||||||
(function(require){ var module={} // make module AMD/node compatible...
|
(function(require){ var module={} // make module AMD/node compatible...
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
|
|
||||||
|
var array = require('lib/types/Array')
|
||||||
|
|
||||||
var actions = require('lib/actions')
|
var actions = require('lib/actions')
|
||||||
var features = require('lib/features')
|
var features = require('lib/features')
|
||||||
|
|
||||||
@ -245,13 +247,22 @@ var SharpActions = actions.Actions({
|
|||||||
NOTE: all options are optional.
|
NOTE: all options are optional.
|
||||||
NOTE: this will not overwrite existing images.
|
NOTE: this will not overwrite existing images.
|
||||||
`,
|
`,
|
||||||
function(images, size, path, options={}){
|
core.abortablePromise('makeResizedImage', function(abort, images, size, path, options={}){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
// sanity check...
|
// sanity check...
|
||||||
if(arguments.length < 3){
|
if(arguments.length < 3){
|
||||||
throw new Error('.makeResizedImage(..): '
|
throw new Error('.makeResizedImage(..): '
|
||||||
+'need at least images, size and path.') }
|
+'need at least images, size and path.') }
|
||||||
|
|
||||||
|
var CHUNK_SIZE = 4
|
||||||
|
|
||||||
|
abort.cleanup(function(reason, res){
|
||||||
|
logger
|
||||||
|
&& logger.emit('close')
|
||||||
|
&& reason == 'aborted'
|
||||||
|
&& logger.emit(res) })
|
||||||
|
|
||||||
// get/normalize images...
|
// get/normalize images...
|
||||||
//images = images || this.current
|
//images = images || this.current
|
||||||
images = images
|
images = images
|
||||||
@ -304,7 +315,7 @@ var SharpActions = actions.Actions({
|
|||||||
logger = logger !== false ?
|
logger = logger !== false ?
|
||||||
(logger || this.logger)
|
(logger || this.logger)
|
||||||
: false
|
: false
|
||||||
logger = logger && logger.push('Resize')
|
logger = logger && logger.push('Resize', {onclose: abort})
|
||||||
|
|
||||||
// backup...
|
// backup...
|
||||||
// XXX make backup name pattern configurable...
|
// XXX make backup name pattern configurable...
|
||||||
@ -314,8 +325,11 @@ var SharpActions = actions.Actions({
|
|||||||
i++ }
|
i++ }
|
||||||
return `${to}.${timestamp}.bak`+ (i || '') }
|
return `${to}.${timestamp}.bak`+ (i || '') }
|
||||||
|
|
||||||
return Promise.all(images
|
return images
|
||||||
.map(function(gid){
|
.mapChunks(CHUNK_SIZE, function(gid){
|
||||||
|
if(abort.isAborted){
|
||||||
|
throw array.StopIteration('aborted') }
|
||||||
|
|
||||||
// skip non-images...
|
// skip non-images...
|
||||||
if(!['image', null, undefined]
|
if(!['image', null, undefined]
|
||||||
.includes(that.images[gid].type)){
|
.includes(that.images[gid].type)){
|
||||||
@ -342,7 +356,7 @@ var SharpActions = actions.Actions({
|
|||||||
&& Math.max(m.width, m.height) < size)
|
&& Math.max(m.width, m.height) < size)
|
||||||
|| (fit == 'outside'
|
|| (fit == 'outside'
|
||||||
&& Math.min(m.width, m.height) < size)){
|
&& Math.min(m.width, m.height) < size)){
|
||||||
skipping(gid)
|
logger && logger.emit('skipping', gid)
|
||||||
return }
|
return }
|
||||||
// continue...
|
// continue...
|
||||||
return img })
|
return img })
|
||||||
@ -362,7 +376,7 @@ var SharpActions = actions.Actions({
|
|||||||
fse.removeSync(to)
|
fse.removeSync(to)
|
||||||
// skip...
|
// skip...
|
||||||
} else {
|
} else {
|
||||||
skipping(gid)
|
logger && logger.emit('skipping', gid)
|
||||||
return } }
|
return } }
|
||||||
|
|
||||||
// write...
|
// write...
|
||||||
@ -396,11 +410,11 @@ var SharpActions = actions.Actions({
|
|||||||
.then(function(){
|
.then(function(){
|
||||||
logger
|
logger
|
||||||
&& logger.emit('done', to)
|
&& logger.emit('done', to)
|
||||||
return img }) }) }) })) }],
|
return img }) }) }) }) })],
|
||||||
|
|
||||||
// XXX test against .makePreviews(..) for speed...
|
|
||||||
// XXX this does not update image.base_path -- is this correct???
|
// XXX this does not update image.base_path -- is this correct???
|
||||||
// XXX do we need to be able to run this in a worker???
|
// XXX add support for offloading the processing to a thread/worker...
|
||||||
|
// XXX should we use task.Queue()???
|
||||||
makePreviews: ['Sharp|File/Make image $previews',
|
makePreviews: ['Sharp|File/Make image $previews',
|
||||||
core.doc`Make image previews
|
core.doc`Make image previews
|
||||||
|
|
||||||
@ -428,16 +442,23 @@ var SharpActions = actions.Actions({
|
|||||||
NOTE: if base_path is given .images will not be updated with new
|
NOTE: if base_path is given .images will not be updated with new
|
||||||
preview paths...
|
preview paths...
|
||||||
`,
|
`,
|
||||||
function(images, sizes, base_path, logger){
|
core.abortablePromise('makePreviews', function(abort, images, sizes, base_path, logger){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
|
var CHUNK_SIZE = 4
|
||||||
|
|
||||||
|
abort.cleanup(function(reason, res){
|
||||||
|
logger
|
||||||
|
&& logger.emit('close')
|
||||||
|
&& reason == 'aborted'
|
||||||
|
&& logger.emit(res) })
|
||||||
|
|
||||||
var logger_mode = this.config['preview-progress-mode'] || 'gids'
|
var logger_mode = this.config['preview-progress-mode'] || 'gids'
|
||||||
logger = logger !== false ?
|
logger = logger !== false ?
|
||||||
(logger || this.logger)
|
(logger || this.logger)
|
||||||
: false
|
: false
|
||||||
var gid_logger = logger && logger.push('Images')
|
var gid_logger = logger && logger.push('Images', {onclose: abort})
|
||||||
logger = logger && logger.push('Previews')
|
logger = logger && logger.push('Previews', {onclose: abort})
|
||||||
|
|
||||||
|
|
||||||
// get/normalize images...
|
// get/normalize images...
|
||||||
//images = images || this.current
|
//images = images || this.current
|
||||||
@ -473,8 +494,11 @@ var SharpActions = actions.Actions({
|
|||||||
var path_tpl = that.config['preview-path-template']
|
var path_tpl = that.config['preview-path-template']
|
||||||
.replace(/\$INDEX|\$\{INDEX\}/g, that.config['index-dir'] || '.ImageGrid')
|
.replace(/\$INDEX|\$\{INDEX\}/g, that.config['index-dir'] || '.ImageGrid')
|
||||||
|
|
||||||
return Promise.all(images
|
return images
|
||||||
.map(function(gid){
|
.mapChunks(CHUNK_SIZE, function(gid){
|
||||||
|
if(abort.isAborted){
|
||||||
|
throw array.StopIteration('aborted') }
|
||||||
|
|
||||||
var img = that.images[gid]
|
var img = that.images[gid]
|
||||||
var base = base_path
|
var base = base_path
|
||||||
|| img.base_path
|
|| img.base_path
|
||||||
@ -484,6 +508,9 @@ var SharpActions = actions.Actions({
|
|||||||
|
|
||||||
return sizes
|
return sizes
|
||||||
.map(function(size, i){
|
.map(function(size, i){
|
||||||
|
if(abort.isAborted){
|
||||||
|
throw array.StopIteration('aborted') }
|
||||||
|
|
||||||
var name = path = path_tpl
|
var name = path = path_tpl
|
||||||
.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, parseInt(size))
|
.replace(/\$RESOLUTION|\$\{RESOLUTION\}/g, parseInt(size))
|
||||||
.replace(/\$GID|\$\{GID\}/g, gid)
|
.replace(/\$GID|\$\{GID\}/g, gid)
|
||||||
@ -512,14 +539,12 @@ var SharpActions = actions.Actions({
|
|||||||
&& that.markChanged('images', [gid]) }
|
&& that.markChanged('images', [gid]) }
|
||||||
|
|
||||||
return [gid, size, name] }) }) })
|
return [gid, size, name] }) }) })
|
||||||
.flat()) }],
|
.then(function(res){
|
||||||
|
return res.flat() }) })],
|
||||||
|
|
||||||
// XXX add support for offloading the processing to a thread/worker...
|
// XXX add support for offloading the processing to a thread/worker...
|
||||||
// XXX would be nice to be able to abort this...
|
// XXX should we use task.Queue()???
|
||||||
// ...and/or have a generic abort protocol triggered when loading...
|
__cache_metadata_reading: null,
|
||||||
// ...use task queue???
|
|
||||||
// XXX make each section optional...
|
|
||||||
cacheMetadata: ['- Sharp|Image/',
|
cacheMetadata: ['- Sharp|Image/',
|
||||||
core.doc`Cache metadata
|
core.doc`Cache metadata
|
||||||
|
|
||||||
@ -550,21 +575,41 @@ var SharpActions = actions.Actions({
|
|||||||
-> promise([ gid | null, .. ])
|
-> promise([ gid | null, .. ])
|
||||||
|
|
||||||
|
|
||||||
|
This quickly reads/caches essential (.orientation and .flipped)
|
||||||
|
metadata and some non-essential but already there values.
|
||||||
|
|
||||||
|
|
||||||
|
This will overwrite/update if:
|
||||||
|
- .orientation and .flipped iff image .orientation AND .flipped
|
||||||
|
are unset or force is true
|
||||||
|
- metadata if image .metadata is not set or
|
||||||
|
.metadata.ImageGridMetadata is not set
|
||||||
|
- all metadata if force is set to true
|
||||||
|
|
||||||
|
|
||||||
NOTE: this will effectively update metadata format to the new spec...
|
NOTE: this will effectively update metadata format to the new spec...
|
||||||
|
NOTE: for info on full metadata format see: .readMetadata(..)
|
||||||
`,
|
`,
|
||||||
function(images, logger){
|
core.abortablePromise('cacheMetadata', function(abort, images, logger){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
|
var CHUNK_SIZE = 4
|
||||||
|
|
||||||
|
abort.cleanup(function(reason, res){
|
||||||
|
logger
|
||||||
|
&& logger.emit('close')
|
||||||
|
&& reason == 'aborted'
|
||||||
|
&& logger.emit(res)
|
||||||
|
delete that.__cache_metadata_reading })
|
||||||
|
|
||||||
// handle logging and processing list...
|
// handle logging and processing list...
|
||||||
// NOTE: these will maintain .__metadata_reading helping
|
// NOTE: these will maintain .__cache_metadata_reading helping
|
||||||
// avoid processing an image more than once at the same
|
// avoid processing an image more than once at the same
|
||||||
// time...
|
// time...
|
||||||
var done = function(gid, msg){
|
var done = function(gid, msg){
|
||||||
logger && logger.emit(msg || 'done', gid)
|
logger && logger.emit(msg || 'done', gid)
|
||||||
if(that.__metadata_reading){
|
if(that.__cache_metadata_reading){
|
||||||
that.__metadata_reading.delete(gid)
|
that.__cache_metadata_reading.delete(gid) }
|
||||||
if(that.__metadata_reading.size == 0){
|
|
||||||
delete that.__metadata_reading } }
|
|
||||||
return gid }
|
return gid }
|
||||||
var skipping = function(gid){
|
var skipping = function(gid){
|
||||||
return done(gid, 'skipping') }
|
return done(gid, 'skipping') }
|
||||||
@ -601,13 +646,14 @@ var SharpActions = actions.Actions({
|
|||||||
images
|
images
|
||||||
: [images])
|
: [images])
|
||||||
.filter(function(gid){
|
.filter(function(gid){
|
||||||
return !that.__metadata_reading
|
return !that.__cache_metadata_reading
|
||||||
|| !that.__metadata_reading.has(gid) })
|
|| !that.__cache_metadata_reading.has(gid) })
|
||||||
|
|
||||||
logger = logger !== false ?
|
logger = logger !== false ?
|
||||||
(logger || this.logger)
|
(logger || this.logger)
|
||||||
: false
|
: false
|
||||||
logger = logger && logger.push('Caching image metadata')
|
logger = logger
|
||||||
|
&& logger.push('Caching image metadata', {onclose: abort})
|
||||||
logger && logger.emit('queued', images)
|
logger && logger.emit('queued', images)
|
||||||
|
|
||||||
/*/ XXX set this to tmp for .location.load =='loadImages'
|
/*/ XXX set this to tmp for .location.load =='loadImages'
|
||||||
@ -624,11 +670,15 @@ var SharpActions = actions.Actions({
|
|||||||
//*/
|
//*/
|
||||||
|
|
||||||
return images
|
return images
|
||||||
.mapChunks(function(gid){
|
.mapChunks(CHUNK_SIZE, function(gid){
|
||||||
|
// abort...
|
||||||
|
if(abort.isAborted){
|
||||||
|
throw array.StopIteration('aborted') }
|
||||||
|
|
||||||
var img = cached_images[gid]
|
var img = cached_images[gid]
|
||||||
var path = img && that.getImagePath(gid)
|
var path = img && that.getImagePath(gid)
|
||||||
;(that.__metadata_reading =
|
;(that.__cache_metadata_reading =
|
||||||
that.__metadata_reading || new Set())
|
that.__cache_metadata_reading || new Set())
|
||||||
.add(gid)
|
.add(gid)
|
||||||
|
|
||||||
// skip...
|
// skip...
|
||||||
@ -702,11 +752,19 @@ var SharpActions = actions.Actions({
|
|||||||
that.ribbons
|
that.ribbons
|
||||||
&& that.ribbons.updateImage(gid)
|
&& that.ribbons.updateImage(gid)
|
||||||
|
|
||||||
return done(gid) }) }) }],
|
return done(gid) }) }) })],
|
||||||
cacheAllMetadata: ['- Sharp|Image/',
|
cacheAllMetadata: ['- Sharp|Image/',
|
||||||
core.doc`Cache all metadata
|
core.doc`Cache all metadata
|
||||||
NOTE: this is a shorthand to .cacheMetadata('all', ..)`,
|
NOTE: this is a shorthand to .cacheMetadata('all', ..)`,
|
||||||
'cacheMetadata: "all" ...'],
|
'cacheMetadata: "all" ...'],
|
||||||
|
|
||||||
|
|
||||||
|
// shorthands...
|
||||||
|
// XXX do we need these???
|
||||||
|
abortMakePreviews: ['- Sharp/',
|
||||||
|
'abort: "makePreviews"'],
|
||||||
|
abortCacheMetadata: ['- Sharp/',
|
||||||
|
'abort: "cacheMetadata"'],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -727,9 +785,19 @@ module.Sharp = core.ImageGridFeatures.Feature({
|
|||||||
isApplicable: function(){ return !!sharp },
|
isApplicable: function(){ return !!sharp },
|
||||||
|
|
||||||
handlers: [
|
handlers: [
|
||||||
/* XXX this needs to be run in the background...
|
// XXX
|
||||||
|
['load.pre',
|
||||||
|
function(){
|
||||||
|
this.abort([
|
||||||
|
'makeResizedImage',
|
||||||
|
'makePreviews',
|
||||||
|
'cacheMetadata',
|
||||||
|
]) }],
|
||||||
|
|
||||||
|
//* XXX this needs to be run in the background...
|
||||||
// XXX this is best done in a thread + needs to be abortable (on .load(..))...
|
// XXX this is best done in a thread + needs to be abortable (on .load(..))...
|
||||||
['loadImages',
|
[['loadImages',
|
||||||
|
'loadNewImages'],
|
||||||
function(){
|
function(){
|
||||||
this.cacheMetadata('all') }],
|
this.cacheMetadata('all') }],
|
||||||
//*/
|
//*/
|
||||||
|
|||||||
@ -24,28 +24,6 @@ var ProgressActions = actions.Actions({
|
|||||||
'progress-update-min': 200,
|
'progress-update-min': 200,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Progress bar widget...
|
|
||||||
//
|
|
||||||
// Create progress bar...
|
|
||||||
// .showProgress('text')
|
|
||||||
//
|
|
||||||
// Update progress bar (value, max, msg)...
|
|
||||||
// .showProgress('text', 0, 10)
|
|
||||||
// .showProgress('text', 10, 50, 'message')
|
|
||||||
//
|
|
||||||
// Update progress bar value (has no effect if max is not set)...
|
|
||||||
// .showProgress('text', 10)
|
|
||||||
//
|
|
||||||
// Close progress bar...
|
|
||||||
// .showProgress('text', 'close')
|
|
||||||
//
|
|
||||||
// Relative progress modification...
|
|
||||||
// .showProgress('text', '+1')
|
|
||||||
// .showProgress('text', '+0', '+1')
|
|
||||||
//
|
|
||||||
// .showProgress(logger)
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// XXX add message to be shown...
|
// XXX add message to be shown...
|
||||||
// XXX should we report errors and stoppages??? (error state??)
|
// XXX should we report errors and stoppages??? (error state??)
|
||||||
// XXX multiple containers...
|
// XXX multiple containers...
|
||||||
@ -53,17 +31,50 @@ var ProgressActions = actions.Actions({
|
|||||||
// XXX revise styles...
|
// XXX revise styles...
|
||||||
__progress_cache: null,
|
__progress_cache: null,
|
||||||
showProgress: ['- Interface/Show progress bar...',
|
showProgress: ['- Interface/Show progress bar...',
|
||||||
function(text, value, max){
|
core.doc`Progress bar widget...
|
||||||
|
|
||||||
|
Create progress bar...
|
||||||
|
.showProgress('text')
|
||||||
|
|
||||||
|
Update progress bar (value, max, msg)...
|
||||||
|
.showProgress('text', 0, 10)
|
||||||
|
.showProgress('text', 10, 50, 'message')
|
||||||
|
|
||||||
|
Update progress bar value (has no effect if max is not set)...
|
||||||
|
.showProgress('text', 10)
|
||||||
|
|
||||||
|
Close progress bar...
|
||||||
|
.showProgress('text', 'close')
|
||||||
|
|
||||||
|
Relative progress modification...
|
||||||
|
.showProgress('text', '+1')
|
||||||
|
.showProgress('text', '+0', '+1')
|
||||||
|
|
||||||
|
.showProgress(logger)
|
||||||
|
|
||||||
|
|
||||||
|
`,
|
||||||
|
function(text, value, max, attrs){
|
||||||
var that = this
|
var that = this
|
||||||
var viewer = this.dom
|
var viewer = this.dom
|
||||||
|
|
||||||
|
// get attrs...
|
||||||
|
var args = [...arguments]
|
||||||
|
attrs = args.slice(1).last() instanceof Object ?
|
||||||
|
args.pop()
|
||||||
|
: null
|
||||||
|
;[text, value, max] = args
|
||||||
|
|
||||||
var msg = text instanceof Array ? text.slice(1).join(': ') : null
|
var msg = text instanceof Array ? text.slice(1).join(': ') : null
|
||||||
text = text instanceof Array ? text[0] : text
|
text = text instanceof Array ? text[0] : text
|
||||||
|
|
||||||
// make sure we do not update too often...
|
// make sure we do not update too often...
|
||||||
if(value != 'close'){
|
if(value != 'close'){
|
||||||
var cache = (this.__progress_cache = this.__progress_cache || {})
|
var cache = (this.__progress_cache = this.__progress_cache || {})
|
||||||
cache = cache[text] = cache[text] || {}
|
cache = cache[text] =
|
||||||
|
Object.assign(
|
||||||
|
cache[text] || {},
|
||||||
|
attrs || {})
|
||||||
|
|
||||||
var updateValue = function(name, value){
|
var updateValue = function(name, value){
|
||||||
var v = cache[name] || 0
|
var v = cache[name] || 0
|
||||||
@ -115,7 +126,11 @@ var ProgressActions = actions.Actions({
|
|||||||
.text(text)
|
.text(text)
|
||||||
// close button...
|
// close button...
|
||||||
.append($('<span class="close">×</span>')
|
.append($('<span class="close">×</span>')
|
||||||
.on('click', function(){ widget.trigger('progressClose') }))
|
.on('click', function(){
|
||||||
|
var cache = (that.__progress_cache || {})[text]
|
||||||
|
cache.onclose
|
||||||
|
&& cache.onclose()
|
||||||
|
widget.trigger('progressClose') }))
|
||||||
// state...
|
// state...
|
||||||
.append($('<span/>')
|
.append($('<span/>')
|
||||||
.addClass('progress-details'))
|
.addClass('progress-details'))
|
||||||
@ -125,10 +140,12 @@ var ProgressActions = actions.Actions({
|
|||||||
.on('progressClose', function(){
|
.on('progressClose', function(){
|
||||||
widget
|
widget
|
||||||
.fadeOut(that.config['progress-fade-duration'] || 200, function(){
|
.fadeOut(that.config['progress-fade-duration'] || 200, function(){
|
||||||
var cache = (that.__progress_cache || {})
|
var cache = (that.__progress_cache || {})[text]
|
||||||
cache[text].timeout
|
cache.timeout
|
||||||
&& clearTimeout(cache[text].timeout)
|
&& clearTimeout(cache.timeout)
|
||||||
delete cache[text]
|
cache.ondone
|
||||||
|
&& cache.ondone()
|
||||||
|
delete (that.__progress_cache || {})[text]
|
||||||
$(this).remove() }) })
|
$(this).remove() }) })
|
||||||
.appendTo(container)
|
.appendTo(container)
|
||||||
: widget
|
: widget
|
||||||
@ -169,7 +186,7 @@ var ProgressActions = actions.Actions({
|
|||||||
// handle logger progress...
|
// handle logger progress...
|
||||||
// XXX revise...
|
// XXX revise...
|
||||||
handleLogItem: ['- System/',
|
handleLogItem: ['- System/',
|
||||||
function(path, status, ...rest){
|
function(logger, path, status, ...rest){
|
||||||
var msg = path.join(': ')
|
var msg = path.join(': ')
|
||||||
var l = (rest.length == 1 && rest[0] instanceof Array) ?
|
var l = (rest.length == 1 && rest[0] instanceof Array) ?
|
||||||
rest[0].length
|
rest[0].length
|
||||||
@ -196,24 +213,24 @@ var ProgressActions = actions.Actions({
|
|||||||
// close...
|
// close...
|
||||||
// XXX is the right keyword...
|
// XXX is the right keyword...
|
||||||
if(status == 'done' && rest.length == 0){
|
if(status == 'done' && rest.length == 0){
|
||||||
this.showProgress(path, 'close')
|
this.showProgress(path, 'close', logger)
|
||||||
|
|
||||||
// report progress...
|
// report progress...
|
||||||
// XXX HACK -- need meaningful status...
|
// XXX HACK -- need meaningful status...
|
||||||
} else if(add.includes(status)){
|
} else if(add.includes(status)){
|
||||||
this.showProgress(path, '+0', '+'+l)
|
this.showProgress(path, '+0', '+'+l, logger)
|
||||||
|
|
||||||
} else if(done.includes(status)){
|
} else if(done.includes(status)){
|
||||||
this.showProgress(path, '+'+l)
|
this.showProgress(path, '+'+l, logger)
|
||||||
|
|
||||||
} else if(skipped.includes(status)){
|
} else if(skipped.includes(status)){
|
||||||
// XXX if everything is skipped the indicator does not
|
// XXX if everything is skipped the indicator does not
|
||||||
// get hidden...
|
// get hidden...
|
||||||
this.showProgress(path, '+'+l)
|
this.showProgress(path, '+'+l, logger)
|
||||||
|
|
||||||
// XXX STUB...
|
// XXX STUB...
|
||||||
} else if(status == 'error' ){
|
} else if(status == 'error' ){
|
||||||
this.showProgress(['Error'].concat(msg), '+0', '+'+l)
|
this.showProgress(['Error'].concat(msg), '+0', '+'+l, logger)
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2189,13 +2189,13 @@ var BrowseActionsActions = actions.Actions({
|
|||||||
// it to sort an prioritize stuff...
|
// it to sort an prioritize stuff...
|
||||||
'action-category-order': [
|
'action-category-order': [
|
||||||
'99:$File',
|
'99:$File',
|
||||||
|
// ...
|
||||||
// We can order any sub-tree we want in the same manner
|
// We can order any sub-tree we want in the same manner
|
||||||
// as the root...
|
// as the root...
|
||||||
'File/-80:Clear viewer',
|
'File/-80:Clear viewer',
|
||||||
'File/-90:Close viewer',
|
'File/-90:Close viewer',
|
||||||
// Non existing elements will not get drawn...
|
// Non existing elements will not get drawn...
|
||||||
//'File/-99:moo',
|
//'File/-99:moo',
|
||||||
// XXX this seems over-crowded -- revise!!!
|
|
||||||
'99:$Edit',
|
'99:$Edit',
|
||||||
'Edit/90:Undo',
|
'Edit/90:Undo',
|
||||||
'Edit/90:Redo',
|
'Edit/90:Redo',
|
||||||
@ -2210,10 +2210,12 @@ var BrowseActionsActions = actions.Actions({
|
|||||||
'Edit/70:.*shift.*',
|
'Edit/70:.*shift.*',
|
||||||
'Edit/60:.*rotate.*',
|
'Edit/60:.*rotate.*',
|
||||||
'Edit/50:.*flip.*',
|
'Edit/50:.*flip.*',
|
||||||
|
// ...
|
||||||
'$Navigate',
|
'$Navigate',
|
||||||
'Navigate/90:.*image.*',
|
'Navigate/90:.*image.*',
|
||||||
'Navigate/80:.*screen.*',
|
'Navigate/80:.*screen.*',
|
||||||
'Navigate/70:.*ribbon.*',
|
'Navigate/70:.*ribbon.*',
|
||||||
|
// ...
|
||||||
'$Image',
|
'$Image',
|
||||||
'Image/99:$Copy image',
|
'Image/99:$Copy image',
|
||||||
'Image/99:.*copy.*',
|
'Image/99:.*copy.*',
|
||||||
@ -2229,6 +2231,7 @@ var BrowseActionsActions = actions.Actions({
|
|||||||
'Image/65:.*shift.*',
|
'Image/65:.*shift.*',
|
||||||
'Image/60:.*rotate.*',
|
'Image/60:.*rotate.*',
|
||||||
'Image/55:.*flip.*',
|
'Image/55:.*flip.*',
|
||||||
|
// ...
|
||||||
'Image/-70:---',
|
'Image/-70:---',
|
||||||
'Image/-70:.*remove.*',
|
'Image/-70:.*remove.*',
|
||||||
'$Virtual block',
|
'$Virtual block',
|
||||||
@ -2238,14 +2241,25 @@ var BrowseActionsActions = actions.Actions({
|
|||||||
'Virtual block/60:.*mark.*',
|
'Virtual block/60:.*mark.*',
|
||||||
'Virtual block/50:---',
|
'Virtual block/50:---',
|
||||||
'Virtual block/40:.*crop.*',
|
'Virtual block/40:.*crop.*',
|
||||||
|
// ...
|
||||||
'$Ribbon',
|
'$Ribbon',
|
||||||
|
'Ribbon/80:set.*',
|
||||||
|
'Ribbon/70:.*shift.*',
|
||||||
|
'Ribbon/60:.*merge.*',
|
||||||
|
'Ribbon/50:Flatten',
|
||||||
|
'Ribbon/40:.*split.*',
|
||||||
|
'Ribbon/30:.*crop.*',
|
||||||
|
'Ribbon/20:.*order.*',
|
||||||
|
'Ribbon/20:.*align.*',
|
||||||
|
// ...
|
||||||
|
'Ribbon/-60:Add.*collection.*',
|
||||||
'Ribbon/-70:---',
|
'Ribbon/-70:---',
|
||||||
'Ribbon/-70:.*remove.*',
|
'Ribbon/-70:.*remove.*',
|
||||||
'$Crop',
|
'$Crop',
|
||||||
'Crop/80:Crop $marked images',
|
'Crop/80:Crop $marked images',
|
||||||
'Crop/80:Crop $bookmarked images',
|
'Crop/80:Crop $bookmarked images',
|
||||||
'Crop/70:$Crop',
|
'Crop/70:$Crop',
|
||||||
'Crop/70:$Flatten',
|
'Crop/70:Crop $flatten',
|
||||||
|
|
||||||
// Path patterns...
|
// Path patterns...
|
||||||
//
|
//
|
||||||
@ -2279,32 +2293,35 @@ var BrowseActionsActions = actions.Actions({
|
|||||||
'Crop/-70:---',
|
'Crop/-70:---',
|
||||||
//*/
|
//*/
|
||||||
|
|
||||||
|
// ...
|
||||||
'Crop/-50:---',
|
'Crop/-50:---',
|
||||||
'Crop/-60:Remove from crop',
|
'Crop/-60:Remove from crop',
|
||||||
'Crop/-70:Remove ribbon.*',
|
'Crop/-70:Remove ribbon.*',
|
||||||
'Crop/-71:Remove marked.*',
|
'Crop/-71:Remove marked.*',
|
||||||
'Crop/-72:.*remove.*',
|
'Crop/-72:.*remove.*',
|
||||||
|
|
||||||
'Crop/-75:---',
|
'Crop/-75:---',
|
||||||
|
|
||||||
'Crop/-80:Uncrop keeping image order',
|
'Crop/-80:Uncrop keeping image order',
|
||||||
'Crop/-81:Uncrop all',
|
'Crop/-81:Uncrop all',
|
||||||
'Crop/-82:$Uncrop',
|
'Crop/-82:$Uncrop',
|
||||||
'Co$llections',
|
'Co$llections',
|
||||||
|
// ...
|
||||||
'Collections/-50:.*exit.*',
|
'Collections/-50:.*exit.*',
|
||||||
'Collections/-60:.*edit.*',
|
'Collections/-60:.*edit.*',
|
||||||
'Collections/-70:---',
|
'Collections/-70:---',
|
||||||
'Collections/-70:.*remove.*',
|
'Collections/-70:.*remove.*',
|
||||||
'$Tag',
|
'$Tag',
|
||||||
|
// ...
|
||||||
// XXX revise...
|
// XXX revise...
|
||||||
'Tag/-80:---',
|
'Tag/-80:---',
|
||||||
'Tag/-90:.*remove.*',
|
'Tag/-90:.*remove.*',
|
||||||
'$Mark',
|
'$Mark',
|
||||||
|
// ...
|
||||||
'Mark/-75:.*collection...',
|
'Mark/-75:.*collection...',
|
||||||
'Mark/-80:---',
|
'Mark/-80:---',
|
||||||
'Mark/-80:.*remove.*',
|
'Mark/-80:.*remove.*',
|
||||||
'Mark/-90:.*unmark.*',
|
'Mark/-90:.*unmark.*',
|
||||||
'$Bookmark',
|
'$Bookmark',
|
||||||
|
// ...
|
||||||
'Bookmark/-80:---',
|
'Bookmark/-80:---',
|
||||||
'Bookmark/-80:.*remove.*',
|
'Bookmark/-80:.*remove.*',
|
||||||
|
|
||||||
@ -2312,6 +2329,7 @@ var BrowseActionsActions = actions.Actions({
|
|||||||
|
|
||||||
'-40:Interface',
|
'-40:Interface',
|
||||||
'Interface/90:Theme',
|
'Interface/90:Theme',
|
||||||
|
// ...
|
||||||
'-50:$Workspace',
|
'-50:$Workspace',
|
||||||
'-60:System',
|
'-60:System',
|
||||||
'-70:$Help',
|
'-70:$Help',
|
||||||
|
|||||||
@ -17,6 +17,13 @@ var object = require('lib/object')
|
|||||||
var QueuePrototype = Object.create(actions.MetaActions)
|
var QueuePrototype = Object.create(actions.MetaActions)
|
||||||
|
|
||||||
|
|
||||||
|
// XXX might be good to add a Promise-like api:
|
||||||
|
// .then(..)
|
||||||
|
// .catch(..)
|
||||||
|
// .finally(..)
|
||||||
|
// ...but since the queue may be fed and running without stopping
|
||||||
|
// not sure what purpose these can serve if they are global...
|
||||||
|
// ...these could have the semantics of run after last task added...
|
||||||
// XXX need a mechanism to either queue chains of tasks that depend on
|
// XXX need a mechanism to either queue chains of tasks that depend on
|
||||||
// on the previous results or a way to delay a task until what it
|
// on the previous results or a way to delay a task until what it
|
||||||
// needs is finished...
|
// needs is finished...
|
||||||
@ -49,9 +56,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
: 0)
|
: 0)
|
||||||
+ (typeof(b) == typeof(1) ? b
|
+ (typeof(b) == typeof(1) ? b
|
||||||
: that[b] ? that[b].len
|
: that[b] ? that[b].len
|
||||||
: 0)
|
: 0) }, 0) },
|
||||||
}, 0)
|
|
||||||
},
|
|
||||||
set length(val){},
|
set length(val){},
|
||||||
|
|
||||||
// can be:
|
// can be:
|
||||||
@ -71,8 +76,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
//
|
//
|
||||||
// XXX should be more informative -- now supports only 'running' and 'stopped'
|
// XXX should be more informative -- now supports only 'running' and 'stopped'
|
||||||
get state(){
|
get state(){
|
||||||
return this._state || 'stopped'
|
return this._state || 'stopped' },
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// General task life cycle events...
|
// General task life cycle events...
|
||||||
@ -111,8 +115,8 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
} else {
|
} else {
|
||||||
var tag = null
|
var tag = null
|
||||||
var task = a
|
var task = a
|
||||||
var mode = b
|
var mode = b }
|
||||||
}
|
|
||||||
mode = mode || this.config['default-queue-mode']
|
mode = mode || this.config['default-queue-mode']
|
||||||
var ready = this.__ready = this.__ready || []
|
var ready = this.__ready = this.__ready || []
|
||||||
|
|
||||||
@ -120,22 +124,19 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
this.taskQueued(tag, task, mode)
|
this.taskQueued(tag, task, mode)
|
||||||
|
|
||||||
// restart in case the queue was depleted...
|
// restart in case the queue was depleted...
|
||||||
this._run()
|
this._run() }],
|
||||||
}],
|
|
||||||
unqueue: ['',
|
unqueue: ['',
|
||||||
function(a, b){
|
function(a, b){
|
||||||
var that = this
|
var that = this
|
||||||
var ready = this.__ready
|
var ready = this.__ready
|
||||||
// empty queue...
|
// empty queue...
|
||||||
if(ready == null || ready.len == 0){
|
if(ready == null || ready.len == 0){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
// special case -- drop all...
|
// special case -- drop all...
|
||||||
if(a == '*'){
|
if(a == '*'){
|
||||||
ready.splice(0, ready.length)
|
ready.splice(0, ready.length)
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
// XXX prep args...
|
// XXX prep args...
|
||||||
var tag = typeof(a) == typeof('str') ? a : b
|
var tag = typeof(a) == typeof('str') ? a : b
|
||||||
@ -143,8 +144,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
|
|
||||||
// no args...
|
// no args...
|
||||||
if(tag == null && task == null){
|
if(tag == null && task == null){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
// remove matching tasks from the queue...
|
// remove matching tasks from the queue...
|
||||||
ready.forEach(function(e, i){
|
ready.forEach(function(e, i){
|
||||||
@ -155,17 +155,13 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
// both task and tag given...
|
// both task and tag given...
|
||||||
: e[0] == tag && e[1] === task){
|
: e[0] == tag && e[1] === task){
|
||||||
delete ready[i]
|
delete ready[i]
|
||||||
that.taskDropped(e[0], e[1], e[2])
|
that.taskDropped(e[0], e[1], e[2]) } }) }],
|
||||||
}
|
|
||||||
})
|
|
||||||
}],
|
|
||||||
delay: ['',
|
delay: ['',
|
||||||
function(a, b){
|
function(a, b){
|
||||||
var ready = this.__ready
|
var ready = this.__ready
|
||||||
// empty queue...
|
// empty queue...
|
||||||
if(ready == null || ready.len == 0){
|
if(ready == null || ready.len == 0){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
// XXX prep args...
|
// XXX prep args...
|
||||||
var tag = typeof(a) == typeof('str') ? a : b
|
var tag = typeof(a) == typeof('str') ? a : b
|
||||||
@ -173,8 +169,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
|
|
||||||
// no args...
|
// no args...
|
||||||
if(tag == null && task == null){
|
if(tag == null && task == null){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
var delayed = []
|
var delayed = []
|
||||||
// remove the matching tasks...
|
// remove the matching tasks...
|
||||||
@ -188,19 +183,14 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
|
|
||||||
if(res){
|
if(res){
|
||||||
delete ready[i]
|
delete ready[i]
|
||||||
|
delayed.push(e) } })
|
||||||
delayed.push(e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// push delayed list to the end of the queue...
|
// push delayed list to the end of the queue...
|
||||||
delayed.forEach(function(e){
|
delayed.forEach(function(e){
|
||||||
ready.push(e)
|
ready.push(e) })
|
||||||
})
|
|
||||||
|
|
||||||
// restart in case the queue was depleted...
|
// restart in case the queue was depleted...
|
||||||
this._run()
|
this._run() }],
|
||||||
}],
|
|
||||||
|
|
||||||
// Run the queue...
|
// Run the queue...
|
||||||
//
|
//
|
||||||
@ -230,8 +220,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
_run: ['',
|
_run: ['',
|
||||||
function(){
|
function(){
|
||||||
if(this.__is_running){
|
if(this.__is_running){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
var that = this
|
var that = this
|
||||||
var size = this.config['running-pool-size']
|
var size = this.config['running-pool-size']
|
||||||
@ -249,8 +238,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
// XXX this might race...
|
// XXX this might race...
|
||||||
var elem = that.__ready.shift()
|
var elem = that.__ready.shift()
|
||||||
if(elem == null){
|
if(elem == null){
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
var task = elem[1]
|
var task = elem[1]
|
||||||
that.__is_running = true
|
that.__is_running = true
|
||||||
@ -292,9 +280,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
that.done()
|
that.done()
|
||||||
|
|
||||||
that.config['clear-on-done']
|
that.config['clear-on-done']
|
||||||
&& that.clear()
|
&& that.clear() } })
|
||||||
}
|
|
||||||
})
|
|
||||||
// push to done and ._run some more...
|
// push to done and ._run some more...
|
||||||
.then(function(){
|
.then(function(){
|
||||||
// pop self of .__running
|
// pop self of .__running
|
||||||
@ -316,9 +302,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
that.done()
|
that.done()
|
||||||
|
|
||||||
that.config['clear-on-done']
|
that.config['clear-on-done']
|
||||||
&& that.clear()
|
&& that.clear() } })
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// other...
|
// other...
|
||||||
} else {
|
} else {
|
||||||
@ -338,13 +322,10 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
that.done()
|
that.done()
|
||||||
|
|
||||||
that.config['clear-on-done']
|
that.config['clear-on-done']
|
||||||
&& that.clear()
|
&& that.clear() } }
|
||||||
}
|
|
||||||
}
|
|
||||||
})() }
|
})() }
|
||||||
|
|
||||||
delete that.__is_running
|
delete that.__is_running }],
|
||||||
}],
|
|
||||||
|
|
||||||
// State manipulation actions...
|
// State manipulation actions...
|
||||||
//
|
//
|
||||||
@ -352,12 +333,10 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
start: ['',
|
start: ['',
|
||||||
function(){
|
function(){
|
||||||
this._state = 'ready'
|
this._state = 'ready'
|
||||||
this._run()
|
this._run() }],
|
||||||
}],
|
|
||||||
stop: ['',
|
stop: ['',
|
||||||
function(){
|
function(){
|
||||||
delete this._state
|
delete this._state }],
|
||||||
}],
|
|
||||||
clear: ['',
|
clear: ['',
|
||||||
function(){
|
function(){
|
||||||
// XXX should this stop???
|
// XXX should this stop???
|
||||||
@ -365,8 +344,7 @@ module.QueueActions = actions.Actions(QueuePrototype, {
|
|||||||
delete this.__ready
|
delete this.__ready
|
||||||
delete this.__running
|
delete this.__running
|
||||||
delete this.__failed
|
delete this.__failed
|
||||||
delete this.__done
|
delete this.__done }],
|
||||||
}],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -376,5 +354,6 @@ object.Constructor('Queue', QueueActions)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* vim:set ts=4 sw=4 : */ return module })
|
* vim:set ts=4 sw=4 : */ return module })
|
||||||
|
|||||||
6
Viewer/package-lock.json
generated
6
Viewer/package-lock.json
generated
@ -1117,9 +1117,9 @@
|
|||||||
"integrity": "sha512-EzT4CP6d6lI8bnknNgT3W8mUQhSVXflO0yPbKD4dKsFcINiC6npjoEBz+8m3VQmWJhc+36pXD4JLwNxUEgzi+Q=="
|
"integrity": "sha512-EzT4CP6d6lI8bnknNgT3W8mUQhSVXflO0yPbKD4dKsFcINiC6npjoEBz+8m3VQmWJhc+36pXD4JLwNxUEgzi+Q=="
|
||||||
},
|
},
|
||||||
"ig-types": {
|
"ig-types": {
|
||||||
"version": "3.0.2",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/ig-types/-/ig-types-3.1.0.tgz",
|
||||||
"integrity": "sha512-djnS6UnS+a0y37DNFUk8PZf0lt7TQO5u/RQPYpFVW4sqwA2HpSdAmmrWyu6UCVdhw+b9Q6E+RjAXrWVEkn1w3A==",
|
"integrity": "sha512-k/QbS9D30Fun3Xrh+6LHpCYsbQOwYlj1PX0uaNOnpmxg2tlWSdLOdykH8IMUbGIm/tI8MsJeKnJc4vu51s89Tg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ig-object": "^5.2.8",
|
"ig-object": "^5.2.8",
|
||||||
"object-run": "^1.0.1"
|
"object-run": "^1.0.1"
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
"ig-argv": "^2.15.0",
|
"ig-argv": "^2.15.0",
|
||||||
"ig-features": "^3.4.2",
|
"ig-features": "^3.4.2",
|
||||||
"ig-object": "^5.2.8",
|
"ig-object": "^5.2.8",
|
||||||
"ig-types": "^3.0.2",
|
"ig-types": "^3.1.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"object-run": "^1.0.1",
|
"object-run": "^1.0.1",
|
||||||
"requirejs": "^2.3.6",
|
"requirejs": "^2.3.6",
|
||||||
|
|||||||
@ -77,8 +77,7 @@ $(function(){
|
|||||||
} catch(err){
|
} catch(err){
|
||||||
console.error(err)
|
console.error(err)
|
||||||
//throw err
|
//throw err
|
||||||
return
|
return }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// used to switch experimental actions on (set to true) or off (unset or false)...
|
// used to switch experimental actions on (set to true) or off (unset or false)...
|
||||||
@ -105,8 +104,7 @@ $(function(){
|
|||||||
err.missing_suggested)
|
err.missing_suggested)
|
||||||
err.missing.length > 0
|
err.missing.length > 0
|
||||||
&& console.warn('Missing dependencies:',
|
&& console.warn('Missing dependencies:',
|
||||||
err.missing)
|
err.missing) }
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// setup the viewer...
|
// setup the viewer...
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user