diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 985f6bd83..a5e7ea251 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -1033,6 +1033,7 @@ flex-flow: column; z-index: 10000; //Z cp-toolbar-drawer-content color: black; + .tools_unselectable(); .fa { font-size: 17px; } diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 386353339..fc514ef3b 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2299,7 +2299,9 @@ define([ value = val; var $val = $innerblock.find('[data-value="'+val+'"]'); var textValue = name || $val.html() || val; - $button.find('.cp-dropdown-button-title').html(textValue); + setTimeout(function () { + $button.find('.cp-dropdown-button-title').html(textValue); + }); }; $container.getValue = function () { return value || ''; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index 19faf940b..6b09656a0 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -1604,6 +1604,26 @@ define([ var allocated = Login.allocateBytes(bytes); blockKeys = allocated.blockKeys; })); + }).nThen(function (waitFor) { + var blockUrl = Block.getBlockUrl(blockKeys); + // Check whether there is a block at that location + Util.fetch(blockUrl, waitFor(function (err, block) { + // If there is no block or the block is invalid, continue. + if (err) { + console.log("no block found"); + return; + } + + var decryptedBlock = Block.decrypt(block, blockKeys); + if (!decryptedBlock) { + console.error("Found a login block but failed to decrypt"); + return; + } + + // If there is already a valid block, abort! We risk overriding another user's data + waitFor.abort(); + cb({ error: 'EEXISTS' }); + })); }).nThen(function (waitFor) { // Write the new login block var temp = { diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index cd3759d8d..803e0a715 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -2779,30 +2779,34 @@ define([ $sortBlock.on('click', 'a', onSortByClick); return $fhSort; }; - var getFolderListHeader = function () { + var getFolderListHeader = function (clickable, small) { var $fohElement = $('
  • ', { 'class': 'cp-app-drive-element-header cp-app-drive-element-list' }); + var clickCls = clickable ? 'cp-app-drive-sort-clickable ' : ''; + var onClick = clickable ? onSortByClick : function () {}; //var $fohElement = $('', {'class': 'element'}).appendTo($folderHeader); var $fhIcon = $('', {'class': 'cp-app-drive-content-icon'}); var $name = $('', { - 'class': 'cp-app-drive-element-name cp-app-drive-sort-foldername ' + - 'cp-app-drive-sort-clickable' - }).text(Messages.fm_folderName).click(onSortByClick); + 'class': 'cp-app-drive-element-name cp-app-drive-sort-foldername ' + clickCls + }).text(Messages.fm_folderName).click(onClick); var $state = $('', {'class': 'cp-app-drive-element-state'}); - var $subfolders = $('', { - 'class': 'cp-app-drive-element-folders cp-app-drive-element-list' - }).text(Messages.fm_numberOfFolders); - var $files = $('', { - 'class': 'cp-app-drive-element-files cp-app-drive-element-list' - }).text(Messages.fm_numberOfFiles); + var $subfolders, $files; + if (!small) { + $subfolders = $('', { + 'class': 'cp-app-drive-element-folders cp-app-drive-element-list' + }).text(Messages.fm_numberOfFolders); + $files = $('', { + 'class': 'cp-app-drive-element-files cp-app-drive-element-list' + }).text(Messages.fm_numberOfFiles); + } var $filler = $('', { 'class': 'cp-app-drive-element-filler cp-app-drive-element-list' }); $fohElement.append($fhIcon).append($name).append($state) .append($subfolders).append($files).append($filler); - addFolderSortIcon($fohElement); + if (clickable) { addFolderSortIcon($fohElement); } return $fohElement; }; var addFileSortIcon = function ($list) { @@ -2859,15 +2863,16 @@ define([ }); if (keys.length < 2) { return keys; } var mult = asc ? 1 : -1; - var getProp = function (el) { - if (folder && root[el] && manager.isSharedFolder(root[el])) { - var title = manager.getSharedFolderData(root[el]).title || el; + var getProp = function (_el) { + var el = useId ? _el : root[_el]; + var sfId = (el && el.root && el.key) ? el.root[el.key] : el; + if (folder && el && manager.isSharedFolder(sfId)) { + var title = manager.getSharedFolderData(sfId).title || el; return String(title).toLowerCase(); } else if (folder) { - return el.toLowerCase(); + return String((el && el.key) || el).toLowerCase(); } - var id = useId ? el : root[el]; - var data = manager.getFileData(id); + var data = manager.getFileData(el); if (!data) { return ''; } if (prop === 'type') { var hrefData = Hash.parsePadUrl(data.href || data.roHref); @@ -2876,15 +2881,19 @@ define([ if (prop === 'atime' || prop === 'ctime') { return typeof(data[prop]) === "number" ? data[prop] : new Date(data[prop]); } - return (manager.getTitle(id) || "").toLowerCase(); + return (manager.getTitle(el) || "").toLowerCase(); }; var props = {}; keys.forEach(function (k) { - props[k] = getProp(k); + var uid = k; + if (typeof(k) === "object") { + uid = k.uid = Util.uid(); + } + props[uid] = getProp(k); }); keys.sort(function(a, b) { - var _a = props[a]; - var _b = props[b]; + var _a = props[(a && a.uid) || a]; + var _b = props[(b && b.uid) || b]; if (_a < _b) { return mult * -1; } if (_b < _a) { return mult; } return 0; @@ -3233,9 +3242,10 @@ define([ $input.focus(); }); - getFileListHeader(false).appendTo($list); $list.closest('#cp-app-drive-content-folder').addClass('cp-app-drive-content-list'); var filesList = manager.search(value); + var sortable = {}; + var sortableFolders = []; filesList.forEach(function (r) { // if r.id === null, then it's a folder, not a file r.paths.forEach(function (path) { @@ -3244,33 +3254,56 @@ define([ var _path = path.slice(); var key = path.pop(); var root = manager.find(path); - var isFolder = manager.isFolder(root[key]); - var $element = createElement(path, key, root, isFolder); - $element.addClass('cp-app-drive-element-notrash cp-app-drive-search-result'); - $element.off('contextmenu'); - $element.contextmenu(openContextMenu('default')); - $element.data('context', 'default'); - if (isFolder) { - $element.find('.cp-app-drive-element-list').css({ - visibility: 'hidden' - }).text(''); - $element.find('.cp-app-drive-element-folders').css({ - visibility: '' - }).text(Messages.fm_folder); - } - - if (manager.isPathIn(_path, ['hrefArray'])) { - _path.pop(); - _path.push(r.data.title); + var obj = { + path: path, + _path: _path, + key: key, + root: root, + data: r.data + }; + if (manager.isFolder(root[key])) { + sortableFolders.push(obj); + return; } - var $path = $('', { - 'class': 'cp-app-drive-search-path' - }).appendTo($element.find('.cp-app-drive-element-name')); - createTitle($path, _path); - - $list.append($element); + sortable[root[key]] = obj; }); }); + var _folders = sortElements(true, [ROOT], sortableFolders, null, !getSortFolderDesc(), true); + var sortableKeys = Object.keys(sortable).map(Number); + var _files = sortElements(false, [ROOT], sortableKeys, APP.store[SORT_FILE_BY], !getSortFileDesc(), true); + + var addEl = function (obj, folder) { + var $element = createElement(obj.path, obj.key, obj.root, folder); + $element.addClass('cp-app-drive-element-notrash cp-app-drive-search-result'); + $element.off('contextmenu'); + $element.contextmenu(openContextMenu('default')); + $element.data('context', 'default'); + if (folder) { + $element.find('.cp-app-drive-element-list').css({ + visibility: 'hidden' + }).text(''); + } + if (manager.isPathIn(obj._path, ['hrefArray'])) { + obj._path.pop(); + obj._path.push(obj.data.title); + } + var $path = $('', { + 'class': 'cp-app-drive-search-path' + }).appendTo($element.find('.cp-app-drive-element-name')); + createTitle($path, obj._path); + + $list.append($element); + }; + if (_folders.length) { getFolderListHeader(true, true).appendTo($list); } + _folders.forEach(function (el) { + var obj = el; + addEl(obj, true); + }); + if (_files.length) { getFileListHeader(true).appendTo($list); } + _files.forEach(function (el) { + var obj = sortable[el]; + addEl(obj, false); + }); setTimeout(collapseDrivePath); }; @@ -3415,7 +3448,7 @@ define([ } var fId = APP.newSharedFolder; var data = folders[fId]; - var $folderHeader = getFolderListHeader(); + var $folderHeader = getFolderListHeader(true); var $fileHeader = getFileListHeader(true); var path = currentPath.slice(1); var root = Util.find(data, path); @@ -3593,7 +3626,7 @@ define([ } updateContextButton(); - var $folderHeader = getFolderListHeader(); + var $folderHeader = getFolderListHeader(true); var $fileHeader = getFileListHeader(true); if (isTemplate) { diff --git a/www/common/migrate-user-object.js b/www/common/migrate-user-object.js index b13aacb1c..000744cc9 100644 --- a/www/common/migrate-user-object.js +++ b/www/common/migrate-user-object.js @@ -478,6 +478,7 @@ define([ store: store, }; var myData = Messaging.createData(userObject); + if (!myData.curvePublic) { return void done(); } Mailbox.sendTo(ctx, 'SAFE_LINKS_DEFAULT', { user: myData, diff --git a/www/common/translations/messages.de.json b/www/common/translations/messages.de.json index 3ab3680ea..8992a1b0b 100644 --- a/www/common/translations/messages.de.json +++ b/www/common/translations/messages.de.json @@ -1394,5 +1394,6 @@ "support_cat_bug": "Fehlerbericht", "oo_refresh": "Neu laden", "support_category": "Wähle eine Kategorie", - "oo_refreshText": "Dieses Dokument wurde aktualisiert" + "oo_refreshText": "Dieses Dokument wurde aktualisiert", + "support_formCategoryError": "Fehler: Kategorie ist leer" } diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index d99fd8d18..ede0c1a5a 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1394,5 +1394,6 @@ "notification_folderSharedTeam": "{0} has shared a folder with the team {2}: {1}", "oo_refresh": "Refresh", "oo_refreshText": "This document has been updated", - "support_category": "Choose a category" + "support_category": "Choose a category", + "support_formCategoryError": "Error: category is empty" } diff --git a/www/common/userObject.js b/www/common/userObject.js index fbe28864a..23978cb65 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -640,6 +640,7 @@ define([ var res = []; // Search title var allFilesList = files[FILES_DATA]; + var allSFList = files[SHARED_FOLDERS]; var lValue = value.toLowerCase(); // parse the search string into tags @@ -661,13 +662,14 @@ define([ }); }; - getFiles([FILES_DATA]).forEach(function (id) { - var data = allFilesList[id]; + getFiles([FILES_DATA, SHARED_FOLDERS]).forEach(function (id) { + var data = allFilesList[id] || allSFList[id]; if (!data) { return; } if (Array.isArray(data.tags) && containsSearchedTag(data.tags)) { - res.push(id); - } else - if ((data.title && data.title.toLowerCase().indexOf(lValue) !== -1) || + return void res.push(id); + } + var title = data.title || data.lastTitle; + if ((title && title.toLowerCase().indexOf(lValue) !== -1) || (data.filename && data.filename.toLowerCase().indexOf(lValue) !== -1)) { res.push(id); } diff --git a/www/common/visible.js b/www/common/visible.js index f73fa49bc..61512ff59 100644 --- a/www/common/visible.js +++ b/www/common/visible.js @@ -25,10 +25,12 @@ typeof document[hidden] === "undefined"); }; - Visible.onChange = function (f) { + Visible.onChange = function (f, once) { document.addEventListener(visibilityChange, function (ev) { f(!document[hidden], ev); - }, false); + }, { + once: once + }); }; Visible.currently = function () { diff --git a/www/kanban/jkanban_cp.js b/www/kanban/jkanban_cp.js index 54fb71f46..1604a1315 100644 --- a/www/kanban/jkanban_cp.js +++ b/www/kanban/jkanban_cp.js @@ -1,8 +1,9 @@ define([ 'jquery', '/customize/messages.js', + '/common/visible.js', '/bower_components/dragula.js/dist/dragula.min.js', -], function ($, Messages, Dragula) { +], function ($, Messages, Visible, Dragula) { /** * jKanban * Vanilla Javascript plugin for manage kanban boards @@ -739,6 +740,8 @@ define([ return self; }; + var todoOnVisible = function () {}; + var onVisibleHandler = false; this.setBoards = function (boards) { var scroll = {}; // Fix the tags @@ -754,15 +757,30 @@ define([ this.removeBoard(boardkey); } this.options.boards = boards; - // Add all new boards - this.addBoards(); - self.options.refresh(); - // Preserve scroll - this.options.boards.list.forEach(function (id) { - if (!scroll[id]) { return; } - $('.kanban-board[data-id="'+id+'"] .kanban-drag').scrollTop(scroll[id]); - }); - $el.scrollLeft(scrollLeft); + + todoOnVisible = function () { + // Add all new boards + self.addBoards(); + self.options.refresh(); + // Preserve scroll + self.options.boards.list.forEach(function (id) { + if (!scroll[id]) { return; } + $('.kanban-board[data-id="'+id+'"] .kanban-drag').scrollTop(scroll[id]); + }); + $el.scrollLeft(scrollLeft); + }; + + // If the tab is not focused, redraw on focus + if (!Visible.currently()) { + if (onVisibleHandler) { return; } + onVisibleHandler = true; + return void Visible.onChange(function (visible) { + if (!visible) { return; } + todoOnVisible(); + onVisibleHandler = false; + }, true); + } + todoOnVisible(); }; this.findBoard = function (id) { diff --git a/www/pad/app-pad.less b/www/pad/app-pad.less index 103241a52..e3de1fcf0 100644 --- a/www/pad/app-pad.less +++ b/www/pad/app-pad.less @@ -36,6 +36,9 @@ body.cp-app-pad { align-items: center; padding: 4px; } + .cke_button__print { + display: none !important; + } } .cke_wysiwyg_frame { width: 100%; diff --git a/www/pad/inner.js b/www/pad/inner.js index 05cf2c788..f189d7447 100644 --- a/www/pad/inner.js +++ b/www/pad/inner.js @@ -456,6 +456,15 @@ define([ }); }; + var mkPrintButton = function (framework, editor) { + var $printButton = framework._.sfCommon.createButton('print', true); + $printButton.click(function () { + editor.execCommand('print'); + framework.feedback('PRINT_PAD'); + }); + framework._.toolbar.$drawer.append($printButton); + }; + var andThen2 = function(editor, Ckeditor, framework) { var mediaTagMap = {}; var $contentContainer = $('#cke_1_contents'); @@ -480,6 +489,8 @@ define([ framework._.sfCommon.addShortcuts(ifrWindow); + mkPrintButton(framework, editor, Ckeditor); + var documentBody = ifrWindow.document.body; var inner = window.inner = documentBody; var $inner = $(inner); diff --git a/www/settings/inner.js b/www/settings/inner.js index 3fc87d175..234402ab5 100644 --- a/www/settings/inner.js +++ b/www/settings/inner.js @@ -488,6 +488,7 @@ define([ UI.removeLoadingScreen(); if (obj && obj.error) { // TODO + // XXX EEXISTS error message? UI.alert(Messages.settings_changePasswordError); } });