From 9a25ac537a1bfd009f9a67eb021fc961ae2ad70f Mon Sep 17 00:00:00 2001 From: ClemDee Date: Mon, 22 Jul 2019 12:02:24 +0200 Subject: [PATCH 1/7] Add file plugin to display plain text files --- www/common/media-tag.js | 33 +++++++++++++++++++++++++++++++++ www/file/app-file.less | 10 ++++++++++ 2 files changed, 43 insertions(+) diff --git a/www/common/media-tag.js b/www/common/media-tag.js index c820d9201..95830e296 100644 --- a/www/common/media-tag.js +++ b/www/common/media-tag.js @@ -30,9 +30,22 @@ }; + var isplainTextFile = function (metadata) { + // does it type begins with "text/" + if (metadata.type.indexOf("text/") === 0) { return true; } + // no type and no file extension -> let's guess it's plain text + var parsedName = /^(\.?.+?)(\.[^.]+)?$/.exec(metadata.name) || []; + if (!metadata.type && !parsedName[2]) { return true; } + // other exceptions + if (metadata.type === 'application/x-javascript') { return true; } + if (metadata.type === 'application/xml') { return true; } + return false; + } + // Default config, can be overriden per media-tag call var config = { allowed: [ + 'text/plain', 'image/png', 'image/jpeg', 'image/jpg', @@ -53,6 +66,23 @@ text: "Download" }, Plugins: { + /** + * @param {object} metadataObject {name, metadatatype, owners} containing metadata of the file + * @param {strint} url Url of the blob object + * @param {Blob} content Blob object containing the data of the file + * @param {object} cfg Object {Plugins, allowed, download, pdf} containing infos about plugins + * @param {function} cb Callback function: (err, pluginElement) => {} + */ + text: function (metadata, url, content, cfg, cb) { + var plainText = document.createElement('div'); + plainText.className = "plain-text-reader"; + var reader = new FileReader(); + reader.addEventListener('loadend', function (e) { + plainText.innerText = e.srcElement.result; + cb(void 0, plainText); + }); + reader.readAsText(content); + }, image: function (metadata, url, content, cfg, cb) { var img = document.createElement('img'); img.setAttribute('src', url); @@ -271,6 +301,9 @@ var blob = decrypted.content; var mediaType = getType(mediaObject, metadata, cfg); + if (isplainTextFile(metadata)) { + mediaType = "text"; + } if (mediaType === 'application') { mediaType = mediaObject.extension; diff --git a/www/file/app-file.less b/www/file/app-file.less index 20428b382..4ac94ca33 100644 --- a/www/file/app-file.less +++ b/www/file/app-file.less @@ -52,6 +52,16 @@ max-width: 100%; max-height: ~"calc(100vh - 96px)"; } + .plain-text-reader { + align-self: flex-start; + width: 90vw; + height: 100%; + padding: 2em; + background-color: white; + overflow-y: auto; + word-wrap: break-word; + white-space: pre-wrap; + } } #cp-app-file-upload-form, #cp-app-file-download-form { From ff66c4162bb1ad62332828c808f531c26eee53b4 Mon Sep 17 00:00:00 2001 From: ClemDee Date: Mon, 22 Jul 2019 12:02:24 +0200 Subject: [PATCH 2/7] Add file plugin to display plain text files --- www/common/media-tag.js | 33 +++++++++++++++++++++++++++++++++ www/file/app-file.less | 10 ++++++++++ 2 files changed, 43 insertions(+) diff --git a/www/common/media-tag.js b/www/common/media-tag.js index c820d9201..86bf27b03 100644 --- a/www/common/media-tag.js +++ b/www/common/media-tag.js @@ -30,9 +30,22 @@ }; + var isplainTextFile = function (metadata) { + // does its type begins with "text/" + if (metadata.type.indexOf("text/") === 0) { return true; } + // no type and no file extension -> let's guess it's plain text + var parsedName = /^(\.?.+?)(\.[^.]+)?$/.exec(metadata.name) || []; + if (!metadata.type && !parsedName[2]) { return true; } + // other exceptions + if (metadata.type === 'application/x-javascript') { return true; } + if (metadata.type === 'application/xml') { return true; } + return false; + } + // Default config, can be overriden per media-tag call var config = { allowed: [ + 'text/plain', 'image/png', 'image/jpeg', 'image/jpg', @@ -53,6 +66,23 @@ text: "Download" }, Plugins: { + /** + * @param {object} metadataObject {name, metadatatype, owners} containing metadata of the file + * @param {strint} url Url of the blob object + * @param {Blob} content Blob object containing the data of the file + * @param {object} cfg Object {Plugins, allowed, download, pdf} containing infos about plugins + * @param {function} cb Callback function: (err, pluginElement) => {} + */ + text: function (metadata, url, content, cfg, cb) { + var plainText = document.createElement('div'); + plainText.className = "plain-text-reader"; + var reader = new FileReader(); + reader.addEventListener('loadend', function (e) { + plainText.innerText = e.srcElement.result; + cb(void 0, plainText); + }); + reader.readAsText(content); + }, image: function (metadata, url, content, cfg, cb) { var img = document.createElement('img'); img.setAttribute('src', url); @@ -271,6 +301,9 @@ var blob = decrypted.content; var mediaType = getType(mediaObject, metadata, cfg); + if (isplainTextFile(metadata)) { + mediaType = "text"; + } if (mediaType === 'application') { mediaType = mediaObject.extension; diff --git a/www/file/app-file.less b/www/file/app-file.less index 20428b382..4ac94ca33 100644 --- a/www/file/app-file.less +++ b/www/file/app-file.less @@ -52,6 +52,16 @@ max-width: 100%; max-height: ~"calc(100vh - 96px)"; } + .plain-text-reader { + align-self: flex-start; + width: 90vw; + height: 100%; + padding: 2em; + background-color: white; + overflow-y: auto; + word-wrap: break-word; + white-space: pre-wrap; + } } #cp-app-file-upload-form, #cp-app-file-download-form { From cb76211a3875aaf9cf3487448e87811487b91a70 Mon Sep 17 00:00:00 2001 From: ClemDee Date: Wed, 24 Jul 2019 14:00:00 +0200 Subject: [PATCH 3/7] Fix missing semi-colon --- www/common/media-tag.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/common/media-tag.js b/www/common/media-tag.js index 86bf27b03..186fe4632 100644 --- a/www/common/media-tag.js +++ b/www/common/media-tag.js @@ -40,7 +40,7 @@ if (metadata.type === 'application/x-javascript') { return true; } if (metadata.type === 'application/xml') { return true; } return false; - } + }; // Default config, can be overriden per media-tag call var config = { From fe2539394bd2215a8c8125d0365261c87329234b Mon Sep 17 00:00:00 2001 From: ClemDee Date: Wed, 24 Jul 2019 14:06:04 +0200 Subject: [PATCH 4/7] Add dummy open-in-code in drive context menu --- www/common/common-util.js | 19 +++++++++++++++++++ www/drive/inner.js | 23 ++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/www/common/common-util.js b/www/common/common-util.js index 9fd2305c3..124a72344 100644 --- a/www/common/common-util.js +++ b/www/common/common-util.js @@ -319,6 +319,25 @@ define([], function () { return window.innerHeight < 800 || window.innerWidth < 800; }; + Util.isPlainTextFile = function (metadata) { + if (!metadata || !metadata.href) { return; } + console.log("%c" + metadata.title + " : " + metadata.fileType, "color: #3a7"); + console.log(metadata); + var href = metadata.roHref || metadata.href; + // is it a file ? + if (!href || href.indexOf("/file/") === -1) { return false; } + // does its type begins with "text/" + if (metadata.fileType.indexOf("text/") === 0) { return true; } + // no type and no file extension -> let's guess it's plain text + var parsedName = /^(\.?.+?)(\.[^.]+)?$/.exec(metadata.title) || []; + if (!metadata.fileType && !parsedName[2]) { return true; } + // other exceptions + if (metadata.fileType === 'application/x-javascript') { return true; } + if (metadata.fileType === 'application/xml') { return true; } + return false; + }; + + return Util; }); }(self)); diff --git a/www/drive/inner.js b/www/drive/inner.js index f393cac3f..d3e06e39b 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -81,6 +81,7 @@ define([ var faCollapseAll = 'fa-minus-square-o'; var faShared = 'fa-shhare-alt'; var faReadOnly = 'fa-eye'; + var faOpenInCode = 'cptools-code'; var faRename = 'fa-pencil'; var faColor = 'cptools-palette'; var faTrash = 'fa-trash'; @@ -315,6 +316,10 @@ define([ 'tabindex': '-1', 'data-icon': faReadOnly, }, Messages.fc_open_ro)), + h('li', h('a.cp-app-drive-context-openincode.dropdown-item', { + 'tabindex': '-1', + 'data-icon': faOpenInCode, + }, Messages.fc_openInCode || "Open in Code")), $separator.clone()[0], h('li', h('a.cp-app-drive-context-expandall.dropdown-item', { 'tabindex': '-1', @@ -1019,6 +1024,11 @@ define([ } else if ($element.is('.cp-app-drive-element-noreadonly')) { hide.push('openro'); // Remove open 'view' mode } + // if it's not a plain text file + var metadata = manager.getFileData(manager.find(path)); + if (!metadata || !Util.isPlainTextFile(metadata)) { + hide.push('openincode'); + } } else if ($element.is('.cp-app-drive-element-sharedf')) { if (containsFolder) { // More than 1 folder selected: cannot create a new subfolder @@ -1028,6 +1038,7 @@ define([ } containsFolder = true; hide.push('openro'); + hide.push('openincode'); hide.push('hashtag'); hide.push('delete'); //hide.push('deleteowned'); @@ -1040,6 +1051,7 @@ define([ } containsFolder = true; hide.push('openro'); + hide.push('openincode'); hide.push('properties'); hide.push('share'); hide.push('hashtag'); @@ -1089,7 +1101,7 @@ define([ show = ['newfolder', 'newsharedfolder', 'newdoc']; break; case 'tree': - show = ['open', 'openro', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', 'properties', 'hashtag']; + show = ['open', 'openro', 'openincode', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', 'properties', 'hashtag']; break; case 'default': show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'hashtag']; @@ -3525,6 +3537,15 @@ define([ openFile(null, href); }); } + else if ($(this).hasClass('cp-app-drive-context-openincode')) { + paths.forEach(function (p) { + console.info("p", p); + var el = manager.find(p.path); + var metadata = manager.getFileData(el); + console.log(el); + // open code from template + }); + } else if ($(this).hasClass('cp-app-drive-context-expandall') || $(this).hasClass('cp-app-drive-context-collapseall')) { if (paths.length !== 1) { return; } From f55c8c6b0458b2eac483a832d23be2ba6a0e5ff2 Mon Sep 17 00:00:00 2001 From: ClemDee Date: Tue, 13 Aug 2019 16:09:06 +0200 Subject: [PATCH 5/7] Open plain text files in code app && plain text files thumbnail --- www/common/common-constants.js | 1 + www/common/common-thumbnail.js | 30 ++++++++++++- www/common/common-ui-elements.js | 29 +++++++++++-- www/common/common-util.js | 29 +++++++------ www/common/cryptpad-common.js | 67 +++++++++++++++++++++++++++++- www/common/sframe-app-framework.js | 2 +- www/common/sframe-common-file.js | 2 +- www/common/sframe-common-outer.js | 31 +++++++++++++- www/drive/inner.js | 24 ++++++++--- 9 files changed, 190 insertions(+), 25 deletions(-) diff --git a/www/common/common-constants.js b/www/common/common-constants.js index 986e115e2..ac51dfbca 100644 --- a/www/common/common-constants.js +++ b/www/common/common-constants.js @@ -7,6 +7,7 @@ define(function () { fileHashKey: 'FS_hash', // sessionStorage newPadPathKey: "newPadPath", + newPadFileData: "newPadFileData", // Store displayNameKey: 'cryptpad.username', oldStorageKey: 'CryptPad_RECENTPADS', diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js index 34d44daf5..4b9d7e595 100644 --- a/www/common/common-thumbnail.js +++ b/www/common/common-thumbnail.js @@ -15,6 +15,7 @@ define([ }; var supportedTypes = [ + 'text/plain', 'image/png', 'image/jpeg', 'image/jpg', @@ -23,7 +24,11 @@ define([ 'application/pdf' ]; - Thumb.isSupportedType = function (type) { + Thumb.isSupportedType = function (file) { + var type = file.type; + if (Util.isPlainTextFile(file.type, file.name)) { + type = "text/plain"; + } return supportedTypes.some(function (t) { return type.indexOf(t) !== -1; }); @@ -164,6 +169,26 @@ define([ }); }); }; + Thumb.fromPlainTextBlob = function (blob, cb) { + var canvas = document.createElement("canvas"); + canvas.width = canvas.height = Thumb.dimension; + var reader = new FileReader(); + reader.addEventListener('loadend', function (e) { + var content = e.srcElement.result; + var lines = content.split("\n"); + var canvasContext = canvas.getContext("2d"); + var fontSize = 4; + canvas.height = (lines.length) * (fontSize + 1); + canvasContext.font = fontSize + 'px monospace'; + lines.forEach(function (text, i) { + + canvasContext.fillText(text, 5, i * (fontSize + 1)); + }); + var D = getResizedDimensions(canvas, "txt"); + Thumb.fromCanvas(canvas, D, cb); + }); + reader.readAsText(blob); + }; Thumb.fromBlob = function (blob, cb) { if (blob.type.indexOf('video/') !== -1) { return void Thumb.fromVideoBlob(blob, cb); @@ -171,6 +196,9 @@ define([ if (blob.type.indexOf('application/pdf') !== -1) { return void Thumb.fromPdfBlob(blob, cb); } + if (Util.isPlainTextFile(blob.type, blob.name)) { + return void Thumb.fromPlainTextBlob(blob, cb); + } Thumb.fromImageBlob(blob, cb); }; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index bc465cdfb..831f1bb71 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2274,7 +2274,10 @@ define([ if (!common.isLoggedIn()) { return void cb(); } var sframeChan = common.getSframeChannel(); var metadataMgr = common.getMetadataMgr(); + var privateData = metadataMgr.getPrivateData(); var type = metadataMgr.getMetadataLazy().type; + var fromFileData = privateData.fromFileData; + var $body = $('body'); var $creationContainer = $('
', { id: 'cp-creation-container' }).appendTo($body); @@ -2286,7 +2289,8 @@ define([ // Title //var colorClass = 'cp-icon-color-'+type; //$creation.append(h('h2.cp-creation-title', Messages.newButtonTitle)); - $creation.append(h('h3.cp-creation-title', Messages['button_new'+type])); + var newPadH3Title = Messages['button_new' + type]; + $creation.append(h('h3.cp-creation-title', newPadH3Title)); //$creation.append(h('h2.cp-creation-title.'+colorClass, Messages.newButtonTitle)); // Deleted pad warning @@ -2296,7 +2300,7 @@ define([ )); } - var origin = common.getMetadataMgr().getPrivateData().origin; + var origin = privateData.origin; var createHelper = function (href, text) { var q = h('a.cp-creation-help.fa.fa-question-circle', { title: text, @@ -2453,7 +2457,26 @@ define([ }); if (i < TEMPLATES_DISPLAYED) { $(left).addClass('hidden'); } }; - redraw(0); + if (fromFileData) { + var todo = function (thumbnail) { + allData = [{ + name: fromFileData.title, + id: 0, + thumbnail: thumbnail, + icon: h('span.cptools.cptools-file'), + }]; + redraw(0); + }; + todo(); + sframeChan.query("Q_GET_FILE_THUMBNAIL", null, function (err, res) { + if (err || (res && res.error)) { return; } + todo(res.data); + }); + } + else { + redraw(0); + } + // Change template selection when Tab is pressed next = function (revert) { diff --git a/www/common/common-util.js b/www/common/common-util.js index 124a72344..171d37624 100644 --- a/www/common/common-util.js +++ b/www/common/common-util.js @@ -319,21 +319,26 @@ define([], function () { return window.innerHeight < 800 || window.innerWidth < 800; }; - Util.isPlainTextFile = function (metadata) { - if (!metadata || !metadata.href) { return; } - console.log("%c" + metadata.title + " : " + metadata.fileType, "color: #3a7"); - console.log(metadata); - var href = metadata.roHref || metadata.href; - // is it a file ? - if (!href || href.indexOf("/file/") === -1) { return false; } + // return an + Util.parseFilename = function (filename) { + if (!filename || !filename.trim()) { return {}; } + var parsedName = /^(\.?.+?)(\.[^.]+)?$/.exec(filename) || []; + return { + name: parsedName[1], + ext: parsedName[2], + } + } + + // Tell if a file is plain text from its metadata={title, fileType} + Util.isPlainTextFile = function (type, name) { // does its type begins with "text/" - if (metadata.fileType.indexOf("text/") === 0) { return true; } + if (type && type.indexOf("text/") === 0) { return true; } // no type and no file extension -> let's guess it's plain text - var parsedName = /^(\.?.+?)(\.[^.]+)?$/.exec(metadata.title) || []; - if (!metadata.fileType && !parsedName[2]) { return true; } + var parsedName = Util.parseFilename(name); + if (!type && name && !parsedName.ext) { return true; } // other exceptions - if (metadata.fileType === 'application/x-javascript') { return true; } - if (metadata.fileType === 'application/xml') { return true; } + if (type === 'application/x-javascript') { return true; } + if (type === 'application/xml') { return true; } return false; }; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index fef46951c..f6527bf26 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -9,11 +9,12 @@ define([ '/common/outer/local-store.js', '/common/outer/worker-channel.js', '/common/outer/login-block.js', + '/file/file-crypto.js', '/customize/application_config.js', '/bower_components/nthen/index.js', ], function (Config, Messages, Util, Hash, - Messaging, Constants, Feedback, LocalStore, Channel, Block, + Messaging, Constants, Feedback, LocalStore, Channel, Block, FileCrypto, AppConfig, Nthen) { /* This file exposes functionality which is specific to Cryptpad, but not to @@ -567,6 +568,64 @@ define([ }); }; + common.useFile = function (Crypt, cb, optsPut) { + var data = common.fromFileData; + var parsed = Hash.parsePadUrl(data.href); + var parsed2 = Hash.parsePadUrl(window.location.href); + var hash = parsed.hash; + var name = data.title; + var secret = Hash.getSecrets('file', hash, data.password); + var src = Hash.getBlobPathFromHex(secret.channel); + var key = secret.keys && secret.keys.cryptKey; + + var u8; + var res; + var mode; + var val; + Nthen(function(waitFor) { + Util.fetch(src, waitFor(function (err, _u8) { + if (err) { return void waitFor.abort(); } + u8 = _u8; + })); + }).nThen(function (waitFor) { + FileCrypto.decrypt(u8, key, waitFor(function (err, _res) { + if (err || !_res.content) { return void waitFor.abort(); } + res = _res; + })); + }).nThen(function (waitFor) { + var ext = Util.parseFilename(data.title).ext; + if (!ext) { + mode = "text"; + return; + } + require(["/common/modes.js"], waitFor(function (Modes) { + var fileType = Modes.list.some(function (fType) { + if (fType.ext === ext) { + mode = fType.mode; + return true; + } + }); + })); + }).nThen(function (waitFor) { + var reader = new FileReader(); + reader.addEventListener('loadend', waitFor(function (e) { + val = { + content: e.srcElement.result, + highlightMode: mode, + metadata: { + defaultTitle: name, + title: name, + type: "code", + }, + }; + })); + reader.readAsText(res.content); + }).nThen(function () { + Crypt.put(parsed2.hash, JSON.stringify(val), cb, optsPut); + }); + + }; + // Forget button common.moveToTrash = function (cb, href) { href = href || window.location.href; @@ -1263,6 +1322,12 @@ define([ messenger: rdyCfg.messenger, // Boolean driveEvents: rdyCfg.driveEvents // Boolean }; + // if a pad is created from a file + if (sessionStorage[Constants.newPadFileData]) { + common.fromFileData = JSON.parse(sessionStorage[Constants.newPadFileData]); + delete sessionStorage[Constants.newPadFileData]; + } + if (sessionStorage[Constants.newPadPathKey]) { common.initialPath = sessionStorage[Constants.newPadPathKey]; delete sessionStorage[Constants.newPadPathKey]; diff --git a/www/common/sframe-app-framework.js b/www/common/sframe-app-framework.js index f1068a6de..92311b44b 100644 --- a/www/common/sframe-app-framework.js +++ b/www/common/sframe-app-framework.js @@ -454,7 +454,7 @@ define([ return; } if (!mediaTagEmbedder) { console.log('mediaTagEmbedder missing'); return; } - if (data.type !== 'file') { console.log('unhandled embed type ' + data.type); return; } + if (data.type !== 'file') { console.log('unhandled embed type ' + data.type); return; } var privateDat = cpNfInner.metadataMgr.getPrivateData(); var origin = privateDat.fileHost || privateDat.origin; var src = data.src = origin + data.src; diff --git a/www/common/sframe-common-file.js b/www/common/sframe-common-file.js index 099176afd..573f39357 100644 --- a/www/common/sframe-common-file.js +++ b/www/common/sframe-common-file.js @@ -367,7 +367,7 @@ define([ blobToArrayBuffer(file, function (e, buffer) { if (e) { console.error(e); } file_arraybuffer = buffer; - if (!Thumb.isSupportedType(file.type)) { return getName(); } + if (!Thumb.isSupportedType(file)) { return getName(); } // make a resized thumbnail from the image.. Thumb.fromBlob(file, function (e, thumb64) { if (e) { console.error(e); } diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index fba08279a..588c2bfad 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -317,6 +317,9 @@ define([ channel: secret.channel, enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default devMode: localStorage.CryptPad_dev === "1", + fromFileData: Cryptpad.fromFileData ? { + title: Cryptpad.fromFileData.title + } : undefined, }; if (window.CryptPad_newSharedFolder) { additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder; @@ -357,6 +360,8 @@ define([ sframeChan.event("EV_NEW_VERSION"); }); + + // Put in the following function the RPC queries that should also work in filepicker var addCommonRpc = function (sframeChan) { sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) { @@ -808,6 +813,22 @@ define([ }); }); + sframeChan.on('Q_GET_FILE_THUMBNAIL', function (data, cb) { + if (!Cryptpad.fromFileData.href) { + return void cb({ + error: "EINVAL", + }); + } + var key = getKey(Cryptpad.fromFileData.href, Cryptpad.fromFileData.channel); + Utils.LocalStore.getThumbnail(key, function (e, data) { + if (data === "EMPTY") { data = null; } + cb({ + error: e, + data: data + }); + }); + }); + sframeChan.on('EV_GOTO_URL', function (url) { if (url) { window.location.href = url; @@ -1080,11 +1101,11 @@ define([ })); } }).nThen(function () { + var cryptputCfg = $.extend(true, {}, rtConfig, {password: password}); if (data.template) { // Pass rtConfig to useTemplate because Cryptput will create the file and // we need to have the owners and expiration time in the first line on the // server - var cryptputCfg = $.extend(true, {}, rtConfig, {password: password}); Cryptpad.useTemplate({ href: data.template }, Cryptget, function () { @@ -1093,6 +1114,14 @@ define([ }, cryptputCfg); return; } + // if we open a new code from a file + if (Cryptpad.fromFileData) { + Cryptpad.useFile(Cryptget, function () { + startRealtime(); + cb(); + }, cryptputCfg); + return; + } // Start realtime outside the iframe and callback startRealtime(rtConfig); cb(); diff --git a/www/drive/inner.js b/www/drive/inner.js index d3e06e39b..c6fdc6067 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -1025,10 +1025,15 @@ define([ hide.push('openro'); // Remove open 'view' mode } // if it's not a plain text file + var isPlainTextFile = false; var metadata = manager.getFileData(manager.find(path)); - if (!metadata || !Util.isPlainTextFile(metadata)) { - hide.push('openincode'); + if (metadata) { + var href = metadata.roHref || metadata.href; + if (href && Hash.parsePadUrl(href).type === "file") { + isPlainTextFile = Util.isPlainTextFile(metadata.fileType, metadata.title); + } } + if (!isPlainTextFile) { hide.push('openincode'); } } else if ($element.is('.cp-app-drive-element-sharedf')) { if (containsFolder) { // More than 1 folder selected: cannot create a new subfolder @@ -3539,11 +3544,20 @@ define([ } else if ($(this).hasClass('cp-app-drive-context-openincode')) { paths.forEach(function (p) { - console.info("p", p); var el = manager.find(p.path); var metadata = manager.getFileData(el); - console.log(el); - // open code from template + var simpleData = { + title: metadata.filename || metadata.title, + href: metadata.href, + password: metadata.password, + channel: metadata.channel, + }; + nThen(function (waitFor) { + common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(simpleData), waitFor()); + common.sessionStorage.put(Constants.newPadPathKey, currentPath, waitFor()); + }).nThen(function () { + common.openURL('/code/'); + }); }); } else if ($(this).hasClass('cp-app-drive-context-expandall') || From 4f84a928a9d98d67a90ee289a557bb52d05d355d Mon Sep 17 00:00:00 2001 From: ClemDee Date: Tue, 13 Aug 2019 18:05:03 +0200 Subject: [PATCH 6/7] Small fixes and improvements --- www/common/common-thumbnail.js | 1 + www/common/cryptpad-common.js | 11 ++++---- www/common/sframe-common-outer.js | 2 +- www/drive/inner.js | 42 +++++++++++++++---------------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/www/common/common-thumbnail.js b/www/common/common-thumbnail.js index 4b9d7e595..89f381eea 100644 --- a/www/common/common-thumbnail.js +++ b/www/common/common-thumbnail.js @@ -25,6 +25,7 @@ define([ ]; Thumb.isSupportedType = function (file) { + if (!file) { return false; } var type = file.type; if (Util.isPlainTextFile(file.type, file.name)) { type = "text/plain"; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index f6527bf26..208396d34 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -9,12 +9,11 @@ define([ '/common/outer/local-store.js', '/common/outer/worker-channel.js', '/common/outer/login-block.js', - '/file/file-crypto.js', '/customize/application_config.js', '/bower_components/nthen/index.js', ], function (Config, Messages, Util, Hash, - Messaging, Constants, Feedback, LocalStore, Channel, Block, FileCrypto, + Messaging, Constants, Feedback, LocalStore, Channel, Block, AppConfig, Nthen) { /* This file exposes functionality which is specific to Cryptpad, but not to @@ -588,9 +587,11 @@ define([ u8 = _u8; })); }).nThen(function (waitFor) { - FileCrypto.decrypt(u8, key, waitFor(function (err, _res) { - if (err || !_res.content) { return void waitFor.abort(); } - res = _res; + require(["/file/file-crypto.js"], waitFor(function (FileCrypto) { + FileCrypto.decrypt(u8, key, waitFor(function (err, _res) { + if (err || !_res.content) { return void waitFor.abort(); } + res = _res; + })); })); }).nThen(function (waitFor) { var ext = Util.parseFilename(data.title).ext; diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 588c2bfad..a8283c9f3 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -814,7 +814,7 @@ define([ }); sframeChan.on('Q_GET_FILE_THUMBNAIL', function (data, cb) { - if (!Cryptpad.fromFileData.href) { + if (!Cryptpad.fromFileData || !Cryptpad.fromFileData.href) { return void cb({ error: "EINVAL", }); diff --git a/www/drive/inner.js b/www/drive/inner.js index c6fdc6067..baafae0f4 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -319,7 +319,7 @@ define([ h('li', h('a.cp-app-drive-context-openincode.dropdown-item', { 'tabindex': '-1', 'data-icon': faOpenInCode, - }, Messages.fc_openInCode || "Open in Code")), + }, Messages.fc_openInCode || "Open in Code")), // XXX $separator.clone()[0], h('li', h('a.cp-app-drive-context-expandall.dropdown-item', { 'tabindex': '-1', @@ -1014,6 +1014,7 @@ define([ } if (!$element.is('.cp-border-color-file')) { hide.push('download'); + hide.push('openincode'); } if ($element.is('.cp-app-drive-element-file')) { // No folder in files @@ -1027,13 +1028,9 @@ define([ // if it's not a plain text file var isPlainTextFile = false; var metadata = manager.getFileData(manager.find(path)); - if (metadata) { - var href = metadata.roHref || metadata.href; - if (href && Hash.parsePadUrl(href).type === "file") { - isPlainTextFile = Util.isPlainTextFile(metadata.fileType, metadata.title); - } + if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) { + hide.push('openincode'); } - if (!isPlainTextFile) { hide.push('openincode'); } } else if ($element.is('.cp-app-drive-element-sharedf')) { if (containsFolder) { // More than 1 folder selected: cannot create a new subfolder @@ -1090,6 +1087,7 @@ define([ hide.push('openparent'); hide.push('hashtag'); hide.push('download'); + hide.push('openincode'); // can't because of race condition } if (containsFolder && paths.length > 1) { // Cannot open multiple folders @@ -3543,21 +3541,21 @@ define([ }); } else if ($(this).hasClass('cp-app-drive-context-openincode')) { - paths.forEach(function (p) { - var el = manager.find(p.path); - var metadata = manager.getFileData(el); - var simpleData = { - title: metadata.filename || metadata.title, - href: metadata.href, - password: metadata.password, - channel: metadata.channel, - }; - nThen(function (waitFor) { - common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(simpleData), waitFor()); - common.sessionStorage.put(Constants.newPadPathKey, currentPath, waitFor()); - }).nThen(function () { - common.openURL('/code/'); - }); + if (paths.length !== 1) { return; } + var p = paths[0]; + var el = manager.find(p.path); + var metadata = manager.getFileData(el); + var simpleData = { + title: metadata.filename || metadata.title, + href: metadata.href, + password: metadata.password, + channel: metadata.channel, + }; + nThen(function (waitFor) { + common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(simpleData), waitFor()); + common.sessionStorage.put(Constants.newPadPathKey, currentPath, waitFor()); + }).nThen(function () { + common.openURL('/code/'); }); } else if ($(this).hasClass('cp-app-drive-context-expandall') || From 79b667c8352e0babbf5cd1cc377d13b50ab87085 Mon Sep 17 00:00:00 2001 From: ClemDee Date: Fri, 16 Aug 2019 13:51:16 +0200 Subject: [PATCH 7/7] Remove translation fallback --- www/drive/inner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/drive/inner.js b/www/drive/inner.js index baafae0f4..f1bf3e0be 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -319,7 +319,7 @@ define([ h('li', h('a.cp-app-drive-context-openincode.dropdown-item', { 'tabindex': '-1', 'data-icon': faOpenInCode, - }, Messages.fc_openInCode || "Open in Code")), // XXX + }, Messages.fc_openInCode)), $separator.clone()[0], h('li', h('a.cp-app-drive-context-expandall.dropdown-item', { 'tabindex': '-1',