From a25a72b5dbcbd45023c97d69f3de71eccffcf75b Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 5 Jul 2018 10:37:06 +0200 Subject: [PATCH] Add a proxy manager to handle operations between shared folders --- www/common/outer/async-store.js | 138 ++++--------- www/common/outer/userObject.js | 83 ++++++-- www/common/proxy-manager.js | 338 ++++++++++++++++++++++++++++++++ www/common/userObject.js | 17 +- www/drive/inner.js | 43 +--- 5 files changed, 472 insertions(+), 147 deletions(-) create mode 100644 www/common/proxy-manager.js diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index 35d3dba67..b3601813a 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -1,6 +1,7 @@ define([ 'json.sortify', '/common/userObject.js', + '/common/proxy-manager.js', '/common/migrate-user-object.js', '/common/common-hash.js', '/common/common-util.js', @@ -18,7 +19,7 @@ define([ '/bower_components/chainpad-listmap/chainpad-listmap.js', '/bower_components/nthen/index.js', '/bower_components/saferphore/index.js', -], function (Sortify, UserObject, Migrate, Hash, Util, Constants, Feedback, Realtime, Messaging, Messenger, +], function (Sortify, UserObject, ProxyManager, Migrate, Hash, Util, Constants, Feedback, Realtime, Messaging, Messenger, CpNfWorker, NetConfig, AppConfig, Crypto, ChainPad, Listmap, nThen, Saferphore) { var Store = {}; @@ -78,17 +79,10 @@ define([ if (!userChannel) { return null; } // Get the list of pads' channel ID in your drive - // This list is filtered so that it doesn't include pad owned by other users (you should - // not pin these pads) - var files = store.userObject.getFiles([store.userObject.FILES_DATA]); + // This list is filtered so that it doesn't include pad owned by other users + // It now includes channels from shared folders var edPublic = store.proxy.edPublic; - var list = files.map(function (id) { - var d = store.userObject.getFileData(id); - if (d.owners && d.owners.length && edPublic && - d.owners.indexOf(edPublic) === -1) { return; } - return d.channel; - }) - .filter(function (x) { return x; }); + var list = store.manager.getPinList(edPublic); // Get the avatar var profile = store.proxy.profile; @@ -451,10 +445,16 @@ define([ if (data.expire) { pad.expire = data.expire; } if (data.password) { pad.password = data.password; } if (data.channel) { pad.channel = data.channel; } - store.userObject.pushData(pad, function (e, id) { + var uo = store.userObject; + var path = ['root']; + if (data.path) { + var resolved = store.manager.resolvePath(path); + uo = resolved.userObject; + path = resolved.path; + } + uo.pushData(pad, function (e, id) { if (e) { return void cb({error: "Error while adding a template:"+ e}); } - var path = data.path || ['root']; - store.userObject.add(id, path); + uo.add(id, path); sendDriveEvent('DRIVE_CHANGE', { path: ['drive', UserObject.FILES_DATA] }, clientId); @@ -733,67 +733,28 @@ define([ expire = +channelData.data.expire || undefined; } - var allPads = Util.find(store.proxy, ['drive', 'filesData']) || {}; - var isStronger; - - // If we don't find the new channel in our existing pads, we'll have to add the pads - // to filesData - var contains; - - // Update all pads that use the same channel but with a weaker hash - // Edit > Edit (present) > View > View (present) - for (var id in allPads) { - var pad = allPads[id]; - if (!pad.href && !pad.roHref) { continue; } - - var p2 = Hash.parsePadUrl(pad.href || pad.roHref); - var h2 = p2.hashData; - - // Different types, proceed to the next one - // No hash data: corrupted pad? - if (p.type !== p2.type || !h2) { continue; } - // Different channel: continue - if (pad.channel !== channel) { continue; } - - var shouldUpdate = p.hash.replace(/\/$/, '') === p2.hash.replace(/\/$/, ''); - - // If the hash is different but represents the same channel, check if weaker or stronger - if (!shouldUpdate && h.version !== 0) { - // We had view & now we have edit, update - if (h2.mode === 'view' && h.mode === 'edit') { shouldUpdate = true; } - // Same mode and we had present URL, update - else if (h.mode === h2.mode && h2.present) { shouldUpdate = true; } - // If we're here it means we have a weaker URL: - // update the date but keep the existing hash - else { - pad.atime = +new Date(); - contains = true; - continue; - } + var datas = store.manager.findChannel(channel); + var contains = datas.length !== 0; + datas.forEach(function (obj) { + var pad = obj.data; + pad.atime = +new Date(); + pad.title = title; + if (owners || h.type !== "file") { + // OWNED_FILES + // Never remove owner for files + pad.owners = owners; } - - if (shouldUpdate) { - contains = true; - pad.atime = +new Date(); - pad.title = title; - if (owners || h.type !== "file") { - // OWNED_FILES - // Never remove owner for files - pad.owners = owners; - } - pad.expire = expire; - - // If the href is different, it means we have a stronger one - if (href !== pad.href) { isStronger = true; } - pad.href = href; + pad.expire = expire; + if (h.mode === 'view') { return; } + + // If we only have rohref, it means we have a stronger href + if (!pad.href) { + // If we have a stronger url, remove the possible weaker from the trash. + // If all of the weaker ones were in the trash, add the stronger to ROOT + obj.userObject.restoreHref(href); } - } - - if (isStronger) { - // If we have a stronger url, remove the possible weaker from the trash. - // If all of the weaker ones were in the trash, add the stronger to ROOT - store.userObject.restoreHref(href); - } + pad.href = href; + }); // Add the pad if it does not exist in our drive if (!contains) { @@ -1215,11 +1176,11 @@ define([ }; var rt = Listmap.create(listmapConfig); store.sharedFolders[id] = rt; + store.manager.addProxy(rt.proxy); return rt; }; Store.addSharedFolder = function (clientId, data, cb) { var path = data.path; - var href = data.href; var id; nThen(function (waitFor) { // TODO @@ -1232,13 +1193,13 @@ define([ } id = folderId; })); - nThen(function (waitFor) { + }).nThen(function (waitFor) { // 2a. add the shared folder to the path in our drive store.userObject.add(id, path); onSync(waitFor()); // 2b. load the proxy - var rt = loadSharedFolder(folderId, data); + var rt = loadSharedFolder(id, data); rt.on('ready', waitFor(function () { // TODO // "fixFiles" @@ -1267,22 +1228,7 @@ define([ }); cb(data2); }; - switch (cmdData.cmd) { - case 'move': - store.userObject.move(data.paths, data.newPath, cb2); break; - case 'restore': - store.userObject.restore(data.path, cb2); break; - case 'addFolder': - store.userObject.addFolder(data.path, data.name, cb2); break; - case 'delete': - store.userObject.delete(data.paths, cb2, data.nocheck, data.isOwnPadRemoved); break; - case 'emptyTrash': - store.userObject.emptyTrash(cb2); break; - case 'rename': - store.userObject.rename(data.path, data.newName, cb2); break; - default: - cb(); - } + store.manager.command(cmdData, cb2); }; // Clients management @@ -1416,7 +1362,7 @@ define([ var onReady = function (clientId, returned, cb) { var proxy = store.proxy; - var userObject = store.userObject = UserObject.init(proxy.drive, { + var manager = store.manager = ProxyManager.create(proxy.drive, proxy.edPublic, { pinPads: function (data, cb) { Store.pinPads(null, data, cb); }, unpinPads: function (data, cb) { Store.unpinPads(null, data, cb); }, removeOwnedChannel: function (data, cb) { Store.removeOwnedChannel(null, data, cb); }, @@ -1427,6 +1373,7 @@ define([ sendDriveEvent("DRIVE_LOG", msg); } }); + var userObject = store.userObject = manager.user.userObject; nThen(function (waitFor) { postMessage(clientId, 'LOADING_DRIVE', { state: 2 @@ -1439,12 +1386,13 @@ define([ progress: progress }); }); - }).nThen(function () { + }).nThen(function (waitFor) { postMessage(clientId, 'LOADING_DRIVE', { state: 3 }); userObject.fixFiles(); - + loadSharedFolders(waitFor); + }).nThen(function () { var requestLogin = function () { broadcast([], "REQUEST_LOGIN"); }; diff --git a/www/common/outer/userObject.js b/www/common/outer/userObject.js index 4bc0019c3..94363a2d2 100644 --- a/www/common/outer/userObject.js +++ b/www/common/outer/userObject.js @@ -22,7 +22,7 @@ define([ console.error("removeOwnedChannel was not provided"); }; var loggedIn = config.loggedIn; - var workgroup = config.workgroup; + var sharedFolder = config.sharedFolder; var edPublic = config.edPublic; var ROOT = exp.ROOT; @@ -31,6 +31,7 @@ define([ var UNSORTED = exp.UNSORTED; var TRASH = exp.TRASH; var TEMPLATE = exp.TEMPLATE; + var SHARED_FOLDERS = exp.SHARED_FOLDERS; var debug = exp.debug; @@ -76,9 +77,8 @@ define([ // Find files in FILES_DATA that are not anymore in the drive, and remove them from // FILES_DATA. If there are owned pads, remove them from server too, unless the flag tells // us they're already removed - exp.checkDeletedFiles = function (isOwnPadRemoved) { - // Nothing in FILES_DATA for workgroups - if (workgroup || (!loggedIn && !config.testMode)) { return; } + exp.checkDeletedFiles = function (isOwnPadRemoved, noUnpin) { + if (!loggedIn && !config.testMode) { return; } var filesList = exp.getFiles([ROOT, 'hrefArray', TRASH]); var toClean = []; @@ -107,6 +107,7 @@ define([ } }); if (!toClean.length) { return; } + if (noUnpin) { return; } unpinPads(toClean, function (response) { if (response && response.error) { return console.error(response.error); } // console.error(response); @@ -124,7 +125,7 @@ define([ files[TRASH][obj.name].splice(idx, 1); }); }; - exp.deleteMultiplePermanently = function (paths, nocheck, isOwnPadRemoved) { + exp.deleteMultiplePermanently = function (paths, nocheck, isOwnPadRemoved, noUnpin) { var hrefPaths = paths.filter(function(x) { return exp.isPathIn(x, ['hrefArray']); }); var rootPaths = paths.filter(function(x) { return exp.isPathIn(x, [ROOT]); }); var trashPaths = paths.filter(function(x) { return exp.isPathIn(x, [TRASH]); }); @@ -176,11 +177,66 @@ define([ deleteMultipleTrashRoot(trashRoot); // In some cases, we want to remove pads from a location without removing them from - // OLD_FILES_DATA (replaceHref) - if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved); } + // FILES_DATA (replaceHref) + if (!nocheck) { exp.checkDeletedFiles(isOwnPadRemoved, noUnpin); } }; // Move + + // From another drive + exp.copyFromOtherDrive = function (path, element, data) { + // Copy files data + // We have to remove pads that are already in the current proxy to make sure + // we won't create duplicates + + var toRemove = []; + Object.keys(data).forEach(function (id) { + // Find and maybe update existing pads with the same channel id + var d = data[id]; + var found = false; + for (var i in files[FILES_DATA]) { + if (files[FILES_DATA][i].channel === d.channel) { + // Update href? + if (!files[FILES_DATA][i].href) { files[FILES_DATA][i].href = d.href; } + found = true; + break; + } + } + if (found) { + toRemove.push(id); + return; + } + files[FILES_DATA][id] = data[id]; + }); + + // Remove existing pads from the "element" variable + if (exp.isFile(element) && toRemove.indexOf(element) !== -1) { + // XXX display error in the UI + return; + } else if (exp.isFolder(element)) { + var _removeExisting = function (root) { + for (var k in root) { + if (exp.isFile(root[k])) { + if (toRemove.indexOf(root[k]) !== -1) { + // XXX display message in UI + delete root[k]; + } + } else if (exp.isFolder(root[k])) { + _removeExisting(root[k]); + } + } + }; + _removeExisting(element); + } + + + // Copy file or folder + var newParent = exp.find(path); + var newName = exp.getAvailableName(newParent, Hash.createChannelId()); + newParent[newName] = element; + }; + + // From the same drive var pushToTrash = function (name, element, path) { var trash = files[TRASH]; if (typeof(trash[name]) === "undefined") { trash[name] = []; } @@ -449,6 +505,7 @@ define([ } }; var fixTrashRoot = function () { + if (sharedFolder) { return; } if (typeof(files[TRASH]) !== "object") { debug("TRASH was not an object"); files[TRASH] = {}; } var tr = files[TRASH]; var toClean; @@ -492,6 +549,7 @@ define([ } }; var fixTemplate = function () { + if (sharedFolder) { return; } if (!Array.isArray(files[TEMPLATE])) { debug("TEMPLATE was not an array"); files[TEMPLATE] = []; } files[TEMPLATE] = Util.deduplicateString(files[TEMPLATE].slice()); var us = files[TEMPLATE]; @@ -608,6 +666,10 @@ define([ spliceFileData(id); }); }; + var fixSharedFolders = function () { + if (sharedFolder) { return; } + if (typeof(files[SHARED_FOLDERS]) !== "object") { debug("SHARED_FOLDER was not an object"); files[SHARED_FOLDERS] = {}; } + }; var fixDrive = function () { Object.keys(files).forEach(function (key) { @@ -617,10 +679,9 @@ define([ fixRoot(); fixTrashRoot(); - if (!workgroup) { - fixTemplate(); - fixFilesData(); - } + fixTemplate(); + fixFilesData(); + fixSharedFolders(); fixDrive(); if (JSON.stringify(files) !== before) { diff --git a/www/common/proxy-manager.js b/www/common/proxy-manager.js new file mode 100644 index 000000000..9b774b86d --- /dev/null +++ b/www/common/proxy-manager.js @@ -0,0 +1,338 @@ +define([ + '/common/userObject.js', + '/common/common-util.js', + '/bower_components/nthen/index.js', +], function (UserObject, Util, nThen) { + + + var getConfig = function (Env) { + var cfg = {}; + for (var k in Env.cfg) { cfg[k] = Env[k]; } + return cfg; + }; + + // Add a shared folder to the list + var addProxy = function (Env, id, proxy, leave) { + var cfg = getConfig(); + cfg.sharedFolder = true; + cfg.id = id; + var userObject = UserObject.init(proxy, Env.cfg); + userObject.fixFiles(); + Env.folders[id] = { + proxy: proxy, + userObject: userObject, + leave: leave + }; + return userObject; + }; + + // TODO: Remove a shared folder from the list + var removeProxy = function (Env, id) { + var f = Env.folders[id]; + if (!f) { return; } + f.leave(); + delete Env.folders[id]; + }; + + /* + Paths + */ + + // Transform an absolute path into a path relative to the correct shared folder + var _resolvePath = function (Env, path) { + var res = { + id: null, + userObject: Env.user.userObject, + path: path + }; + if (!Array.isArray(path) || path.length <= 1) { + return res; + } + var current; + var uo = Env.user.userObject; + for (var i=2; i<=path.length; i++) { + current = uo.find(path.slice(0,i)); + if (uo.isSharedFolder(current)) { + res = { + id: current, + userObject: Env.folders[current].userObject, + path: path.slice(i) + }; + break; + } + } + return res; + }; + var _resolvePaths = function (Env, paths) { + var main = []; + var folders = {}; + paths.forEach(function (path) { + var r = _resolvePath(Env, path); + if (r.id) { + if (!folders[r.id]) { + folders[r.id] = [r.path]; + } else { + folders[r.id].push(r.path); + } + } else { + main.push(r.path); + } + }); + return { + main: main, + folders: folders + }; + }; + + // Get a copy of the elements located in the given paths, with their files data + var _getCopyFromPaths = function (paths, userObject) { + var data = []; + paths.forEach(function (path) { + var el = userObject.find(path); + var files = []; + + // Get the files ID from the current path (file or folder) + if (userObject.isFile(el)) { + files.push(el); + } else { + userObject.getFilesRecursively(el, files); + } + + // Remove the shared folder from this list of files ID + files.filter(function (f) { return !userObject.isSharedFolder(f); }); + // Deduplicate + Util.deduplicateString(files); + + // Get the files data associated to these files + var filesData = {}; + files.forEach(function (f) { + filesData[f] = userObject.getFileData(f); + }); + + // TODO RO + // Encrypt or decrypt edit link here + // filesData.forEach(function (d) { d.href = encrypt(d.href); }); + + + data.push({ + el: el, + data: filesData + }); + }); + return data; + }; + + /* + RPC commands + */ + + // Move files or folders in the drive + var _move = function (Env, data, cb) { + var resolved = _resolvePaths(Env, data.paths); + var newResolved = _resolvePath(Env, data.newPath); + + if (!newResolved.userObject.isFolder(newResolved.path)) { return void cb(); } // XXX + + nThen(function (waitFor) { + if (resolved.main.length) { + // Move from the main drive + if (!newResolved.id) { + // Move from the main drive to the main drive + Env.user.userObject.move(resolved.main, newResolved.path, waitFor()); + } else { + // Move from the main drive to a shared folder + + // Copy the elements to the new location + var toCopy = _getCopyFromPaths(resolved.main, Env.user.userObject); + var newUserObject = newResolved.userObject; + newUserObject.copyFromOtherDrive(newResolved.path, toCopy.el, toCopy.data); + + // Filter owned pads so that we won't remove them from our drive + var toRemove = resolved.main.slice(); + toRemove.filter(function (id) { + var owners = Env.user.userObject.getFileData(id).owners; + return !Array.isArray(owners) || owners.indexOf(Env.edPublic) === -1; + }); + + // Remove the elements from the old location (without unpinning) + Env.user.userObject.delete(resolved.main, waitFor(), false, false, true); + } + } + var folderIds = Object.keys(resolved.folders); + if (folderIds.length) { + // Move from a shared folder + folderIds.forEach(function (fIdStr) { + var fId = Number(fIdStr); + var paths = resolved.folders[fId]; + if (newResolved.id === fId) { + // Move to the same shared folder + newResolved.userObject.move(paths, newResolved.path, waitFor()); + } else { + // Move to a different shared folder or to main drive + var uoFrom = Env.folders[fId].userObject; + var uoTo = newResolved.userObject; + + // Copy the elements to the new location + var toCopy = _getCopyFromPaths(paths, uoFrom); + uoTo.copyFromOtherDrive(newResolved.path, toCopy.el, toCopy.data); + + // Remove the elements from the old location (without unpinning) + uoFrom.delete(paths, waitFor(), false, false, true); + } + }); + } + }).nThen(function () { + cb(); + }); + }; + // Restore from the trash (main drive only) + var _restore = function (Env, data, cb) { + var userObject = Env.user.userObject; + data = data || {}; + userObject.restore(data.path, cb); + }; + // Add a folder/subfolder + var _addFolder = function (Env, data, cb) { + data = data || {}; + var resolved = _resolvePath(Env, data.path); + if (!resolved || !resolved.userObject) { return void cb({error: 'E_NOTFOUND'}); } + resolved.userObject.addFolder(resolved.path, data.name, cb); + }; + // Delete permanently some pads or folders + var _delete = function (Env, data, cb) { + data = data || {}; + var resolved = _resolvePaths(Env, data.paths); + if (!resolved.main.length && !Object.keys(resolved.folders).length) { + return void cb({error: 'E_NOTFOUND'}); + } + nThen(function (waitFor)  { + if (resolved.main.length) { + Env.user.userObject.delete(resolved.main, waitFor(), data.nocheck, + data.isOwnPadRemoved); + } + Object.keys(resolved.folders).forEach(function (id) { + Env.folders[id].userObject.delete(resolved.folders[id], waitFor(), data.nocheck, + data.isOwnPadRemoved); + }); + }).nThen(function () { + cb(); + }); + }; + // Empty the trash (main drive only) + var _emptyTrash = function (Env, data, cb) { + Env.user.userObject.emptyTrash(cb); + }; + // Rename files or folders + var _rename = function (Env, data, cb) { + data = data || {}; + var resolved = _resolvePath(Env, data.path); + if (!resolved || !resolved.userObject) { return void cb({error: 'E_NOTFOUND'}); } + resolved.userObject.rename(resolved.path, data.newName, cb); + }; + var onCommand = function (Env, cmdData, cb) { + var cmd = cmdData.cmd; + var data = cmdData.data || {}; + switch (cmd) { + case 'move': + _move(Env, data, cb); break; + //store.userObject.move(data.paths, data.newPath, cb2); break; + case 'restore': + _restore(Env, data, cb); break; + case 'addFolder': + _addFolder(Env, data, cb); break; + case 'delete': + _delete(Env, data, cb); break; + case 'emptyTrash': + _emptyTrash(Env, data, cb); break; + case 'rename': + _rename(Env, data, cb); break; + default: + cb(); + } + }; + + // Return files data objects associated to a channel for setPadTitle + // All occurences are returned, in drive or shared folders + var findChannel = function (Env, channel) { + var ret = []; + Env.user.userObject.findChannels([channel]).forEach(function (id) { + ret.push({ + data: Env.user.userObject.getFileData(id), + userObject: Env.user.userObject + }); + }); + Object.keys(Env.folders).forEach(function (fId) { + Env.folders[fId].userObject.findChannels([channel]).forEach(function (id) { + ret.push({ + data: Env.folders[fId].userObject.getFileData(id), + userObject: Env.folders[fId].userObject + }); + }); + }); + return ret; + }; + + // Get the list of channels that should be pinned + var getPinList = function (Env, edPublic) { + if (!edPublic) { return; } + var toPin = []; + var addChannel = function (userObject) { + return function (fileId) { + var data = userObject.getFileData(fileId); + // Don't pin pads owned by someone else + if (Array.isArray(data.owners) && data.owners.length && + data.owners.indexOf(edPublic) === -1) { return; } + // Don't push duplicates + if (toPin.indexOf(data.channel) === -1) { + toPin.push(data.channel); + } + }; + }; + + // Get the list of user objects + var userObjects = [Env.user.userObject]; + var foldersUO = Object.keys(Env.folders).map(function (k) { + return Env.folders[k].userObject; + }); + Array.prototype.push.apply(userObjects, foldersUO); + + userObjects.forEach(function (uo) { + var files = uo.getFiles([UserObject.FILES_DATA]); + files.forEach(addChannel(uo)); + }); + }; + + var create = function (proxy, edPublic, uoConfig) { + var Env = { + cfg: uoConfig, + edPublic: edPublic, + user: { + proxy: proxy, + userObject: UserObject.init(proxy, uoConfig) + }, + folders: {} + }; + + var callWithEnv = function (f) { + return function () { + [].unshift.call(arguments, Env); + return f.apply(null, arguments); + }; + }; + + return { + addProxy: callWithEnv(addProxy), + removeProxy: callWithEnv(removeProxy), + command: callWithEnv(onCommand), + findChannel: callWithEnv(findChannel), + getPinList: callWithEnv(getPinList), + resolvePath: callWithEnv(_resolvePath), + user: Env.user, + folders: Env.folders + }; + }; + + return { + create: create + }; +}); diff --git a/www/common/userObject.js b/www/common/userObject.js index f44310296..87a1653fa 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -29,6 +29,7 @@ define([ exp.UNSORTED = UNSORTED; exp.TRASH = TRASH; exp.TEMPLATE = TEMPLATE; + exp.SHARED_FOLDERS = SHARED_FOLDERS; // Logging var logging = function () { @@ -42,9 +43,6 @@ define([ console.error.apply(console, arguments); }; - // TODO: workgroup - var workgroup = config.workgroup; - if (pinPads) { // Extend "exp" with methods used only outside of the iframe (requires access to store) OuterFO.init(config, exp, files); @@ -89,6 +87,9 @@ define([ if (!isFolder(element)) { return false; } return Object.keys(element).length === 0; }; + exp.isSharedFolder = function (element) { + return Boolean(files[SHARED_FOLDERS][element]); + }; exp.hasSubfolder = function (element, trashRoot) { if (!isFolder(element)) { return false; } @@ -134,7 +135,6 @@ define([ // Data from filesData var getTitle = exp.getTitle = function (file, type) { - if (workgroup) { debug("No titles in workgroups"); return; } var data = getFileData(file); if (!file || !data || !(data.href || data.roHref)) { error("getTitle called with a non-existing file id: ", file, data); @@ -206,7 +206,8 @@ define([ // GET FILES - var getFilesRecursively = function (root, arr) { + var getFilesRecursively = exp.getFilesRecursively = function (root, arr) { + arr = arr || []; for (var e in root) { if (isFile(root[e])) { if(arr.indexOf(root[e]) === -1) { arr.push(root[e]); } @@ -214,6 +215,7 @@ define([ getFilesRecursively(root[e], arr); } } + return arr; }; var _getFiles = {}; _getFiles['array'] = function (cat) { @@ -552,18 +554,19 @@ define([ // 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) - exp.delete = function (paths, cb, nocheck, isOwnPadRemoved) { + exp.delete = function (paths, cb, nocheck, isOwnPadRemoved, noUnpin) { if (sframeChan) { return void sframeChan.query("Q_DRIVE_USEROBJECT", { cmd: "delete", data: { paths: paths, nocheck: nocheck, + noUnpin: noUnpin, isOwnPadRemoved: isOwnPadRemoved } }, cb); } - exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved); + exp.deleteMultiplePermanently(paths, nocheck, isOwnPadRemoved, noUnpin); if (typeof cb === "function") { cb(); } }; exp.emptyTrash = function (cb) { diff --git a/www/drive/inner.js b/www/drive/inner.js index fb6f56bf4..a6fd5c9ec 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -244,27 +244,27 @@ define([ 'tabindex': '-1', 'data-icon': faTags, }, Messages.fc_hashtag)), - h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.pad, 'data-type': 'pad' }, Messages.button_newpad)), - h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.code, 'data-type': 'code' }, Messages.button_newcode)), - h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.slide, 'data-type': 'slide' }, Messages.button_newslide)), - h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.poll, 'data-type': 'poll' }, Messages.button_newpoll)), - h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable.cp-app-drive-context-own', { + h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.whiteboard, 'data-type': 'whiteboard' @@ -311,13 +311,6 @@ define([ var edPublic = priv.edPublic; APP.origin = priv.origin; - var isOwnDrive = function () { - return true; // TODO - }; - var isWorkgroup = function () { - return files.workgroup === 1; - }; - config.workgroup = isWorkgroup(); config.loggedIn = APP.loggedIn; config.sframeChan = sframeChan; @@ -357,11 +350,9 @@ define([ } // FILE MANAGER - // _WORKGROUP_ and other people drive : display Documents as main page - var currentPath = APP.currentPath = isOwnDrive() ? getLastOpenedFolder() : [ROOT]; + var currentPath = APP.currentPath = getLastOpenedFolder(); // Categories dislayed in the menu - // _WORKGROUP_ : do not display unsorted var displayedCategories = [ROOT, TRASH, SEARCH, RECENT]; // PCS enabled: display owned pads @@ -371,7 +362,6 @@ define([ // Tags used: display Tags category if (Object.keys(filesOp.getTagsList()).length) { displayedCategories.push(TAGS); } - if (isWorkgroup()) { displayedCategories = [ROOT, TRASH, SEARCH]; } var virtualCategories = [SEARCH, RECENT, OWNED, TAGS]; if (!APP.loggedIn) { @@ -856,7 +846,6 @@ define([ show.forEach(function (className) { var $el = $contextMenu.find('.cp-app-drive-context-' + className); if (!APP.editable && $el.is('.cp-app-drive-context-editable')) { return; } - if (!isOwnDrive && $el.is('.cp-app-drive-context-own')) { return; } if (filter($el, className)) { return; } $el.parent('li').show(); filtered.push('.cp-app-drive-context-' + className); @@ -1212,10 +1201,6 @@ define([ if (movedPaths && movedPaths.length) { moveElements(movedPaths, newPath, null, refresh); } - if (importedElements && importedElements.length) { - // TODO workgroup - //filesOp.importElements(importedElements, newPath, refresh); - } }; var addDragAndDropHandlers = function ($element, path, isFolder, droppable) { @@ -1266,7 +1251,6 @@ define([ addDragAndDropHandlers($content, null, true, true); // In list mode, display metadata from the filesData object - // _WORKGROUP_ : Do not display title, atime and ctime columns since we don't have files data var addFileData = function (element, $span) { if (!filesOp.isFile(element)) { return; } @@ -1323,10 +1307,7 @@ define([ var $cdate = $('', { 'class': 'cp-app-drive-element-ctime cp-app-drive-element-list' }).text(getDate(data.ctime)); - $span.append($type); - if (!isWorkgroup()) { - $span.append($adate).append($cdate); - } + $span.append($type).append($adate).append($cdate); }; var addFolderData = function (element, key, $span) { @@ -1804,7 +1785,6 @@ define([ $list.find('.' + classSorted).addClass('cp-app-drive-sort-active').prepend($icon); } }; - // _WORKGROUP_ : do not display title, atime and ctime in workgroups since we don't have files data var getFileListHeader = function () { var $fihElement = $('
  • ', { 'class': 'cp-app-drive-element-header cp-app-drive-element-list' @@ -1827,9 +1807,7 @@ define([ }).text(Messages.fm_creation).click(onSortByClick); // If displayTitle is false, it means the "name" is the title, so do not display the "name" header $fihElement.append($fhIcon).append($fhName).append($fhState).append($fhType); - if (!isWorkgroup()) { - $fihElement.append($fhAdate).append($fhCdate); - } + $fihElement.append($fhAdate).append($fhCdate); addFileSortIcon($fihElement); return $fihElement; }; @@ -2277,7 +2255,6 @@ define([ // Display the selected directory into the content part (rightside) // NOTE: Elements in the trash are not using the same storage structure as the others - // _WORKGROUP_ : do not change the lastOpenedFolder value in localStorage var _displayDirectory = function (path, force) { APP.hideMenu(); if (!APP.editable) { debug("Read-only mode"); } @@ -2331,9 +2308,7 @@ define([ $tree.find('#cp-app-drive-tree-search-input')[0].selectionEnd = getSearchCursor(); } - if (!isWorkgroup()) { - setLastOpenedFolder(path); - } + setLastOpenedFolder(path); var $toolbar = createToolbar(path); var $info = createInfoBox(path);