Display thumbnails in the drive and then file picker

pull/1/head
yflory 7 years ago
parent e553351b79
commit 4116d08dd1

@ -42,7 +42,8 @@
"diff-dom": "2.1.1", "diff-dom": "2.1.1",
"nthen": "^0.1.5", "nthen": "^0.1.5",
"open-sans-fontface": "^1.4.2", "open-sans-fontface": "^1.4.2",
"bootstrap-tokenfield": "^0.12.1" "bootstrap-tokenfield": "^0.12.1",
"localforage": "^1.5.2"
}, },
"resolutions": { "resolutions": {
"bootstrap": "v4.0.0-alpha.6" "bootstrap": "v4.0.0-alpha.6"

@ -3,14 +3,19 @@ define([
'/api/config', '/api/config',
'/common/cryptpad-common.js', '/common/cryptpad-common.js',
'/common/common-util.js', '/common/common-util.js',
'/common/common-hash.js',
'/common/media-tag.js', '/common/media-tag.js',
'/common/tippy.min.js', '/common/tippy.min.js',
'/customize/application_config.js', '/customize/application_config.js',
'/file/file-crypto.js',
'/bower_components/localforage/dist/localforage.min.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
'css!/common/tippy.css', 'css!/common/tippy.css',
], function ($, Config, Cryptpad, Util, MediaTag, Tippy, AppConfig) { ], function ($, Config, Cryptpad, Util, Hash, MediaTag, Tippy, AppConfig, FileCrypto, localForage) {
var UI = {}; var UI = {};
var Messages = Cryptpad.Messages; var Messages = Cryptpad.Messages;
var Nacl = window.nacl;
/** /**
* Requirements from cryptpad-common.js * Requirements from cryptpad-common.js
@ -28,6 +33,40 @@ define([
* - createDropdown * - createDropdown
*/ */
var addThumbnail = function (err, thumb, $span, cb) {
var img = new Image();
img.src = 'data:;base64,'+thumb;
$span.find('.cp-icon').hide();
$span.prepend(img);
cb($(img));
};
UI.displayThumbnail = function (href, $container, cb) {
cb = cb || $.noop;
var parsed = Hash.parsePadUrl(href);
if (parsed.type !== 'file') { return; }
var k ='thumbnail-' + href;
var whenNewThumb = function () {
var secret = Hash.getSecrets('file', parsed.hash);
var hexFileName = Util.base64ToHex(secret.channel);
var src = Hash.getBlobPathFromHex(hexFileName);
var cryptKey = secret.keys && secret.keys.fileKeyStr;
var key = Nacl.util.decodeBase64(cryptKey);
FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) {
if (!metadata.thumbnail) {
return void localForage.setItem(k, 'EMPTY');
}
localForage.setItem(k, metadata.thumbnail, function (err) {
addThumbnail(err, metadata.thumbnail, $container, cb);
});
});
};
localForage.getItem(k, function (err, v) {
if (!v) { return void whenNewThumb(); }
if (v === 'EMPTY') { return; }
addThumbnail(err, v, $container, cb);
});
};
UI.updateTags = function (common, href) { UI.updateTags = function (common, href) {
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
sframeChan.query('Q_TAGS_GET', href || null, function (err, res) { sframeChan.query('Q_TAGS_GET', href || null, function (err, res) {
@ -92,7 +131,7 @@ define([
target: data.target target: data.target
}; };
if (data.filter && !data.filter(file)) { if (data.filter && !data.filter(file)) {
Cryptpad.log('TODO: invalid avatar (type or size)'); Cryptpad.log('Invalid avatar (type or size)');
return; return;
} }
data.FM.handleFile(file, ev); data.FM.handleFile(file, ev);
@ -398,9 +437,6 @@ define([
}, LIMIT_REFRESH_RATE * 3); }, LIMIT_REFRESH_RATE * 3);
updateUsage(); updateUsage();
/*getProxy().on('change', ['drive'], function () {
updateUsage();
}); TODO*/
cb(null, $container); cb(null, $container);
}; };

@ -80,6 +80,7 @@ define([
funcs.createButton = callWithCommon(UI.createButton); funcs.createButton = callWithCommon(UI.createButton);
funcs.createUsageBar = callWithCommon(UI.createUsageBar); funcs.createUsageBar = callWithCommon(UI.createUsageBar);
funcs.updateTags = callWithCommon(UI.updateTags); funcs.updateTags = callWithCommon(UI.updateTags);
funcs.displayThumbnail = UI.displayThumbnail;
// History // History
funcs.getHistory = callWithCommon(History.create); funcs.getHistory = callWithCommon(History.create);

@ -51,6 +51,7 @@ min-height: auto;
text-overflow: ellipsis; text-overflow: ellipsis;
padding-top: 5px; padding-top: 5px;
padding-bottom: 5px; padding-bottom: 5px;
border: 1px solid transparent;
&:not(.cp-app-drive-element-selected):not(.cp-app-drive-element-selected-tmp) { &:not(.cp-app-drive-element-selected):not(.cp-app-drive-element-selected-tmp) {
border: 1px solid #CCC; border: 1px solid #CCC;
@ -516,6 +517,13 @@ span {
font-size: 18px; font-size: 18px;
} }
} }
.cp-app-drive-element-thumbnail {
max-width: 64px;
max-height: 64px;
& ~ .fa {
display: none;
}
}
} }
.cp-app-drive-element-list { .cp-app-drive-element-list {
display: none; display: none;

@ -1159,11 +1159,16 @@ define([
// The element with the class '.name' is underlined when the 'li' is hovered // The element with the class '.name' is underlined when the 'li' is hovered
var $name = $('<span>', {'class': 'cp-app-drive-element-name'}).text(name); var $name = $('<span>', {'class': 'cp-app-drive-element-name'}).text(name);
$span.html('');
$span.append($name); $span.append($name);
$span.append($state); $span.append($state);
var type = Messages.type[hrefData.type] || hrefData.type; var type = Messages.type[hrefData.type] || hrefData.type;
common.displayThumbnail(data.href, $span, function ($thumb) {
// Called only if the thumbnail exists
$span.find('.cp-icon').addClass('cp-app-drive-element-list');
$thumb.addClass('cp-app-drive-element-grid')
.addClass('cp-app-drive-element-thumbnail');
});
var $type = $('<span>', { var $type = $('<span>', {
'class': 'cp-app-drive-element-type cp-app-drive-element-list' 'class': 'cp-app-drive-element-type cp-app-drive-element-list'
}).text(type); }).text(type);
@ -1181,7 +1186,6 @@ define([
var addFolderData = function (element, key, $span) { var addFolderData = function (element, key, $span) {
if (!element || !filesOp.isFolder(element)) { return; } if (!element || !filesOp.isFolder(element)) { return; }
$span.html('');
// The element with the class '.name' is underlined when the 'li' is hovered // The element with the class '.name' is underlined when the 'li' is hovered
var sf = filesOp.hasSubfolder(element); var sf = filesOp.hasSubfolder(element);
var files = filesOp.hasFile(element); var files = filesOp.hasFile(element);
@ -1239,11 +1243,6 @@ define([
APP.selectedFiles.splice(idx, 1); APP.selectedFiles.splice(idx, 1);
} }
} }
if (isFolder) {
addFolderData(element, key, $element);
} else {
addFileData(element, $element);
}
$element.prepend($icon).dblclick(function () { $element.prepend($icon).dblclick(function () {
if (isFolder) { if (isFolder) {
APP.displayDirectory(newPath); APP.displayDirectory(newPath);
@ -1252,6 +1251,11 @@ define([
if (isTrash) { return; } if (isTrash) { return; }
openFile(root[key]); openFile(root[key]);
}); });
if (isFolder) {
addFolderData(element, key, $element);
} else {
addFileData(element, $element);
}
$element.addClass(liClass); $element.addClass(liClass);
$element.data('path', newPath); $element.data('path', newPath);
addDragAndDropHandlers($element, newPath, isFolder, !isTrash); addDragAndDropHandlers($element, newPath, isFolder, !isTrash);
@ -1850,10 +1854,10 @@ define([
APP.selectedFiles.splice(sidx, 1); APP.selectedFiles.splice(sidx, 1);
} }
} }
addFileData(id, $element);
$element.prepend($icon).dblclick(function () { $element.prepend($icon).dblclick(function () {
openFile(id); openFile(id);
}); });
addFileData(id, $element);
var path = [rootName, idx]; var path = [rootName, idx];
$element.data('path', path); $element.data('path', path);
$element.click(function(e) { $element.click(function(e) {
@ -1886,12 +1890,12 @@ define([
var $element = $('<li>', { var $element = $('<li>', {
'class': 'cp-app-drive-element cp-app-drive-element-row' + roClass 'class': 'cp-app-drive-element cp-app-drive-element-row' + roClass
}); });
addFileData(id, $element);
$element.data('path', [FILES_DATA, id]);
$element.data('element', id);
$element.prepend($icon).dblclick(function () { $element.prepend($icon).dblclick(function () {
openFile(id); openFile(id);
}); });
addFileData(id, $element);
$element.data('path', [FILES_DATA, id]);
$element.data('element', id);
$element.click(function(e) { $element.click(function(e) {
e.stopPropagation(); e.stopPropagation();
onElementClick(e, $element); onElementClick(e, $element);
@ -2018,10 +2022,10 @@ define([
var $element = $('<li>', { var $element = $('<li>', {
'class': 'cp-app-drive-element cp-app-drive-element-file cp-app-drive-element-row' + roClass, 'class': 'cp-app-drive-element cp-app-drive-element-file cp-app-drive-element-row' + roClass,
}); });
addFileData(id, $element);
$element.prepend($icon).dblclick(function () { $element.prepend($icon).dblclick(function () {
openFile(id); openFile(id);
}); });
addFileData(id, $element);
$element.data('path', path); $element.data('path', path);
$element.click(function(e) { $element.click(function(e) {
e.stopPropagation(); e.stopPropagation();

@ -21,11 +21,15 @@
.cp-filepicker-content-element { .cp-filepicker-content-element {
@darker: darken(@colortheme_modal-fg, 30%); @darker: darken(@colortheme_modal-fg, 30%);
width: 200px; width: 125px;
min-width: 200px; //min-width: 200px;
height: 1em; //height: 1em;
padding: 0.5em; padding: 10px;
margin: 5px; margin: 5px;
display: inline-flex;
flex-flow: column;
box-sizing: content-box; box-sizing: content-box;
text-align: left; text-align: left;
@ -41,15 +45,24 @@
color: @colortheme_modal-fg; color: @colortheme_modal-fg;
} }
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
align-items: center; align-items: center;
.cp-filepicker-content-element-name {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
height: 20px;
line-height: 20px;
margin-top: 5px;
max-width: 100%;
}
.fa { .fa {
cursor: pointer; cursor: pointer;
margin-right: 0.5em; width: 100px;
height: 100px;
font-size: 70px;
text-align: center;
line-height: 100px;
} }
} }
} }

@ -114,6 +114,7 @@ define([
} }
var $container = $('<span>', {'class': 'cp-filepicker-content'}).appendTo($block); var $container = $('<span>', {'class': 'cp-filepicker-content'}).appendTo($block);
// Update the files list when needed // Update the files list when needed
updateContainer = function () { updateContainer = function () {
$container.html(''); $container.html('');
@ -132,10 +133,14 @@ define([
'title': name, 'title': name,
}).appendTo($container); }).appendTo($container);
$span.append(Cryptpad.getFileIcon(data)); $span.append(Cryptpad.getFileIcon(data));
$span.append(name); $('<span>', {'class': 'cp-filepicker-content-element-name'}).text(name)
.appendTo($span);
$span.click(function () { $span.click(function () {
if (typeof onSelect === "function") { onSelect(data.href); } if (typeof onSelect === "function") { onSelect(data.href); }
}); });
// Add thumbnail if it exists
common.displayThumbnail(data.href, $span);
}); });
$input.focus(); $input.focus();
}; };

Loading…
Cancel
Save