diff --git a/customize.dist/loading.js b/customize.dist/loading.js
index 52a70b5c3..22dc69c31 100644
--- a/customize.dist/loading.js
+++ b/customize.dist/loading.js
@@ -279,7 +279,7 @@ button:not(.btn).primary:hover{
var built = false;
var types = ['less', 'drive', 'migrate', 'sf', 'team', 'pad', 'end'];
- var current;
+ var current, progress;
var makeList = function (data) {
var c = types.indexOf(data.type);
current = c;
@@ -295,7 +295,7 @@ button:not(.btn).primary:hover{
};
var list = '
';
types.forEach(function (el, i) {
- if (i >= 6) { return; }
+ if (el === "end") { return; }
list += getLi(i);
});
list += '
';
@@ -303,7 +303,7 @@ button:not(.btn).primary:hover{
};
var makeBar = function (data) {
var c = types.indexOf(data.type);
- var l = types.length;
+ var l = types.length - 1; // don't count "end" as a type
var progress = Math.min(data.progress, 100);
var p = (progress / l) + (100 * c / l);
var bar = '
'+
@@ -315,8 +315,13 @@ button:not(.btn).primary:hover{
var hasErrored = false;
var updateLoadingProgress = function (data) {
if (!built || !data) { return; }
+
+ // Make sure progress doesn't go backward
var c = types.indexOf(data.type);
if (c < current) { return console.error(data); }
+ if (c === current && progress > data.progress) { return console.error(data); }
+ progress = data.progress;
+
try {
var el1 = document.querySelector('.cp-loading-spinner-container');
if (el1) { el1.style.display = 'none'; }
diff --git a/customize.dist/src/less2/include/sidebar-layout.less b/customize.dist/src/less2/include/sidebar-layout.less
index ace7350df..4273b0b9a 100644
--- a/customize.dist/src/less2/include/sidebar-layout.less
+++ b/customize.dist/src/less2/include/sidebar-layout.less
@@ -118,7 +118,7 @@
//border-radius: 0 0.25em 0.25em 0;
//border: 1px solid #adadad;
border-left: 0px;
- height: @variables_input-height;
+ height: 40px;
margin: 0 !important;
}
}
diff --git a/www/common/common-interface.js b/www/common/common-interface.js
index 9fae121dc..3e9d848cd 100644
--- a/www/common/common-interface.js
+++ b/www/common/common-interface.js
@@ -65,12 +65,13 @@ define([
switch (e.which) {
case 27: // cancel
if (typeof(no) === 'function') { no(e); }
+ $(el || window).off('keydown', handler);
break;
case 13: // enter
if (typeof(yes) === 'function') { yes(e); }
+ $(el || window).off('keydown', handler);
break;
}
- $(el || window).off('keydown', handler);
};
$(el || window).keydown(handler);
diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js
index 076fa52fe..5dd029def 100644
--- a/www/common/cryptpad-common.js
+++ b/www/common/cryptpad-common.js
@@ -701,7 +701,7 @@ define([
});
};
- common.useFile = function (Crypt, cb, optsPut) {
+ common.useFile = function (Crypt, cb, optsPut, onProgress) {
var fileHost = Config.fileHost || window.location.origin;
var data = common.fromFileData;
var parsed = Hash.parsePadUrl(data.href);
@@ -758,7 +758,9 @@ define([
return void cb(err);
}
u8 = _u8;
- }));
+ }), function (progress) {
+ onProgress(progress * 50);
+ });
}).nThen(function (waitFor) {
require(["/file/file-crypto.js"], waitFor(function (FileCrypto) {
FileCrypto.decrypt(u8, key, waitFor(function (err, _res) {
@@ -767,7 +769,9 @@ define([
return void cb(err);
}
res = _res;
- }));
+ }), function (progress) {
+ onProgress(50 + progress * 50);
+ });
}));
}).nThen(function (waitFor) {
var ext = Util.parseFilename(data.title).ext;
diff --git a/www/common/inner/common-mediatag.js b/www/common/inner/common-mediatag.js
index 3d28d126a..86900f5bb 100644
--- a/www/common/inner/common-mediatag.js
+++ b/www/common/inner/common-mediatag.js
@@ -17,11 +17,18 @@ define([
var Nacl = window.nacl;
// Configure MediaTags to use our local viewer
+ // This file is loaded by sframe-common so the following config is used in all the inner apps
if (MediaTag) {
MediaTag.setDefaultConfig('pdf', {
viewer: '/common/pdfjs/web/viewer.html'
});
+ Messages.mediatag_saveButton = "Save"; // XXX
+ MediaTag.setDefaultConfig('download', {
+ text: Messages.download_mt_button,
+ textDl: Messages.mediatag_saveButton
+ });
}
+ MT.MediaTag = MediaTag;
// Cache of the avatars outer html (including )
var avatars = {};
@@ -68,7 +75,7 @@ define([
childList: true,
characterData: false
});
- MediaTag($tag[0]).on('error', function (data) {
+ MediaTag($tag[0], {force: true}).on('error', function (data) {
console.error(data);
});
};
@@ -362,6 +369,10 @@ define([
});
};
+ Messages.pad_mediatagShare = "Share file"; // XXX
+ Messages.pad_mediatagOpen = "Open file"; // XXX
+ Messages.mediatag_notReady = "Not ready"; // XXX
+
var mediatagContextMenu;
MT.importMediaTagMenu = function (common) {
if (mediatagContextMenu) { return mediatagContextMenu; }
@@ -377,6 +388,14 @@ define([
'tabindex': '-1',
'data-icon': "fa-eye",
}, Messages.pad_mediatagPreview)),
+ h('li.cp-svg', h('a.cp-app-code-context-openin.dropdown-item', {
+ 'tabindex': '-1',
+ 'data-icon': "fa-external-link",
+ }, Messages.pad_mediatagOpen)),
+ h('li.cp-svg', h('a.cp-app-code-context-share.dropdown-item', {
+ 'tabindex': '-1',
+ 'data-icon': "fa-shhare-alt",
+ }, Messages.pad_mediatagShare)),
h('li', h('a.cp-app-code-context-saveindrive.dropdown-item', {
'tabindex': '-1',
'data-icon': "fa-cloud-upload",
@@ -413,12 +432,29 @@ define([
}
else if ($this.hasClass("cp-app-code-context-download")) {
var media = Util.find($mt, [0, '_mediaObject']);
+ if (!media) { return void console.error('no media'); }
+ if (!media.complete) { return void UI.warn(Messages.mediatag_notReady); }
if (!(media && media._blob)) { return void console.error($mt); }
window.saveAs(media._blob.content, media.name);
}
else if ($this.hasClass("cp-app-code-context-open")) {
$mt.trigger('preview');
}
+ else if ($this.hasClass("cp-app-code-context-openin")) {
+ var hash = common.getHashFromMediaTag($mt);
+ common.openURL(Hash.hashToHref(hash, 'file'));
+ }
+ else if ($this.hasClass("cp-app-code-context-share")) {
+ var data = {
+ file: true,
+ pathname: '/file/',
+ hashes: {
+ fileHash: common.getHashFromMediaTag($mt)
+ },
+ title: Util.find($mt[0], ['_mediaObject', 'name']) || ''
+ };
+ common.getSframeChannel().event('EV_SHARE_OPEN', data);
+ }
});
return m;
diff --git a/www/common/media-tag.js b/www/common/media-tag.js
index e86fd6071..e4ec9ce2a 100644
--- a/www/common/media-tag.js
+++ b/www/common/media-tag.js
@@ -603,7 +603,8 @@ var factory = function (Cache) {
if (cfg.force) { dl(); return mediaObject; }
- var maxSize = 5 * 1024 * 1024;
+ var maxSize = typeof(config.maxDownloadSize) === "number" ? config.maxDownloadSize
+ : (5 * 1024 * 1024);
getFileSize(src, function (err, size) {
if (err) {
return void error(err);
diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js
index ededee769..a46a94837 100644
--- a/www/common/sframe-common-outer.js
+++ b/www/common/sframe-common-outer.js
@@ -1808,7 +1808,12 @@ define([
}
startRealtime();
cb();
- }, cryptputCfg);
+ }, cryptputCfg, function (progress) {
+ sframeChan.event('EV_LOADING_INFO', {
+ type: 'pad',
+ progress: progress
+ });
+ });
return;
}
// Start realtime outside the iframe and callback
diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js
index 4198a649a..328bd70c8 100644
--- a/www/common/sframe-common.js
+++ b/www/common/sframe-common.js
@@ -142,7 +142,7 @@ define([
}
return;
};
- funcs.importMediaTag = function ($mt) {
+ var getMtData = function ($mt) {
if (!$mt || !$mt.is('media-tag')) { return; }
var chanStr = $mt.attr('src');
var keyStr = $mt.attr('data-crypto-key');
@@ -154,10 +154,27 @@ define([
var channel = src.replace(/\/blob\/[0-9a-f]{2}\//i, '');
// Get key
var key = keyStr.replace(/cryptpad:/i, '');
+ return {
+ channel: channel,
+ key: key
+ };
+ };
+ funcs.getHashFromMediaTag = function ($mt) {
+ var data = getMtData($mt);
+ if (!data) { return; }
+ return Hash.getFileHashFromKeys({
+ version: 1,
+ channel: data.channel,
+ keys: { fileKeyStr: data.key }
+ });
+ };
+ funcs.importMediaTag = function ($mt) {
+ var data = getMtData($mt);
+ if (!data) { return; }
var metadata = $mt[0]._mediaObject._blob.metadata;
ctx.sframeChan.query('Q_IMPORT_MEDIATAG', {
- channel: channel,
- key: key,
+ channel: data.channel,
+ key: data.key,
name: metadata.name,
type: metadata.type,
owners: metadata.owners
@@ -792,6 +809,12 @@ define([
var privateData = ctx.metadataMgr.getPrivateData();
funcs.addShortcuts(window, Boolean(privateData.app));
+ var mt = Util.find(privateData, ['settings', 'general', 'mediatag-size']);
+ if (MT.MediaTag && typeof(mt) === "number") {
+ var maxMtSize = mt === -1 ? Infinity : mt * 1024 * 1024;
+ MT.MediaTag.setDefaultConfig('maxDownloadSize', maxMtSize);
+ }
+
try {
var feedback = privateData.feedbackAllowed;
Feedback.init(feedback);
diff --git a/www/file/inner.js b/www/file/inner.js
index c29657672..6cc129de5 100644
--- a/www/file/inner.js
+++ b/www/file/inner.js
@@ -39,9 +39,6 @@ define([
var Nacl = window.nacl;
var APP = window.APP = {};
- MediaTag.setDefaultConfig('download', {
- text: Messages.download_mt_button
- });
var andThen = function (common) {
var $appContainer = $('#cp-app-file-content');
@@ -203,7 +200,6 @@ define([
cb();
}
}).on('progress', function (data) {
- if (data.progress > 75) { return; }
var p = data.progress +'%';
$progress.width(p);
$progressTxt.text(Math.floor(data.progress) + '%');
diff --git a/www/pad/inner.js b/www/pad/inner.js
index 5139197e0..8a99b6101 100644
--- a/www/pad/inner.js
+++ b/www/pad/inner.js
@@ -46,6 +46,7 @@ define([
'/common/test.js',
'/bower_components/diff-dom/diffDOM.js',
+ '/bower_components/file-saver/FileSaver.min.js',
'css!/customize/src/print.css',
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
@@ -1085,6 +1086,9 @@ define([
border: Messages.pad_mediatagBorder,
preview: Messages.pad_mediatagPreview,
'import': Messages.pad_mediatagImport,
+ download: Messages.download_mt_button,
+ share: Messages.pad_mediatagShare,
+ open: Messages.pad_mediatagOpen,
options: Messages.pad_mediatagOptions
};
Ckeditor._commentsTranslations = {
@@ -1165,6 +1169,28 @@ define([
editor.plugins.mediatag.import = function($mt) {
framework._.sfCommon.importMediaTag($mt);
};
+ editor.plugins.mediatag.download = function($mt) {
+ var media = Util.find($mt, [0, '_mediaObject']);
+ if (!media) { return void console.error('no media'); }
+ if (!media.complete) { return void UI.warn(Messages.mediatag_notReady); }
+ if (!(media && media._blob)) { return void console.error($mt); }
+ window.saveAs(media._blob.content, media.name);
+ };
+ editor.plugins.mediatag.open = function($mt) {
+ var hash = framework._.sfCommon.getHashFromMediaTag($mt);
+ framework._.sfCommon.openURL(Hash.hashToHref(hash, 'file'));
+ };
+ editor.plugins.mediatag.share = function($mt) {
+ var data = {
+ file: true,
+ pathname: '/file/',
+ hashes: {
+ fileHash: framework._.sfCommon.getHashFromMediaTag($mt)
+ },
+ title: Util.find($mt[0], ['_mediaObject', 'name']) || ''
+ };
+ framework._.sfCommon.getSframeChannel().event('EV_SHARE_OPEN', data);
+ };
Links.init(Ckeditor, editor);
}).nThen(function() {
// Move ckeditor parts to have a structure like the other apps
diff --git a/www/pad/mediatag-plugin.js b/www/pad/mediatag-plugin.js
index 46747b18a..22a732748 100644
--- a/www/pad/mediatag-plugin.js
+++ b/www/pad/mediatag-plugin.js
@@ -53,15 +53,57 @@
editor.plugins.mediatag.import($mt);
}
});
+ editor.addCommand('downloadMT', {
+ exec: function (editor) {
+ var w = targetWidget;
+ targetWidget = undefined;
+ var $mt = $(w.$).find('media-tag');
+ editor.plugins.mediatag.download($mt);
+ }
+ });
+ editor.addCommand('openMT', {
+ exec: function (editor) {
+ var w = targetWidget;
+ targetWidget = undefined;
+ var $mt = $(w.$).find('media-tag');
+ editor.plugins.mediatag.open($mt);
+ }
+ });
+ editor.addCommand('shareMT', {
+ exec: function (editor) {
+ var w = targetWidget;
+ targetWidget = undefined;
+ var $mt = $(w.$).find('media-tag');
+ editor.plugins.mediatag.share($mt);
+ }
+ });
if (editor.addMenuItems) {
editor.addMenuGroup('mediatag');
+ editor.addMenuItem('open', {
+ label: Messages.open,
+ icon: 'iframe',
+ command: 'openMT',
+ group: 'mediatag'
+ });
+ editor.addMenuItem('share', {
+ label: Messages.share,
+ icon: 'link',
+ command: 'shareMT',
+ group: 'mediatag'
+ });
editor.addMenuItem('importMediatag', {
label: Messages.import,
icon: 'save',
command: 'importMediatag',
group: 'mediatag'
});
+ editor.addMenuItem('download', {
+ label: Messages.download,
+ icon: 'save',
+ command: 'downloadMT',
+ group: 'mediatag'
+ });
editor.addMenuItem('mediatag', {
label: Messages.options,
icon: 'image',
@@ -76,6 +118,9 @@
targetWidget = element;
return {
mediatag: CKEDITOR.TRISTATE_OFF,
+ open: CKEDITOR.TRISTATE_OFF,
+ share: CKEDITOR.TRISTATE_OFF,
+ download: CKEDITOR.TRISTATE_OFF,
importMediatag: CKEDITOR.TRISTATE_OFF,
};
}
diff --git a/www/secureiframe/inner.js b/www/secureiframe/inner.js
index c20d53a80..4d5b8ee4f 100644
--- a/www/secureiframe/inner.js
+++ b/www/secureiframe/inner.js
@@ -52,10 +52,10 @@ define([
: Share.getShareModal;
f(common, {
origin: priv.origin,
- pathname: priv.pathname,
- password: priv.password,
- isTemplate: priv.isTemplate,
- hashes: priv.hashes,
+ pathname: data.pathname || priv.pathname,
+ password: data.hashes ? '' : priv.password,
+ isTemplate: data.hashes ? false : priv.isTemplate,
+ hashes: data.hashes || priv.hashes,
common: common,
title: data.title,
versionHash: data.versionHash,
@@ -64,8 +64,8 @@ define([
hideIframe();
},
fileData: {
- hash: priv.hashes.fileHash,
- password: priv.password
+ hash: (data.hashes && data.hashes.fileHash) || priv.hashes.fileHash,
+ password: data.hashes ? '' : priv.password
}
}, function (e, modal) {
if (e) { console.error(e); }
diff --git a/www/settings/app-settings.less b/www/settings/app-settings.less
index 1f0da1263..0ac3d10f2 100644
--- a/www/settings/app-settings.less
+++ b/www/settings/app-settings.less
@@ -74,6 +74,10 @@
margin-right: 100%;
}
}
+ & > .fa {
+ align-self: center;
+ margin-right: -16px;
+ }
}
.cp-settings-info-block {
[type="text"] {
diff --git a/www/settings/inner.js b/www/settings/inner.js
index 8882f5861..9ff57aae7 100644
--- a/www/settings/inner.js
+++ b/www/settings/inner.js
@@ -51,7 +51,7 @@ define([
'cp-settings-info-block',
'cp-settings-displayname',
'cp-settings-language-selector',
- 'cp-settings-resettips',
+ 'cp-settings-mediatag-size',
'cp-settings-change-password',
'cp-settings-delete'
],
@@ -62,6 +62,7 @@ define([
'cp-settings-userfeedback',
],
'drive': [
+ 'cp-settings-resettips',
'cp-settings-drive-duplicate',
'cp-settings-thumbnails',
'cp-settings-drive-backup',
@@ -576,6 +577,59 @@ define([
cb(form);
}, true);
+ Messages.settings_mediatagSizeTitle = "Autodownload size in MegaBytes (MB)"; // XXX
+ Messages.settings_mediatagSizeHint = 'Maximum size for automatically loading media elements (images, videos, pdf) embedded into the pads. Elements bigger than the specified size can be loaded manually. Use "-1" to always load the media elements automatically.'; // XXX
+ makeBlock('mediatag-size', function(cb) {
+ var $inputBlock = $('
', {
+ 'class': 'cp-sidebarlayout-input-block',
+ });
+
+ var spinner;
+ var $input = $('', {
+ 'min': -1,
+ 'max': 1000,
+ type: 'number',
+ }).appendTo($inputBlock);
+
+ var oldVal;
+
+ var todo = function () {
+ var val = parseInt($input.val());
+ if (val === oldVal) { return; }
+ if (typeof(val) !== 'number') { return UI.warn(Messages.error); }
+ spinner.spin();
+ common.setAttribute(['general', 'mediatag-size'], val, function (err) {
+ if (err) {
+ spinner.hide();
+ console.error(err);
+ return UI.warn(Messages.error);
+ }
+ spinner.done();
+ UI.log(Messages.saved);
+ });
+ };
+ var $save = $(h('button.btn.btn-primary', Messages.settings_save)).appendTo($inputBlock);
+ spinner = UI.makeSpinner($inputBlock);
+
+ $save.click(todo);
+ $input.on('keyup', function(e) {
+ if (e.which === 13) { todo(); }
+ });
+
+ common.getAttribute(['general', 'mediatag-size'], function(e, val) {
+ if (e) { return void console.error(e); }
+ if (typeof(val) !== 'number') {
+ oldVal = 5;
+ $input.val(5);
+ } else {
+ oldVal = val;
+ $input.val(val);
+ }
+ });
+
+ cb($inputBlock);
+ }, true);
+
// Security
makeBlock('safe-links', function(cb) {
diff --git a/www/support/ui.js b/www/support/ui.js
index 9b86d6f20..a58fdf170 100644
--- a/www/support/ui.js
+++ b/www/support/ui.js
@@ -397,6 +397,7 @@ define([
var fmConfig = {
body: $('body'),
+ noStore: true, // Don't store attachments into our drive
onUploaded: function (ev, data) {
if (ev.callback) {
ev.callback(data);
diff --git a/www/whiteboard/inner.js b/www/whiteboard/inner.js
index 44efd1421..bab1603dc 100644
--- a/www/whiteboard/inner.js
+++ b/www/whiteboard/inner.js
@@ -331,10 +331,11 @@ define([
APP.FM.handleFile(blob);
});
};
+ var MAX_IMAGE_SIZE = 1 * 1024 * 1024; // 1 MB
+ var maxSizeStr = Messages._getKey('formattedMB', [Util.bytesToMegabytes(MAX_IMAGE_SIZE)]);
var addImageToCanvas = function (img) {
- // 1 MB maximum
- if (img.src && img.src.length > 1 * 1024 * 1024) {
- UI.warn(Messages.upload_tooLargeBrief);
+ if (img.src && img.src.length > MAX_IMAGE_SIZE) {
+ UI.warn(Messages._getKey('upload_tooLargeBrief', [maxSizeStr])); // XXX update key
return;
}
var w = img.width;
@@ -356,8 +357,8 @@ define([
var file = e.target.files[0];
var reader = new FileReader();
// 1 MB maximum
- if (file.size > 1 * 1024 * 1024) {
- UI.warn(Messages.upload_tooLargeBrief);
+ if (file.size > MAX_IMAGE_SIZE) {
+ UI.warn(Messages._getKey('upload_tooLargeBrief', [maxSizeStr]));
return;
}
reader.onload = function () {