Merge branch 'staging' into responsiveContextmenu

This commit is contained in:
ClemDee
2019-08-12 12:15:44 +02:00
98 changed files with 3150 additions and 757 deletions

View File

@@ -17,8 +17,6 @@ define([
'/bower_components/chainpad-listmap/chainpad-listmap.js',
'/customize/messages.js',
'/common/jscolor.js',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
'less!/drive/app-drive.less',
@@ -43,7 +41,10 @@ define([
{
var APP = window.APP = {
editable: false,
mobile: function () { return $('body').width() <= 600; }, // Menu and content area are not inline-block anymore for mobiles
mobile: function () {
if (window.matchMedia) { return !window.matchMedia('(any-pointer:fine)').matches; }
else { return $('body').width() <= 600; }
},
isMac: navigator.platform === "MacIntel",
};
@@ -77,6 +78,8 @@ define([
var faFolderOpen = 'cptools-folder-open';
var faSharedFolder = 'cptools-shared-folder';
var faSharedFolderOpen = 'cptools-shared-folder-open';
var faExpandAll = 'fa-plus-square-o';
var faCollapseAll = 'fa-minus-square-o';
var faShared = 'fa-shhare-alt';
var faReadOnly = 'fa-eye';
var faRename = 'fa-pencil';
@@ -297,6 +300,33 @@ define([
});
};
APP.selectedFiles = [];
var isElementSelected = function ($element) {
var elementId = $element.data("path").slice(-1)[0];
return APP.selectedFiles.indexOf(elementId) !== -1;
};
var selectElement = function ($element) {
var elementId = $element.data("path").slice(-1)[0];
if (APP.selectedFiles.indexOf(elementId) === -1) {
APP.selectedFiles.push(elementId);
}
$element.addClass("cp-app-drive-element-selected");
};
var unselectElement = function ($element) {
var elementId = $element.data("path").slice(-1)[0];
var index = APP.selectedFiles.indexOf(elementId);
if (index !== -1) {
APP.selectedFiles.splice(index, 1);
}
$element.removeClass("cp-app-drive-element-selected");
};
var findSelectedElements = function () {
return $(".cp-app-drive-element-selected");
};
var createContextMenu = function () {
var menu = h('div.cp-contextmenu.dropdown.cp-unselectable', [
h('ul.dropdown-menu', {
@@ -316,11 +346,11 @@ define([
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-expandall.dropdown-item', {
'tabindex': '-1',
'data-icon': "expandAll",
'data-icon': faExpandAll,
}, Messages.fc_expandAll)),
h('li', h('a.cp-app-drive-context-collapseall.dropdown-item', {
'tabindex': '-1',
'data-icon': "collapseAll",
'data-icon': faCollapseAll,
}, Messages.fc_collapseAll)),
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-color.dropdown-item.cp-app-drive-context-editable', {
@@ -543,13 +573,14 @@ define([
// Tags used: display Tags category
if (Object.keys(manager.getTagsList()).length) { displayedCategories.push(TAGS); }
var virtualCategories = [SEARCH, RECENT, OWNED, TAGS, SHARED_FOLDER];
var virtualCategories = [SEARCH, RECENT, OWNED, TAGS];
if (!APP.loggedIn) {
$tree.hide();
if (APP.newSharedFolder) {
// ANON_SHARED_FOLDER
displayedCategories = [SHARED_FOLDER];
virtualCategories.push(SHARED_FOLDER);
currentPath = [SHARED_FOLDER, ROOT];
} else {
displayedCategories = [FILES_DATA];
@@ -595,7 +626,8 @@ define([
var sel = {};
var removeSelected = function (keepObj) {
$('.cp-app-drive-element-selected').removeClass("cp-app-drive-element-selected");
APP.selectedFiles = [];
findSelectedElements().removeClass("cp-app-drive-element-selected");
var $container = $driveToolbar.find('#cp-app-drive-toolbar-contextbuttons');
if (!$container.length) { return; }
$container.html('');
@@ -705,7 +737,9 @@ define([
delete sel.move;
$content.find('.cp-app-drive-element-selected-tmp')
.removeClass('cp-app-drive-element-selected-tmp')
.addClass('cp-app-drive-element-selected');
.each(function (idx, element) {
selectElement($(element));
});
e.stopPropagation();
});
@@ -740,7 +774,9 @@ define([
// Ctrl+A select all
if (e.which === 65 && (e.ctrlKey || (e.metaKey && APP.isMac))) {
$content.find('.cp-app-drive-element:not(.cp-app-drive-element-selected)')
.addClass('cp-app-drive-element-selected');
.each(function (idx, element) {
selectElement($(element));
});
return;
}
@@ -753,7 +789,7 @@ define([
APP.onElementClick(ev, $(el));
};
var $selection = $content.find('.cp-app-drive-element.cp-app-drive-element-selected');
var $selection = findSelectedElements();
if ($selection.length === 0) { return void click($elements.first()[0]); }
var lastIndex = typeof sel.endSelected === "number" ? sel.endSelected :
@@ -872,12 +908,12 @@ define([
return;
}
removeInput();
removeSelected();
var $name = $element.find('.cp-app-drive-element-name');
if (!$name.length) {
$name = $element.find('> .cp-app-drive-element');
}
$name.hide();
var isFolder = $element.is(".cp-app-drive-element-folder:not(.cp-app-drive-element-sharedf)");
var el = manager.find(path);
var name = manager.isFile(el) ? manager.getTitle(el) : path[path.length - 1];
if (manager.isSharedFolder(el)) {
@@ -899,14 +935,21 @@ define([
var newName = $input.val();
if (JSON.stringify(path) === JSON.stringify(currentPath)) {
manager.rename(path, $input.val(), function () {
renameFoldersOpened(path, newName);
path[path.length - 1] = newName;
if (isFolder) {
renameFoldersOpened(path, newName);
path[path.length - 1] = newName;
}
APP.displayDirectory(path);
});
}
else {
manager.rename(path, $input.val(), function () {
renameFoldersOpened(path, newName);
if (isFolder) {
renameFoldersOpened(path, newName);
unselectElement($element);
$element.data("path", $element.data("path").slice(0, -1).concat(newName));
selectElement($element);
}
refresh();
});
}
@@ -927,7 +970,6 @@ define([
// We don't want to open the file/folder when clicking on the input
$input.on('click dblclick', function (e) {
removeSelected();
e.stopPropagation();
});
// Remove the browser ability to drag text from the input to avoid
@@ -1147,8 +1189,9 @@ define([
var getSelectedPaths = function ($element) {
var paths = [];
if ($('.cp-app-drive-element-selected').length > 1) {
var $selected = $('.cp-app-drive-element-selected');
if (!$element || $element.length === 0) { return paths; }
if (findSelectedElements().length > 1) {
var $selected = findSelectedElements();
$selected.each(function (idx, elmt) {
var ePath = $(elmt).data('path');
if (ePath) {
@@ -1177,7 +1220,7 @@ define([
} else {
$driveToolbar.find('cp-app-drive-toolbar-emptytrash').hide();
}
var $li = $content.find('.cp-app-drive-element-selected');
var $li = findSelectedElements();
if ($li.length === 0) {
$li = findDataHolder($tree.find('.cp-app-drive-element-active'));
}
@@ -1244,6 +1287,7 @@ define([
if (pos+eh <= h && pos >= 0) { return; }
$content.scrollTop(v);
};
// Add the "selected" class to the "li" corresponding to the clicked element
var onElementClick = APP.onElementClick = function (e, $element) {
// If "Ctrl" is pressed, do not remove the current selection
@@ -1280,23 +1324,23 @@ define([
var $el;
removeSelected(true);
sel.oldSelection.forEach(function (el) {
if (!$(el).hasClass("cp-app-drive-element-selected")) {
$(el).addClass("cp-app-drive-element-selected");
if (!isElementSelected($(el))) {
selectElement($(el));
}
});
for (var i = Math.min(sel.startSelected, sel.endSelected);
i <= Math.max(sel.startSelected, sel.endSelected);
i++) {
$el = $($elements.get(i));
if (!$el.hasClass("cp-app-drive-element-selected")) {
$el.addClass("cp-app-drive-element-selected");
if (!isElementSelected($el)) {
selectElement($el);
}
}
} else {
if (!$element.hasClass("cp-app-drive-element-selected")) {
$element.addClass("cp-app-drive-element-selected");
if (!isElementSelected($element)) {
selectElement($element);
} else {
$element.removeClass("cp-app-drive-element-selected");
unselectElement($element);
}
}
updateContextButton();
@@ -1340,7 +1384,14 @@ define([
});
// show contextmenu at cursor position
$menu.css({ display: "block" });
if (APP.mobile()) { return; }
if (APP.mobile()) {
$menu.css({
top: ($("#cp-app-drive-toolbar-context-mobile").offset().top + 32) + 'px',
right: '0px',
left: ''
});
return;
}
var h = $menu.outerHeight();
var w = $menu.outerWidth();
var wH = window.innerHeight;
@@ -1393,6 +1444,17 @@ define([
} else {
var $element = findDataHolder($(e.target));
// if clicked from tree
var fromTree = $element.closest("#cp-app-drive-tree").length;
if (fromTree) {
removeSelected();
}
// if clicked on non selected element
if (!isElementSelected($element)) {
removeSelected();
}
if (type === 'trash' && !$element.data('path')) { return; }
if (!$element.length) {
@@ -1401,8 +1463,8 @@ define([
return false;
}
if (!$element.hasClass('cp-app-drive-element-selected')) {
onElementClick(undefined, $element);
if (!isElementSelected($element)) {
selectElement($element);
}
paths = getSelectedPaths($element);
@@ -1472,6 +1534,7 @@ define([
if (!res) { return; }
manager.delete(pathsList, function () {
pathsList.forEach(removeFoldersOpened);
removeSelected();
refresh();
});
}, null, true);
@@ -1482,7 +1545,7 @@ define([
var paths = [];
var $element = findDataHolder($(ev.target));
if ($element.hasClass('cp-app-drive-element-selected')) {
var $selected = $('.cp-app-drive-element-selected');
var $selected = findSelectedElements();
$selected.each(function (idx, elmt) {
var ePath = $(elmt).data('path');
if (ePath) {
@@ -1499,7 +1562,7 @@ define([
});
} else {
removeSelected();
$element.addClass('cp-app-drive-element-selected');
selectElement($element);
var val = manager.find(path);
if (!val) { return; } // The element is not in the object
paths = [{
@@ -1518,7 +1581,13 @@ define([
var findDropPath = function (target) {
var $target = $(target);
var $el = findDataHolder($target);
var $el;
if ($target.is(".cp-app-drive-path-element")) {
$el = $target;
}
else {
$el = findDataHolder($target);
}
var newPath = $el.data('path');
var dropEl = newPath && manager.find(newPath);
if (newPath && manager.isSharedFolder(dropEl)) {
@@ -1646,7 +1715,8 @@ define([
$owner.attr('title', Messages.fm_padIsOwnedOther);
}
};
var addFileData = function (element, $span) {
var thumbsUrls = {};
var addFileData = function (element, $element) {
if (!manager.isFile(element)) { return; }
var data = manager.getFileData(element);
@@ -1655,7 +1725,7 @@ define([
var hrefData = Hash.parsePadUrl(href);
if (hrefData.type) {
$span.addClass('cp-border-color-'+hrefData.type);
$element.addClass('cp-border-color-'+hrefData.type);
}
var $state = $('<span>', {'class': 'cp-app-drive-element-state'});
@@ -1675,25 +1745,38 @@ define([
var $expire = $expirableIcon.clone().appendTo($state);
$expire.attr('title', Messages._getKey('fm_expirablePad', [new Date(data.expire).toLocaleString()]));
}
_addOwnership($span, $state, data);
_addOwnership($element, $state, data);
var name = manager.getTitle(element);
// The element with the class '.name' is underlined when the 'li' is hovered
var $name = $('<span>', {'class': 'cp-app-drive-element-name'}).text(name);
$span.append($name);
$span.append($state);
$span.attr('title', name);
$element.append($name);
$element.append($state);
$element.attr('title', name);
// display the thumbnail
// if the thumbnail has already been displayed once, do not reload it, keep the same url
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);
}
else {
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');
$thumb.addClass('cp-app-drive-element-grid cp-app-drive-element-thumbnail');
$thumb.attr("draggable", false);
thumbsUrls[element] = $thumb[0].src;
});
}
var type = Messages.type[hrefData.type] || hrefData.type;
common.displayThumbnail(href || data.roHref, data.channel, data.password, $span, function ($thumb) {
// Called only if the thumbnail exists
// Remove the .hide() added by displayThumnail() because it hides the icon in
// list mode too
$span.find('.cp-icon').removeAttr('style').addClass('cp-app-drive-element-list');
$thumb.addClass('cp-app-drive-element-grid')
.addClass('cp-app-drive-element-thumbnail');
});
var $type = $('<span>', {
'class': 'cp-app-drive-element-type cp-app-drive-element-list'
}).text(type);
@@ -1703,7 +1786,7 @@ define([
var $cdate = $('<span>', {
'class': 'cp-app-drive-element-ctime cp-app-drive-element-list'
}).text(getDate(data.ctime));
$span.append($type).append($adate).append($cdate);
$element.append($type).append($adate).append($cdate);
};
var addFolderData = function (element, key, $span) {
@@ -1779,12 +1862,9 @@ define([
draggable: true,
'class': 'cp-app-drive-element-row'
});
if (!isFolder && Array.isArray(APP.selectedFiles)) {
var idx = APP.selectedFiles.indexOf(element);
if (idx !== -1) {
$element.addClass('cp-app-drive-element-selected');
APP.selectedFiles.splice(idx, 1);
}
$element.data('path', newPath);
if (isElementSelected($element)) {
selectElement($element);
}
$element.prepend($icon).dblclick(function () {
if (isFolder) {
@@ -1800,11 +1880,10 @@ define([
addFileData(element, $element);
}
$element.addClass(liClass);
$element.data('path', newPath);
addDragAndDropHandlers($element, newPath, isFolder, !isTrash);
$element.click(function(e) {
e.stopPropagation();
onElementClick(e, $element, newPath);
onElementClick(e, $element);
});
if (!isTrash) {
$element.contextmenu(openContextMenu('tree'));
@@ -1955,6 +2034,8 @@ define([
} else if (idx > 0 && manager.isFile(el)) {
name = getElementName(path);
}
$span.data("path", path.slice(0, idx + 1));
addDragAndDropHandlers($span, path.slice(0, idx), true, true);
if (idx === 0) { name = p === SHARED_FOLDER ? name : getPrettyName(p); }
else {
@@ -2265,15 +2346,22 @@ define([
var data = manager.getSharedFolderData(id);
var parsed = Hash.parsePadUrl(data.href);
if (!parsed || !parsed.hash) { return void console.error("Invalid href: "+data.href); }
var friends = common.getFriends();
var modal = UIElements.createSFShareModal({
origin: APP.origin,
pathname: "/drive/",
friends: friends,
title: data.title,
password: data.password,
common: common,
hashes: {
editHash: parsed.hash
}
});
$shareBlock.click(function () {
UI.openCustomModal(modal);
UI.openCustomModal(modal, {
wide: Object.keys(friends).length !== 0
});
});
$container.append($shareBlock);
};
@@ -2592,22 +2680,19 @@ define([
'class': 'cp-app-drive-element cp-app-drive-element-file cp-app-drive-element-row' + roClass,
draggable: draggable
});
if (Array.isArray(APP.selectedFiles)) {
var sidx = APP.selectedFiles.indexOf(id);
if (sidx !== -1) {
$element.addClass('cp-app-drive-element-selected');
APP.selectedFiles.splice(sidx, 1);
}
var path = [rootName, idx];
$element.data('path', path);
if (isElementSelected($element)) {
selectElement($element);
}
$element.prepend($icon).dblclick(function () {
openFile(id);
});
addFileData(id, $element);
var path = [rootName, idx];
$element.data('path', path);
$element.click(function(e) {
e.stopPropagation();
onElementClick(e, $element, path);
onElementClick(e, $element);
});
$element.contextmenu(openContextMenu('default'));
$element.data('context', 'default');
@@ -2734,8 +2819,8 @@ define([
e.preventDefault();
if (manager.isInTrashRoot(parentPath)) { parentPath = [TRASH]; }
else { parentPath.pop(); }
APP.selectedFiles = [r.id];
APP.displayDirectory(parentPath);
APP.selectedFiles = path.slice(-1);
}).appendTo($openDir);
}
$('<a>').text(Messages.fc_prop).click(function () {
@@ -2748,7 +2833,7 @@ define([
else {
$icon.append($folderIcon.clone());
$type.text(Messages.fm_folder);
$('<a>').text(Messages.fm_OpenFolder || "Open folder").click(function (e) {
$('<a>').text(Messages.fc_open).click(function (e) {
e.preventDefault();
APP.displayDirectory(path);
}).appendTo($openDir);
@@ -2826,7 +2911,7 @@ define([
$element.data('path', path);
$element.click(function(e) {
e.stopPropagation();
onElementClick(e, $element, path);
onElementClick(e, $element);
});
$element.contextmenu(openContextMenu('default'));
$element.data('context', 'default');
@@ -3050,7 +3135,7 @@ define([
$context.click(function (e) {
e.preventDefault();
e.stopPropagation();
var $li = $content.find('.cp-app-drive-element-selected');
var $li = findSelectedElements();
if ($li.length !== 1) {
$li = findDataHolder($tree.find('.cp-app-drive-element-active'));
}
@@ -3060,11 +3145,6 @@ define([
return;
}
// Open the menu
$('.cp-contextmenu').css({
top: ($context.offset().top + 32) + 'px',
right: '0px',
left: ''
});
$li.contextmenu();
});
} else {
@@ -3132,7 +3212,7 @@ define([
}
});*/
var $sel = $content.find('.cp-app-drive-element-selected');
var $sel = findSelectedElements();
if ($sel.length) {
$sel[0].scrollIntoView();
} else {
@@ -3144,6 +3224,9 @@ define([
if (history.isHistoryMode) {
return void _displayDirectory(path, force);
}
if (!manager.comparePath(currentPath, path)) {
removeSelected();
}
updateObject(sframeChan, proxy, function () {
copyObjectValue(files, proxy.drive);
updateSharedFolders(sframeChan, manager, files, folders, function () {
@@ -3470,7 +3553,9 @@ define([
//data.noPassword = true;
data.noEditPassword = true;
data.noExpiration = true;
data.sharedFolder = true; // XXX debug
// this is here to allow users to check the channel id of a shared folder
// we should remove it at some point
data.sharedFolder = true;
}
UIElements.getProperties(common, data, cb);
@@ -3492,6 +3577,7 @@ define([
if (!res) { return; }
manager.delete(pathsList, function () {
pathsList.forEach(removeFoldersOpened);
removeSelected();
refresh();
});
});
@@ -3608,6 +3694,7 @@ define([
friends: friends,
title: data.title,
common: common,
password: data.password,
hashes: {
editHash: parsed.hash
}
@@ -3621,6 +3708,7 @@ define([
origin: APP.origin,
pathname: "/" + padType + "/",
friends: friends,
password: data.password,
hashes: {
editHash: parsed.hash,
viewHash: roParsed.hash,
@@ -3630,6 +3718,7 @@ define([
hash: parsed.hash,
password: data.password
},
isTemplate: paths[0].path[0] === 'template',
title: data.title,
common: common
};
@@ -3735,16 +3824,15 @@ define([
var parentPath = paths[0].path.slice();
if (manager.isInTrashRoot(parentPath)) { parentPath = [TRASH]; }
else { parentPath.pop(); }
el = manager.find(paths[0].path);
APP.selectedFiles = [el];
APP.displayDirectory(parentPath);
APP.selectedFiles = paths[0].path.slice(-1);
}
APP.hideMenu();
});
$content.on("keydown", function (e) {
if (e.which === 113) {
var paths = $contextMenu.data('paths');
$(window).on("keydown", function (e) {
if (e.which === 113) { // if F2 key pressed
var paths = getSelectedPaths(findSelectedElements().first());
if (paths.length !== 1) { return; }
displayRenameInput(paths[0].element, paths[0].path);
}
@@ -3756,11 +3844,9 @@ define([
e.preventDefault();
});
$appContainer.on('mouseup', function (e) {
//if (sel.down) { return; }
if (e.which !== 1) { return ; }
if ($(e.target).is(".dropdown-submenu a, .dropdown-submenu a span")) { return; } // if we click on dropdown-submenu, don't close menu
APP.hideMenu(e);
//removeSelected(e);
});
$appContainer.on('click', function (e) {
if (e.which !== 1) { return ; }
@@ -3779,7 +3865,7 @@ define([
if (manager.isPathIn(currentPath, [FILES_DATA]) && APP.loggedIn) {
return; // We can't remove elements directly from filesData
}
var $selected = $('.cp-app-drive-element-selected');
var $selected = findSelectedElements();
if (!$selected.length) { return; }
var paths = [];
var isTrash = manager.isPathIn(currentPath, [TRASH]);