diff --git a/customize.dist/messages.js b/customize.dist/messages.js index b322ac044..e4cce8381 100755 --- a/customize.dist/messages.js +++ b/customize.dist/messages.js @@ -26,7 +26,7 @@ var map = { //'sv': 'Svenska', //'te': 'తెలుగు', 'uk': 'Українська', - 'zh': '繁體中文', + 'zh': '中文(簡體)', }; var messages = {}; diff --git a/customize.dist/pages/login.js b/customize.dist/pages/login.js index d3fb04aa8..889bc6b09 100644 --- a/customize.dist/pages/login.js +++ b/customize.dist/pages/login.js @@ -39,6 +39,7 @@ define([ type: 'password', 'name': 'password', placeholder: Msg.login_password, + autocomplete: "current-password" }), ]), ]), diff --git a/customize.dist/pages/register.js b/customize.dist/pages/register.js index df9dd4cd1..3787a01c3 100644 --- a/customize.dist/pages/register.js +++ b/customize.dist/pages/register.js @@ -79,6 +79,7 @@ define([ h('input.form-control#password', { type: 'password', placeholder: Msg.login_password, + autocomplete: "new-password" }), ]), h('div.input-container', [ @@ -86,6 +87,7 @@ define([ h('input.form-control#password-confirm', { type: 'password', placeholder: Msg.login_confirm, + autocomplete: "new-password" }), ]), ]), diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less index 0280d62e2..f01e69a37 100644 --- a/customize.dist/src/less2/include/alertify.less +++ b/customize.dist/src/less2/include/alertify.less @@ -497,7 +497,7 @@ overflow-x: auto; } } - // XXX this might not be the best place for this. + // this might not be the best place for this. // I just put it next to other "share" styles // --Aaron #cp-qr-container { diff --git a/customize.dist/src/less2/include/drive.less b/customize.dist/src/less2/include/drive.less index eb92cb79d..c70b37ee9 100644 --- a/customize.dist/src/less2/include/drive.less +++ b/customize.dist/src/less2/include/drive.less @@ -1,9 +1,3 @@ -/* - * SPDX-FileCopyrightText: 2023 XWiki CryptPad Team and contributors - * - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - @import (reference) "./browser.less"; @import (reference) './leftside-menu.less'; @import (reference) "./tools.less"; @@ -484,6 +478,7 @@ flex-flow: column; flex: 1; min-width: 0; + min-height: 100%; position: relative; .cp-splitter { position: absolute; @@ -655,15 +650,20 @@ font-size: 14px; height: auto; } - .cp-app-drive-element-state { + .cp-app-drive-element-state, .cp-app-drive-element-menu { position: absolute; top: 3px; - right: 3px; .fa, .cptools { margin: 0; font-size: 18px; } } + .cp-app-drive-element-state { + left: 3px; + } + .cp-app-drive-element-menu { + right: 3px; + } .cp-app-drive-element-thumbnail { max-width: 100px; max-height: 100px; diff --git a/customize.dist/src/less2/include/markdown.less b/customize.dist/src/less2/include/markdown.less index 33ea1ee78..16e6654ed 100644 --- a/customize.dist/src/less2/include/markdown.less +++ b/customize.dist/src/less2/include/markdown.less @@ -132,7 +132,7 @@ text { &.taskText { &[class*="doneText"], &[class*="activeText"] { - fill: #444 !important; // XXX PR to mermaid or find a suitable variable + fill: #444 !important; // TODO PR to mermaid or find a suitable variable } } &.titleText { diff --git a/customize.dist/src/less2/include/toolbar-history.less b/customize.dist/src/less2/include/toolbar-history.less index 2acd36731..d2c854034 100644 --- a/customize.dist/src/less2/include/toolbar-history.less +++ b/customize.dist/src/less2/include/toolbar-history.less @@ -106,7 +106,6 @@ margin-right: 5px; } &:hover { - // XXX DB: check hover in light/dark themes background-color: fade(@cp_toolbar-fg, 30%); } &:disabled { diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index dd412963e..73fc6fad9 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -21,7 +21,6 @@ @bg-color: @colortheme_apps[default], // color of the toolbar background ) { @toolbar-bg-color: @bg-color; - // XXX: check contrasts of app colors used as btn background @toolbar-bg-color-light: lighten(@bg-color, 30%); @toolbar-bg-color-fade: fade(@toolbar-bg-color-light, 60%); }; diff --git a/lib/challenge-commands/totp.js b/lib/challenge-commands/totp.js index 0ad8d15ef..769643c61 100644 --- a/lib/challenge-commands/totp.js +++ b/lib/challenge-commands/totp.js @@ -61,7 +61,7 @@ var decode32 = S => { }; -// XXX Decide expire time +// Decide expire time // Allow user settings? var EXPIRATION = 7 * 24 * 3600 * 1000; // Sessions are valid 7 days diff --git a/lib/hk-util.js b/lib/hk-util.js index 19b207975..b92d846bf 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -596,7 +596,8 @@ const handleFirstMessage = function (Env, channelName, metadata) { }); // write tasks - if(metadata.expire && typeof(metadata.expire) === 'number') { + var maxExpire = new Date().setMonth(new Date().getMonth() + 100); // UI limit + if(metadata.expire && typeof(metadata.expire) === 'number' && metadata.expire < maxExpire) { // the fun part... // the user has said they want this pad to expire at some point Env.writeTask(metadata.expire, "EXPIRE", [ channelName ], function (err) { diff --git a/lib/storage/file.js b/lib/storage/file.js index 8a5a8fd62..e22c3be85 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -804,7 +804,7 @@ var unarchiveChannel = function (env, channelName, cb) { } if (exists) { w.abort(); - return CB("UNARCHIVE_METADATA_CONFLICT"); // XXX + return CB("UNARCHIVE_METADATA_CONFLICT"); } })); }).nThen(function (w) { diff --git a/www/admin/app-admin.less b/www/admin/app-admin.less index 28efad7e7..f674160ca 100644 --- a/www/admin/app-admin.less +++ b/www/admin/app-admin.less @@ -354,14 +354,14 @@ table.cp-block-stats, table.cp-pin-list, table.cp-document-stats { - @color: #777; // XXX + @color: #777; // TODO use a colotheme variable border: 1px solid @color; margin: 15px; td, pre { color: @cryptpad_text_col; } td, th { - max-width: 60vw; // XXX + max-width: 60vw; border: 1px solid @color; padding: 5px; .scroll { diff --git a/www/admin/inner.js b/www/admin/inner.js index e71dedb00..0e8cf8c4c 100644 --- a/www/admin/inner.js +++ b/www/admin/inner.js @@ -3511,6 +3511,7 @@ Example sFrameChan = common.getSframeChannel(); sFrameChan.onReady(waitFor()); }).nThen(function (waitFor) { + if (!common.isAdmin()) { return; } updateStatus(waitFor()); }).nThen(function (/*waitFor*/) { createToolbar(); diff --git a/www/calendar/app-calendar.less b/www/calendar/app-calendar.less index 232f3467d..85fc68991 100644 --- a/www/calendar/app-calendar.less +++ b/www/calendar/app-calendar.less @@ -534,7 +534,7 @@ color: @cp_toolbar-fg; border-color: @cp_toolbar-fg; &:hover { - background-color: fade(@cp_toolbar-fg, 50%); //XXX check light theme + background-color: fade(@cp_toolbar-fg, 50%); cursor: pointer; } } diff --git a/www/common/clipboard.js b/www/common/clipboard.js index c221f09d5..00d875041 100644 --- a/www/common/clipboard.js +++ b/www/common/clipboard.js @@ -47,8 +47,8 @@ define(['jquery'], function ($) { navigator.clipboard.writeText(text).then(() => { cb(); }).catch((err) => { - console.warn(err); - cb(err); + var success = oldCopy(text, true); + cb(!success && err); }); }; diff --git a/www/common/common-interface.js b/www/common/common-interface.js index bdfc3141e..19e94d5a7 100644 --- a/www/common/common-interface.js +++ b/www/common/common-interface.js @@ -875,8 +875,8 @@ define([ opts = opts || {}; var attributes = merge({ type: 'password', - autocomplete: 'new-password', // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values tabindex: '1', + autocomplete: 'one-time-code', // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete#values }, opts); var input = h('input.cp-password-input', attributes); @@ -1046,9 +1046,9 @@ define([ window.parent.location = href; }); if (exitable) { - // XXX if true or function, ALSO add a button to leave + // if true or function, ALSO add a button to leave $(window).focus(); - $(window).keydown(function (e) { // XXX what if they don't have a keyboard? + $(window).keydown(function (e) { // what if they don't have a keyboard? if (e.which === 27) { e.preventDefault(); e.stopPropagation(); diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 6c92a2d76..7b2798d46 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2658,7 +2658,7 @@ define([ UI.createCheckbox('cp-creation-expire', Messages.creation_expiration, false, { labelAlt: Messages.creation_expiresIn }), - h('span.cp-creation-expire-picker.cp-creation-slider', [ + h('form.cp-creation-expire-picker.cp-creation-slider', { autocomplete: "off" }, [ h('input#cp-creation-expire-val', { type: "number", min: 1, @@ -2920,7 +2920,7 @@ define([ case "month": unit = 3600 * 24 * 30; break; default: unit = 0; } - expireVal = ($('#cp-creation-expire-val').val() || 0) * unit; + expireVal = (Math.min(Number($('#cp-creation-expire-val').val()), 100) || 0) * unit; } // Password var passwordVal = $('#cp-creation-password').is(':checked') ? @@ -3009,7 +3009,7 @@ define([ if (err.type === 'EEXPIRED') { msg = Messages.expiredError; if (err.loaded) { - // XXX You can still use the current version in read-only mode by pressing Esc. + // You can still use the current version in read-only mode by pressing Esc. // what if they don't have a keyboard (ie. mobile) msg += Messages.errorCopy; } @@ -3033,7 +3033,7 @@ define([ }); } if (err.message && (err.message !== "PASSWORD_CHANGE" || viewer)) { - // XXX If readonly, tell the viewer that their link won't work with the new password + // If readonly, tell the viewer that their link won't work with the new password UI.errorLoadingScreen(UI.getDestroyedPlaceholder(err.message, false), exitable, exitable); return; diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 94d582cfb..001c09a89 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -111,6 +111,7 @@ define([ var $folderIcon = $('', { "class": faFolder + " cptools cp-app-drive-icon-folder cp-app-drive-content-icon" }); + var $fileMenuIcon = $('', {"class": "fa fa-ellipsis-h"}); //var $folderIcon = $('', {src: "/customize/images/icons/folder.svg", "class": "folder icon"}); var $folderEmptyIcon = $folderIcon.clone(); var $folderOpenedIcon = $('', {"class": faFolderOpen + " cptools cp-app-drive-icon-folder"}); @@ -386,6 +387,10 @@ define([ 'tabindex': '-1', 'data-icon': faFolderOpen, }, Messages.fc_open)), + h('li', h('a.cp-app-drive-context-openfolder.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faFolderOpen, + }, Messages.fc_open)), h('li', h('a.cp-app-drive-context-openro.dropdown-item', { 'tabindex': '-1', 'data-icon': faReadOnly, @@ -732,9 +737,6 @@ define([ var removeSelected = function (keepObj) { APP.selectedFiles = []; findSelectedElements().removeClass("cp-app-drive-element-selected"); - var $container = $driveToolbar.find('#cp-app-drive-toolbar-contextbuttons'); - if (!$container.length) { return; } - $container.html(''); if (!keepObj) { delete sel.startSelected; delete sel.endSelected; @@ -1038,6 +1040,11 @@ define([ if ([37, 38, 39, 40].indexOf(e.which) === -1) { return; } e.preventDefault(); + // If the arrow keys aren't caught by another listener before, it means we can + // use them to select content in the drive. If that's the case, we'll also + // focus the drive container to avoid conflicts with other focused elements + $content.focus(); + var click = function (el) { if (!el) { return; } APP.onElementClick(ev, $(el)); @@ -1334,6 +1341,9 @@ define([ hide.push('savelocal'); hide.push('color'); } + if ($element.is('.cp-app-drive-element-folder')) { + hide.push('open'); + } if (!$element.is('.cp-app-drive-element-owned')) { hide.push('deleteowned'); } @@ -1354,6 +1364,7 @@ define([ } if ($element.is('.cp-app-drive-element-file')) { // No folder in files + hide.push('openfolder'); hide.push('color'); hide.push('newfolder'); if ($element.is('.cp-app-drive-element-readonly')) { @@ -1480,7 +1491,7 @@ define([ show = ['newfolder', 'newsharedfolder', 'uploadfiles', 'uploadfolder', 'newdoc']; break; case 'tree': - show = ['open', 'openro', 'preview', 'openincode', 'expandall', 'collapseall', + show = ['open', 'openfolder', 'openro', 'preview', 'openincode', 'expandall', 'collapseall', 'color', 'download', 'share', 'savelocal', 'rename', 'delete', 'makeacopy', 'openinsheet', 'openindoc', 'openinpresentation', 'deleteowned', 'removesf', 'access', 'properties', 'hashtag']; @@ -1509,66 +1520,6 @@ define([ return filtered; }; - var updateContextButton = function () { - if (manager.isPathIn(currentPath, [TRASH])) { - $driveToolbar.find('cp-app-drive-toolbar-emptytrash').show(); - } else { - $driveToolbar.find('cp-app-drive-toolbar-emptytrash').hide(); - } - var $li = findSelectedElements(); - if ($li.length === 0) { - $li = findDataHolder($tree.find('.cp-app-drive-element-active')); - } - var $button = $driveToolbar.find('#cp-app-drive-toolbar-context-mobile'); - $button.attr('aria-label', Messages.context_menu); - if ($button.length) { // mobile - if ($li.length !== 1 - || !$._data($li[0], 'events').contextmenu - || $._data($li[0], 'events').contextmenu.length === 0) { - $button.hide(); - return; - } - $button.show(); - $button.css({ - background: '#63b1f7' - }); - window.setTimeout(function () { - $button.css({ - background: '' - }); - }, 500); - return; - } - // Non mobile - /* - var $container = $driveToolbar.find('#cp-app-drive-toolbar-contextbuttons'); - if (!$container.length) { return; } - $container.html(''); - var $element = $li.length === 1 ? $li : $($li[0]); - var paths = getSelectedPaths($element); - var menuType = $element.data('context'); - if (!menuType) { return; } - //var actions = []; - var toShow = filterContextMenu(menuType, paths); - var $actions = $contextMenu.find('a'); - $contextMenu.data('paths', paths); - $actions = $actions.filter(function (i, el) { - return toShow.some(function (className) { return $(el).is(className); }); - }); - $actions.each(function (i, el) { - var $a = $('