mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-29 10:20:08 +00:00
started work on fs writer...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
4e31790f95
commit
0d47a559ba
@ -7,16 +7,21 @@
|
||||
var pathlib = require('path')
|
||||
var events = require('events')
|
||||
|
||||
var fse = require('fs.extra')
|
||||
var fse = require('fs-extra')
|
||||
var glob = require('glob')
|
||||
var Promise = require('promise')
|
||||
|
||||
// XXX seems that we need different buids of this for use with node and nw...
|
||||
// XXX BUG: nw-gyp does not support msvs2015...
|
||||
//var sharp = require('sharp')
|
||||
|
||||
var guaranteeEvents = require('guarantee-events')
|
||||
|
||||
|
||||
define(function(require){ var module = {}
|
||||
console.log('>>> file')
|
||||
|
||||
|
||||
//var DEBUG = DEBUG != null ? DEBUG : true
|
||||
|
||||
var data = require('data')
|
||||
@ -73,8 +78,8 @@ module.gGlob = function(){
|
||||
|
||||
var listIndexes =
|
||||
module.listIndexes =
|
||||
function(base){
|
||||
return gGlob(base +'/**/'+ INDEX_DIR)
|
||||
function(base, index_dir){
|
||||
return gGlob(base +'/**/'+ index_dir || INDEX_DIR)
|
||||
}
|
||||
|
||||
|
||||
@ -93,6 +98,8 @@ function listJSON(path, pattern){
|
||||
|
||||
|
||||
var loadFile = Promise.denodeify(fse.readFile)
|
||||
var writeFile = Promise.denodeify(fse.writeFile)
|
||||
var ensureDir = Promise.denodeify(fse.ensureDir)
|
||||
|
||||
|
||||
// XXX handle errors...
|
||||
@ -174,7 +181,8 @@ function loadJSON(path){
|
||||
// ...(a) seems more logical...
|
||||
var loadIndex =
|
||||
module.loadIndex =
|
||||
function(path, logger){
|
||||
function(path, index_dir, logger){
|
||||
index_dir = index_dir || INDEX_DIR
|
||||
// XXX should this be interactive (a-la EventEmitter) or as it is now
|
||||
// return the whole thing as a block (Promise)...
|
||||
// NOTE: one way to do this is use the logger, it will get
|
||||
@ -182,7 +190,7 @@ function(path, logger){
|
||||
return new Promise(function(resolve, reject){
|
||||
// we've got an index...
|
||||
// XXX do we need to check if if it's a dir???
|
||||
if(pathlib.basename(path) == INDEX_DIR){
|
||||
if(pathlib.basename(path) == index_dir){
|
||||
|
||||
logger && logger.emit('path', path)
|
||||
|
||||
@ -355,7 +363,7 @@ function(path, logger){
|
||||
var loaders = []
|
||||
|
||||
// XXX handle 'error' event...
|
||||
listIndexes(path)
|
||||
listIndexes(path, index_dir)
|
||||
// XXX handle errors...
|
||||
.on('error', function(err){
|
||||
logger && logger.emit('error', err)
|
||||
@ -369,7 +377,7 @@ function(path, logger){
|
||||
// dir (the parent dir to the index root)
|
||||
// we do not need to include the index
|
||||
// itself in the base path...
|
||||
var p = path.split(INDEX_DIR)[0]
|
||||
var p = path.split(index_dir)[0]
|
||||
res[p] = obj[path]
|
||||
}))
|
||||
})
|
||||
@ -401,8 +409,9 @@ function(path, logger){
|
||||
// XXX handle errors....
|
||||
var loadPreviews =
|
||||
module.loadPreviews =
|
||||
function(base, previews, absolute_path){
|
||||
function(base, previews, index_dir, absolute_path){
|
||||
previews = previews || {}
|
||||
index_dir = index_dir || INDEX_DIR
|
||||
|
||||
return new Promise(function(resolve, reject){
|
||||
listIndexes(base)
|
||||
@ -438,7 +447,7 @@ function(base, previews, absolute_path){
|
||||
// add a preview...
|
||||
// NOTE: this will overwrite a previews if they are found in
|
||||
// several locations...
|
||||
images[gid].preview[res] = INDEX_DIR +'/'+ path.split(INDEX_DIR)[1]
|
||||
images[gid].preview[res] = index_dir +'/'+ path.split(index_dir)[1]
|
||||
})
|
||||
})
|
||||
.on('end', function(){
|
||||
@ -518,8 +527,130 @@ module.buildIndex = function(index, base_path){
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
// Builder...
|
||||
// - read list
|
||||
// - generate previews (use config)
|
||||
// - build images/data
|
||||
// .loadURLs(..)
|
||||
// - write (writer)
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
// Writer...
|
||||
//
|
||||
// This is just like the loader, done in two stages:
|
||||
// - format dependent de-construction (symetric to buildIndex(..))
|
||||
// - generic writer...
|
||||
//
|
||||
// NOTE: for now we'll stick to the current format...
|
||||
|
||||
// this will take the output of .json()
|
||||
//
|
||||
// .data
|
||||
// .images
|
||||
// .bookmarked
|
||||
// .marked
|
||||
// .tags
|
||||
// .current
|
||||
//
|
||||
// NOTE: this will prepare for version 2.0 file structure...
|
||||
//
|
||||
// XXX write tags, marks and bookmarks only if changed...
|
||||
var prepareIndex =
|
||||
module.prepareIndex =
|
||||
function(json, changes){
|
||||
changes = changes || {}
|
||||
|
||||
var res = {
|
||||
data: json.data,
|
||||
current: json.data.current,
|
||||
}
|
||||
|
||||
// NOTE: we write the whole set ONLY if an item is true or undefined
|
||||
// i.e. not false...
|
||||
if(changes.bookmarked !== false){
|
||||
res.bookmarked = json.data.tags.bookmark
|
||||
}
|
||||
|
||||
if(changes.selected !== false){
|
||||
res.marked = json.data.tags.selected
|
||||
}
|
||||
|
||||
if(changes.tags !== false){
|
||||
res.tags = json.data.tags
|
||||
}
|
||||
|
||||
// clean out some stuff from data...
|
||||
delete res.data.tags.bookmark
|
||||
delete res.data.tags.selected
|
||||
delete res.data.tags
|
||||
|
||||
if(changes.images){
|
||||
var diff = res['images-diff'] = {}
|
||||
changes.images.forEach(function(gid){
|
||||
diff[gid] = json.images[gid]
|
||||
})
|
||||
|
||||
} else {
|
||||
res.images = json.images
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
var FILENAME = '${DATE}-${KEYWORD}.${EXT}'
|
||||
|
||||
var writeIndex =
|
||||
module.writeIndex =
|
||||
function(json, path, filename_tpl, logger){
|
||||
filename_tpl = filename_tpl || FILENAME
|
||||
// XXX for some reason this gets the unpatched node.js Date, so we
|
||||
// get the patched date explicitly...
|
||||
var date = window.Date.timeStamp()
|
||||
var files = []
|
||||
|
||||
// build the path if it does not exist...
|
||||
return ensureDir(path)
|
||||
.catch(function(err){
|
||||
logger && logger.emit('error', err)
|
||||
})
|
||||
.then(function(){
|
||||
logger && logger.emit('path', path)
|
||||
|
||||
// write files...
|
||||
// NOTE: we are not doing this sequencilly as there will not
|
||||
// be too many files...
|
||||
return Promise
|
||||
.all(Object.keys(json).map(function(keyword){
|
||||
var file = path +'/'+ (filename_tpl
|
||||
.replace('${DATE}', date)
|
||||
.replace('${KEYWORD}', keyword)
|
||||
.replace('${EXT}', 'json'))
|
||||
|
||||
return ensureDir(pathlib.dirname(file))
|
||||
.then(function(){
|
||||
files.push(file)
|
||||
var data = JSON.stringify(json[keyword])
|
||||
|
||||
logger && logger.emit('queued', file)
|
||||
|
||||
return writeFile(file, data, 'utf8')
|
||||
.catch(function(err){
|
||||
logger && logger.emit('error', err)
|
||||
})
|
||||
.then(function(){
|
||||
logger && logger.emit('written', file)
|
||||
})
|
||||
})
|
||||
}))
|
||||
.then(function(){
|
||||
logger && logger.emit('done', files)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -18,10 +18,11 @@
|
||||
"dependencies": {
|
||||
"flickrapi": "^0.3.28",
|
||||
"fs-walk": "0.0.1",
|
||||
"fs.extra": "^1.2.1",
|
||||
"fs-extra": "*",
|
||||
"glob": "^4.0.6",
|
||||
"guarantee-events": "^1.0.0",
|
||||
"promise": "^6.0.1",
|
||||
"requirejs": "*"
|
||||
"requirejs": "*",
|
||||
"sharp": "^0.12.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
|
||||
window.nodejs = (typeof(process) === 'object' && process.features.uv)
|
||||
? {
|
||||
require: window.require,
|
||||
|
||||
@ -2079,13 +2079,6 @@ module.AutoAlignRibbons = ImageGridFeatures.Feature({
|
||||
})
|
||||
|
||||
|
||||
// XXX add a feature not to align the ribbons and focus the central
|
||||
// image on next prev ribbon...
|
||||
// XXX in general need a way to control .nextRibbon(..)/.prevRibbon(..)
|
||||
// image selection...
|
||||
|
||||
// XXX this should also define up/down navigation behavior e.g. what to
|
||||
// focus on next/prev ribbon...
|
||||
// XXX should .alignByOrder(..) be a feature-specific action or global
|
||||
// as it is now???
|
||||
var AlignRibbonsToImageOrder =
|
||||
@ -2157,6 +2150,7 @@ module.ManualAlignRibbons = ImageGridFeatures.Feature({
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// XXX at this point this does not support target lists...
|
||||
// XXX shift up/down to new ribbon is not too correct...
|
||||
var ShiftAnimation =
|
||||
module.ShiftAnimation = ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
@ -2166,7 +2160,9 @@ module.ShiftAnimation = ImageGridFeatures.Feature({
|
||||
depends: ['ui'],
|
||||
|
||||
handlers: [
|
||||
['shiftImageUp.pre shiftImageDown.pre',
|
||||
//['shiftImageUp.pre shiftImageDown.pre '
|
||||
// +'travelImageUp.pre travelImageDown.pre',
|
||||
['shiftImageUp.pre shiftImageDown.pre',
|
||||
function(target){
|
||||
// XXX do not do target lists...
|
||||
if(target != null && target.constructor === Array
|
||||
@ -3329,10 +3325,16 @@ if(window.nodejs != null){
|
||||
|
||||
|
||||
var FileSystemLoaderActions = actions.Actions({
|
||||
config: {
|
||||
'index-dir': '.ImageGrid',
|
||||
},
|
||||
|
||||
// NOTE: when passed no path this will not do anything...
|
||||
// XXX should this set something like .path???
|
||||
// ...and how should this be handled when merging indexes or
|
||||
// viewing multiple/clustered indexes???
|
||||
// XXX add a symmetric equivalent to .prepareIndexForWrite(..) so as
|
||||
// to enable features to load their data...
|
||||
// XXX look inside...
|
||||
loadIndex: ['File/Load index',
|
||||
function(path, logger){
|
||||
@ -3345,7 +3347,7 @@ var FileSystemLoaderActions = actions.Actions({
|
||||
// XXX get a logger...
|
||||
logger = logger || this.logger
|
||||
|
||||
file.loadIndex(path, logger)
|
||||
file.loadIndex(path, this.config['index-dir'], logger)
|
||||
.then(function(res){
|
||||
// XXX if res is empty load raw...
|
||||
|
||||
@ -3593,6 +3595,67 @@ module.FileSystemLoaderUI = ImageGridFeatures.Feature({
|
||||
//---------------------------------------------------------------------
|
||||
// fs writer...
|
||||
|
||||
var FileSystemWriterActions = actions.Actions({
|
||||
config: {
|
||||
// XXX should this include the '.ImageGrid/' section???
|
||||
'index-filename-template': '${DATE}-${KEYWORD}.${EXT}',
|
||||
},
|
||||
|
||||
// This is here so as other features can participate in index
|
||||
// preparation...
|
||||
// There are several stages features can control the output format:
|
||||
// 1) .json() action
|
||||
// - use this for global high level serialization format
|
||||
// - the output of this is .load(..) compatible
|
||||
// 2) .prepareIndex(..) action
|
||||
// - use this for file system write preparation
|
||||
// - this directly affects the index structure
|
||||
prepareIndexForWrite: ['File/Prepare index for writing',
|
||||
function(json){
|
||||
return file.prepareIndex(json || this.json())
|
||||
}],
|
||||
// XXX should this get the base uncropped state or the current state???
|
||||
// XXX get real base path...
|
||||
saveIndex: ['File/save index',
|
||||
function(path, logger){
|
||||
// XXX get real base path...
|
||||
path = path || this.base_path +'/'+ this.config['index-dir']
|
||||
|
||||
file.writeIndex(
|
||||
this.prepareIndexForWrite(),
|
||||
path,
|
||||
this.config['index-filename-template'],
|
||||
logger || this.logger)
|
||||
}],
|
||||
|
||||
// XXX same as ctrl-shif-s in gen3
|
||||
exportView: ['File/Export current view',
|
||||
function(){
|
||||
}],
|
||||
// XXX export current state as a full loadable index
|
||||
// XXX might be interresting to unify this and .exportView(..)
|
||||
exportCollection: ['File/Export as collection',
|
||||
function(){
|
||||
}],
|
||||
})
|
||||
|
||||
|
||||
var FileSystemWriter =
|
||||
module.FileSystemWriter = ImageGridFeatures.Feature({
|
||||
title: '',
|
||||
doc: '',
|
||||
|
||||
tag: 'fs-writer',
|
||||
// NOTE: this is mostly because of the base path handling...
|
||||
depends: ['fs-loader'],
|
||||
|
||||
actions: FileSystemWriterActions,
|
||||
|
||||
isApplicable: function(){
|
||||
return window.nodejs != null
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@ -3623,6 +3686,7 @@ ImageGridFeatures.Feature('viewer-testing', [
|
||||
|
||||
'fs-loader',
|
||||
'fs-loader-ui',
|
||||
'fs-writer',
|
||||
|
||||
'app-control',
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user