diff --git a/customize.dist/src/less2/include/colortheme.less b/customize.dist/src/less2/include/colortheme.less index 8a323be6c..8aa99e403 100644 --- a/customize.dist/src/less2/include/colortheme.less +++ b/customize.dist/src/less2/include/colortheme.less @@ -26,6 +26,8 @@ @colortheme_form-warning: #f49842; @colortheme_form-warning-hov: darken(@colortheme_form-warning, 5%); +@colortheme_context-menu-icon-color: #7b7b7b; + @colortheme_modal-bg: @colortheme_form-bg-alt; // TODO Modals bg @colortheme_modal-fg: @colortheme_form-color-alt; @colortheme_modal-link: @colortheme_link-color; diff --git a/customize.dist/src/less2/include/contextmenu.less b/customize.dist/src/less2/include/contextmenu.less index 1a9049b54..2063a239e 100644 --- a/customize.dist/src/less2/include/contextmenu.less +++ b/customize.dist/src/less2/include/contextmenu.less @@ -13,7 +13,17 @@ font-size: @colortheme_app-font-size; a { cursor: pointer; + .fa, .cptools { + margin-right: 1rem; + color: @colortheme_context-menu-icon-color; + } } } + .cp-app-drive-context-noAction { + font-style: italic; + color: #aaa; + cursor: default; + display: none; + } } } diff --git a/www/common/translations/messages.de.json b/www/common/translations/messages.de.json index 6125abf5c..a24c1a9f7 100644 --- a/www/common/translations/messages.de.json +++ b/www/common/translations/messages.de.json @@ -1075,5 +1075,33 @@ "share_description": "Wähle aus, was du teilen möchtest. Dir wird dann ein entsprechender Link anzeigt. Du kannst es auch direkt an deine Freunde in CryptPad senden.", "fc_expandAll": "Alle ausklappen", "fc_collapseAll": "Alle einklappen", - "fc_color": "Farbe ändern" + "fc_color": "Farbe ändern", + "supportPage": "", + "admin_cat_support": "", + "admin_supportInitHelp": "", + "admin_supportInitPrivate": "", + "admin_supportAddKey": "", + "admin_supportAddError": "", + "admin_supportInitTitle": "", + "admin_supportInitHint": "", + "admin_supportListTitle": "", + "admin_supportListHint": "", + "support_disabledTitle": "", + "support_disabledHint": "", + "support_cat_new": "", + "support_formTitle": "", + "support_formHint": "", + "support_formButton": "", + "support_formTitleError": "", + "support_formContentError": "", + "support_formMessage": "", + "support_cat_tickets": "", + "support_listTitle": "", + "support_listHint": "", + "support_answer": "", + "support_close": "", + "support_remove": "", + "support_showData": "", + "support_from": "", + "support_closed": "" } diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json index a5bd0f946..f9ef1f7e8 100644 --- a/www/common/translations/messages.fr.json +++ b/www/common/translations/messages.fr.json @@ -1056,7 +1056,7 @@ "friendRequest_accepted": "{0} a accepté votre demande d'ami", "friendRequest_received": "{0} souhaite être votre ami", "friendRequest_notification": "{0} vous a envoyé une demande d'ami", - "notifications_empty": "Vous n'avez pas de nouvelle notification", + "notifications_empty": "Pas de nouvelle notification", "notifications_title": "Vous avez des notifications non lues", "profile_addDescription": "Ajouter une description", "profile_editDescription": "Modifier votre description", @@ -1075,5 +1075,35 @@ "notifications_dismiss": "Cacher", "fm_info_sharedFolderHistory": "Vous regardez l'historique de votre dossier partagé {0}
Votre CryptDrive restera en lecture seule pendant la navigation.", "share_description": "Choisissez ce que vous souhaitez partager puis obtenez le lien ou envoyez-le directement à vos amis CryptPad.", - "fc_color": "Changer la couleur" + "fc_color": "Changer la couleur", + "supportPage": "Support", + "admin_cat_support": "Support", + "admin_supportAddKey": "Ajouter la clé", + "admin_supportAddError": "Clé privée non valide", + "admin_supportInitTitle": "Initialisation du support", + "admin_supportListTitle": "Messagerie du support", + "support_disabledTitle": "Le support n'est pas activé", + "support_disabledHint": "Cette instance de CryptPad n'est pas encore configurée pour utiliser le formulaire de support.", + "support_cat_new": "Nouveau ticket", + "support_formTitle": "Titre du ticket", + "support_formButton": "Envoyer", + "support_formTitleError": "Erreur : le titre est vide", + "support_formContentError": "Erreur : le contenu est vide", + "support_formMessage": "Taper votre message...", + "support_cat_tickets": "Tickets existants", + "support_listTitle": "Tickets de support", + "support_answer": "Répondre", + "support_close": "Fermer le ticket", + "support_remove": "Supprimer le ticket", + "support_showData": "Afficher/cacher les données de l'utilisateur", + "support_from": "De : {0}", + "support_closed": "Ce ticket a été fermé", + "fc_noAction": "Pas d'action disponible", + "notificationsPage": "Notifications", + "openNotificationsApp": "Ouvrir le panneau de notifications", + "notifications_cat_all": "Toutes", + "notifications_cat_friends": "Demandes d'ami", + "notifications_cat_pads": "Partagé avec moi", + "notifications_cat_archived": "Historique", + "notifications_dismissAll": "Tout cacher" } diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json index e0885452f..ca1783b25 100644 --- a/www/common/translations/messages.json +++ b/www/common/translations/messages.json @@ -1057,7 +1057,7 @@ "friendRequest_accepted": "{0} accepted your friend request", "friendRequest_received": "{0} would like to be your friend", "friendRequest_notification": "{0} sent you a friend request", - "notifications_empty": "You have no new notifications", + "notifications_empty": "No notifications available", "notifications_title": "You have unread notifications", "profile_addDescription": "Add a description", "profile_editDescription": "Edit your description", @@ -1103,5 +1103,13 @@ "support_remove": "Remove the ticket", "support_showData": "Show/hide user data", "support_from": "From: {0}", - "support_closed": "This ticket has been closed" + "support_closed": "This ticket has been closed", + "fc_noAction": "No action available", + "notificationsPage": "Notifications", + "openNotificationsApp": "Open notifications panel", + "notifications_cat_all": "All", + "notifications_cat_friends": "Friend requests", + "notifications_cat_pads": "Shared with me", + "notifications_cat_archived": "History", + "notifications_dismissAll": "Dismiss all" } diff --git a/www/common/userObject.js b/www/common/userObject.js index f39e80aee..39b55484a 100644 --- a/www/common/userObject.js +++ b/www/common/userObject.js @@ -514,6 +514,31 @@ define([ data: exp.getFileData(l) }); }); + + // find folders + var resFolders = []; + var findFoldersRec = function (folder, path) { + for (var key in folder) { + if (isFolder(folder[key]) && !isSharedFolder(folder[key])) { + if (key.toLowerCase().indexOf(lValue) !== -1) { + resFolders.push({ + id: null, + paths: [path.concat(key)], + data: { + title: key + } + }); + } + findFoldersRec(folder[key], path.concat(key)); + } + } + }; + findFoldersRec(files[ROOT], [ROOT]); + resFolders = resFolders.sort(function (a, b) { + return a.data.title.toLowerCase() > b.data.title.toLowerCase(); + }); + ret = resFolders.concat(ret); + return ret; }; exp.getRecentPads = function () { diff --git a/www/drive/app-drive.less b/www/drive/app-drive.less index ba59e9124..c85cd3c88 100644 --- a/www/drive/app-drive.less +++ b/www/drive/app-drive.less @@ -513,12 +513,18 @@ } .cp-app-drive-search-path { font-style: italic; - display: flex; - flex-flow: row-reverse; - justify-content: right; - .cp-app-drive-path-element { - display: inline-block; - margin-right: 5px; + .cp-app-drive-path-inner { + display: flex; + flex-flow: row-reverse wrap-reverse; + justify-content: flex-end; + .cp-app-drive-path-element { + flex-shrink: 0; + display: inline-block; + margin-right: 5px; + white-space: normal; + word-wrap: break-word; + max-width: 100%; + } } } .cp-app-drive-search-title { diff --git a/www/drive/inner.js b/www/drive/inner.js index c2c0332a4..8c35e2300 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -124,6 +124,7 @@ define([ var $tagsIcon = $('', {"class": "fa " + faTags}); var $passwordIcon = $('', {"class": "fa fa-lock"}); var $expirableIcon = $('', {"class": "fa fa-clock-o"}); + var $separator = $('
', {"class": "dropdown-divider"}); var LS_LAST = "app-drive-lastOpened"; var LS_OPENED = "app-drive-openedFolders"; @@ -303,6 +304,7 @@ define([ 'aria-labelledby': 'dropdownMenu', 'style': 'display:block;position:static;margin-bottom:5px;' }, [ + h('span.cp-app-drive-context-noAction.dropdown-item.disabled', Messages.fc_noAction || "No action possible"), h('li', h('a.cp-app-drive-context-open.dropdown-item', { 'tabindex': '-1', 'data-icon': faFolderOpen, @@ -311,6 +313,7 @@ define([ 'tabindex': '-1', 'data-icon': faReadOnly, }, Messages.fc_open_ro)), + $separator.clone()[0], h('li', h('a.cp-app-drive-context-expandall.dropdown-item', { 'tabindex': '-1', 'data-icon': "expandAll", @@ -319,6 +322,7 @@ define([ 'tabindex': '-1', 'data-icon': "collapseAll", }, Messages.fc_collapseAll)), + $separator.clone()[0], h('li', h('a.cp-app-drive-context-color.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': faColor, @@ -347,6 +351,7 @@ define([ 'tabindex': '-1', 'data-icon': faTags, }, Messages.fc_hashtag)), + $separator.clone()[0], h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': AppConfig.applicationsIcon.pad, @@ -372,6 +377,7 @@ define([ 'data-icon': AppConfig.applicationsIcon.whiteboard, 'data-type': 'whiteboard' }, Messages.button_newwhiteboard)), + $separator.clone()[0], h('li', h('a.cp-app-drive-context-empty.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': faEmpty, @@ -380,6 +386,7 @@ define([ 'tabindex': '-1', 'data-icon': faRestore, }, Messages.fc_restore)), + $separator.clone()[0], h('li', h('a.cp-app-drive-context-rename.dropdown-item.cp-app-drive-context-editable', { 'tabindex': '-1', 'data-icon': faRename, @@ -406,6 +413,16 @@ define([ }, Messages.fc_prop)), ]) ]); + $(menu).find("li a.dropdown-item").each(function (i, el) { + var $icon = $(""); + if ($(el).attr('data-icon')) { + var font = $(el).attr('data-icon').indexOf('cptools') === 0 ? 'cptools' : 'fa'; + $icon.addClass(font).addClass($(el).attr('data-icon')); + } else { + $icon.text($(el).text()); + } + $(el).prepend($icon); + }); return $(menu); }; @@ -1053,8 +1070,7 @@ define([ show = ['newfolder', 'newsharedfolder', 'newdoc']; break; case 'tree': - show = ['open', 'openro', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', - 'newfolder', 'properties', 'hashtag']; + show = ['open', 'openro', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', 'properties', 'hashtag']; break; case 'default': show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'hashtag']; @@ -1238,6 +1254,20 @@ define([ var displayMenu = function (e) { var $menu = $contextMenu; + var showSep = false; + var $lastVisibleSep = null; + $menu.find(".dropdown-menu").children().each(function (i, el) { + var $el = $(el); + if ($el.is(".dropdown-divider")) { + $el.css("display", showSep ? "list-item" : "none"); + if (showSep) { $lastVisibleSep = $el; } + showSep = false; + } + else if ($el.is("li") && $el.css("display") !== "none") { + showSep = true; + } + }); + if (!showSep && $lastVisibleSep) { $lastVisibleSep.css("display", "none"); } // remove last divider if no options after $menu.css({ display: "block" }); if (APP.mobile()) { return; } var h = $menu.outerHeight(); @@ -1313,11 +1343,7 @@ define([ displayMenu(e); - if ($contextMenu.find('li:visible').length === 0) { - debug("No visible element in the context menu. Abort."); - $contextMenu.hide(); - return true; - } + $(".cp-app-drive-context-noAction").toggle($contextMenu.find('li:visible').length === 0); $contextMenu.data('paths', paths); return false; @@ -1345,6 +1371,7 @@ define([ }); cb(); }; + if (paths.some(function (p) { return manager.comparePath(newPath, p); })) { return void cb(); } manager.move(paths, newPath, newCb, copy); }; // Delete paths from the drive and/or shared folders (without moving them to the trash) @@ -2601,32 +2628,17 @@ define([ var displaySearch = function ($list, value) { var filesList = manager.search(value); filesList.forEach(function (r) { + // if r.id === null, then it's a folder, not a file r.paths.forEach(function (path) { if (!r.inSharedFolder && APP.hideDuplicateOwned && manager.isDuplicateOwned(path)) { return; } var href = r.data.href; var parsed = Hash.parsePadUrl(href); var $table = $(''); - var $icon = $('').append($icon).append($title).append($typeName).append($type).appendTo($table); @@ -3199,7 +3234,7 @@ define([ placeholder: Messages.fm_searchPlaceholder }).keyup(function (e) { if (search.to) { window.clearTimeout(search.to); } - if ([38, 39, 40, 41].indexOf(e.which) !== -1) { + if ([37, 38, 39, 40].indexOf(e.which) !== -1) { if (!$input.val()) { $input.blur(); $content.focus(); @@ -3647,6 +3682,14 @@ define([ APP.hideMenu(); }); + $content.on("keydown", function (e) { + if (e.which === 113) { + var paths = $contextMenu.data('paths'); + if (paths.length !== 1) { return; } + displayRenameInput(paths[0].element, paths[0].path); + } + }); + // Chrome considers the double-click means "select all" in the window $content.on('mousedown', function (e) { $content.focus();
', {'rowspan': '3', 'class': 'cp-app-drive-search-icon'}) - .append(getFileIcon(r.id)); + var $icon = $('', {'rowspan': '3', 'class': 'cp-app-drive-search-icon'}); var $title = $('', { 'class': 'cp-app-drive-search-col1 cp-app-drive-search-title' - }).text(r.data.title) - .click(function () { - openFile(null, r.data.href); - }); - var $typeName = $('', {'class': 'cp-app-drive-search-label2'}) - .text(Messages.fm_type); - var $type = $('', {'class': 'cp-app-drive-search-col2'}) - .text(Messages.type[parsed.type] || parsed.type); - var $atimeName = $('', {'class': 'cp-app-drive-search-label2'}) - .text(Messages.fm_lastAccess); - var $atime = $('', {'class': 'cp-app-drive-search-col2'}) - .text(new Date(r.data.atime).toLocaleString()); - var $ctimeName = $('', {'class': 'cp-app-drive-search-label2'}) - .text(Messages.fm_creation); - var $ctime = $('', {'class': 'cp-app-drive-search-col2'}) - .text(new Date(r.data.ctime).toLocaleString()); + }).text(r.data.title); if (manager.isPathIn(path, ['hrefArray'])) { path.pop(); path.push(r.data.title); @@ -2635,25 +2647,48 @@ define([ 'class': 'cp-app-drive-search-col1 cp-app-drive-search-path' }); createTitle($path, path, true); - var parentPath = path.slice(); - var $a; - if (parentPath) { - $a = $('').text(Messages.fm_openParent).click(function (e) { - e.preventDefault(); - if (manager.isInTrashRoot(parentPath)) { parentPath = [TRASH]; } - else { parentPath.pop(); } - APP.selectedFiles = [r.id]; - APP.displayDirectory(parentPath); + var $typeName = $('', {'class': 'cp-app-drive-search-label2'}).text(Messages.fm_type); + var $type = $('', {'class': 'cp-app-drive-search-col2'}); + var $atimeName = $('', {'class': 'cp-app-drive-search-label2'}); + var $atime = $('', {'class': 'cp-app-drive-search-col2'}); + var $ctimeName = $('', {'class': 'cp-app-drive-search-label2'}); + var $ctime = $('', {'class': 'cp-app-drive-search-col2'}); + var $openDir = $('', {'class': 'cp-app-drive-search-opendir'}); + if (r.id) { + $icon.append(getFileIcon(r.id)); + $type.text(Messages.type[parsed.type] || parsed.type); + $title.click(function () { + openFile(null, r.data.href); }); + $atimeName.text(Messages.fm_lastAccess); + $atime.text(new Date(r.data.atime).toLocaleString()); + $ctimeName.text(Messages.fm_creation); + $ctime.text(new Date(r.data.ctime).toLocaleString()); + var parentPath = path.slice(); + if (parentPath) { + $('').text(Messages.fm_openParent).click(function (e) { + e.preventDefault(); + if (manager.isInTrashRoot(parentPath)) { parentPath = [TRASH]; } + else { parentPath.pop(); } + APP.selectedFiles = [r.id]; + APP.displayDirectory(parentPath); + }).appendTo($openDir); + } + $('').text(Messages.fc_prop).click(function () { + APP.getProperties(r.id, function (e, $prop) { + if (e) { return void logError(e); } + UI.alert($prop[0], undefined, true); + }); + }).appendTo($openDir); + } + else { + $icon.append($folderIcon.clone()); + $type.text(Messages.fm_folder); + $('').text(Messages.fc_open).click(function (e) { + e.preventDefault(); + APP.displayDirectory(path); + }).appendTo($openDir); } - var $openDir = $('', {'class': 'cp-app-drive-search-opendir'}).append($a); - - $('').text(Messages.fc_prop).click(function () { - APP.getProperties(r.id, function (e, $prop) { - if (e) { return void logError(e); } - UI.alert($prop[0], undefined, true); - }); - }).appendTo($openDir); // rows 1-3 $('