2015-12-17 03:34:20 +03:00
|
|
|
/**********************************************************************
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
|
|
define(function(require){ var module = {}
|
|
|
|
|
|
|
|
|
|
//var DEBUG = DEBUG != null ? DEBUG : true
|
|
|
|
|
|
|
|
|
|
var util = require('lib/util')
|
|
|
|
|
|
|
|
|
|
var actions = require('lib/actions')
|
|
|
|
|
var features = require('lib/features')
|
|
|
|
|
|
|
|
|
|
var core = require('features/core')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
|
2016-06-05 03:46:24 +03:00
|
|
|
// XXX add url scheme support...
|
|
|
|
|
// <method>://<path>#<current>?<other>
|
2015-12-28 07:23:28 +03:00
|
|
|
// XXX add .hash support for in-location .current setting when no index
|
|
|
|
|
// available...
|
2015-12-17 03:34:20 +03:00
|
|
|
// XXX this should provide mechaincs to define location handlers, i.e.
|
|
|
|
|
// a set for loader/saver per location type (.method)
|
|
|
|
|
// XXX revise the wording...
|
|
|
|
|
// .path or .url
|
|
|
|
|
|
|
|
|
|
var LocationActions = actions.Actions({
|
2016-06-04 20:50:37 +03:00
|
|
|
config: {
|
|
|
|
|
'recover-load-errors-to-previous-location': true,
|
2016-06-05 03:46:24 +03:00
|
|
|
|
|
|
|
|
'default-load-method': null,
|
2016-06-04 20:50:37 +03:00
|
|
|
},
|
|
|
|
|
|
2015-12-17 03:34:20 +03:00
|
|
|
// Format:
|
|
|
|
|
// {
|
|
|
|
|
// path: <base-path>,
|
|
|
|
|
// method: <load-method>,
|
2015-12-28 07:23:28 +03:00
|
|
|
// current: <current-gid>,
|
2016-06-05 03:46:24 +03:00
|
|
|
// ...
|
2015-12-17 03:34:20 +03:00
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// NOTE: these will remove the trailing '/' (or '\') from .path
|
|
|
|
|
// unless the path is root (i.e. "/")...
|
|
|
|
|
// ...this is mainly to facilitate better browse support, i.e.
|
|
|
|
|
// to open the dir (open parent + select current) and not
|
|
|
|
|
// within the dir
|
|
|
|
|
__location: null,
|
2016-05-06 21:17:54 +03:00
|
|
|
|
2015-12-17 03:34:20 +03:00
|
|
|
get location(){
|
|
|
|
|
this.__location = this.__location || {}
|
|
|
|
|
|
|
|
|
|
var b = this.__location.path
|
|
|
|
|
if(b && b != '/' && b != '\\'){
|
|
|
|
|
b = util.normalizePath(b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(b){
|
|
|
|
|
this.__location.path = b
|
|
|
|
|
}
|
2015-12-29 01:02:57 +03:00
|
|
|
|
2015-12-31 05:44:14 +03:00
|
|
|
this.__location.current = this.current
|
2015-12-29 01:02:57 +03:00
|
|
|
|
2015-12-17 03:34:20 +03:00
|
|
|
return this.__location
|
|
|
|
|
},
|
2016-06-05 03:46:24 +03:00
|
|
|
// NOTE: this is a shorthand for .loadLocation(..)
|
|
|
|
|
// NOTE: the method is needed to enable us to get the action return
|
|
|
|
|
// value...
|
2015-12-17 03:34:20 +03:00
|
|
|
set location(value){
|
2016-06-05 03:46:24 +03:00
|
|
|
this.loadLocation(value)
|
|
|
|
|
},
|
2015-12-17 03:34:20 +03:00
|
|
|
|
|
|
|
|
|
2016-06-05 03:46:24 +03:00
|
|
|
// Load location...
|
|
|
|
|
//
|
|
|
|
|
// Reload current location...
|
|
|
|
|
// .loadLocation()
|
|
|
|
|
// -> result
|
|
|
|
|
//
|
|
|
|
|
// Load new path using current location method and data...
|
|
|
|
|
// .loadLocation(path)
|
|
|
|
|
// -> result
|
|
|
|
|
//
|
|
|
|
|
// Load new location...
|
|
|
|
|
// .loadLocation(location)
|
|
|
|
|
// -> result
|
|
|
|
|
// NOTE: this is almost the same as .location = location but
|
|
|
|
|
// here we can access the call return value.
|
|
|
|
|
//
|
|
|
|
|
// XXX not sure about where to set the .__location -- see inside...
|
|
|
|
|
loadLocation: ['File/Load location',
|
|
|
|
|
function(location){
|
|
|
|
|
location = location || this.location
|
|
|
|
|
|
|
|
|
|
// got a path -> load using current location data...
|
|
|
|
|
if(typeof(location) == typeof('str')){
|
|
|
|
|
location = {
|
|
|
|
|
path: path,
|
|
|
|
|
method: (this.__location && this.__location.method)
|
|
|
|
|
|| this.config['default-load-method'],
|
|
|
|
|
current: this.current,
|
|
|
|
|
}
|
2015-12-17 03:34:20 +03:00
|
|
|
|
2016-06-05 03:46:24 +03:00
|
|
|
// got an object...
|
|
|
|
|
} else {
|
|
|
|
|
// clone the location...
|
|
|
|
|
location = JSON.parse(JSON.stringify(location))
|
|
|
|
|
}
|
2015-12-28 07:23:28 +03:00
|
|
|
|
2016-06-05 03:46:24 +03:00
|
|
|
var method = location.method
|
|
|
|
|
|| this.location.method
|
|
|
|
|
|| this.config['default-load-method']
|
|
|
|
|
var cur = location.current
|
|
|
|
|
var path = location.path
|
2015-12-29 01:02:57 +03:00
|
|
|
|
2016-06-05 03:46:24 +03:00
|
|
|
// normalize path if it's not root...
|
|
|
|
|
if(path != '/' && path != '\\'){
|
|
|
|
|
path = location.path = util.normalizePath(path)
|
|
|
|
|
}
|
2016-06-04 20:50:37 +03:00
|
|
|
|
2016-06-05 03:46:24 +03:00
|
|
|
|
|
|
|
|
// XXX ???
|
|
|
|
|
this.__location = location
|
|
|
|
|
|
|
|
|
|
// NOTE: the method should set the proper location if it uses .clear()...
|
|
|
|
|
var res = method && this[method](path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// load current...
|
|
|
|
|
if(cur){
|
|
|
|
|
if(res && res.then != null){
|
|
|
|
|
var that = this
|
|
|
|
|
res.then(function(){
|
|
|
|
|
that.current = cur
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
this.current = cur
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
|
|
// Load index with recovery...
|
2016-06-04 20:50:37 +03:00
|
|
|
//
|
2016-06-05 03:46:24 +03:00
|
|
|
// This will:
|
|
|
|
|
// - save recovery data (.__recover)
|
|
|
|
|
// - load
|
|
|
|
|
// - clear recovery data (if load successful)
|
2016-06-04 20:50:37 +03:00
|
|
|
//
|
2016-06-05 03:46:24 +03:00
|
|
|
// NOTE: for more info on the load protocol see: base.BaseActions.load
|
|
|
|
|
load: [
|
|
|
|
|
function(data){
|
|
|
|
|
var location = data.location
|
|
|
|
|
|
|
|
|
|
// prepare to recover, just in case...
|
|
|
|
|
this.__recover = (this.__recover !== false
|
|
|
|
|
&& this.config['recover-load-errors-to-previous-location']) ?
|
|
|
|
|
this.location
|
|
|
|
|
: false
|
|
|
|
|
|
|
|
|
|
return function(){
|
2016-06-04 20:50:37 +03:00
|
|
|
// NOTE: we are setting this after the load because the
|
|
|
|
|
// loader may .clear() the viewer, thus clearing the
|
|
|
|
|
// .location too...
|
|
|
|
|
this.__location = location
|
|
|
|
|
|
|
|
|
|
// all went well clear the recovery data...
|
|
|
|
|
delete this.__recover
|
2016-06-05 03:46:24 +03:00
|
|
|
}
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
|
|
// Load data and recover on error...
|
|
|
|
|
//
|
|
|
|
|
// This is the same as .load(..) but will monitor for load errors
|
|
|
|
|
// and attempt to recover if it fails...
|
|
|
|
|
//
|
|
|
|
|
// NOTE: this avoids load loops by attempting to recover only once...
|
|
|
|
|
// NOTE: this is done as a wrapper because we can't catch errors in
|
|
|
|
|
// parent actions at this point...
|
|
|
|
|
loadOrRecover: ['- Location/',
|
|
|
|
|
function(data){
|
|
|
|
|
// this is the critical section, after this point we
|
|
|
|
|
// are doing the actual loading....
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
|
|
this.load(data)
|
2016-06-04 20:50:37 +03:00
|
|
|
|
|
|
|
|
// something bad happened, clear and handle it...
|
|
|
|
|
} catch(err){
|
|
|
|
|
this.clear()
|
|
|
|
|
|
|
|
|
|
console.error(err)
|
|
|
|
|
|
|
|
|
|
// recover to last location...
|
|
|
|
|
if(this.__recover){
|
2016-06-05 03:46:24 +03:00
|
|
|
this.recover()
|
2016-06-04 20:50:37 +03:00
|
|
|
|
|
|
|
|
// fail...
|
|
|
|
|
} else {
|
|
|
|
|
// clear the recovery data...
|
|
|
|
|
delete this.__recover
|
|
|
|
|
|
|
|
|
|
// fail...
|
|
|
|
|
throw err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}],
|
2016-06-05 03:46:24 +03:00
|
|
|
|
|
|
|
|
// Recover from load error...
|
|
|
|
|
//
|
|
|
|
|
// This will:
|
|
|
|
|
// - get recovery data if present
|
|
|
|
|
// - load recovery data
|
|
|
|
|
// - clear recovery data
|
|
|
|
|
//
|
|
|
|
|
// NOTE: if no recovery data present (.__recover) this will do nothing.
|
|
|
|
|
recover: ['- File/Recover from load error',
|
|
|
|
|
function(){
|
|
|
|
|
var l = this.__recover
|
|
|
|
|
|
|
|
|
|
// nothing to recover...
|
|
|
|
|
if(!l){
|
|
|
|
|
delete this.__recover
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: this will prevent us from entering
|
|
|
|
|
// a recover attempt loop...
|
|
|
|
|
// ...if the recovery fails we will just
|
|
|
|
|
// clear and stop.
|
|
|
|
|
this.__recover = false
|
|
|
|
|
|
|
|
|
|
// do the loading...
|
|
|
|
|
this.location = l
|
|
|
|
|
}],
|
2015-12-17 03:34:20 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
module.Location = core.ImageGridFeatures.Feature({
|
|
|
|
|
title: '',
|
|
|
|
|
doc: '',
|
|
|
|
|
|
|
|
|
|
tag: 'location',
|
|
|
|
|
|
|
|
|
|
actions: LocationActions,
|
2016-05-06 21:17:54 +03:00
|
|
|
|
|
|
|
|
handlers: [
|
2016-05-29 05:27:31 +03:00
|
|
|
['clone',
|
|
|
|
|
function(res){
|
|
|
|
|
if(this.location){
|
|
|
|
|
res.__location = JSON.parse(JSON.stringify(this.__location))
|
|
|
|
|
}
|
|
|
|
|
}],
|
|
|
|
|
['clear',
|
|
|
|
|
function(){
|
|
|
|
|
delete this.__location
|
|
|
|
|
}],
|
|
|
|
|
|
|
|
|
|
// 1) store .location
|
|
|
|
|
// 2) cleanup .images[..].base_path
|
|
|
|
|
//
|
|
|
|
|
// XXX might be good to make the .base_path relative to location
|
|
|
|
|
// if possible...
|
|
|
|
|
// XXX not sure if this is the right place for .images[..].base_path
|
|
|
|
|
// handling...
|
2016-05-06 21:17:54 +03:00
|
|
|
['json',
|
|
|
|
|
function(res){
|
|
|
|
|
if(this.location){
|
2016-05-28 21:36:17 +03:00
|
|
|
var l = res.location = JSON.parse(JSON.stringify(this.location))
|
|
|
|
|
|
|
|
|
|
// cleanup base_path...
|
|
|
|
|
Object.keys(res.images).forEach(function(gid){
|
|
|
|
|
var img = res.images[gid]
|
|
|
|
|
|
|
|
|
|
if(l.path == img.base_path){
|
|
|
|
|
delete img.base_path
|
|
|
|
|
}
|
|
|
|
|
})
|
2016-05-06 21:17:54 +03:00
|
|
|
}
|
|
|
|
|
}],
|
|
|
|
|
['load',
|
|
|
|
|
function(_, data){
|
|
|
|
|
if(data.location){
|
|
|
|
|
this.__location = data.location
|
|
|
|
|
}
|
|
|
|
|
}],
|
|
|
|
|
],
|
2015-12-17 03:34:20 +03:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
|
* vim:set ts=4 sw=4 : */
|
|
|
|
|
return module })
|