From 8bdc8415ab2cab2185d87cdf8f09a63bc3e770d5 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Mar 2017 10:15:13 +0100 Subject: [PATCH 1/5] Find a pad in the drive --- customize.dist/fsStore.js | 4 ++ www/common/cryptpad-common.js | 2 + www/common/fileObject.js | 120 ++++++++++++++++++++++++++++++++++ www/drive/file.css | 1 + www/drive/file.less | 1 + www/drive/main.js | 2 +- 6 files changed, 129 insertions(+), 1 deletion(-) diff --git a/customize.dist/fsStore.js b/customize.dist/fsStore.js index fbf7a5719..7ccde1947 100644 --- a/customize.dist/fsStore.js +++ b/customize.dist/fsStore.js @@ -119,6 +119,10 @@ define([ return filesOp.getStructure(); }; + ret.replaceHref = function (o, n) { + return filesOp.replaceHref(o, n); + }; + var changeHandlers = ret.changeHandlers = []; ret.change = function (f) {}; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index c78f938d2..222c658c4 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -423,6 +423,8 @@ define([ var ret = {}; + if (!href) { return ret; } + if (!/^https*:\/\//.test(href)) { var idx = href.indexOf('/#'); ret.type = href.slice(1, idx); diff --git a/www/common/fileObject.js b/www/common/fileObject.js index d8f10ced4..822035583 100644 --- a/www/common/fileObject.js +++ b/www/common/fileObject.js @@ -242,6 +242,90 @@ define([ return ret; }; + var _findFileInRoot = function (path, href) { + if (path[0] !== ROOT) { return []; } + var paths = []; + var root = exp.findElement(files, path); + + var addPaths = function (p) { + if (paths.indexOf(p) === -1) { + paths.push(p); + } + }; + + if (isFile(root)) { + if (compareFiles(href, root[e])) { + if (paths.indexOf(path) === -1) { + paths.push(path); + } + } + return paths; + } + for (var e in root) { + if (!isFile(root[e])) { + var nPath = path.slice(); + nPath.push(e); + _findFileInRoot(nPath, href).forEach(addPaths); + } + } + + return paths; + }; + var _findFileInArray = 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 = exp.findElement(files, path); + var paths = []; + var addPaths = function (p) { + if (paths.indexOf(p) === -1) { + paths.push(p); + } + }; + if (path.length === 1) { + 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 = exp.findFile = function (href) { + var rootpaths = _findFileInRoot([ROOT], href); + var unsortedpaths = _findFileInHrefArray(UNSORTED, href); + var templatepaths = _findFileInHrefArray(TEMPLATE, href); + var trashpaths = _findFileInTrash([TRASH], href); + // TODO return concat all + }; + + // Remove the selected 'href' from the tree located at 'path', and push its locations to the 'paths' array var removeFileFromRoot = function (path, href) { var paths = []; @@ -802,6 +886,42 @@ define([ } }; + var replaceFile = function (path, o, n) { + var root = exp.findElement(files, 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.replaceHref = function (o, n) { + replaceFile([ROOT], o, n); + var i = files[UNSORTED].indexOf(o); + if (i !== -1) { + files[UNSORTED].splice(i, 1); + files[UNSORTED].push(n); + } + var j = files[TEMPLATE].indexOf(o); + if (j !== -1) { + files[TEMPLATE].splice(j, 1); + files[TEMPLATE].push(n); + } + var k = getTrashFiles().indexOf(o); + if (k !== -1) { + // TODO? + } + }; + // addTemplate is called when we want to add a new pad, never visited, to the templates list // first, we must add it to FILES_DATA, so the input has to be an fileDAta object var addTemplate = exp.addTemplate = function (fileData) { diff --git a/www/drive/file.css b/www/drive/file.css index e80d6f98a..5f25a8957 100644 --- a/www/drive/file.css +++ b/www/drive/file.css @@ -112,6 +112,7 @@ span.fa-folder-open { #tree li > span.element-row { width: 100%; display: inline-block; + cursor: pointer; } #tree li > span.element-row:not(.selected):hover { background-color: #eee; diff --git a/www/drive/file.less b/www/drive/file.less index d5a7c1d73..930d82ec1 100644 --- a/www/drive/file.less +++ b/www/drive/file.less @@ -146,6 +146,7 @@ span { & > span.element-row { width: 100%; display: inline-block; + cursor: pointer; } & > span.element-row:not(.selected):hover { background-color: @drive-hover; diff --git a/www/drive/main.js b/www/drive/main.js index 1b6dd4a79..e53f1c94d 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -1164,7 +1164,7 @@ define([ var e = useData ? element : filesOp.getFileData(element); if (!e) { e = { - href : el, + href : element, title : Messages.fm_noname, atime : 0, ctime : 0 From c5f983ecd7c581d9383cc6d75a05ce9b20531507 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Mar 2017 16:01:34 +0100 Subject: [PATCH 2/5] Convert read-only link to editing link in the drive --- www/common/cryptpad-common.js | 14 ++++++++ www/common/fileObject.js | 64 +++++++++++++++++++---------------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 222c658c4..b07adc422 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -630,6 +630,7 @@ define([ return; } + var updateWeaker = []; var contains; var renamed = recent.map(function (pad) { var p = parsePadUrl(pad.href); @@ -663,6 +664,14 @@ define([ // set the name pad.title = name; + + // If we now have a stronger version of a stored href, replace the weaker one by the strong one + if (pad && pad.href && href !== pad.href) { + updateWeaker.push({ + o: pad.href, + n: href + }); + } pad.href = href; } return pad; @@ -677,6 +686,11 @@ define([ } setRecentPads(renamed, function (err, data) { + if (updateWeaker.length > 0) { + updateWeaker.forEach(function (obj) { + getStore().replaceHref(obj.o, obj.n); + }); + } cb(err, data); }); }); diff --git a/www/common/fileObject.js b/www/common/fileObject.js index 822035583..158f664ff 100644 --- a/www/common/fileObject.js +++ b/www/common/fileObject.js @@ -243,10 +243,9 @@ define([ }; var _findFileInRoot = function (path, href) { - if (path[0] !== ROOT) { return []; } + if (path[0] !== ROOT && path[0] !== TRASH) { return []; } var paths = []; var root = exp.findElement(files, path); - var addPaths = function (p) { if (paths.indexOf(p) === -1) { paths.push(p); @@ -254,7 +253,7 @@ define([ }; if (isFile(root)) { - if (compareFiles(href, root[e])) { + if (compareFiles(href, root)) { if (paths.indexOf(path) === -1) { paths.push(path); } @@ -262,16 +261,14 @@ define([ return paths; } for (var e in root) { - if (!isFile(root[e])) { - var nPath = path.slice(); - nPath.push(e); - _findFileInRoot(nPath, href).forEach(addPaths); - } + var nPath = path.slice(); + nPath.push(e); + _findFileInRoot(nPath, href).forEach(addPaths); } return paths; }; - var _findFileInArray = function (rootName, href) { + var _findFileInHrefArray = function (rootName, href) { var unsorted = files[rootName].slice(); var ret = []; var i = -1; @@ -322,10 +319,9 @@ define([ var unsortedpaths = _findFileInHrefArray(UNSORTED, href); var templatepaths = _findFileInHrefArray(TEMPLATE, href); var trashpaths = _findFileInTrash([TRASH], href); - // TODO return concat all + return rootpaths.concat(unsortedpaths, templatepaths, trashpaths); }; - // Remove the selected 'href' from the tree located at 'path', and push its locations to the 'paths' array var removeFileFromRoot = function (path, href) { var paths = []; @@ -458,7 +454,6 @@ define([ var parentEl = exp.findElement(files, 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 - console.log(path); if (path.length === 4) { trashRoot.push({ name: path[1], @@ -657,7 +652,6 @@ define([ // Import elements in the file manager var importElements = exp.importElements = function (elements, path, cb) { if (!elements || elements.length === 0) { return; } - console.log(elements); var newParent = findElement(files, path); if (!newParent) { debug("Trying to import elements into a non-existing folder"); return; } elements.forEach(function (e) { @@ -754,7 +748,7 @@ define([ }; // Delete permanently (remove from the trash root and from filesData) - var removeFromTrash = exp.removeFromTrash = function (path, cb) { + var removeFromTrash = exp.removeFromTrash = function (path, cb, nocheck) { if (!path || path.length < 4 || path[0] !== TRASH) { return; } // Remove the last element from the path to get the parent path and the element name var parentPath = path.slice(); @@ -775,7 +769,9 @@ define([ parentEl[name] = undefined; delete parentEl[name]; } - checkDeletedFiles(); + if (!nocheck) { + checkDeletedFiles(); + } if(cb) { cb(); } }; @@ -857,7 +853,7 @@ define([ pushToTrash(key, href, path); }; - var addUnsortedPad = exp.addPad = function (href, path, name) { + var addPad = exp.addPad = function (href, path, name) { if (workgroup) { return; } if (!href) { return; } var unsortedFiles = getUnsortedFiles(); @@ -882,6 +878,7 @@ define([ } } if (unsortedFiles.indexOf(href) === -1 && rootFiles.indexOf(href) === -1 && templateFiles.indexOf(href) === -1 && trashFiles.indexOf(href) === -1) { + console.log('push', href); files[UNSORTED].push(href); } }; @@ -905,20 +902,27 @@ define([ // Replace a href by a stronger one everywhere in the drive (except FILES_DATA) var replaceHref = exp.replaceHref = function (o, n) { - replaceFile([ROOT], o, n); - var i = files[UNSORTED].indexOf(o); - if (i !== -1) { - files[UNSORTED].splice(i, 1); - files[UNSORTED].push(n); - } - var j = files[TEMPLATE].indexOf(o); - if (j !== -1) { - files[TEMPLATE].splice(j, 1); - files[TEMPLATE].push(n); - } - var k = getTrashFiles().indexOf(o); - if (k !== -1) { - // TODO? + 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 = findElement(files, parentPath); + parentEl[key] = n; + } + }); + if (allInTrash) { + addPad(n); } }; From 370ae8110672fb0a9f712cabf37db587fd7b4821 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Mar 2017 16:29:17 +0100 Subject: [PATCH 3/5] Use the display name in the backup file name if not logged in --- www/settings/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/www/settings/main.js b/www/settings/main.js index 70cf938dc..bbb7d4524 100644 --- a/www/settings/main.js +++ b/www/settings/main.js @@ -124,7 +124,8 @@ define([ var exportFile = function () { var sjson = JSON.stringify(obj); - var suggestion = obj.login_name + '-' + new Date().toDateString(); + var name = obj.login_name || obj[USERNAME_KEY] || Messages.anonymous; + var suggestion = name + '-' + new Date().toDateString(); Cryptpad.prompt(Cryptpad.Messages.exportPrompt, Cryptpad.fixFileName(suggestion) + '.json', function (filename) { if (!(typeof(filename) === 'string' && filename)) { return; } From 9a7c2dd5e2f437c168bc1603ea81bbb16ba5d124 Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Mar 2017 16:38:22 +0100 Subject: [PATCH 4/5] Add a 'settings' link to the user menu in static pages --- www/common/cryptpad-common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index b07adc422..6660cac5b 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -1199,7 +1199,7 @@ define([ content: Messages.user_rename }); } - if (parsed && parsed.type && parsed.type !== 'settings') { + if (parsed && (!parsed.type || parsed.type !== 'settings')) { options.push({ tag: 'a', attributes: {'class': 'settings'}, From 2b6e44189d9a71099d7aeebffdac8b8cad63e37a Mon Sep 17 00:00:00 2001 From: yflory Date: Thu, 2 Mar 2017 17:01:27 +0100 Subject: [PATCH 5/5] When trying to reset the drive, tell the user if the input text is invalid --- customize.dist/translations/messages.fr.js | 1 + customize.dist/translations/messages.js | 1 + www/settings/main.js | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 3bcd145de..e31bd5a9b 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -250,6 +250,7 @@ define(function () { "Êtes-vous sûr de vouloir continuer ?
" + "Tapez “I love CryptPad” pour confirmer."; out.settings_resetDone = "Votre drive est désormais vide!"; + out.settings_resetError = "Texte de vérification incorrect. Votre CryptDrive n'a pas été modifié."; out.settings_resetTips = "Astuces et informations dans CryptDrive"; out.settings_resetTipsButton = "Réinitialiser les astuces visibles dans CryptDrive"; out.settings_resetTipsDone = "Toutes les astuces sont de nouveau visibles."; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 479cde75f..c32f346eb 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -252,6 +252,7 @@ define(function () { "Are you sure you want to continue?
" + "Type “I love CryptPad” to confirm."; out.settings_resetDone = "Your drive is now empty!"; + out.settings_resetError = "Incorrect verification text. Your CryptDrive has not been changed."; out.settings_resetTips = "Tips in CryptDrive"; out.settings_resetTipsButton = "Reset the available tips in CryptDrive"; out.settings_resetTipsDone = "All the tips are now visible again."; diff --git a/www/settings/main.js b/www/settings/main.js index bbb7d4524..ab3330ccd 100644 --- a/www/settings/main.js +++ b/www/settings/main.js @@ -165,7 +165,10 @@ define([ $button.click(function () { Cryptpad.prompt(Messages.settings_resetPrompt, "", function (val) { - if (val !== "I love CryptPad") { return; } + if (val !== "I love CryptPad") { + Cryptpad.alert(Messages.settings_resetError); + return; + } obj.proxy.drive = Cryptpad.getStore().getEmptyObject(); Cryptpad.alert(Messages.settings_resetDone); });