Display thumbnails in the drive and then file picker

This commit is contained in:
yflory 2017-10-17 17:17:31 +02:00
parent e553351b79
commit 4116d08dd1
7 changed files with 96 additions and 28 deletions

View File

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

View File

@ -3,14 +3,19 @@ define([
'/api/config',
'/common/cryptpad-common.js',
'/common/common-util.js',
'/common/common-hash.js',
'/common/media-tag.js',
'/common/tippy.min.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',
], function ($, Config, Cryptpad, Util, MediaTag, Tippy, AppConfig) {
], function ($, Config, Cryptpad, Util, Hash, MediaTag, Tippy, AppConfig, FileCrypto, localForage) {
var UI = {};
var Messages = Cryptpad.Messages;
var Nacl = window.nacl;
/**
* Requirements from cryptpad-common.js
@ -28,6 +33,40 @@ define([
* - 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) {
var sframeChan = common.getSframeChannel();
sframeChan.query('Q_TAGS_GET', href || null, function (err, res) {
@ -92,7 +131,7 @@ define([
target: data.target
};
if (data.filter && !data.filter(file)) {
Cryptpad.log('TODO: invalid avatar (type or size)');
Cryptpad.log('Invalid avatar (type or size)');
return;
}
data.FM.handleFile(file, ev);
@ -398,9 +437,6 @@ define([
}, LIMIT_REFRESH_RATE * 3);
updateUsage();
/*getProxy().on('change', ['drive'], function () {
updateUsage();
}); TODO*/
cb(null, $container);
};

View File

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

View File

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

View File

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

View File

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

View File

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