diff --git a/scripts/copy-components.js b/scripts/copy-components.js index 577100c81..24831aca7 100644 --- a/scripts/copy-components.js +++ b/scripts/copy-components.js @@ -46,6 +46,6 @@ Fse.rmSync(oldComponentsPath, { recursive: true, force: true }); ].forEach(l => { const source = Path.join("node_modules", l); const destination = Path.join(componentsPath, l); - Fs.rmSync(destination, { recursive: true }); + Fs.rmSync(destination, { recursive: true, force: true }); Fs.cpSync(source, destination, { recursive: true }); }); diff --git a/www/diagram/inner.js b/www/diagram/inner.js index f3388492a..8d92bd55e 100644 --- a/www/diagram/inner.js +++ b/www/diagram/inner.js @@ -4,6 +4,8 @@ define([ '/customize/messages.js', // translation keys '/components/pako/dist/pako.min.js', '/components/x2js/x2js.js', + '/common/common-util.js', + '/file/file-crypto.js', '/components/tweetnacl/nacl-fast.min.js', 'less!/diagram/app-diagram.less', 'css!/diagram/drawio.css', @@ -11,8 +13,11 @@ define([ Framework, Messages, pako, - X2JS) { + X2JS, + Util, + FileCrypto) { const Nacl = window.nacl; + const APP = window.APP = {}; // As described here: https://drawio-app.com/extracting-the-xml-from-mxfiles/ const decompressDrawioXml = function(xmlDocStr) { @@ -55,6 +60,8 @@ define([ // This is the main initialization loop var onFrameworkReady = function (framework) { + console.log('XXX framework', framework); + const common = framework._.sfCommon; // TODO do not access internals var EMPTY_DRAWIO = ""; var drawioFrame = document.querySelector('#cp-app-diagram-content'); var x2js = new X2JS(); @@ -121,6 +128,70 @@ define([ autosave: onDrawioAutosave, }; + const createDataUrl = (mimeType, blob) => { + return new Promise((resolve) => { + const reader = new FileReader(); + reader.addEventListener( + "load", + () => { + resolve(reader.result); + }, + false + ); + + const fixedBlob = new Blob([blob], {type: mimeType}); + reader.readAsDataURL(fixedBlob); + }); + }; + + APP.getImageURL = function(data, callback) { + Util.fetch(data.src, function (err, u8) { + if (err) { + console.error(err); + return void callback(""); + } + try { + FileCrypto.decrypt(u8, Nacl.util.decodeBase64(data.key), async (err, res) => { + if (err || !res.content) { + console.error("Decrypting failed"); + return void callback(""); + } + console.log('XXX res', res); + + try { + const dataUrl = await createDataUrl(data.fileType, res.content); + callback(dataUrl); + } catch (e) {} + }); + } catch (e) { + console.error(e); + callback(""); + } + }, void 0, common.getCache()); + }; + + APP.addImage = function() { + return new Promise((resolve) => { + common.openFilePicker({ + types: ['file'], + where: ['root'], + filter: { + fileType: ['image/'] + } + }, (data) => { + console.log('XXX data', data); + // TODO wait for realtime.onSettle + APP.getImageURL(data, function(url) { + common.setPadAttribute('atime', +new Date(), null, data.href); + resolve({ + name: data.name, + url: url + }); + }); + }); + }); + }; + // This is the function from which you will receive updates from CryptPad framework.onContentUpdate(function (newContent) { lastContent = newContent; @@ -175,7 +246,7 @@ define([ embed: 1, drafts: 0, // plugins: 0, - p: '/cryptpad.js', + p: 'cryptpad', chrome: framework.isReadOnly() ? 0 : 1, dark: window.CryptPad_theme === "dark" ? 1 : 0,