Display thumbnails in the drive and then file picker
This commit is contained in:
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…
x
Reference in New Issue
Block a user