diff --git a/customize.dist/src/less2/include/drive.less b/customize.dist/src/less2/include/drive.less index 4a8b53006..20aaff649 100644 --- a/customize.dist/src/less2/include/drive.less +++ b/customize.dist/src/less2/include/drive.less @@ -3,6 +3,7 @@ @import (reference) "./tools.less"; @import (reference) "./limit-bar.less"; @import (reference) "./tokenfield.less"; +@import (reference) "./dropdown.less"; .drive_main() { --LessLoader_require: LessLoader_currentFile(); @@ -102,12 +103,13 @@ .cp-app-drive-container { flex: 1; - overflow-x: auto; width: 100%; display: flex; flex-flow: row; + min-height: 0; @media screen and (max-width: @browser_media-medium-screen) { display: block; + overflow-y: auto; #cp-app-drive-toolbar { .path .element { display: none; @@ -159,7 +161,6 @@ .cp-app-drive-element-selected { background: @drive_selected-bg !important; color: #eee; - margin: -1px; .fa-minus-square-o, .fa-plus-square-o { color: @colortheme_sidebar-left-fg; } @@ -169,7 +170,6 @@ border: 1px dotted #bbb; background: #AAA; color: #ddd; - margin: -1px; .fa-minus-square-o, .fa-plus-square-o { color: @colortheme_sidebar-left-fg; } @@ -434,10 +434,8 @@ #cp-app-drive-content-container { display: flex; flex-flow: column; - flex: 1; - // Needed to avoid the folder's path to overflows - // https://stackoverflow.com/questions/38223879/white-space-nowrap-breaks-flexbox-layout - // min-width: 0; + flex: 1 1 100%; + min-width: 0; } #cp-app-drive-content { box-sizing: border-box; @@ -486,61 +484,31 @@ #cp-app-drive-content-folder { li { &.cp-app-drive-search-result { - border-bottom: 1px solid @drive_info-box-border; - display: block; - &:hover { - background-color: initial; - } - table { - width: 100%; - .cp-app-drive-search-label2 { - width: 150px; - font-size: 15px; - text-align: right; - padding-right: 15px; - } - .cp-app-drive-search-opendir { + display: flex; + height: 2 * @variables_bar-height; + .cp-app-drive-search-path { + .cp-app-drive-path-inner { display: flex; - justify-content: space-between; - a { + 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-path-clickable { cursor: pointer; - color: #41b7d8; &:hover { - color: #014c8c; - text-decoration: underline; - } - } - } - .cp-app-drive-search-path { - font-style: italic; - .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%; + background-color: #eee; } } } - .cp-app-drive-search-title { - font-weight: bold; - cursor: pointer; - &:hover { - background-color: @drive_hover; - } - } - .cp-app-drive-search-col2 { - width: 250px; - } - td.cp-app-drive-search-icon { - width: 50px; - font-size: 40px; - } + font-size: 12px; + line-height: 16px; + color: @drive_table-header-fg; } } &.cp-app-drive-tags-list { @@ -637,22 +605,72 @@ display: none; } // Make it act as a table! - padding-left: 20px; + padding-left: 10px; ul { - display: table; width: 100%; - padding: 0px 10px; } li { - display: table-row; + display: flex; input { border: 1px solid #ddd; margin: 0; padding: 0 4px; + flex: 1; + min-width: 0; } + &> span { padding: 0 5px; - display: table-cell; + display: inline-block; + white-space: nowrap; + &:first-child, &.cp-icon { + min-width: 20px; + text-align: center; + font-size: 18px; + line-height: 32px; + padding: 0; + } + &.cp-app-drive-element-name { + flex: 1; + min-width: 0; + text-align: left; + text-overflow: ellipsis; + overflow: hidden; + } + &.cp-app-drive-element-state { + min-width: 40px; + text-align: right; + display: flex; + align-items: center; + justify-content: end; + height: @variables_bar-height; + .fa, .cptools { + &:not(:last-child) { + margin-right: 2px; + } + } + } + &.cp-app-drive-element-list { + width: 120px; + } + &.cp-app-drive-element-sort { + display: none; + .dropdown_main(); + .cp-dropdown-content a { + display: block !important; + .sortdesc { + order: 2; + } + } + button { + color: inherit; + background: none; + border: none; + .fa { + margin-right: 5px; + } + } + } } &:not(.cp-app-drive-element-header) { height: @variables_bar-height; @@ -663,6 +681,7 @@ height: 1.5 * @variables_bar-height; line-height: 1.5 * @variables_bar-height; span { + line-height: 1.5 * @variables_bar-height; position: absolute; } } @@ -674,14 +693,11 @@ text-align: left; } &.sortasc, &.sortdesc { - float: right; + margin-right: 3px; } } &> span { - padding: 15px 5px; - &.cp-app-drive-sort-active { - font-weight: bold; - } + padding: 14px 5px; &.cp-app-drive-sort-clickable { cursor: pointer; &:hover { @@ -696,28 +712,29 @@ overflow: hidden; white-space: nowrap; box-sizing: border-box; - &.cp-app-drive-element-state { - .fa, .cptools { - &:not(:last-child) { - margin-right: 5px; - } - } - } - &.cp-app-drive-content-icon, &.cp-app-drive-element-state, &.cp-icon { - width: 30px; - } - &.cp-app-drive-element-type, &.cp-app-drive-element-atime, &.cp-app-drive-element-ctime { - width: 175px; - } - &.cp-app-drive-element-title { - width: 250px; - @media screen and (max-width: 1200px) { - display: none; - } - } - &.cp-app-drive-element-folders, &.cp-app-drive-element-files { - width: 150px; - } + } + } + @media screen and (max-width: 840px) { + .cp-app-drive-element-type, .cp-app-drive-element-filler { + display: none !important; + } + } + + @media screen and (max-width: 740px) { + .cp-app-drive-element-folders, .cp-app-drive-element-ctime { + display: none !important; + } + } + + @media screen and (max-width: 670px) { + .cp-app-drive-element-files, .cp-app-drive-element-atime { + display: none !important; + } + .cp-app-drive-element-header .cp-app-drive-element-state { + display: none !important; + } + .cp-app-drive-element-sort { + display: block !important; } } } diff --git a/www/common/drive-ui.js b/www/common/drive-ui.js index 57e40ffdb..dcb540ee7 100644 --- a/www/common/drive-ui.js +++ b/www/common/drive-ui.js @@ -698,7 +698,6 @@ define([ } }; $content.on('mousedown', function (e) { - if (currentPath[0] === SEARCH) { return; } if (e.which !== 1) { return; } $content.focus(); sel.down = true; @@ -1931,7 +1930,6 @@ define([ if (thumbsUrls[element]) { var img = new Image(); img.src = thumbsUrls[element]; - $element.find('.cp-icon').addClass('cp-app-drive-element-list'); $element.prepend(img); $(img).addClass('cp-app-drive-element-grid cp-app-drive-element-thumbnail'); $(img).attr("draggable", false); @@ -1940,7 +1938,7 @@ define([ common.displayThumbnail(href || data.roHref, data.channel, data.password, $element, function ($thumb) { // Called only if the thumbnail exists // Remove the .hide() added by displayThumnail() because it hides the icon in list mode too - $element.find('.cp-icon').removeAttr('style').addClass('cp-app-drive-element-list'); + $element.find('.cp-icon').removeAttr('style'); $thumb.addClass('cp-app-drive-element-grid cp-app-drive-element-thumbnail'); $thumb.attr("draggable", false); thumbsUrls[element] = $thumb[0].src; @@ -1998,10 +1996,13 @@ define([ var $files = $('', { 'class': 'cp-app-drive-element-files cp-app-drive-element-list' }).text(files); + var $filler = $('', { + 'class': 'cp-app-drive-element-filler cp-app-drive-element-list' + }); if (getViewMode() === 'grid') { $span.attr('title', key); } - $span.append($name).append($state).append($subfolders).append($files); + $span.append($name).append($state).append($subfolders).append($files).append($filler); }; // This is duplicated in cryptpad-common, it should be unified @@ -2271,7 +2272,8 @@ define([ if (idx < path.length - 1) { if (!noStyle) { $span.addClass('cp-app-drive-path-clickable'); - $span.click(function () { + $span.click(function (e) { + e.stopPropagation(); var sliceEnd = idx + 1; if (isTrash && idx === 1) { sliceEnd = 4; } // Make sure we don't show the index or 'element' and 'path' APP.displayDirectory(path.slice(0, sliceEnd)); @@ -2714,7 +2716,7 @@ define([ value = ''; } } else { - ['cp-app-drive-element-title', 'cp-app-drive-element-type', + ['cp-app-drive-element-type', 'cp-app-drive-element-atime', 'cp-app-drive-element-ctime'].some(function (c) { if ($span.hasClass(c)) { var nValue = c.replace(/cp-app-drive-element-/, ''); @@ -2744,6 +2746,34 @@ define([ $list.find('.cp-app-drive-sort-foldername').addClass('cp-app-drive-sort-active').prepend($icon); } }; + Messages.fm_sort = "Sort"; // XXX + var getSortDropdown = function () { + var $fhSort = $(h('span.cp-dropdown-container.cp-app-drive-element-sort.cp-app-drive-sort-clickable')); + var options = [{ + tag: 'a', + attributes: {'class': 'cp-app-drive-element-type'}, + content: Messages.fm_type + },{ + tag: 'a', + attributes: {'class': 'cp-app-drive-element-atime'}, + content: Messages.fm_lastAccess + },{ + tag: 'a', + attributes: {'class': 'cp-app-drive-element-ctime'}, + content: Messages.fm_creation + }]; + var dropdownConfig = { + text: '', // Button initial text + options: options, // Entries displayed in the menu + container: $fhSort, + left: true, + common: common + }; + var $sortBlock = UIElements.createDropdown(dropdownConfig); + $sortBlock.find('button').append(h('span.fa.fa-sort-amount-desc')).append(h('span', Messages.fm_sort)); + $sortBlock.on('click', 'a', onSortByClick); + return $fhSort; + }; var getFolderListHeader = function () { var $fohElement = $('
  • ', { 'class': 'cp-app-drive-element-header cp-app-drive-element-list' @@ -2754,6 +2784,7 @@ define([ 'class': 'cp-app-drive-element-name cp-app-drive-sort-foldername ' + 'cp-app-drive-sort-clickable' }).text(Messages.fm_folderName).click(onSortByClick); + var $state = $('', {'class': 'cp-app-drive-element-state'}); var $subfolders = $('', { 'class': 'cp-app-drive-element-folders cp-app-drive-element-list' @@ -2761,8 +2792,11 @@ define([ var $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($subfolders).append($files).append($filler); addFolderSortIcon($fohElement); return $fohElement; }; @@ -2778,30 +2812,33 @@ define([ $list.find('.' + classSorted).addClass('cp-app-drive-sort-active').prepend($icon); } }; - var getFileListHeader = function () { + var getFileListHeader = function (clickable) { var $fihElement = $('
  • ', { '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 $fihElement = $('', {'class': 'element'}).appendTo($fileHeader); var $fhIcon = $('', {'class': 'cp-app-drive-content-icon'}); var $fhName = $('', { - 'class': 'cp-app-drive-element-name cp-app-drive-sort-filename ' + - 'cp-app-drive-sort-clickable' - }).text(Messages.fm_fileName).click(onSortByClick); + 'class': 'cp-app-drive-element-name cp-app-drive-sort-filename ' + clickCls + }).text(Messages.fm_fileName).click(onClick); + var $fhSort = clickable ? getSortDropdown() : undefined; + var $fhState = $('', {'class': 'cp-app-drive-element-state'}); var $fhType = $('', { - 'class': 'cp-app-drive-element-type cp-app-drive-sort-clickable' - }).text(Messages.fm_type).click(onSortByClick); + 'class': 'cp-app-drive-element-type cp-app-drive-element-list ' + clickCls + }).text(Messages.fm_type).click(onClick); var $fhAdate = $('', { - 'class': 'cp-app-drive-element-atime cp-app-drive-sort-clickable' - }).text(Messages.fm_lastAccess).click(onSortByClick); + 'class': 'cp-app-drive-element-atime cp-app-drive-element-list ' + clickCls + }).text(Messages.fm_lastAccess).click(onClick); var $fhCdate = $('', { - 'class': 'cp-app-drive-element-ctime cp-app-drive-sort-clickable' - }).text(Messages.fm_creation).click(onSortByClick); + 'class': 'cp-app-drive-element-ctime cp-app-drive-element-list ' + clickCls + }).text(Messages.fm_creation).click(onClick); // 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); + $fihElement.append($fhIcon).append($fhName).append($fhSort).append($fhState).append($fhType); $fihElement.append($fhAdate).append($fhCdate); - addFileSortIcon($fihElement); + if (clickable) { addFileSortIcon($fihElement); } return $fihElement; }; @@ -2989,7 +3026,7 @@ define([ var displayHrefArray = function ($container, rootName, draggable) { var unsorted = files[rootName]; if (unsorted.length) { - var $fileHeader = getFileListHeader(false); + var $fileHeader = getFileListHeader(true); $container.append($fileHeader); } var keys = unsorted; @@ -3044,7 +3081,7 @@ define([ } var allfiles = files[FILES_DATA]; if (allfiles.length === 0) { return; } - var $fileHeader = getFileListHeader(false); + var $fileHeader = getFileListHeader(true); $container.append($fileHeader); var keys = manager.getFiles([FILES_DATA]); var sortedFiles = sortElements(false, [FILES_DATA], keys, APP.store[SORT_FILE_BY], !getSortFileDesc(), true); @@ -3108,74 +3145,42 @@ define([ }; var displaySearch = function ($list, value) { + getFileListHeader(false).appendTo($list); + $list.closest('#cp-app-drive-content-folder').addClass('cp-app-drive-content-list'); 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 || r.data.roHref; - var parsed = Hash.parsePadUrl(href); - var $table = $(''); - var $icon = $('').append($icon).append($title).append($typeName).append($type).appendTo($table); - $('').append($path).append($atimeName).append($atime).appendTo($table); - $('').append($openDir).append($ctimeName).append($ctime).appendTo($table); - $('
  • ', {'class':'cp-app-drive-search-result'}).append($table).appendTo($list); + $list.append($element); }); }); }; @@ -3259,7 +3264,7 @@ define([ var displayOwned = function ($container) { var list = manager.getOwnedPads(); if (list.length === 0) { return; } - var $fileHeader = getFileListHeader(false); + var $fileHeader = getFileListHeader(true); $container.append($fileHeader); var sortedFiles = sortElements(false, false, list, APP.store[SORT_FILE_BY], !getSortFileDesc(), true); sortedFiles.forEach(function (id) {
  • ', {'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); - if (manager.isPathIn(path, ['hrefArray'])) { - path.pop(); - path.push(r.data.title); + 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); } - var $path = $('', { - 'class': 'cp-app-drive-search-col1 cp-app-drive-search-path' - }); - createTitle($path, path, true); - 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(r.id); - }); - $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.displayDirectory(parentPath); - APP.selectedFiles = path.slice(-1); - }).appendTo($openDir); - } - $('').text(Messages.fc_prop).click(function () { - APP.getProperties(r.id, function (e) { - if (e) { return void logError(e); } - }); - }).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); + + if (manager.isPathIn(_path, ['hrefArray'])) { + _path.pop(); + _path.push(r.data.title); } + var $path = $('', { + 'class': 'cp-app-drive-search-path' + }).appendTo($element.find('.cp-app-drive-element-name')); + createTitle($path, _path); - // rows 1-3 - $('