mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-23 18:55:26 +00:00
548 lines
18 KiB
JavaScript
548 lines
18 KiB
JavaScript
/* global CloudCmd */
|
|
/* global Util */
|
|
/* global DOM */
|
|
/* global rendy */
|
|
/* global spero */
|
|
/* global remedy */
|
|
/* global ishtar */
|
|
|
|
(function(CloudCmd, Util, DOM, rendy) {
|
|
'use strict';
|
|
|
|
CloudCmd.Operation = OperationProto;
|
|
|
|
function OperationProto(operation, data) {
|
|
var Name = 'Operation',
|
|
TITLE = CloudCmd.TITLE,
|
|
Loaded,
|
|
RESTful = DOM.RESTful,
|
|
|
|
exec = Util.exec,
|
|
|
|
copyFn = RESTful.cp,
|
|
moveFn = RESTful.mv,
|
|
deleteFn = RESTful.delete,
|
|
packFn = RESTful.pack,
|
|
extractFn = RESTful.extract,
|
|
|
|
Images = DOM.Images,
|
|
Dialog = DOM.Dialog,
|
|
|
|
showLoad = Images.show.load.bind(null, 'top'),
|
|
|
|
Operation = this;
|
|
|
|
function init() {
|
|
showLoad();
|
|
|
|
Util.exec.series([
|
|
DOM.loadSocket,
|
|
function(callback) {
|
|
var Files = DOM.Files;
|
|
|
|
Files.get('config', function(error, config) {
|
|
if (error)
|
|
Dialog.alert('Config', error);
|
|
else if (config.progress)
|
|
load(function(callback) {
|
|
create(CloudCmd.PREFIX, callback);
|
|
});
|
|
|
|
callback();
|
|
});
|
|
},
|
|
function() {
|
|
Loaded = true;
|
|
Images.hide();
|
|
Operation.show(operation, data);
|
|
}
|
|
]);
|
|
}
|
|
|
|
function authCheck(spawn, ok) {
|
|
DOM.Files.get('config', function(error, config) {
|
|
if (error)
|
|
return Dialog.alert(TITLE, error);
|
|
|
|
if (!config.auth) {
|
|
ok();
|
|
} else {
|
|
spawn.on('accept', ok);
|
|
spawn.on('reject', function() {
|
|
Dialog.alert(TITLE, 'Wrong credentials!');
|
|
});
|
|
|
|
spawn.emit('auth', config.username, config.password);
|
|
}
|
|
});
|
|
}
|
|
|
|
function create(prefix, callback) {
|
|
exec.series([
|
|
function(fn) {
|
|
spero(prefix + '/spero', prefix, function(copier) {
|
|
fn();
|
|
|
|
copier.on('connect', function() {
|
|
authCheck(copier, function() {
|
|
copyFn = function(data, callback) {
|
|
setListeners(copier, callback);
|
|
copier.copy(data.from, data.to, data.names);
|
|
};
|
|
});
|
|
});
|
|
|
|
copier.on('disconnect', function() {
|
|
copyFn = DOM.RESTful.cp;
|
|
});
|
|
});
|
|
},
|
|
|
|
function(fn) {
|
|
remedy(prefix + '/remedy', prefix, function(remover) {
|
|
fn();
|
|
remover.on('connect', function() {
|
|
authCheck(remover, function() {
|
|
deleteFn = function(from, files, callback) {
|
|
setListeners(remover, callback);
|
|
from = from.replace(/\?.*/, '');
|
|
remover.remove(from, files);
|
|
};
|
|
});
|
|
});
|
|
|
|
remover.on('disconnect', function() {
|
|
deleteFn = DOM.RESTful.remove;
|
|
});
|
|
});
|
|
},
|
|
|
|
function(fn) {
|
|
ishtar(prefix + '/ishtar', prefix, function(packer) {
|
|
fn();
|
|
packer.on('connect', function() {
|
|
authCheck(packer, function() {
|
|
packFn = function(data, callback) {
|
|
setListeners(packer, {noContinue: true}, callback);
|
|
packer.pack(data.from, data.to, data.names);
|
|
};
|
|
|
|
extractFn = function(data, callback) {
|
|
setListeners(packer, {noContinue: true}, callback);
|
|
packer.extract(data.from, data.to);
|
|
};
|
|
});
|
|
});
|
|
|
|
packer.on('disconnect', function() {
|
|
packFn = RESTful.pack;
|
|
extractFn = RESTful.extract;
|
|
});
|
|
});
|
|
}
|
|
]);
|
|
|
|
Util.exec(callback);
|
|
}
|
|
|
|
function setListeners(emitter, options, callback) {
|
|
if (!callback) {
|
|
callback = options;
|
|
options = {};
|
|
}
|
|
|
|
var done;
|
|
|
|
var listeners = {
|
|
progress: function(value) {
|
|
done = value === 100;
|
|
Images.setProgress(value);
|
|
},
|
|
|
|
end: function(error) {
|
|
Images
|
|
.hide()
|
|
.clearProgress();
|
|
|
|
events.forEach(function(name) {
|
|
emitter.removeListener(name, listeners[name]);
|
|
});
|
|
|
|
if (error || done)
|
|
callback(error);
|
|
},
|
|
|
|
error: function(error) {
|
|
if (options.noContinue) {
|
|
listeners.end(error);
|
|
Dialog.alert(TITLE, error)
|
|
} else {
|
|
Dialog.confirm(TITLE, error + '\n Continue?')
|
|
.then(function() {
|
|
emitter.continue();
|
|
}, function() {
|
|
emitter.abort();
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
var events = Object.keys(listeners);
|
|
|
|
events.forEach(function(name) {
|
|
emitter.on(name, listeners[name]);
|
|
});
|
|
}
|
|
|
|
this.hide = function() {
|
|
CloudCmd.View.hide();
|
|
};
|
|
|
|
this.show = function(operation, data) {
|
|
if (Loaded)
|
|
switch(operation) {
|
|
case 'copy':
|
|
Operation.copy(data);
|
|
break;
|
|
|
|
case 'move':
|
|
Operation.move(data);
|
|
break;
|
|
|
|
case 'delete':
|
|
Operation.delete();
|
|
break;
|
|
|
|
case 'delete:silent':
|
|
Operation.deleteSilent();
|
|
break;
|
|
|
|
case 'pack':
|
|
Operation.pack();
|
|
break;
|
|
|
|
case 'extract':
|
|
Operation.extract();
|
|
break;
|
|
|
|
}
|
|
};
|
|
|
|
this.copy = function(data) {
|
|
processFiles(data, copyFn, message('Copy'));
|
|
};
|
|
|
|
this.move = function(data) {
|
|
processFiles(data, moveFn, message('Rename/Move'));
|
|
};
|
|
|
|
this.delete = function() {
|
|
promptDelete();
|
|
};
|
|
|
|
this.deleteSilent = function() {
|
|
deleteSilent();
|
|
};
|
|
|
|
this.pack = function() {
|
|
twopack('pack');
|
|
};
|
|
|
|
this.extract = function() {
|
|
twopack('extract');
|
|
};
|
|
|
|
|
|
/**
|
|
* prompt and delete current file or selected files
|
|
*
|
|
* @currentFile
|
|
*/
|
|
function promptDelete() {
|
|
var type, isDir, msg,
|
|
name = '',
|
|
msgAsk = 'Do you really want to delete the ',
|
|
msgSel = 'selected ',
|
|
files = DOM.getSelectedFiles(),
|
|
names = DOM.getFilenames(files),
|
|
i,
|
|
n = names.length,
|
|
current = DOM.getCurrentFile();
|
|
|
|
if (n) {
|
|
for (i = 0; i < 5 && i < n; i++)
|
|
name += '\n' + names[i];
|
|
|
|
if (n >= 5)
|
|
name += '\n...';
|
|
|
|
msg = msgAsk + msgSel + n + ' files/directories?\n' + name ;
|
|
} else {
|
|
isDir = DOM.isCurrentIsDir(current);
|
|
|
|
if (isDir)
|
|
type = 'directory';
|
|
else
|
|
type = 'file';
|
|
|
|
type += ' ';
|
|
|
|
name = DOM.getCurrentName(current);
|
|
msg = msgAsk + msgSel + type + name + '?';
|
|
}
|
|
|
|
if (name === '..')
|
|
return Dialog.alert.noFiles(TITLE);
|
|
|
|
Dialog.confirm(TITLE, msg, {cancel: false}).then(function() {
|
|
deleteSilent(files);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* delete current or selected files
|
|
*
|
|
* @files
|
|
*/
|
|
function deleteSilent(files) {
|
|
var n, names,
|
|
query = '?files',
|
|
Info = DOM.CurrentInfo,
|
|
path = Info.dirPath,
|
|
name = Info.name;
|
|
|
|
if (name === '..')
|
|
return Dialog.alert.noFiles(TITLE);
|
|
|
|
showLoad();
|
|
|
|
if (!files)
|
|
files = DOM.getSelectedFiles();
|
|
|
|
names = DOM.getFilenames(files),
|
|
n = names.length;
|
|
|
|
if (!n)
|
|
names = [Info.name];
|
|
|
|
deleteFn(path + query, names, function(error) {
|
|
var Storage = DOM.Storage,
|
|
dirPath = Info.dirPath,
|
|
delCurrent = DOM.deleteCurrent,
|
|
delSelected = DOM.deleteSelected,
|
|
getByName = DOM.getCurrentByName;
|
|
|
|
if (!error) {
|
|
if (n > 1)
|
|
delSelected(files);
|
|
else
|
|
delCurrent(getByName(name));
|
|
|
|
Storage.removeMatch(dirPath);
|
|
}
|
|
});
|
|
}
|
|
|
|
/*
|
|
* process files (copy or move)
|
|
* @param data
|
|
* @param operation
|
|
*/
|
|
function processFiles(data, operation, message) {
|
|
var name, selFiles, files,
|
|
Info = DOM.CurrentInfo,
|
|
panel,
|
|
shouldAsk,
|
|
sameName,
|
|
ok,
|
|
tmpl = '"{{ name }}" already exist. Overwrite?',
|
|
|
|
from = '',
|
|
to = '',
|
|
|
|
names = [];
|
|
|
|
if (data) {
|
|
from = data.from;
|
|
to = data.to;
|
|
names = data.names;
|
|
panel = Info.panel;
|
|
} else {
|
|
from = Info.dirPath;
|
|
to = DOM.getNotCurrentDirPath();
|
|
selFiles = DOM.getSelectedFiles();
|
|
names = DOM.getFilenames(selFiles);
|
|
data = {};
|
|
shouldAsk = true;
|
|
panel = Info.panelPassive;
|
|
}
|
|
|
|
if (!names.length)
|
|
names.push(DOM.getCurrentName());
|
|
|
|
name = names[0];
|
|
|
|
sameName = !!DOM.getCurrentByName(name, panel);
|
|
|
|
if (name === '..') {
|
|
Dialog.alert.noFiles(TITLE);
|
|
} else {
|
|
if (shouldAsk)
|
|
message(to, names).then(ask);
|
|
else
|
|
ask(to);
|
|
}
|
|
|
|
function ask(to) {
|
|
ok = from !== to && to;
|
|
|
|
if (ok)
|
|
if (shouldAsk && sameName)
|
|
Dialog.confirm(TITLE, rendy(tmpl, {
|
|
name: name
|
|
}), {cancel: false}).then(function() {
|
|
go();
|
|
});
|
|
else
|
|
go();
|
|
|
|
function go() {
|
|
showLoad();
|
|
|
|
files = {
|
|
from : from,
|
|
to : to,
|
|
names : names
|
|
};
|
|
|
|
operation(files, function(error) {
|
|
!error && DOM.Storage.remove(from, function() {
|
|
var panel = Info.panel,
|
|
panelPassive = Info.panelPassive,
|
|
setCurrent = function() {
|
|
var current;
|
|
|
|
if (!name)
|
|
name = data.names[0];
|
|
|
|
current = DOM.getCurrentByName(name);
|
|
DOM.setCurrentFile(current);
|
|
};
|
|
|
|
if (!Info.isOnePanel)
|
|
CloudCmd.refresh(panelPassive, {
|
|
noCurrent: true
|
|
});
|
|
|
|
CloudCmd.refresh(panel, setCurrent);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
function twopack(operation) {
|
|
var op,
|
|
Images = DOM.Images,
|
|
Info = DOM.CurrentInfo,
|
|
name = Info.name,
|
|
path = Info.path,
|
|
dirPath = Info.dirPath,
|
|
activeFiles = DOM.getActiveFiles(),
|
|
names = DOM.getFilenames(activeFiles),
|
|
fileFrom;
|
|
|
|
Util.check(arguments, ['operation']);
|
|
|
|
if (!names.length) {
|
|
Dialog.alert.noFiles(TITLE);
|
|
} else {
|
|
switch(operation) {
|
|
case 'extract':
|
|
op = extractFn;
|
|
|
|
fileFrom = {
|
|
from : path,
|
|
to : dirPath
|
|
};
|
|
|
|
name = name.replace(/\.tar\.gz$/, '');
|
|
|
|
break;
|
|
|
|
case 'pack':
|
|
op = packFn;
|
|
|
|
if (names.length > 1)
|
|
name = Info.dir;
|
|
|
|
name += '.tar.gz';
|
|
|
|
fileFrom = {
|
|
from : dirPath,
|
|
to : dirPath + name,
|
|
names : names
|
|
};
|
|
break;
|
|
}
|
|
|
|
Images.show.load('top');
|
|
|
|
op(fileFrom, function(error) {
|
|
!error && CloudCmd.refresh(null, function() {
|
|
var file = DOM.getCurrentByName(name);
|
|
|
|
DOM.setCurrentFile(file);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
function message(msg) {
|
|
return function(to, names) {
|
|
var promise,
|
|
n = names.length,
|
|
name = names[0];
|
|
|
|
msg += ' ';
|
|
|
|
if (names.length > 1)
|
|
msg += n + ' file(s)';
|
|
else
|
|
msg += '"' + name + '"';
|
|
|
|
msg += ' to';
|
|
|
|
promise = Dialog.prompt(TITLE, msg, to, {cancel: false});
|
|
|
|
return promise;
|
|
};
|
|
}
|
|
|
|
function load(callback) {
|
|
var prefix = CloudCmd.PREFIX,
|
|
files = [
|
|
'/spero/spero.js',
|
|
'/remedy/remedy.js',
|
|
'/ishtar/ishtar.js'
|
|
].map(function(name) {
|
|
return prefix + name;
|
|
});
|
|
|
|
DOM.load.parallel(files, function(error) {
|
|
if (error) {
|
|
Dialog.alert(TITLE, error.message);
|
|
} else {
|
|
Loaded = true;
|
|
Util.timeEnd(Name + ' load');
|
|
Util.exec(callback);
|
|
}
|
|
});
|
|
|
|
Util.time(Name + ' load');
|
|
}
|
|
|
|
init();
|
|
}
|
|
|
|
})(CloudCmd, Util, DOM, rendy);
|