diff --git a/customize.dist/main.css b/customize.dist/main.css index 49f06eedc..9e459880a 100644 --- a/customize.dist/main.css +++ b/customize.dist/main.css @@ -1164,6 +1164,57 @@ html.cp, .limit-container .upgrade { margin-left: 10px; } +/* Upload status table */ +#uploadStatusContainer { + position: absolute; + left: 10vw; + right: 10vw; + bottom: 100px; + background-color: rgba(0, 0, 0, 0.5); + color: white; + opacity: 0.7; + font-family: Ubuntu,Georgia,Cambria,serif; + box-sizing: border-box; + z-index: 10; + display: none; +} +#uploadStatusContainer #uploadStatus { + width: 80vw; + border: 1px solid black; + border-collapse: collapse; +} +#uploadStatusContainer #uploadStatus tr:nth-child(1) { + background-color: #888; + border: 1px solid #999; +} +#uploadStatusContainer #uploadStatus tr:nth-child(1) td { + text-align: center; +} +#uploadStatusContainer #uploadStatus td { + border-left: 1px solid #BBB; + border-right: 1px solid #BBB; + padding: 0 10px; +} +#uploadStatusContainer #uploadStatus .upProgress { + width: 200px; + position: relative; + text-align: center; + box-sizing: border-box; +} +#uploadStatusContainer #uploadStatus .progressContainer { + position: absolute; + width: 0px; + left: 5px; + top: 1px; + bottom: 1px; + background-color: rgba(0, 0, 255, 0.3); +} +#uploadStatusContainer #uploadStatus .upCancel { + text-align: center; +} +#uploadStatusContainer #uploadStatus .fa.cancel { + color: #ff0073; +} #cors-store { display: none; } diff --git a/customize.dist/src/less/cryptpad.less b/customize.dist/src/less/cryptpad.less index 49608df00..e0c071d41 100644 --- a/customize.dist/src/less/cryptpad.less +++ b/customize.dist/src/less/cryptpad.less @@ -600,6 +600,52 @@ noscript { } } +/* Upload status table */ +#uploadStatusContainer { + position: absolute; + left: 10vw; right: 10vw; + bottom: 100px; + background-color: rgba(0,0,0,0.5); + color: white; + opacity: 0.7; + font-family: Ubuntu,Georgia,Cambria,serif; + box-sizing: border-box; + z-index:10; + display: none; + #uploadStatus { + width: 80vw; + border: 1px solid black; + border-collapse: collapse; + tr:nth-child(1) { + background-color: #888; + border: 1px solid #999; + td { text-align: center; } + } + td { + border-left: 1px solid #BBB; + border-right: 1px solid #BBB; + padding: 0 10px; + } + .upProgress { + width: 200px; + position: relative; + text-align: center; + box-sizing: border-box; + } + .progressContainer { + position: absolute; + width: 0px; + left: 5px; + top: 1px; bottom: 1px; + background-color: rgba(0,0,255,0.3); + } + .upCancel { text-align: center; } + .fa.cancel { + color: rgb(255, 0, 115); + } + } +} + // hack for our cross-origin iframe #cors-store { display: none; diff --git a/www/common/common-file.js b/www/common/common-file.js index 7cb62a083..bd6a85908 100644 --- a/www/common/common-file.js +++ b/www/common/common-file.js @@ -6,7 +6,7 @@ define([ var Nacl = window.nacl; var module = {}; - module.create = function (common) { + module.create = function (common, config) { var File = {}; var Messages = common.Messages; @@ -32,7 +32,24 @@ define([ return File.$container; }; - var upload = function (blob, metadata, id) { + var getData = function (file, href) { + var data = {}; + + data.name = file.metadata.name; + data.url = href; + if (file.metadata.type.slice(0,6) === 'image/') { + data.mediatag = true; + } + //var generatedBlob = new Blob([file.blob]); + //window.URL.createObjectURL(generatedBlob); + + return data; + }; + + var upload = function (file) { + var blob = file.blob; + var metadata = file.metadata; + var id = file.id; if (queue.inProgress) { return; } queue.inProgress = true; @@ -102,12 +119,18 @@ define([ // TODO add button to table which copies link to clipboard? //APP.toolbar.addElement(['fileshare'], {}); - var title = document.title = metadata.name; + var title = metadata.name; common.renamePad(title || "", href, function (err) { - if (err) { console.error(err); } // TODO + if (err) { return void console.error(err); } // TODO console.log(title); common.log(Messages._getKey('upload_success', [title])); + + if (config.onUploaded) { + var data = getData(file, href); + config.onUploaded(file.dropEvent, data); + } + queue.inProgress = false; queue.next(); }); @@ -157,10 +180,16 @@ define([ }; queue.next = function () { - if (queue.queue.length === 0) { return; } + if (queue.queue.length === 0) { + queue.to = window.setTimeout(function () { + File.$container.fadeOut(); + }, 3000); + return; + } if (queue.inProgress) { return; } + File.$container.show(); var file = queue.queue.shift(); - upload(file.blob, file.metadata, file.id); + upload(file); }; queue.push = function (obj) { var id = uid(); @@ -195,7 +224,7 @@ define([ queue.next(); }; - var handleFile = File.handleFile = function (file) { + var handleFile = File.handleFile = function (file, e) { console.log(file); var reader = new FileReader(); reader.onloadend = function () { @@ -204,7 +233,8 @@ define([ metadata: { name: file.name, type: file.type, - } + }, + dropEvent: e }); }; reader.readAsArrayBuffer(file); @@ -241,16 +271,18 @@ define([ $hoverArea.removeClass('hovering'); Array.prototype.slice.call(dropped).forEach(function (d) { - todo(d); + todo(d, e); }); }); }; - File.createUploader = function ($area, $hover, $body) { + var createUploader = function ($area, $hover, $body) { createAreaHandlers($area, null, handleFile); createTableContainer($body); }; + createUploader(config.dropArea, config.hoverArea, config.body); + return File; }; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index af8a600ca..7d2885d15 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -117,7 +117,7 @@ define([ common.createCodemirror = CodeMirror.create; // Files - common.createFileManager = function () { return Files.create(common); }; + common.createFileManager = function (config) { return Files.create(common, config); }; // History common.getHistory = function (config) { return History.create(common, config); }; @@ -594,7 +594,7 @@ define([ common.alert(Messages.pinLimitNotPinned, null, true); return; } - else { throw new Error("Cannot push this pad to CryptDrive", e); } + else { return void cb(e); } } getStore().addPad(id, common.initialPath); }); @@ -637,7 +637,7 @@ define([ common.setPadTitle(title, href, function (err) { if (err) { console.log("unable to set pad title"); - console.log(err); + console.error(err); return; } callback(null, title); diff --git a/www/common/diffMarked.js b/www/common/diffMarked.js index f53e01d61..d78dc5480 100644 --- a/www/common/diffMarked.js +++ b/www/common/diffMarked.js @@ -1,8 +1,11 @@ define([ 'jquery', '/bower_components/marked/marked.min.js', - '/bower_components/diff-dom/diffDOM.js' -],function ($, Marked) { + '/common/cryptpad-common.js', + '/common/media-tag.js', + '/bower_components/diff-dom/diffDOM.js', + '/bower_components/tweetnacl/nacl-fast.min.js', +],function ($, Marked, Cryptpad, MediaTag) { var DiffMd = {}; var DiffDOM = window.diffDOM; @@ -33,6 +36,20 @@ define([ var cls = (isCheckedTaskItem || isUncheckedTaskItem) ? ' class="todo-list-item"' : ''; return '' + text + '\n'; }; + renderer.image = function (href, title, text) { + if (href.slice(0,6) === '/file/') { + var parsed = Cryptpad.parsePadUrl(href); + var hexFileName = Cryptpad.base64ToHex(parsed.hashData.channel); + var mt = ''; + return mt; + } + var out = '' + text + '' : '>'; + return out; + }; var forbiddenTags = [ 'SCRIPT', @@ -61,6 +78,30 @@ define([ } }; + var getSubMediaTag = function (element) { + var result = []; + console.log(element); + if (element.nodeName === "MEDIA-TAG") { + result.push(element); + return result; + } + if (element.childNodes) { + element.childNodes.forEach(function (el) { + result = result.concat(getSubMediaTag(el, result)); + }); + } + console.log(result); + return result; + }; + var mediaTag = function (info) { + if (info.diff.action === 'addElement') { + return getSubMediaTag(info.diff.element); + //MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes); + //MediaTag($mt[0]); + } + return; + }; + var slice = function (coll) { return Array.prototype.slice.call(coll); }; @@ -82,9 +123,20 @@ define([ return Dom; }; + //var toTransform = []; var DD = new DiffDOM({ preDiffApply: function (info) { if (unsafeTag(info)) { return true; } + //var mt = mediaTag(info); + //console.log(mt); + //if (mt) { toTransform = toTransform.concat(mt); } + }, + postDiffApply: function () { + /*while (toTransform.length) { + var el = toTransform.pop(); + console.log(el); + MediaTag(el); + }*/ } }); @@ -119,6 +171,29 @@ define([ throw new Error(patch); } else { DD.apply($content[0], patch); + var $mts = $content.find('media-tag:not(:has(*))'); + $mts.each(function (i, el) { + console.log(el); + var allowedMediaTypes = [ + 'image/png', + 'image/jpeg', + 'image/jpg', + 'image/gif', + 'audio/mp3', + 'audio/ogg', + 'audio/wav', + 'audio/webm', + 'video/mp4', + 'video/ogg', + 'video/webm', + 'application/pdf', + 'application/dash+xml', + 'download' + ]; + + MediaTag.CryptoFilter.setAllowedMediaTypes(allowedMediaTypes); + MediaTag(el); + }); } }; diff --git a/www/file/main.js b/www/file/main.js index 2351df39c..dcd2139d1 100644 --- a/www/file/main.js +++ b/www/file/main.js @@ -158,16 +158,19 @@ define([ display: 'block', }); - var FM = Cryptpad.createFileManager(); + var fmConfig = { + dropArea: $form, + hoverArea: $label, + body: $body + }; + + var FM = Cryptpad.createFileManager(fmConfig); $form.find("#file").on('change', function (e) { var file = e.target.files[0]; FM.handleFile(file); }); - //FM.createDropArea($form, $label, handleFile); - FM.createUploader($form, $label, $body); - // we're in upload mode Cryptpad.removeLoadingScreen(); }; diff --git a/www/slide/main.js b/www/slide/main.js index 4d6765e14..e197fcc52 100644 --- a/www/slide/main.js +++ b/www/slide/main.js @@ -47,6 +47,7 @@ define([ }; var andThen = function (CMeditor) { + var $iframe = $('#pad-iframe').contents(); var CodeMirror = Cryptpad.createCodemirror(CMeditor, ifrw, Cryptpad); editor = CodeMirror.editor; @@ -508,6 +509,37 @@ define([ if (readOnly) { return; } UserList.getLastName(toolbar.$userNameButton, isNew); + + + /*editor.on('dragover', function (e) { + //console.log(editor.coordsChar()); + console.log(e); + });*/ + var fmConfig = { + dropArea: $iframe.find('.CodeMirror'), + body: $iframe.find('body'), + onUploaded: function (ev, data) { + console.log(ev, data); + /* + TODO: test if getCursor() works + If we can drop a file without updating the cursor, we'll need the following + code to get the cursor position from the drop event + var obj = { + left: ev.originalEvent.pageX, + top: ev.originalEvent.pageY, + }; + var cursor = editor.coordsChar(obj); + */ + var cursor = editor.getCursor(); + var cleanName = data.name.replace(/[\[\]]/g, ''); + var text = '['+cleanName+']('+data.url+')'; + if (data.mediatag) { + var text = '!['+cleanName+']('+data.url+')'; + } + editor.replaceSelection(text); + } + }; + var FM = Cryptpad.createFileManager(fmConfig); }; config.onRemote = function () {