Deduplicate code between File and MediaTag

This commit is contained in:
yflory 2020-12-03 15:22:39 +01:00
parent 1c4ddf6e7b
commit 43ad4f0a84
9 changed files with 89 additions and 234 deletions

View File

@ -64,26 +64,7 @@
}
}
.markdown_cryptpad() {
word-wrap: break-word;
h1, h2, h3, h4, h5, h6 {
font-weight: bold;
padding-bottom: 0.3em;
border-bottom: 1px solid #eee;
}
li {
min-height: 22px;
}
.todo-list-item {
list-style: none;
position: relative;
.fa {
position: absolute;
margin-left: -17px;
margin-top: 4px;
}
}
.mediatag_cryptpad() {
media-tag {
cursor: pointer;
* {
@ -126,6 +107,30 @@
display: inline-block;
border: 1px solid #BBB;
}
}
.markdown_cryptpad() {
word-wrap: break-word;
h1, h2, h3, h4, h5, h6 {
font-weight: bold;
padding-bottom: 0.3em;
border-bottom: 1px solid #eee;
}
li {
min-height: 22px;
}
.todo-list-item {
list-style: none;
position: relative;
.fa {
position: absolute;
margin-left: -17px;
margin-top: 4px;
}
}
.mediatag_cryptpad();
pre.markmap {
border: 1px solid #ddd;

View File

@ -1,6 +1,7 @@
@import (reference) "./colortheme-all.less";
@import (reference) "./variables.less";
@import (reference) "./browser.less";
@import (reference) "./markdown.less";
.modals-ui-elements_main() {
--LessLoader_require: LessLoader_currentFile();
@ -214,6 +215,7 @@
flex: 1;
min-width: 0;
overflow: auto;
.mediatag_cryptpad();
media-tag {
& > * {
max-width: 100%;

View File

@ -3,9 +3,9 @@ define([
'/common/common-util.js',
'/common/visible.js',
'/common/common-hash.js',
'/file/file-crypto.js',
'/common/media-tag.js',
'/bower_components/tweetnacl/nacl-fast.min.js',
], function ($, Util, Visible, Hash, FileCrypto) {
], function ($, Util, Visible, Hash, MediaTag) {
var Nacl = window.nacl;
var Thumb = {
dimension: 100,
@ -314,7 +314,7 @@ define([
var hexFileName = secret.channel;
var src = fileHost + Hash.getBlobPathFromHex(hexFileName);
var key = secret.keys && secret.keys.cryptKey;
FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) {
MediaTag.fetchDecryptedMetadata(src, key, function (e, metadata) {
if (e) {
if (e === 'XHR_ERROR') { return; }
return console.error(e);

View File

@ -125,7 +125,6 @@ var factory = function () {
};
var makeProgressBar = function (cfg, mediaObject) {
// XXX CSP: we'll need to add style in cryptpad's less
if (mediaObject.bar) { return; }
mediaObject.bar = true;
var style = (function(){/*
@ -151,10 +150,10 @@ var factory = function () {
}
.mediatag-progress-text {
height: 25px;
width: 50px;
margin-left: 5px;
line-height: 25px;
vertical-align: top;
width: auto;
display: inline-block;
color: #3F4141;
font-weight: bold;
@ -618,6 +617,7 @@ var factory = function () {
var handlers = cfg.handlers || {
'progress': [],
'complete': [],
'metadata': [],
'error': []
};
@ -700,8 +700,7 @@ var factory = function () {
if (errDecryption) {
return void reject(errDecryption);
}
// XXX emit 'metadata' u8Decrypted.metadata
// Cache and display the decrypted blob
emit('metadata', u8Decrypted.metadata);
resolve(u8Decrypted);
}, function (progress) {
emit('progress', {
@ -736,21 +735,18 @@ var factory = function () {
var maxSize = typeof(config.maxDownloadSize) === "number" ? config.maxDownloadSize
: (5 * 1024 * 1024);
getFileSize(src, function (err, size) {
if (err) {
return void error(err);
}
// If the size is smaller than the autodownload limit, load the blob.
// If the blob is already loaded or being loaded, don't show the button.
if (!size || size < maxSize || getCache()) {
makeProgressBar(cfg, mediaObject);
return void dl();
}
var sizeMb = Math.round(10 * size / 1024 / 1024) / 10;
fetchDecryptedMetadata(src, strKey, function (err, md) {
if (err) { return void error(err); }
cfg.metadata = md;
// XXX emit 'metadata'
fetchDecryptedMetadata(src, strKey, function (err, md) {
if (err) { return void error(err); }
cfg.metadata = md;
emit('metadata', md);
getFileSize(src, function (err, size) {
// If the size is smaller than the autodownload limit, load the blob.
// If the blob is already loaded or being loaded, don't show the button.
if (!size || size < maxSize || getCache()) {
makeProgressBar(cfg, mediaObject);
return void dl();
}
var sizeMb = Math.round(10 * size / 1024 / 1024) / 10;
makeDownloadButton(cfg, mediaObject, sizeMb, dl);
});
});
@ -765,6 +761,8 @@ var factory = function () {
config[key] = value;
};
init.fetchDecryptedMetadata = fetchDecryptedMetadata;
return init;
};

View File

@ -1,5 +1,6 @@
@import (reference) '../../customize/src/less2/include/tokenfield.less';
@import (reference) '../../customize/src/less2/include/framework.less';
@import (reference) '../../customize/src/less2/include/markdown.less';
&.cp-app-file {
@ -47,6 +48,7 @@
z-index: -1;
}
.mediatag_cryptpad();
media-tag {
img {
max-width: 100%;
@ -198,6 +200,9 @@
max-height: 100%;
max-width: 100%;
}
&:empty {
display: none !important;
}
}
}

View File

@ -48,69 +48,6 @@ define([
return new Blob(chunks);
};
var concatBuffer = function (a, b) { // TODO make this not so ugly
return new Uint8Array(slice(a).concat(slice(b)));
};
var fetchMetadata = function (src, cb) {
var done = false;
var CB = function (err, res) {
if (done) { return; }
done = true;
cb(err, res);
};
var xhr = new XMLHttpRequest();
xhr.open("GET", src, true);
xhr.setRequestHeader('Range', 'bytes=0-1');
xhr.responseType = 'arraybuffer';
xhr.onerror= function () { return CB('XHR_ERROR'); };
xhr.onload = function () {
if (/^4/.test('' + this.status)) { return CB('XHR_ERROR'); }
var res = new Uint8Array(xhr.response);
var size = decodePrefix(res);
var xhr2 = new XMLHttpRequest();
xhr2.open("GET", src, true);
xhr2.setRequestHeader('Range', 'bytes=2-' + (size + 2));
xhr2.responseType = 'arraybuffer';
xhr2.onload = function () {
if (/^4/.test('' + this.status)) { return CB('XHR_ERROR'); }
var res2 = new Uint8Array(xhr2.response);
var all = concatBuffer(res, res2);
CB(void 0, all);
};
xhr2.send(null);
};
xhr.send(null);
};
var decryptMetadata = function (u8, key) {
var prefix = u8.subarray(0, 2);
var metadataLength = decodePrefix(prefix);
var metaBox = new Uint8Array(u8.subarray(2, 2 + metadataLength));
var metaChunk = Nacl.secretbox.open(metaBox, createNonce(), key);
try {
return JSON.parse(Nacl.util.encodeUTF8(metaChunk));
}
catch (e) { return null; }
};
var fetchDecryptedMetadata = function (src, key, cb) {
if (typeof(src) !== 'string') {
return window.setTimeout(function () {
cb('NO_SOURCE');
});
}
fetchMetadata(src, function (e, buffer) {
if (e) { return cb(e); }
cb(void 0, decryptMetadata(buffer, key));
});
};
var decrypt = function (u8, key, done, progress) {
var MAX = u8.length;
var _progress = function (offset) {
@ -268,8 +205,5 @@ define([
encrypt: encrypt,
joinChunks: joinChunks,
computeEncryptedSize: computeEncryptedSize,
decryptMetadata: decryptMetadata,
fetchMetadata: fetchMetadata,
fetchDecryptedMetadata: fetchDecryptedMetadata,
};
});

View File

@ -16,7 +16,6 @@
<label for="cp-app-file-upfile" class="btn btn-primary cp-app-file-block unselectable" data-localization-title="upload_choose"
data-localization="upload_choose"></label>
</div>
<div id="cp-app-file-download-form" style="display: none;"> </div>
<div id="cp-app-file-download-view" style="display: none;">
<media-tag id="cp-app-file-view"></media-tag>
</div>

View File

@ -43,7 +43,6 @@ define([
var andThen = function (common) {
var $appContainer = $('#cp-app-file-content');
var $form = $('#cp-app-file-upload-form');
var $dlform = $('#cp-app-file-download-form');
var $dlview = $('#cp-app-file-download-view');
var $label = $form.find('label');
var $bar = $('.cp-toolbar-container');
@ -86,36 +85,44 @@ define([
if (!uploadMode) {
(function () {
Messages.download = "Download"; // XXX
Messages.decrypt = "Decrypt"; // XXX
var progress = h('div.cp-app-file-progress');
var progressTxt = h('span.cp-app-file-progress-txt');
var $progress = $(progress);
var $progressTxt = $(progressTxt);
var downloadEl = h('span.cp-app-file-progress-dl', Messages.download);
var decryptEl = h('span.cp-app-file-progress-dc', Messages.decrypt);
var progressContainer = h('div.cp-app-file-progress-container', [
downloadEl,
decryptEl,
progress
]);
var hexFileName = secret.channel;
var src = fileHost + Hash.getBlobPathFromHex(hexFileName);
var key = secret.keys && secret.keys.cryptKey;
var cryptKey = Nacl.util.encodeBase64(key);
FileCrypto.fetchDecryptedMetadata(src, key, function (e, metadata) {
if (e) {
if (e === 'XHR_ERROR') {
return void UI.errorLoadingScreen(Messages.download_resourceNotAvailable, false, function () {
common.gotoURL('/file/');
});
}
return void console.error(e);
var $mt = $dlview.find('media-tag');
$mt.attr('src', src);
$mt.attr('data-crypto-key', 'cryptpad:'+cryptKey);
$mt.css('transform', 'scale(2)');
var rightsideDisplayed = false;
var metadataReceived = false;
UI.removeLoadingScreen();
$dlview.show();
MediaTag($mt[0]).on('complete', function (decrypted) {
$mt.css('transform', '');
if (!rightsideDisplayed) {
toolbar.$drawer
.append(common.createButton('export', true, {}, function () {
saveAs(decrypted.content, decrypted.metadata.name);
}));
rightsideDisplayed = true;
}
// make pdfs big
var toolbarHeight = $('#cp-toolbar').height();
$('media-tag iframe').css({
'height': 'calc(100vh - ' + toolbarHeight + 'px)',
'width': '100vw',
'position': 'absolute',
'bottom': 0,
'left': 0,
'border': 0
});
}).on('metadata', function (metadata) {
if (metadataReceived) { return; }
metadataReceived = true;
// Add pad attributes when the file is saved in the drive
Title.onTitleChange(function () {
var owners = metadata.owners;
@ -150,106 +157,11 @@ define([
toolbar.$drawer.append(common.createButton('hashtag', true));
}
toolbar.$file.show();
var displayFile = function (ev, sizeMb, CB) {
var called_back;
var cb = function (e) {
if (called_back) { return; }
called_back = true;
if (CB) { CB(e); }
};
var $mt = $dlview.find('media-tag');
$mt.attr('src', src);
$mt.attr('data-crypto-key', 'cryptpad:'+cryptKey);
var rightsideDisplayed = false;
MediaTag($mt[0], {
force: true // Download starts automatically
}).on('complete', function (decrypted) {
$dlview.show();
$dlform.hide();
var $dlButton = $dlview.find('media-tag button');
if (ev) { $dlButton.click(); }
if (!rightsideDisplayed) {
toolbar.$drawer
.append(common.createButton('export', true, {}, function () {
saveAs(decrypted.content, decrypted.metadata.name);
}));
rightsideDisplayed = true;
}
// make pdfs big
var toolbarHeight = $('#cp-toolbar').height();
var $another_iframe = $('media-tag iframe').css({
'height': 'calc(100vh - ' + toolbarHeight + 'px)',
'width': '100vw',
'position': 'absolute',
'bottom': 0,
'left': 0,
'border': 0
});
if ($another_iframe.length) {
$another_iframe.load(function () {
cb();
});
} else {
cb();
}
}).on('progress', function (data) {
var p = data.progress +'%';
$progress.width(p);
$progressTxt.text(Math.floor(data.progress) + '%');
}).on('error', function (err) {
console.error(err);
});
};
// XXX Update "download_button" key to use "download" first and "decrypt" second
var todoBigFile = function (sizeMb) {
$dlform.show();
UI.removeLoadingScreen();
var button = h('button.btn.btn-primary', {
title: Messages.download_button
}, Messages.download_button);
$dlform.append([
h('h2', Util.fixHTML(metadata.name)),
h('div.cp-button-container', [
button,
progressTxt
]),
]);
// don't display the size if you don't know it.
if (typeof(sizeMb) === 'number') {
$dlform.find('h2').append(' - ' +
Messages._getKey('formattedMB', [sizeMb]));
}
var decrypting = false;
var onClick = function (ev) {
if (decrypting) { return; }
decrypting = true;
$(button).prop('disabled', 'disabled');
$dlform.append(progressContainer);
displayFile(ev, sizeMb, function (err) {
$appContainer.css('background-color',
common.getAppConfig().appBackgroundColor);
if (err) { UI.alert(err); }
});
};
if (typeof(sizeMb) === 'number' && sizeMb < 5) { return void onClick(); }
$(button).click(onClick);
};
common.getFileSize(hexFileName, function (e, data) {
if (e) {
return void UI.errorLoadingScreen(e);
}
var size = Util.bytesToMegabytes(data);
return void todoBigFile(size);
});
}).on('error', function (err) {
$appContainer.css('background-color',
common.getAppConfig().appBackgroundColor);
UI.warn(Messages.error);
console.error(err);
});
})();
return;

View File

@ -478,7 +478,7 @@ define([
var list_values = slice(el.children)
.map(function (el) { return el.outerHTML; })
.join('');
mediaMap[el.getAttribute('src')] = list_values;
mediaTagMap[el.getAttribute('src')] = list_values;
if (mediaObject.complete) { observer.disconnect(); }
}
});