From c1e0316d4335aa52c5b33767aec43d49b8649f99 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 12 Apr 2017 18:54:22 +0200 Subject: [PATCH 1/2] Refactor fileObject --- www/common/cryptpad-common.js | 5 +- www/common/fsStore.js | 16 +- www/common/userObject.js | 839 ++++++++++++++++++++++++++++++++++ www/drive/main.js | 52 +-- 4 files changed, 877 insertions(+), 35 deletions(-) create mode 100644 www/common/userObject.js diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 9eedd1106..f815b8e4f 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -506,8 +506,9 @@ load pinpad dynamically only after you know that it will be needed */ }); return templates; }; - var addTemplate = common.addTemplate = function (href) { - getStore().addTemplate(href); + var addTemplate = common.addTemplate = function (data) { + getStore().pushData(data); + getStore().addPad(data.href, ['template']); }; var isTemplate = common.isTemplate = function (href) { diff --git a/www/common/fsStore.js b/www/common/fsStore.js index 1974aa27d..e2b283f4b 100644 --- a/www/common/fsStore.js +++ b/www/common/fsStore.js @@ -90,20 +90,22 @@ define([ ret.pushData = filesOp.pushData; ret.addPad = function (href, path, name) { - filesOp.addPad(href, path, name); + filesOp.add(href, path, name); }; ret.forgetPad = function (href, cb) { - filesOp.forgetPad(href); + filesOp.forget(href); cb(); }; - ret.addTemplate = function (href) { - filesOp.addTemplate(href); - }; - ret.listTemplates = function () { - return filesOp.listTemplates(); + var templateFiles = filesOp.getFiles(['template']); + var res = []; + templateFiles.forEach(function (f) { + var data = filesOp.getFileData(f); + res.push(JSON.parse(JSON.stringify(data))); + }); + return res; }; ret.getProxy = function () { diff --git a/www/common/userObject.js b/www/common/userObject.js new file mode 100644 index 000000000..7e7f7b292 --- /dev/null +++ b/www/common/userObject.js @@ -0,0 +1,839 @@ +define([ + '/bower_components/jquery/dist/jquery.min.js', +], function () { + var $ = window.jQuery; + var module = {}; + + var ROOT = module.ROOT = "root"; + var UNSORTED = module.UNSORTED = "unsorted"; + var TRASH = module.TRASH = "trash"; + var TEMPLATE = module.TEMPLATE = "template"; + + var init = module.init = function (files, config) { + var Cryptpad = config.Cryptpad; + var Messages = Cryptpad.Messages; + + var FILES_DATA = Cryptpad.storageKey; + var NEW_FOLDER_NAME = Messages.fm_newFolder; + var NEW_FILE_NAME = Messages.fm_newFile; + + // Logging + var DEBUG = config.DEBUG || false; + var logging = function () { + console.log.apply(console, arguments); + }; + var log = config.log || logging; + var logError = config.logError || logging; + var debug = config.debug || logging; + var error = exp.error = function() { + exp.fixFiles(); + console.error.apply(console, arguments); + }; + + // TODO: workgroup + var workgroup = config.workgroup; + + var exp = {}; + + + /* + * UTILS + */ + + var getStructure = exp.getStructure = function () { + var a = {}; + a[ROOT] = {}; + a[UNSORTED] = []; + a[TRASH] = {}; + a[FILES_DATA] = []; + a[TEMPLATE] = []; + return a; + }; + + var compareFiles = function (fileA, fileB) { return fileA === fileB; }; + + var isFile = exp.isFile = function (element) { + return typeof(element) === "string"; + }; + + var isReadOnlyFile = exp.isReadOnlyFile = function (element) { + if (!isFile(element)) { return false; } + var parsed = Cryptpad.parsePadUrl(element); + if (!parsed) { return false; } + var hash = parsed.hash; + var pHash = Cryptpad.parseHash(hash); + if (pHash && !pHash.mode) { return; } + return pHash && pHash.mode === 'view'; + }; + + var isFolder = exp.isFolder = function (element) { + return typeof(element) !== "string"; + }; + var isFolderEmpty = exp.isFolderEmpty = function (element) { + if (typeof(element) !== "object") { return false; } + return Object.keys(element).length === 0; + }; + + var hasSubfolder = exp.hasSubfolder = function (element, trashRoot) { + if (typeof(element) !== "object") { return false; } + var subfolder = 0; + var addSubfolder = function (el, idx) { + subfolder += isFolder(el.element) ? 1 : 0; + }; + for (var f in element) { + if (trashRoot) { + if ($.isArray(element[f])) { + element[f].forEach(addSubfolder); + } + } else { + subfolder += isFolder(element[f]) ? 1 : 0; + } + } + return subfolder; + }; + + var hasFile = exp.hasFile = function (element, trashRoot) { + if (typeof(element) !== "object") { return false; } + var file = 0; + var addFile = function (el, idx) { + file += isFile(el.element) ? 1 : 0; + }; + for (var f in element) { + if (trashRoot) { + if ($.isArray(element[f])) { + element[f].forEach(addFile); + } + } else { + file += isFile(element[f]) ? 1 : 0; + } + } + return file; + }; + + // Get data from AllFiles (Cryptpad_RECENTPADS) + var getFileData = exp.getFileData = function (file) { + if (!file) { return; } + var res; + files[FILES_DATA].some(function(arr) { + var href = arr.href; + if (href === file) { + res = arr; + return true; + } + return false; + }); + return res; + }; + + // Data from filesData + var getTitle = exp.getTitle = function (href) { + if (workgroup) { debug("No titles in workgroups"); return; } + var data = getFileData(href); + if (!href || !data) { + error("getTitle called with a non-existing href: ", href); + return; + } + return data.title; + }; + + + // PATHS + + var comparePath = exp.comparePath = function (a, b) { + if (!a || !b || !$.isArray(a) || !$.isArray(b)) { return false; } + if (a.length !== b.length) { return false; } + var result = true; + var i = a.length - 1; + while (result && i >= 0) { + result = a[i] === b[i]; + i--; + } + return result; + }; + + var isSubpath = exp.isSubpath = function (path, parentPaths) { + var pathA = parentPath.slice(); + var pathB = path.slice(0, pathA.length); + return comparePath(pathA, pathB); + }; + + var isPathIn = function (path, categories) { + return categories.some(function (c) { + return Array.isArray(path) && path[0] === c; + }); + }; + + var isInTrashRoot = exp.isInTrashRoot = function (path) { + return path[0] === TRASH && path.length === 4; + }; + + + // FIND + + var compareFiles = function (fileA, fileB) { return fileA === fileB; }; + + var findElement = function (root, pathInput) { + if (!pathInput) { + error("Invalid path:\n", pathInput, "\nin root\n", root); + return; + } + if (pathInput.length === 0) { return root; } + var path = pathInput.slice(); + var key = path.shift(); + if (typeof root[key] === "undefined") { + debug("Unable to find the key '" + key + "' in the root object provided:", root); + return; + } + return findElement(root[key], path); + }; + + var find = exp.find = function (path) { + return findElement(files, path); + }; + + + // GET FILES + + var getFilesRecursively = function (root, arr) { + for (var e in root) { + if (isFile(root[e])) { + if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); } + } else { + getFilesRecursively(root[e], arr); + } + } + }; + var _getFiles = {}; + _getFiles['array'] = function (cat) { + if (!files[cat]) { + files[cat] = []; + } + return files[cat].slice(); + }; + _getFiles[UNSORTED] = function () { + return _getFiles['array'](UNSORTED); + }; + _getFiles[TEMPLATE] = function () { + return _getFiles['array'](TEMPLATE); + }; + _getFiles['hrefArray'] = function () { + var ret = []; + ret = ret.concat(_getFiles[UNSORTED]); + ret = ret.concat(_getFiles[TEMPLATE]); + return Cryptpad.deduplicateString(ret); + }; + _getFiles[ROOT] = function () { + var ret = []; + getFilesRecursively(files[ROOT], ret); + return ret; + }; + _getFiles[TRASH] = function () { + var root = files[TRASH]; + var ret = []; + var addFiles = function (el, idx) { + if (isFile(el.element)) { + if(ret.indexOf(el.element) === -1) { ret.push(el.element); } + } else { + getFilesRecursively(el.element, ret); + } + }; + for (var e in root) { + if (!$.isArray(root[e])) { + error("Trash contains a non-array element"); + return; + } + root[e].forEach(addFiles); + } + return ret; + }; + _getFiles[FILES_DATA] = function () { + var ret = []; + files[FILES_DATA].forEach(function (el) { + if (el.href && ret.indexOf(el.href) === -1) { + ret.push(el.href); + } + }); + return ret; + }; + var getFiles = function (categories) { + var ret = []; + categories.forEach(function (c) { + if (typeof _getFiles[c] === "function") { + ret = ret.concat(_getFiles[c]); + } + }); + return Cryptpad.deduplicateString(ret); + }; + + // SEARCH + var _findFileInRoot = function (path, href) { + if (!isPathIn([ROOT, TRASH])) { return []; } + var paths = []; + var root = find(path); + var addPaths = function (p) { + if (paths.indexOf(p) === -1) { + paths.push(p); + } + }; + + if (isFile(root)) { + if (compareFiles(href, root)) { + if (paths.indexOf(path) === -1) { + paths.push(path); + } + } + return paths; + } + for (var e in root) { + var nPath = path.slice(); + nPath.push(e); + _findFileInRoot(nPath, href).forEach(addPaths); + } + + return paths; + }; + var _findFileInHrefArray = function (rootName, href) { + var unsorted = files[rootName].slice(); + var ret = []; + var i = -1; + while ((i = unsorted.indexOf(href, i+1)) !== -1){ + ret.push([rootName, i]); + } + return ret; + }; + var _findFileInTrash = function (path, href) { + var root = find(path); + var paths = []; + var addPaths = function (p) { + if (paths.indexOf(p) === -1) { + paths.push(p); + } + }; + if (path.length === 1 && typeof(root) === 'object') { + Object.keys(root).forEach(function (key) { + var arr = root[key]; + if (!Array.isArray(arr)) { return; } + var nPath = path.slice(); + nPath.push(key); + _findFileInTrash(nPath, href).forEach(addPaths); + }); + } + if (path.length === 2) { + if (!Array.isArray(root)) { return []; } + root.forEach(function (el, i) { + var nPath = path.slice(); + nPath.push(i); + nPath.push('element'); + if (isFile(el.element)) { + if (compareFiles(href, el.element)) { + addPaths(nPath); + } + return; + } + _findFileInTrash(nPath, href).forEach(addPaths); + }); + } + if (path.length >= 4) { + _findFileInRoot(path, href).forEach(addPaths); + } + return paths; + }; + var findFile = function (href) { + var rootpaths = _findFileInRoot([ROOT], href); + var unsortedpaths = _findFileInHrefArray(UNSORTED, href); + var templatepaths = _findFileInHrefArray(TEMPLATE, href); + var trashpaths = _findFileInTrash([TRASH], href); + return rootpaths.concat(unsortedpaths, templatepaths, trashpaths); + }; + var search = exp.search = function (value) { + if (typeof(value) !== "string") { return []; } + var res = []; + // Search in ROOT + var findIn = function (root) { + Object.keys(root).forEach(function (k) { + if (isFile(root[k])) { + if (k.toLowerCase().indexOf(value.toLowerCase()) !== -1) { + res.push(root[k]); + } + return; + } + findIn(root[k]); + }); + }; + findIn(files[ROOT]); + // Search in TRASH + var trash = files[TRASH]; + Object.keys(trash).forEach(function (k) { + if (k.toLowerCase().indexOf(value.toLowerCase()) !== -1) { + trash[k].forEach(function (el) { + if (isFile(el.element)) { + res.push(el.element); + } + }); + } + trash[k].forEach(function (el) { + if (isFolder(el.element)) { + findIn(el.element); + } + }); + }); + + // Search title + var allFilesList = files[FILES_DATA].slice(); + allFilesList.forEach(function (t) { + if (t.title && t.title.toLowerCase().indexOf(value.toLowerCase()) !== -1) { + res.push(t.href); + } + }); + + // Search Href + var href = Cryptpad.getRelativeHref(value); + if (href) { + res.push(href); + } + + res = Cryptpad.deduplicateString(res); + + var ret = []; + res.forEach(function (l) { + var paths = findFile(l); + ret.push({ + paths: findFile(l), + data: exp.getFileData(l) + }); + }); + return ret; + }; + + /** + * OPERATIONS + */ + + var getAvailableName = function (parentEl, name) { + if (typeof(parentEl[name]) === "undefined") { return name; } + var newName = name; + var i = 1; + while (typeof(parentEl[newName]) !== "undefined") { + newName = name + "_" + i; + i++; + } + return newName; + }; + + // FILES DATA + var pushFileData = exp.pushData = function (data) { + Cryptpad.pinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) { + console.log(hash); + }); + files[FILES_DATA].push(data); + }; + var spliceFileData = exp.removeData = function (idx) { + var data = files[FILES_DATA][idx]; + if (typeof data === "object") { + Cryptpad.unpinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) { + console.log(hash); + }); + } + files[FILES_DATA].splice(idx, 1); + }; + + // MOVE + var pushToTrash = function (name, element, path) { + var trash = files[TRASH]; + if (typeof(trash[name]) === "undefined") { trash[name] = []; } + var trashArray = trash[name]; + var trashElement = { + element: element, + path: path + }; + trashArray.push(trashElement); + }; + var copyElement = function (elementPath, newParentPath) { + if (comparePath(elementPath, newParentPath)) { return; } // Nothing to do... + var element = find(elementPath); + var newParent = find(newParentPath); + + // Never move a folder in one of its children + if (isSubpath(newParentPath, elementPath)) { + log(Messages.fo_moveFolderToChildError); + return; + } + + // Move to Trash + if (isPathIn(newParentPath, [TRASH])) { + if (!elementPath || elementPath.length < 2 || elementPath[0] === TRASH) { + debug("Can't move an element from the trash to the trash: ", path); + return; + } + var key = elementPath[elementPath.length - 1]; + var name = isPathIn(elementPath, ['hrefArray']) ? getTitle(element) : key; + var parentPath = elementPath.slice(); + parentPath.pop(); + pushToTrash(name, element, parentPath); + return true; + } + // Move to hrefArray + if (isPathIn(newParentPath, ['hrefArray'])) { + if (isFolder(element)) { + log(Messages.fo_moveUnsortedError); + return; + } else { + if (elementPath[0] === newParentPath[0]) { return; } + var fileRoot = newParentPath[0]; + if (files[fileRoot].indexOf(element) === -1) { + files[fileRoot].push(element); + } + return true; + } + } + // Move to root + var name; + if (isPathIn(elementPath, ['hrefArray'])) { + name = getTitle(element); + } else if (isInTrashRoot(elementPath)) { + // Element from the trash root: elementPath = [TRASH, "{dirName}", 0, 'element'] + name = elementPath[1]; + } else { + name = elementPath[elementPath.length-1]; + } + var newName = !isPathInRoot(elementPath) ? getAvailableName(newParent, name) : name; + + if (typeof(newParent[newName]) !== "undefined") { + log(Messages.fo_unavailableName); + return; + } + newParent[newName] = element; + return true; + }; + var move = exp.move = function (paths, newPath, cb) { + // Copy the elements to their new location + var toRemove = []; + paths.forEach(function (p) { + var parentPath = p.slice(); + parentPath.pop(); + if (comparePath(parentPath, newPath)) { return; } + copyElement(p, newPath); + toRemove.push(p); + }); + exp.delete(toRemove, cb); + }; + + // ADD + var add = exp.add = function (href, path, name, cb) { + if (!href) { return; } + var newPath = path, parentEl; + if (path && !Array.isArray(path)) { + newPath = decodeURIComponent(path).split(','); + } + // Add to href array + if (path && isPathIn(newPath, ['hrefArray'])) { + parentEl = find(newPath); + parentEl.push(href); + return; + } + // Add to root + if (path && isPathIn(newPath, [ROOT]) && name) { + parentEl = find(newPath); + if (parentEl) { + var newName = getAvailableName(parentEl, name); + parentEl[newName] = href; + return; + } + } + // No path: push to unsorted + var filesList = getFiles([ROOT, TRASH, 'hrefArray']); + if (filesList.indexOf(href) === -1) { files[UNSORTED].push(href); } + + if (typeof cb === "function") { cb(); } + }; + var addFile = exp.addFile = function (filePath, name, type, cb) { + var parentEl = findElement(files, filePath); + var fileName = getAvailableName(parentEl, name || NEW_FILE_NAME); + var href = '/' + type + '/#' + Cryptpad.createRandomHash(); + parentEl[fileName] = href; + + pushFileData({ + href: href, + title: fileName, + atime: +new Date(), + ctime: +new Date() + }); + + var newPath = filePath.slice(); + newPath.push(fileName); + cb({ + newPath: newPath + }); + }; + var addFolder = exp.addFolder = function (folderPath, name, cb) { + var parentEl = find(folderPath); + var folderName = getAvailableName(parentEl, name || NEW_FOLDER_NAME); + parentEl[folderName] = {}; + var newPath = folderPath.slice(); + newPath.push(folderName); + cb({ + newPath: newPath + }); + }; + + // FORGET (move with href not path) + var forget = exp.forget = function (href) { + var paths = findFile(href); + move(paths, [TRASH]); + }; + + // DELETE + // Permanently delete multiple files at once using a list of paths + // NOTE: We have to be careful when removing elements from arrays (trash root, unsorted or template) + var removePadAttribute = function (f) { + Object.keys(files).forEach(function (key) { + var hash = f.indexOf('#') !== -1 ? f.slice(f.indexOf('#') + 1) : null; + if (hash && key.indexOf(hash) === 0) { + debug("Deleting pad attribute in the realtime object"); + files[key] = undefined; + delete files[key]; + } + }); + }; + var checkDeletedFiles = function () { + // Nothing in FILES_DATA for workgroups + if (workgroup) { return; } + + var filesList = getFiles[ROOT, 'hrefArray', TRASH]; + var toRemove = []; + files[FILES_DATA].forEach(function (arr) { + var f = arr.href; + if (filesList.indexOf(f) === -1) { + toRemove.push(arr); + } + }); + toRemove.forEach(function (f) { + var idx = files[FILES_DATA].indexOf(f); + if (idx !== -1) { + debug("Removing", f, "from filesData"); + spliceFileData(idx); + removePadAttribute(f.href); + } + }); + }; + var deleteHrefs = function (hrefs) { + hrefs.forEach(function (obj) { + var idx = files[obj.root].indexOf(obj.href); + files[obj.root].splice(idx, 1); + }); + }; + var deleteMultipleTrashRoot = function (roots) { + roots.forEach(function (obj) { + var idx = files[TRASH][obj.name].indexOf(obj.el); + files[TRASH][obj.name].splice(idx, 1); + }); + }; + var deleteMultiplePermanently = function (paths) { + var hrefPaths = paths.filter(isPathInHrefArray); + var rootPaths = paths.filter(isPathInRoot); + var trashPaths = paths.filter(isPathInTrash); + + var hrefs = []; + hrefPaths.forEach(function (path) { + var href = find(path); + hrefs.push({ + root: path[0], + href: href + }); + }); + deleteHrefs(hrefs); + + rootPaths.forEach(function (path) { + var parentPath = path.slice(); + var key = parentPath.pop(); + var parentEl = find(parentPath); + parentEl[key] = undefined; + delete parentEl[key]; + }); + + var trashRoot = []; + trashPaths.forEach(function (path) { + var parentPath = path.slice(); + var key = parentPath.pop(); + var parentEl = find(parentPath); + // Trash root: we have array here, we can't just splice with the path otherwise we might break the path + // of another element in the loop + if (path.length === 4) { + trashRoot.push({ + name: path[1], + el: parentEl + }); + return; + } + // Trash but not root: it's just a tree so remove the key + parentEl[key] = undefined; + delete parentEl[key]; + }); + deleteMultipleTrashRoot(trashRoot); + + checkDeletedFiles(); + }; + var deletePath = exp.delete = function (paths, cb) { + deletePathsPermanently(paths); + if (typeof cb === "function") { cb(); } + }; + var emptyTrash = exp.emptyTrash = function (cb) { + files[TRASH] = {}; + checkDeletedFiles(); + if(cb) { cb(); } + }; + + // RENAME + var rename = exp.rename = function (path, newName, cb) { + if (path.length <= 1) { + logError('Renaming `root` is forbidden'); + return; + } + if (!newName || newName.trim() === "") { return; } + // Copy the element path and remove the last value to have the parent path and the old name + var element = find(path); + var parentPath = path.slice(); + var oldName = parentPath.pop(); + if (oldName === newName) { + return; + } + var parentEl = find(parentPath); + if (typeof(parentEl[newName]) !== "undefined") { + log(Messages.fo_existingNameError); + return; + } + parentEl[newName] = element; + parentEl[oldName] = undefined; + delete parentEl[oldName]; + cb(); + }; + + /** + * INTEGRITY CHECK + */ + + var fixFiles = exp.fixFiles = function () { + // Explore the tree and check that everything is correct: + // * 'root', 'trash', 'unsorted' and 'filesData' exist and are objects + // * ROOT: Folders are objects, files are href + // * TRASH: Trash root contains only arrays, each element of the array is an object {element:.., path:..} + // * FILES_DATA: - Data (title, cdate, adte) are stored in filesData. filesData contains only href keys linking to object with title, cdate, adate. + // - Dates (adate, cdate) can be parsed/formatted + // - All files in filesData should be either in 'root', 'trash' or 'unsorted'. If that's not the case, copy the fily to 'unsorted' + // * UNSORTED: Contains only files (href), and does not contains files that are in ROOT + debug("Cleaning file system..."); + + var before = JSON.stringify(files); + + var fixRoot = function (elem) { + if (typeof(files[ROOT]) !== "object") { debug("ROOT was not an object"); files[ROOT] = {}; } + var element = elem || files[ROOT]; + for (var el in element) { + if (!isFile(element[el]) && !isFolder(element[el])) { + debug("An element in ROOT was not a folder nor a file. ", element[el]); + element[el] = undefined; + delete element[el]; + } else if (isFolder(element[el])) { + fixRoot(element[el]); + } + } + }; + var fixTrashRoot = function () { + if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; } + var tr = files[TRASH]; + var toClean; + var addToClean = function (obj, idx) { + if (typeof(obj) !== "object") { toClean.push(idx); return; } + if (!isFile(obj.element) && !isFolder(obj.element)) { toClean.push(idx); return; } + if (!$.isArray(obj.path)) { toClean.push(idx); return; } + }; + for (var el in tr) { + if (!$.isArray(tr[el])) { + debug("An element in TRASH root is not an array. ", tr[el]); + tr[el] = undefined; + delete tr[el]; + } else { + toClean = []; + tr[el].forEach(addToClean); + for (var i = toClean.length-1; i>=0; i--) { + tr[el].splice(toClean[i], 1); + } + } + } + }; + var fixUnsorted = function () { + if (!Array.isArray(files[UNSORTED])) { debug("UNSORTED was not an array"); files[UNSORTED] = []; } + files[UNSORTED] = Cryptpad.deduplicateString(files[UNSORTED].slice()); + var us = files[UNSORTED]; + var rootFiles = getFiles([ROOT, TEMPLATE]).slice(); + var toClean = []; + us.forEach(function (el, idx) { + if (!isFile(el) || rootFiles.indexOf(el) !== -1) { + toClean.push(idx); + } + }); + toClean.forEach(function (idx) { + us.splice(idx, 1); + }); + }; + var fixTemplate = function () { + if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; } + files[TEMPLATE] = Cryptpad.deduplicateString(files[TEMPLATE].slice()); + var us = files[TEMPLATE]; + var rootFiles = getFiles([ROOT, UNSORTED]).slice(); + var toClean = []; + us.forEach(function (el, idx) { + if (!isFile(el) || rootFiles.indexOf(el) !== -1) { + toClean.push(idx); + } + }); + toClean.forEach(function (idx) { + us.splice(idx, 1); + }); + }; + var fixFilesData = function () { + if (!$.isArray(files[FILES_DATA])) { debug("FILES_DATA was not an array"); files[FILES_DATA] = []; } + var fd = files[FILES_DATA]; + var rootFiles = getFiles([ROOT, TRASH, 'hrefArray']); + var toClean = []; + fd.forEach(function (el, idx) { + if (!el || typeof(el) !== "object") { + debug("An element in filesData was not an object.", el); + toClean.push(el); + return; + } + if (rootFiles.indexOf(el.href) === -1) { + debug("An element in filesData was not in ROOT, UNSORTED or TRASH.", el); + files[UNSORTED].push(el.href); + return; + } + }); + toClean.forEach(function (el) { + var idx = fd.indexOf(el); + if (idx !== -1) { + spliceFileData(idx); + } + }); + }; + + fixRoot(); + fixTrashRoot(); + if (!workgroup) { + fixUnsorted(); + fixTemplate(); + fixFilesData(); + } + + if (JSON.stringify(files) !== before) { + debug("Your file system was corrupted. It has been cleaned so that the pads you visit can be stored safely"); + return; + } + debug("File system was clean"); + }; + + return exp; + }; + + return module; +}); + diff --git a/www/drive/main.js b/www/drive/main.js index 474ea4b06..f4a8d05a8 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -661,7 +661,7 @@ define([ } // Unsorted or template if (filesOp.isPathInUnsorted(path) || filesOp.isPathInTemplate(path)) { - var file = filesOp.findElement(files, path); + var file = filesOp.find(path); if (filesOp.isFile(file) && filesOp.getTitle(file)) { return filesOp.getTitle(file); } @@ -688,7 +688,7 @@ define([ var msg = Messages._getKey('fm_removeSeveralDialog', [paths.length]); if (paths.length === 1) { var path = paths[0]; - var name = path[0] === UNSORTED ? filesOp.getTitle(filesOp.findElement(files, path)) : path[path.length - 1]; + var name = path[0] === UNSORTED ? filesOp.getTitle(filesOp.find(path)) : path[path.length - 1]; msg = Messages._getKey('fm_removeDialog', [name]); } Cryptpad.confirm(msg, function (res) { @@ -707,7 +707,7 @@ define([ $selected.each(function (idx, elmt) { var ePath = $(elmt).data('path'); if (ePath) { - var val = filesOp.findElement(files, ePath); + var val = filesOp.find(ePath); if (!val) { return; } // Error? A ".selected" element in not in the object paths.push({ path: ePath, @@ -721,7 +721,7 @@ define([ } else { removeSelected(); $element.addClass('selected'); - var val = filesOp.findElement(files, path); + var val = filesOp.find(path); if (!val) { return; } // The element in not in the object paths = [{ path: path, @@ -749,7 +749,7 @@ define([ var movedPaths = []; var importedElements = []; oldPaths.forEach(function (p) { - var el = filesOp.findElement(files, p.path); + var el = filesOp.find(p.path); if (el && (stringify(el) === stringify(p.value.el) || !p.value || !p.value.el)) { movedPaths.push(p.path); } else { @@ -882,7 +882,7 @@ define([ newPath.push(key); } - var element = filesOp.findElement(files, newPath); + var element = filesOp.find(newPath); var $icon = !isFolder ? getFileIcon(element) : undefined; var ro = filesOp.isReadOnlyFile(element); // ro undefined mens it's an old hash which doesn't support read-only @@ -1119,17 +1119,17 @@ define([ refresh(); }; $block.find('a.newFolder').click(function () { - filesOp.createNewFolder(currentPath, null, onCreated); + filesOp.addFolder(currentPath, null, onCreated); // TODO START HERE }); $block.find('a.newdoc').click(function (e) { var type = $(this).attr('data-type') || 'pad'; var name = Cryptpad.getDefaultName({type: type}); - filesOp.createNewFile(currentPath, name, type, onCreated); + filesOp.addFile(currentPath, name, type, onCreated); }); } else { $block.find('a.newdoc').click(function (e) { var type = $(this).attr('data-type') || 'pad'; - sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathInTrash(currentPath) ? '' : currentPath; + sessionStorage[Cryptpad.newPadPathKey] = filesOp.isPathIn(currentPath, [TRASH]) ? '' : currentPath; window.open('/' + type + '/'); }); } @@ -1251,11 +1251,11 @@ define([ }; var allFilesSorted = function () { - return filesOp.getUnsortedFiles().length === 0; + return filesOp.getFiles([UNSORTED]).length === 0; }; var sortElements = function (folder, path, oldkeys, prop, asc, useHref, useData) { - var root = filesOp.findElement(files, path); + var root = filesOp.find(path); var test = folder ? filesOp.isFolder : filesOp.isFile; var keys; if (!useData) { @@ -1478,7 +1478,7 @@ define([ var $atime = $('', {'class': 'col2'}).text(new Date(r.data.atime).toLocaleString()); var $ctimeName = $('', {'class': 'label2'}).text(Messages.fm_creation); var $ctime = $('', {'class': 'col2'}).text(new Date(r.data.ctime).toLocaleString()); - if (filesOp.isPathInHrefArray(path)) { + if (filesOp.isPathIn(path, ['hrefArray'])) { path.pop(); path.push(r.data.title); } @@ -1522,14 +1522,14 @@ define([ if (!path || path.length === 0) { path = [ROOT]; } - var isInRoot = filesOp.isPathInRoot(path); + var isInRoot = filesOp.isPathIn(path, [ROOT]); var isTrashRoot = filesOp.comparePath(path, [TRASH]); var isUnsorted = filesOp.comparePath(path, [UNSORTED]); var isTemplate = filesOp.comparePath(path, [TEMPLATE]); var isAllFiles = filesOp.comparePath(path, [FILES_DATA]); var isSearch = path[0] === SEARCH; - var root = isSearch ? undefined : filesOp.findElement(files, path); + var root = isSearch ? undefined : filesOp.find(path); if (!isSearch && typeof(root) === "undefined") { log(Messages.fm_unknownFolderError); debug("Unable to locate the selected directory: ", path); @@ -1642,11 +1642,11 @@ define([ var $el = $(e); if ($el.data('path')) { var path = $el.data('path'); - var element = filesOp.findElement(files, path); + var element = filesOp.find(path); if (!filesOp.isFile(element)) { return; } var data = filesOp.getFileData(element); if (!data) { return; } - if (filesOp.isPathInHrefArray(path)) { $el.find('.name').attr('title', data.title).text(data.title); } + if (filesOp.isPathIn(path, ['hrefArray'])) { $el.find('.name').attr('title', data.title).text(data.title); } $el.find('.title').attr('title', data.title).text(data.title); $el.find('.atime').attr('title', getDate(data.atime)).text(getDate(data.atime)); $el.find('.ctime').attr('title', getDate(data.ctime)).text(getDate(data.ctime)); @@ -1700,7 +1700,7 @@ define([ }; var createTree = function ($container, path) { - var root = filesOp.findElement(files, path); + var root = filesOp.find(path); // don't try to display what doesn't exist if (!root) { return; } @@ -1930,7 +1930,7 @@ define([ } else if ($(this).hasClass('open_ro')) { paths.forEach(function (p) { - var el = filesOp.findElement(files, p.path); + var el = filesOp.find(p.path); if (filesOp.isFolder(el)) { return; } var roUrl = getReadOnlyUrl(el); openFile(roUrl, false); @@ -1942,11 +1942,11 @@ define([ module.newFolder = info.newPath; module.displayDirectory(paths[0].path); }; - filesOp.createNewFolder(paths[0].path, null, onCreated); + filesOp.addFolder(paths[0].path, null, onCreated); } else if ($(this).hasClass("properties")) { if (paths.length !== 1) { return; } - var el = filesOp.findElement(files, paths[0].path); + var el = filesOp.find(paths[0].path); var prop = getProperties(el); Cryptpad.alert('', undefined, true); $('.alertify .msg').html(prop); @@ -1972,8 +1972,8 @@ define([ } else if ($(this).hasClass('open_ro')) { paths.forEach(function (p) { - var el = filesOp.findElement(files, p.path); - if (filesOp.isPathInFilesData(p.path)) { el = el.href; } + var el = filesOp.find(p.path); + if (filesOp.isPathIn(p.path, [FILES_DATA])) { el = el.href; } if (!el || filesOp.isFolder(el)) { return; } var roUrl = getReadOnlyUrl(el); openFile(roUrl, false); @@ -1986,7 +1986,7 @@ define([ } else if ($(this).hasClass("properties")) { if (paths.length !== 1) { return; } - var el = filesOp.findElement(files, paths[0].path); + var el = filesOp.find(paths[0].path); var prop = getProperties(el); Cryptpad.alert('', undefined, true); $('.alertify .msg').html(prop); @@ -2004,12 +2004,12 @@ define([ refresh(); }; if ($(this).hasClass("newfolder")) { - filesOp.createNewFolder(path, null, onCreated); + filesOp.addFolder(path, null, onCreated); } else if ($(this).hasClass("newdoc")) { var type = $(this).data('type') || 'pad'; var name = Cryptpad.getDefaultName({type: type}); - filesOp.createNewFile(path, name, type, onCreated); + filesOp.addFile(path, name, type, onCreated); } module.hideMenu(); }); @@ -2046,7 +2046,7 @@ define([ if (path.length === 4) { name = path[1]; } Cryptpad.confirm(Messages._getKey("fm_removePermanentlyDialog", [name]), function(res) { if (!res) { return; } - filesOp.removeFromTrash(path, refresh); + filesOp.removeFromTrash(path, refresh); // TODO END HERE }); return; } From daabb0b3adbee90cd995ca4c30fead39ec0ca4aa Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 13 Apr 2017 14:06:40 +0200 Subject: [PATCH 2/2] Integrate and fix the new fileObject (userObject) --- www/common/cryptpad-common.js | 2 +- www/common/fsStore.js | 4 +- www/common/mergeDrive.js | 14 ++--- www/common/userObject.js | 113 ++++++++++++++++++++++++++-------- www/drive/main.js | 66 ++++++++------------ 5 files changed, 122 insertions(+), 77 deletions(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index f815b8e4f..7f7f8b5eb 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -994,7 +994,7 @@ load pinpad dynamically only after you know that it will be needed */ var userChannel = common.parseHash(userHash).channel; if (!userChannel) { return null; } - var list = fo.getFilesDataFiles().map(hrefToHexChannelId) + var list = fo.getFiles([fo.FILES_DATA]).map(hrefToHexChannelId) .filter(function (x) { return x; }); list.push(common.base64ToHex(userChannel)); diff --git a/www/common/fsStore.js b/www/common/fsStore.js index e2b283f4b..edab0e252 100644 --- a/www/common/fsStore.js +++ b/www/common/fsStore.js @@ -2,7 +2,7 @@ define([ '/bower_components/chainpad-listmap/chainpad-listmap.js', '/bower_components/chainpad-crypto/crypto.js?v=0.1.5', '/bower_components/textpatcher/TextPatcher.amd.js', - '/common/fileObject.js', + '/common/userObject.js', '/bower_components/jquery/dist/jquery.min.js', ], function (Listmap, Crypto, TextPatcher, FO) { /* @@ -125,7 +125,7 @@ define([ }; ret.replaceHref = function (o, n) { - return filesOp.replaceHref(o, n); + return filesOp.replace(o, n); }; var changeHandlers = ret.changeHandlers = []; diff --git a/www/common/mergeDrive.js b/www/common/mergeDrive.js index 688f1cedc..784817d1d 100644 --- a/www/common/mergeDrive.js +++ b/www/common/mergeDrive.js @@ -2,7 +2,7 @@ require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/J define([ '/common/cryptpad-common.js', '/common/cryptget.js', - '/common/fileObject.js', + '/common/userObject.js', 'json.sortify' ], function (Cryptpad, Crypt, FO, Sortify) { var exp = {}; @@ -76,8 +76,8 @@ define([ console.error(msg || "Unable to find that path", path); }; - if (path[0] === FO.TRASH && path.length === 4) { - href = oldFo.getTrashElementData(path); + if (oldFo.isInTrashRoot(path)) { + href = oldFo.find(path.slice(0,3)); path.pop(); } @@ -156,13 +156,13 @@ define([ var newData = Cryptpad.getStore().getProxy(); var newFo = newData.fo; var newRecentPads = proxy.drive[Cryptpad.storageKey]; - var newFiles = newFo.getFilesDataFiles(); - var oldFiles = oldFo.getFilesDataFiles(); + var newFiles = newFo.getFiles([newFo.FILES_DATA]); + var oldFiles = oldFo.getFiles([newFo.FILES_DATA]); oldFiles.forEach(function (href) { // Do not migrate a pad if we already have it, it would create a duplicate in the drive if (newFiles.indexOf(href) !== -1) { return; } // If we have a stronger version, do not add the current href - if (Cryptpad.findStronger(href, newRecentPads)) { return; } + if (Cryptpad.findStronger(href, newRecentPads)) { console.log(href); return; } // If we have a weaker version, replace the href by the new one // NOTE: if that weaker version is in the trash, the strong one will be put in unsorted var weaker = Cryptpad.findWeaker(href, newRecentPads); @@ -176,7 +176,7 @@ define([ return; }); // Update the file in the drive - newFo.replaceHref(weaker, href); + newFo.replace(weaker, href); return; } // Here it means we have a new href, so we should add it to the drive at its old location diff --git a/www/common/userObject.js b/www/common/userObject.js index 7e7f7b292..d9669c408 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -10,10 +10,11 @@ define([ var TEMPLATE = module.TEMPLATE = "template"; var init = module.init = function (files, config) { + var exp = {}; var Cryptpad = config.Cryptpad; var Messages = Cryptpad.Messages; - var FILES_DATA = Cryptpad.storageKey; + var FILES_DATA = module.FILES_DATA = exp.FILES_DATA = Cryptpad.storageKey; var NEW_FOLDER_NAME = Messages.fm_newFolder; var NEW_FILE_NAME = Messages.fm_newFile; @@ -33,8 +34,6 @@ define([ // TODO: workgroup var workgroup = config.workgroup; - var exp = {}; - /* * UTILS @@ -49,6 +48,10 @@ define([ a[TEMPLATE] = []; return a; }; + var getHrefArray = function () { + return [UNSORTED, TEMPLATE]; + }; + var compareFiles = function (fileA, fileB) { return fileA === fileB; }; @@ -151,13 +154,19 @@ define([ return result; }; - var isSubpath = exp.isSubpath = function (path, parentPaths) { + var isSubpath = exp.isSubpath = function (path, parentPath) { var pathA = parentPath.slice(); var pathB = path.slice(0, pathA.length); return comparePath(pathA, pathB); }; - var isPathIn = function (path, categories) { + var isPathIn = exp.isPathIn = function (path, categories) { + if (!categories) { return; } + var idx = categories.indexOf('hrefArray'); + if (idx !== -1) { + categories.splice(idx, 1); + categories = categories.concat(getHrefArray()); + } return categories.some(function (c) { return Array.isArray(path) && path[0] === c; }); @@ -205,21 +214,17 @@ define([ }; var _getFiles = {}; _getFiles['array'] = function (cat) { - if (!files[cat]) { - files[cat] = []; - } + if (!files[cat]) { files[cat] = []; } return files[cat].slice(); }; - _getFiles[UNSORTED] = function () { - return _getFiles['array'](UNSORTED); - }; - _getFiles[TEMPLATE] = function () { - return _getFiles['array'](TEMPLATE); - }; + getHrefArray().forEach(function (c) { + _getFiles[c] = function () { return _getFiles['array'](c); }; + }); _getFiles['hrefArray'] = function () { var ret = []; - ret = ret.concat(_getFiles[UNSORTED]); - ret = ret.concat(_getFiles[TEMPLATE]); + getHrefArray().forEach(function (c) { + ret = ret.concat(_getFiles[c]()); + }); return Cryptpad.deduplicateString(ret); }; _getFiles[ROOT] = function () { @@ -255,11 +260,14 @@ define([ }); return ret; }; - var getFiles = function (categories) { + var getFiles = exp.getFiles = function (categories) { var ret = []; + if (!categories || !categories.length) { + categories = [ROOT, 'hrefArray', TRASH, FILES_DATA]; + } categories.forEach(function (c) { if (typeof _getFiles[c] === "function") { - ret = ret.concat(_getFiles[c]); + ret = ret.concat(_getFiles[c]()); } }); return Cryptpad.deduplicateString(ret); @@ -267,7 +275,7 @@ define([ // SEARCH var _findFileInRoot = function (path, href) { - if (!isPathIn([ROOT, TRASH])) { return []; } + if (!isPathIn(path, [ROOT, TRASH])) { return []; } var paths = []; var root = find(path); var addPaths = function (p) { @@ -338,7 +346,7 @@ define([ } return paths; }; - var findFile = function (href) { + var findFile = exp.findFile = function (href) { var rootpaths = _findFileInRoot([ROOT], href); var unsortedpaths = _findFileInHrefArray(UNSORTED, href); var templatepaths = _findFileInHrefArray(TEMPLATE, href); @@ -423,6 +431,7 @@ define([ // FILES DATA var pushFileData = exp.pushData = function (data) { Cryptpad.pinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) { + if (e) { console.log(e); return; } console.log(hash); }); files[FILES_DATA].push(data); @@ -431,6 +440,7 @@ define([ var data = files[FILES_DATA][idx]; if (typeof data === "object") { Cryptpad.unpinPads([Cryptpad.hrefToHexChannelId(data.href)], function (e, hash) { + if (e) { console.log(e); return; } console.log(hash); }); } @@ -496,7 +506,7 @@ define([ } else { name = elementPath[elementPath.length-1]; } - var newName = !isPathInRoot(elementPath) ? getAvailableName(newParent, name) : name; + var newName = !isPathIn(elementPath, [ROOT]) ? getAvailableName(newParent, name) : name; if (typeof(newParent[newName]) !== "undefined") { log(Messages.fo_unavailableName); @@ -517,6 +527,14 @@ define([ }); exp.delete(toRemove, cb); }; + var restore = exp.restore = function (path, cb) { + if (!isInTrashRoot(path)) { return; } + var parentPath = path.slice(); + parentPath.pop(); + var oldPath = find(parentPath).path; + move([path], oldPath, cb); + }; + // ADD var add = exp.add = function (href, path, name, cb) { @@ -599,7 +617,7 @@ define([ // Nothing in FILES_DATA for workgroups if (workgroup) { return; } - var filesList = getFiles[ROOT, 'hrefArray', TRASH]; + var filesList = getFiles([ROOT, 'hrefArray', TRASH]); var toRemove = []; files[FILES_DATA].forEach(function (arr) { var f = arr.href; @@ -629,9 +647,9 @@ define([ }); }; var deleteMultiplePermanently = function (paths) { - var hrefPaths = paths.filter(isPathInHrefArray); - var rootPaths = paths.filter(isPathInRoot); - var trashPaths = paths.filter(isPathInTrash); + var hrefPaths = paths.filter(function(x) { return isPathIn(x, ['hrefArray']); }); + var rootPaths = paths.filter(function(x) { return isPathIn(x, [ROOT]); }); + var trashPaths = paths.filter(function(x) { return isPathIn(x, [TRASH]); }); var hrefs = []; hrefPaths.forEach(function (path) { @@ -674,7 +692,7 @@ define([ checkDeletedFiles(); }; var deletePath = exp.delete = function (paths, cb) { - deletePathsPermanently(paths); + deleteMultiplePermanently(paths); if (typeof cb === "function") { cb(); } }; var emptyTrash = exp.emptyTrash = function (cb) { @@ -708,6 +726,49 @@ define([ cb(); }; + // REPLACE + var replaceFile = function (path, o, n) { + var root = find(path); + + if (isFile(root)) { return; } + for (var e in root) { + if (isFile(root[e])) { + if (compareFiles(o, root[e])) { + root[e] = n; + } + } else { + var nPath = path.slice(); + nPath.push(e); + replaceFile(nPath, o, n); + } + } + }; + // Replace a href by a stronger one everywhere in the drive (except FILES_DATA) + var replaceHref = exp.replace = function (o, n) { + if (!isFile(o) || !isFile(n)) { return; } + var paths = findFile(o); + + // Remove all the occurences in the trash + // Replace all the occurences not in the trash + // If all the occurences are in the trash or no occurence, add the pad to unsorted + var allInTrash = true; + paths.forEach(function (p) { + if (p[0] === TRASH) { + removeFromTrash(p, null, true); // 3rd parameter means skip "checkDeletedFiles" + return; + } else { + allInTrash = false; + var parentPath = p.slice(); + var key = parentPath.pop(); + var parentEl = find(parentPath); + parentEl[key] = n; + } + }); + if (allInTrash) { + add(n); + } + }; + /** * INTEGRITY CHECK */ diff --git a/www/drive/main.js b/www/drive/main.js index f4a8d05a8..1b57b41ae 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -5,7 +5,7 @@ define([ '/bower_components/textpatcher/TextPatcher.amd.js', 'json.sortify', '/common/cryptpad-common.js', - '/common/fileObject.js', + '/common/userObject.js', '/common/toolbar.js', '/customize/application_config.js', '/common/cryptget.js', @@ -264,9 +264,7 @@ define([ var removeInput = function (cancel) { if (!cancel && $iframe.find('.element-row > input').length === 1) { var $input = $iframe.find('.element-row > input'); - filesOp.renameElement($input.data('path'), $input.val(), function () { - APP.refresh(); - }); + filesOp.rename($input.data('path'), $input.val(), APP.refresh); } $iframe.find('.element-row > input').remove(); $iframe.find('.element-row > span:hidden').removeAttr('style'); @@ -332,9 +330,7 @@ define([ $input.on('keyup', function (e) { if (e.which === 13) { removeInput(true); - filesOp.renameElement(path, $input.val(), function () { - refresh(); - }); + filesOp.rename(path, $input.val(), refresh); return; } if (e.which === 27) { @@ -371,6 +367,7 @@ define([ var filterContextMenu = function ($menu, paths) { //var path = $element.data('path'); + if (!paths || paths.length === 0) { console.error('no paths'); } var hide = []; var hasFolder = false; @@ -652,15 +649,11 @@ define([ var getElementName = function (path) { // Trash root - if (filesOp.isInTrashRoot(path)) { - return path[0]; - } + if (filesOp.isInTrashRoot(path)) { return path[0]; } // Root or trash - if (filesOp.isPathInRoot(path) || filesOp.isPathInTrash(path)) { - return path[path.length - 1]; - } + if (filesOp.isPathIn(path, [ROOT, TRASH])) { return path[path.length - 1]; } // Unsorted or template - if (filesOp.isPathInUnsorted(path) || filesOp.isPathInTemplate(path)) { + if (filesOp.isPathIn(path, ['hrefArray'])) { var file = filesOp.find(path); if (filesOp.isFile(file) && filesOp.getTitle(file)) { return filesOp.getTitle(file); @@ -674,10 +667,10 @@ define([ var moveElements = function (paths, newPath, force, cb) { if (!APP.editable) { return; } var andThen = function () { - filesOp.moveElements(paths, newPath, cb); + filesOp.move(paths, newPath, cb); }; // Cancel drag&drop from TRASH to TRASH - if (filesOp.comparePath(newPath, [TRASH]) && paths.length >= 1 && paths[0][0] === TRASH) { + if (filesOp.isPathIn(newPath, [TRASH]) && paths.length && paths[0][0] === TRASH) { return; } // "force" is currently unused but may be configurable by user @@ -764,7 +757,8 @@ define([ moveElements(movedPaths, newPath, null, refresh); } if (importedElements && importedElements.length) { - filesOp.importElements(importedElements, newPath, refresh); + // TODO workgroup + //filesOp.importElements(importedElements, newPath, refresh); } }; @@ -967,7 +961,7 @@ define([ // Create the title block with the "parent folder" button var createTitle = function (path, noStyle) { if (!path || path.length === 0) { return; } - var isTrash = filesOp.isPathInTrash(path); + var isTrash = filesOp.isPathIn(path, [TRASH]); var $title = $('', {'class': 'path unselectable'}); if (APP.mobile()) { return $title; @@ -1119,7 +1113,7 @@ define([ refresh(); }; $block.find('a.newFolder').click(function () { - filesOp.addFolder(currentPath, null, onCreated); // TODO START HERE + filesOp.addFolder(currentPath, null, onCreated); }); $block.find('a.newdoc').click(function (e) { var type = $(this).attr('data-type') || 'pad'; @@ -2046,7 +2040,7 @@ define([ if (path.length === 4) { name = path[1]; } Cryptpad.confirm(Messages._getKey("fm_removePermanentlyDialog", [name]), function(res) { if (!res) { return; } - filesOp.removeFromTrash(path, refresh); // TODO END HERE + filesOp.delete([path], refresh); }); return; } @@ -2055,8 +2049,7 @@ define([ var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]); Cryptpad.confirm(msg, function(res) { if (!res) { return; } - filesOp.deletePathsPermanently(pathsList); - refresh(); + filesOp.delete(pathsList, refresh); }); } else if ($(this).hasClass("restore")) { @@ -2064,13 +2057,12 @@ define([ if (path.length === 4) { name = path[1]; } Cryptpad.confirm(Messages._getKey("fm_restoreDialog", [name]), function(res) { if (!res) { return; } - filesOp.restoreTrash(path, refresh); + filesOp.restore(path, refresh); }); } else if ($(this).hasClass("properties")) { - if (paths.length !== 1) { return; } - if (path.length !== 4) { return; } - var element = filesOp.getTrashElementData(path); + if (paths.length !== 1 || path.length !== 4) { return; } + var element = filesOp.find(path.slice(0,3)); // element containing the oldpath var sPath = stringifyPath(element.path); Cryptpad.alert('' + Messages.fm_originalPath + ":
" + sPath, undefined, true); } @@ -2094,20 +2086,17 @@ define([ $appContainer.on('keydown', function (e) { // "Del" if (e.which === 46) { - if (filesOp.isPathInFilesData(currentPath)) { return; } // We can't remove elements directly from filesData + if (filesOp.isPathIn(currentPath, [FILES_DATA])) { return; } // We can't remove elements directly from filesData var $selected = $iframe.find('.selected'); if (!$selected.length) { return; } var paths = []; - var isTrash = filesOp.isPathInTrash(currentPath); + var isTrash = filesOp.isPathIn(currentPath, [TRASH]); $selected.each(function (idx, elmt) { if (!$(elmt).data('path')) { return; } paths.push($(elmt).data('path')); }); // If we are in the trash or anon pad or if we are holding the "shift" key, delete permanently, if (isTrash || e.shiftKey) { - //var cb = filesOp.removeFromTrash; // We're in the trash - //if (!isTrash) { cb = filesOp.deletePathPermanently; } // We're in root - var msg = Messages._getKey("fm_removeSeveralPermanentlyDialog", [paths.length]); if (paths.length === 1) { msg = Messages.fm_removePermanentlyDialog; @@ -2116,8 +2105,7 @@ define([ Cryptpad.confirm(msg, function(res) { $(ifrw).focus(); if (!res) { return; } - filesOp.deletePathsPermanently(paths); - refresh(); + filesOp.delete(paths, refresh); }); return; } @@ -2143,10 +2131,8 @@ define([ if (path[0] !== 'drive') { return false; } path = path.slice(1); var cPath = currentPath.slice(); - if ((filesOp.isPathInUnsorted(cPath) && filesOp.isPathInUnsorted(path)) || - (filesOp.isPathInTemplate(cPath) && filesOp.isPathInTemplate(path)) || - (path.length >= cPath.length && filesOp.isSubpath(path, cPath)) || - (filesOp.isPathInTrash(cPath) && filesOp.isPathInTrash(path))) { + if ((filesOp.isPathIn(cPath, ['hrefArray', TRASH]) && cPath[0] === path[0]) || + (path.length >= cPath.length && filesOp.isSubpath(path, cPath))) { // Reload after a few ms to make sure all the change events have been received onRefresh.refresh(); } else if (path.length && path[0] === FILES_DATA) { @@ -2159,10 +2145,8 @@ define([ if (path[0] !== 'drive') { return false; } path = path.slice(1); var cPath = currentPath.slice(); - if ((filesOp.isPathInUnsorted(cPath) && filesOp.isPathInUnsorted(path)) || - (filesOp.isPathInTemplate(cPath) && filesOp.isPathInTemplate(path)) || - (path.length >= cPath.length && filesOp.isSubpath(path, cPath)) || - (filesOp.isPathInTrash(cPath) && filesOp.isPathInTrash(path))) { + if ((filesOp.isPathIn(cPath, ['hrefArray', TRASH]) && cPath[0] === path[0]) || + (path.length >= cPath.length && filesOp.isSubpath(path, cPath))) { // Reload after a few to make sure all the change events have been received onRefresh.to = window.setTimeout(refresh, 500); }