refactor(client) callbacks -> async

This commit is contained in:
coderaiser 2019-08-16 17:37:02 +03:00
parent eee2cb1b10
commit 7d5b3463cc
9 changed files with 224 additions and 236 deletions

View file

@ -19,18 +19,17 @@ const {unregisterSW} = require('./sw/register');
const jonny = require('jonny/legacy');
const currify = require('currify/legacy');
const bind = (f, ...a) => () => f(...a);
const noop = () => {};
const noJS = (a) => a.replace(/.js$/, '');
const loadCSS = promisify(load.css);
const loadJS = promisify(load.js);
const {
apiURL,
formatMsg,
buildFromJSON,
} = require('../common/cloudfunc');
const callbackify = require('../common/callbackify');
const loadModule = require('./load-module');
inherits(CloudCmdProto, Emitify);
@ -137,19 +136,7 @@ function CloudCmdProto(DOM) {
* выполняет весь функционал по
* инициализации
*/
this.init = (prefix, config) => {
const func = bind(exec.series, [
initModules,
baseInit,
loadStyle,
exec.with(CloudCmd.route, location.hash),
], noop);
const funcBefore = (callback) => {
const src = prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js';
load.js(src, callback);
};
this.init = async (prefix, config) => {
CloudCmd.prefix = prefix;
CloudCmd.prefixURL = `${prefix}${apiURL}`;
CloudCmd.prefixSocket = config.prefixSocket;
@ -171,14 +158,21 @@ function CloudCmdProto(DOM) {
if (config.oneFilePanel)
CloudCmd.MIN_ONE_PANEL_WIDTH = Infinity;
exec.if(document.body.scrollIntoViewIfNeeded, func, funcBefore);
if (!document.body.scrollIntoViewIfNeeded)
await loadJS(prefix + CloudCmd.DIRCLIENT_MODULES + 'polyfill.js');
await initModules();
await baseInit();
await loadStyle();
CloudCmd.route(location.hash);
};
function loadStyle(callback) {
async function loadStyle() {
const {prefix} = CloudCmd;
const name = prefix + '/dist/cloudcmd.common.css';
load.css(name, callback);
await loadCSS(name);
}
this.route = (path) => {
@ -203,12 +197,12 @@ function CloudCmdProto(DOM) {
CloudCmd.execFromModule(module, 'show');
};
this.logOut = () => {
this.logOut = async () => {
const url = CloudCmd.prefix + '/logout';
const error = () => document.location.reload();
const {prefix} = CloudCmd;
DOM.Storage.clear();
await DOM.Storage.clear();
unregisterSW(prefix);
DOM.load.ajax({
url,
@ -216,7 +210,7 @@ function CloudCmdProto(DOM) {
});
};
const initModules = callbackify(async () => {
const initModules = async () => {
exec.if(CloudCmd.Key, () => {
Key = new CloudCmd.Key();
CloudCmd.Key = Key;
@ -253,9 +247,9 @@ function CloudCmdProto(DOM) {
for (const module of modules.local) {
load(null, module, doBefore[module]);
}
});
};
function baseInit(callback) {
async function baseInit() {
const files = DOM.getFiles();
CloudCmd.on('current-file', DOM.updateCurrentInfo);
@ -279,15 +273,12 @@ function CloudCmdProto(DOM) {
Listeners.initKeysPanel();
if (!CloudCmd.config('dirStorage'))
return callback();
return;
Storage.get(dirPath, (error, data) => {
if (!data) {
data = getJSONfromFileTable();
Storage.set(dirPath, data);
}
callback();
});
const data = await Storage.get(dirPath);
if (!data)
await Storage.set(dirPath, getJSONfromFileTable());
}
function getPanels() {

View file

@ -3,8 +3,8 @@
/* global CloudCmd */
const jonny = require('jonny/legacy');
const exec = require('execon');
const tryToPromiseAll = require('../../common/try-to-promise-all');
const Storage = require('./storage');
const DOM = require('./');
@ -58,7 +58,19 @@ function BufferProto() {
showMessage('Buffer disabled in config!');
}
function copy() {
async function readBuffer() {
const [e, result] = await tryToPromiseAll([
Storage.get(COPY),
Storage.get(CUT),
]);
return [
e,
...result,
];
}
async function copy() {
const names = getNames();
const from = Info.dirPath;
@ -67,14 +79,14 @@ function BufferProto() {
if (!names.length)
return;
Storage.remove(CUT)
.set(COPY, {
from,
names,
});
await Storage.remove(CUT);
await Storage.set(COPY, {
from,
names,
});
}
function cut() {
async function cut() {
const names = getNames();
const from = Info.dirPath;
@ -85,11 +97,10 @@ function BufferProto() {
addCutClass();
Storage
.set(CUT, {
from,
names,
});
await Storage.set(CUT, {
from,
names,
});
}
function clear() {
@ -99,33 +110,28 @@ function BufferProto() {
rmCutClass();
}
function paste() {
const copy = Storage.get.bind(Storage, COPY);
const cut = Storage.get.bind(Storage, CUT);
async function paste() {
const [error, cp, ct] = await readBuffer();
exec.parallel([copy, cut], (error, cp, ct) => {
const opStr = cp ? 'copy' : 'move';
const opData = cp || ct;
const {Operation} = CloudCmd;
const msg = 'Path is same!';
const path = Info.dirPath;
if (!error && !cp && !ct)
error = 'Buffer is empty!';
if (error)
return showMessage(error);
const data = jonny.parse(opData);
data.to = path;
if (data.from === path)
return showMessage(msg);
Operation.show(opStr, data);
clear();
});
if (error || !cp && !ct)
return showMessage(error || 'Buffer is empty!');
const opStr = cp ? 'copy' : 'move';
const opData = cp || ct;
const {Operation} = CloudCmd;
const msg = 'Path is same!';
const path = Info.dirPath;
const data = jonny.parse(opData);
data.to = path;
if (data.from === path)
return showMessage(msg);
Operation.show(opStr, data);
clear();
}
return Buffer;
}

View file

@ -168,7 +168,6 @@ function unsetCurrentFile(currentFile) {
*/
module.exports.setCurrentFile = (currentFile, options) => {
const o = options;
const CENTER = true;
const currentFileWas = DOM.getCurrentFile();
if (!currentFile)
@ -203,6 +202,7 @@ module.exports.setCurrentFile = (currentFile, options) => {
}
/* scrolling to current file */
const CENTER = true;
DOM.scrollIntoViewIfNeeded(currentFile, CENTER);
CloudCmd.emit('current-file', currentFile);
@ -212,6 +212,11 @@ module.exports.setCurrentFile = (currentFile, options) => {
return DOM;
};
this.setCurrentByName = (name) => {
const current = DOM.getCurrentByName(name);
return DOM.setCurrentFile(current);
};
/*
* set current file by position
*

View file

@ -5,6 +5,7 @@
const itype = require('itype/legacy');
const exec = require('execon');
const jonny = require('jonny/legacy');
const tryToPromiseAll = require('../../common/try-to-promise-all');
const Util = require('../../common/util');
const callbackify = require('../../common/callbackify');
@ -26,15 +27,6 @@ const DOM = {
...new CmdProto(),
};
const read = callbackify(async (...args) => {
const [e, data] = await RESTful.read(...args);
if (e)
throw e;
return data;
});
DOM.Images = Images;
DOM.load = load;
DOM.Files = Files;
@ -262,12 +254,13 @@ function CmdProto() {
* @callback
* @currentFile
*/
this.loadCurrentHash = (callback, currentFile) => {
this.loadCurrentHash = async (currentFile) => {
const current = currentFile || DOM.getCurrentFile();
const query = '?hash';
const link = DOM.getCurrentPath(current);
read(link + query, callback);
const [, data] = await RESTful.read(link + query);
return data;
};
/**
@ -275,12 +268,13 @@ function CmdProto() {
* @callback
* @currentFile
*/
this.loadCurrentTime = (callback, currentFile) => {
this.loadCurrentTime = async (currentFile) => {
const current = currentFile || DOM.getCurrentFile();
const query = '?time';
const link = DOM.getCurrentPath(current);
read(link + query, callback);
const [, data] = await RESTful.read(link + query);
return data;
};
/**
@ -314,55 +308,57 @@ function CmdProto() {
return owner.textContent;
};
const mixArgs = (f) => (a, b) => f(b, a);
/**
* unified way to get current file content
*
* @param callback
* @param currentFile
*/
this.getCurrentData = (callback, currentFile) => {
let hash;
this.getCurrentData = callbackify(mixArgs(async (callback, currentFile) => {
const {Dialog} = DOM;
const Info = DOM.CurrentInfo;
const current = currentFile || DOM.getCurrentFile();
const path = DOM.getCurrentPath(current);
const isDir = DOM.isCurrentIsDir(current);
const func = (error, data) => {
const ONE_MEGABYTE = 1024 * 1024 * 1024;
if (!error) {
if (itype.object(data))
data = jonny.stringify(data);
const {length} = data;
if (hash && length < ONE_MEGABYTE)
DOM.saveDataToStorage(path, data, hash);
}
callback(error, data);
};
if (Info.name === '..') {
Dialog.alert.noFiles();
return callback(Error('No files selected!'));
}
if (isDir)
return read(path, func);
if (isDir) {
const [e, data] = await RESTful.read(path);
if (e)
throw e;
return data;
}
DOM.checkStorageHash(path, (error, equal, hashNew) => {
if (error)
return callback(error);
if (equal)
return DOM.getDataFromStorage(path, callback);
hash = hashNew;
read(path, func);
});
};
const [hashNew, hash] = await DOM.checkStorageHash(path);
if (hash === hashNew)
return await DOM.getDataFromStorage(path);
let [e, data] = await RESTful.read(path);
if (e)
return;
const ONE_MEGABYTE = 1024 * 1024 * 1024;
if (itype.object(data))
data = jonny.stringify(data);
const {length} = data;
if (hash && length < ONE_MEGABYTE)
await DOM.saveDataToStorage(path, data, hashNew);
return data;
}));
/**
* unified way to get RefreshButton
@ -374,11 +370,6 @@ function CmdProto() {
return refresh;
};
this.setCurrentByName = (name) => {
const current = DOM.getCurrentByName(name);
return DOM.setCurrentFile(current);
};
/**
* select current file
* @param currentFile
@ -530,28 +521,21 @@ function CmdProto() {
/**
* check storage hash
*/
this.checkStorageHash = (name, callback) => {
const {parallel} = exec;
this.checkStorageHash = async (name) => {
const nameHash = name + '-hash';
const getStoreHash = exec.with(Storage.get, nameHash);
if (typeof name !== 'string')
throw Error('name should be a string!');
if (typeof callback !== 'function')
throw Error('callback should be a function!');
const [error, loadHash, storeHash] = await tryToPromiseAll([
DOM.loadCurrentHash(),
Storage.get(nameHash),
]);
parallel([DOM.loadCurrentHash, getStoreHash], (error, loadHash, storeHash) => {
let equal;
const isContain = /error/.test(loadHash);
if (isContain)
error = loadHash;
else if (loadHash === storeHash)
equal = true;
callback(error, equal, loadHash);
});
if (error)
throw error;
return [loadHash, storeHash];
};
/**
@ -562,25 +546,21 @@ function CmdProto() {
* @param hash
* @param callback
*/
this.saveDataToStorage = function(name, data, hash, callback) {
this.saveDataToStorage = async (name, data, hash) => {
const isDir = DOM.isCurrentIsDir();
if (isDir)
return;
hash = hash || await DOM.loadCurrentHash();
const nameHash = name + '-hash';
const nameData = name + '-data';
if (isDir)
return exec(callback);
await Storage.set(nameHash, hash);
await Storage.set(nameData, data);
exec.if(hash, () => {
Storage.set(nameHash, hash);
Storage.set(nameData, data);
exec(callback, hash);
}, (callback) => {
DOM.loadCurrentHash((error, loadHash) => {
hash = loadHash;
callback();
});
});
return hash;
};
/**
@ -590,7 +570,7 @@ function CmdProto() {
* @param data
* @param callback
*/
this.getDataFromStorage = (name, callback) => {
this.getDataFromStorage = callbackify(async (name, callback) => {
const nameHash = name + '-hash';
const nameData = name + '-data';
const isDir = DOM.isCurrentIsDir();
@ -598,11 +578,13 @@ function CmdProto() {
if (isDir)
return exec(callback);
exec.parallel([
exec.with(Storage.get, nameData),
exec.with(Storage.get, nameHash),
], callback);
};
const result = Promise.all([
await Storage.get(nameData),
await Storage.get(nameHash),
]);
return result;
});
this.getFM = () => {
return DOM.getPanel().parentElement;

View file

@ -1,20 +1,22 @@
'use strict';
const itype = require('itype/legacy');
const jonny = require('jonny/legacy');
const exec = require('execon');
const tryCatch = require('try-catch');
const setItem = localStorage.setItem.bind(localStorage);
/** remove element */
module.exports.remove = (item, callback) => {
localStorage.removeItem(item);
exec(callback, null);
return module.exports;
module.exports.set = async (name, data) => {
localStorage.setItem(name, data);
};
module.exports.removeMatch = (string, callback) => {
module.exports.get = async (name) => {
return localStorage.getItem(name);
};
module.exports.clear = async () => {
localStorage.clear();
};
module.exports.remove = async(item) => {
localStorage.removeItem(item);
};
module.exports.removeMatch = (string) => {
const reg = RegExp('^' + string + '.*$');
const test = (a) => reg.test(a);
const remove = (a) => localStorage.removeItem(a);
@ -22,46 +24,5 @@ module.exports.removeMatch = (string, callback) => {
Object.keys(localStorage)
.filter(test)
.forEach(remove);
exec(callback);
return module.exports;
};
/** если доступен localStorage и
* в нём есть нужная нам директория -
* записываем данные в него
*/
module.exports.set = (name, data, callback) => {
let str;
let error;
if (itype.object(data))
str = jonny.stringify(data);
if (name)
[error] = tryCatch(setItem, name, str || data);
exec(callback, error);
return module.exports;
};
/** Если доступен Storage принимаем из него данные*/
module.exports.get = (name, callback) => {
const ret = localStorage.getItem(name);
exec(callback, null, ret);
return module.exports;
};
/** функция чистит весь кэш для всех каталогов*/
module.exports.clear = (callback) => {
localStorage.clear();
exec(callback);
return module.exports;
};

View file

@ -6,7 +6,6 @@ const Info = DOM.CurrentInfo;
const exec = require('execon');
const clipboard = require('@cloudcmd/clipboard');
const wraptile = require('wraptile/legacy');
const Events = require('../dom/events');
const Buffer = require('../dom/buffer');
@ -56,7 +55,7 @@ function KeyProto() {
return fromCharCode(event.keyIdentifier);
}
function listener(event) {
async function listener(event) {
const {keyCode} = event;
const alt = event.altKey;
@ -85,7 +84,7 @@ function KeyProto() {
return setCurrentByChar(char, Chars);
Chars([]);
switchKey(event);
await switchKey(event);
if (keyCode >= KEY.F1 && keyCode <= KEY.F10)
return;
@ -115,7 +114,7 @@ function KeyProto() {
return char;
}
function switchKey(event) {
async function switchKey(event) {
let i;
let isSelected;
let prev;
@ -483,7 +482,8 @@ function KeyProto() {
case Key.D:
if (ctrlMeta) {
CloudCmd.log('clearing storage...');
DOM.Storage.clear(wraptile(CloudCmd.log, 'storage cleared'));
await DOM.Storage.clear();
CloudCmd.log('storage cleared');
event.preventDefault();
}
break;

View file

@ -412,26 +412,26 @@ async function _processFiles(options, data) {
names,
};
operation(files, () => {
DOM.Storage.remove(from, () => {
const {
panel,
panelPassive,
} = Info;
const setCurrent = () => {
const currentName = name || data.names[0];
DOM.setCurrentByName(currentName);
};
if (!Info.isOnePanel)
CloudCmd.refresh({
panel: panelPassive,
noCurrent: true,
});
CloudCmd.refresh({panel}, setCurrent);
});
operation(files, async () => {
await DOM.Storage.remove(from);
const {
panel,
panelPassive,
} = Info;
const setCurrent = () => {
const currentName = name || data.names[0];
DOM.setCurrentByName(currentName);
};
if (!Info.isOnePanel)
CloudCmd.refresh({
panel: panelPassive,
noCurrent: true,
});
CloudCmd.refresh({panel}, setCurrent);
});
}
}

View file

@ -0,0 +1,14 @@
'use strict';
const tryToCatch = require('try-to-catch/legacy');
const all = Promise.all.bind(Promise);
module.exports = async (a) => {
const [e, result = []] = await tryToCatch(all, a);
return [
e,
...result,
];
};

View file

@ -0,0 +1,29 @@
'use strict';
const test = require('supertape');
const tryToPromiseAll = require('./try-to-promise-all');
const resolve = Promise.resolve.bind(Promise);
const reject = Promise.reject.bind(Promise);
test('try-to-promise-all', async (t) => {
const [, ...result] = await tryToPromiseAll([
resolve('a'),
resolve('b'),
]);
const expected = ['a', 'b'];
t.deepEqual(result, expected);
t.end();
});
test('try-to-promise-all: error', async (t) => {
const [e] = await tryToPromiseAll([
reject('a'),
]);
t.equal(e, 'a');
t.end();
});