diff --git a/www/code/export.js b/www/code/export.js new file mode 100644 index 000000000..23d689361 --- /dev/null +++ b/www/code/export.js @@ -0,0 +1,17 @@ +// This file is used when a user tries to export the entire CryptDrive. +// Pads from the code app will be exported using this format instead of plain text. +define([ + '/common/sframe-common-codemirror.js', +], function (SFCodeMirror) { + var module = {}; + + module.main = function (userDoc, cb) { + var mode = userDoc.highlightMode || 'gfm'; + var content = userDoc.content; + module.type = SFCodeMirror.getContentExtension(mode); + cb(SFCodeMirror.fileExporter(content)); + }; + + return module; +}); + diff --git a/www/common/cryptget.js b/www/common/cryptget.js index b3a3c7511..5279a17c9 100644 --- a/www/common/cryptget.js +++ b/www/common/cryptget.js @@ -12,11 +12,18 @@ define([ S.cb(err, doc); S.done = true; - var disconnect = Util.find(S, ['network', 'disconnect']); - if (typeof(disconnect) === 'function') { disconnect(); } - var abort = Util.find(S, ['realtime', 'realtime', 'abort']); + if (!S.hasNetwork) { + var disconnect = Util.find(S, ['network', 'disconnect']); + if (typeof(disconnect) === 'function') { disconnect(); } + } + if (S.leave) { + try { + S.leave(); + } catch (e) { console.log(e); } + } + var abort = Util.find(S, ['session', 'realtime', 'abort']); if (typeof(abort) === 'function') { - S.realtime.realtime.sync(); + S.session.realtime.sync(); abort(); } }; @@ -51,11 +58,12 @@ define([ opt = opt || {}; var config = makeConfig(hash, opt.password); - var Session = { cb: cb, }; + var Session = { cb: cb, hasNetwork: Boolean(opt.network) }; config.onReady = function (info) { var rt = Session.session = info.realtime; Session.network = info.network; + Session.leave = info.leave; finish(Session, void 0, rt.getUserDoc()); }; diff --git a/www/common/cryptpad-common.js b/www/common/cryptpad-common.js index cabab6ca4..030c6e7f2 100644 --- a/www/common/cryptpad-common.js +++ b/www/common/cryptpad-common.js @@ -59,6 +59,19 @@ define([ cb(); }; + common.makeNetwork = function (cb) { + require([ + '/bower_components/netflux-websocket/netflux-client.js', + '/common/outer/network-config.js' + ], function (Netflux, NetConfig) { + var wsUrl = NetConfig.getWebsocketURL(); + Netflux.connect(wsUrl).then(function (network) { + cb(null, network); + }, function (err) { + cb(err); + }); + }); + }; // RESTRICTED // Settings only diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 0c1a6a7a5..58d84a616 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -38,6 +38,12 @@ define([ return cursor; }; + module.getContentExtension = function (mode) { + return (Modes.extensionOf(mode) || '.txt').slice(1); + }; + module.fileExporter = function (content) { + return new Blob([ content ], { type: 'text/plain;charset=utf-8' }); + }; module.setValueAndCursor = function (editor, oldDoc, remoteDoc) { var scroll = editor.getScrollInfo(); //get old cursor here @@ -271,10 +277,10 @@ define([ }; exp.getContentExtension = function () { - return (Modes.extensionOf(exp.highlightMode) || '.txt').slice(1); + return module.getContentExtension(exp.highlightMode); }; exp.fileExporter = function () { - return new Blob([ editor.getValue() ], { type: 'text/plain;charset=utf-8' }); + return module.fileExporter(editor.getValue()); }; exp.fileImporter = function (content, file) { var $toolbarContainer = $('#cme_toolbox'); diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index f40bd6514..aff66dddc 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -21,7 +21,9 @@ define([ var FilePicker; var Messaging; var Notifier; - var Utils = {}; + var Utils = { + nThen: nThen + }; var AppConfig; var Test; var password; @@ -744,13 +746,46 @@ define([ Cryptpad.removeLoginBlock(data, cb); }); + var cgNetwork; + var whenCGReady = function (cb) { + if (cgNetwork && cgNetwork !== true) { console.log(cgNetwork); return void cb(); } + setTimeout(function () { + whenCGReady(cb); + }, 500); + }; + var i = 0; sframeChan.on('Q_CRYPTGET', function (data, cb) { - Cryptget.get(data.hash, function (err, val) { - cb({ - error: err, - data: val + var todo = function () { + data.opts.network = cgNetwork; + Cryptget.get(data.hash, function (err, val) { + cb({ + error: err, + data: val + }); + }, data.opts); + }; + //return void todo(); + if (i > 30) { + i = 0; + cgNetwork = undefined; + } + i++ + if (!cgNetwork) { + cgNetwork = true; + return void Cryptpad.makeNetwork(function (err, nw) { + console.log(nw); + cgNetwork = nw; + todo(); }); - }, data.opts); + } else if (cgNetwork === true) { + return void whenCGReady(todo); + } + todo(); + }); + sframeChan.on('EV_CRYPTGET_DISCONNECT', function () { + if (!cgNetwork) { return; } + cgNetwork.disconnect(); + cgNetwork = undefined; }); if (cfg.addRpc) { diff --git a/www/common/sframe-protocol.js b/www/common/sframe-protocol.js index f349ef8da..c222fc485 100644 --- a/www/common/sframe-protocol.js +++ b/www/common/sframe-protocol.js @@ -274,5 +274,6 @@ define({ // Ability to get a pad's content from its hash 'Q_CRYPTGET': true, + 'EV_CRYPTGET_DISCONNECT': true, }); diff --git a/www/kanban/export.js b/www/kanban/export.js new file mode 100644 index 000000000..2240031fe --- /dev/null +++ b/www/kanban/export.js @@ -0,0 +1,16 @@ +// This file is used when a user tries to export the entire CryptDrive. +// Pads from the code app will be exported using this format instead of plain text. +define([ +], function () { + var module = {}; + + module.main = function (userDoc, cb) { + var content = userDoc.content; + cb(new Blob([JSON.stringify(content, 0, 2)], { + type: 'application/json', + })); + }; + + return module; +}); + diff --git a/www/kanban/inner.js b/www/kanban/inner.js index ed34b837e..48e4e76e0 100644 --- a/www/kanban/inner.js +++ b/www/kanban/inner.js @@ -368,7 +368,7 @@ define([ } framework.setFileExporter('json', function () { - return new Blob([JSON.stringify(kanban.getBoardsJSON())], { + return new Blob([JSON.stringify(kanban.getBoardsJSON(), 0, 2)], { type: 'application/json', }); }); diff --git a/www/pad/export.js b/www/pad/export.js new file mode 100644 index 000000000..2bc54a430 --- /dev/null +++ b/www/pad/export.js @@ -0,0 +1,64 @@ +define([ + 'jquery', + '/common/common-util.js', + '/bower_components/hyperjson/hyperjson.js', + '/bower_components/nthen/index.js', +], function ($, Util, Hyperjson, nThen) { + var module = { + type: 'html' + }; + + var exportMediaTags = function (inner, cb) { + var $clone = $(inner).clone(); + nThen(function (waitFor) { + $(inner).find('media-tag').each(function (i, el) { + if (!$(el).data('blob') || !el.blob) { return; } + Util.blobToImage(el.blob || $(el).data('blob'), waitFor(function (imgSrc) { + $clone.find('media-tag[src="' + $(el).attr('src') + '"] img') + .attr('src', imgSrc); + $clone.find('media-tag').parent() + .find('.cke_widget_drag_handler_container').remove(); + })); + }); + }).nThen(function () { + cb($clone[0]); + }); + }; + + module.getHTML = function (inner) { + return ('\n' + '\n' + + '
\n ' + + inner.innerHTML.replace(/]*class="cke_anchor"[^>]*data-cke-realelement="([^"]*)"[^>]*>/g, + function(match,realElt){ + //console.log("returning realElt \"" + unescape(realElt)+ "\"."); + return decodeURIComponent(realElt); }) + + ' \n' + ); + }; + + module.main = function (userDoc, cb) { + var inner; + if (userDoc instanceof Element || userDoc instanceof HTMLElement) { + inner = userDoc; + } else { + try { + if (Array.isArray(userDoc)) { + inner = Hyperjson.toDOM(userDoc); + } else { + console.error('This Pad is not an array!', userDoc); + return void cb(''); + } + } catch (e) { + console.log(JSON.stringify(userDoc)); + console.error(userDoc); + console.error(e); + return void cb(''); + } + } + exportMediaTags(inner, function (toExport) { + cb(new Blob([ module.getHTML(toExport) ], { type: "text/html;charset=utf-8" })); + }); + }; + + return module; +}); diff --git a/www/pad/inner.js b/www/pad/inner.js index a97406d70..1700132b5 100644 --- a/www/pad/inner.js +++ b/www/pad/inner.js @@ -25,6 +25,7 @@ define([ '/common/TypingTests.js', '/customize/messages.js', '/pad/links.js', + '/pad/export.js', '/bower_components/nthen/index.js', '/common/media-tag.js', '/api/config', @@ -49,6 +50,7 @@ define([ TypingTest, Messages, Links, + Exporter, nThen, MediaTag, ApiConfig, @@ -166,17 +168,6 @@ define([ //'AUDIO' ]; - var getHTML = function (inner) { - return ('\n' + '\n' + - ' \n ' + - inner.innerHTML.replace(/]*class="cke_anchor"[^>]*data-cke-realelement="([^"]*)"[^>]*>/g, - function(match,realElt){ - //console.log("returning realElt \"" + unescape(realElt)+ "\"."); - return decodeURIComponent(realElt); }) + - ' \n' - ); - }; - var CKEDITOR_CHECK_INTERVAL = 100; var ckEditorAvailable = function (cb) { var intr; @@ -647,26 +638,8 @@ define([ }); }, true); - var exportMediaTags = function (inner, cb) { - var $clone = $(inner).clone(); - nThen(function (waitFor) { - $(inner).find('media-tag').each(function (i, el) { - if (!$(el).data('blob') || !el.blob) { return; } - Util.blobToImage(el.blob || $(el).data('blob'), waitFor(function (imgSrc) { - $clone.find('media-tag[src="' + $(el).attr('src') + '"] img') - .attr('src', imgSrc); - $clone.find('media-tag').parent() - .find('.cke_widget_drag_handler_container').remove(); - })); - }); - }).nThen(function () { - cb($clone[0]); - }); - }; - framework.setFileExporter('html', function (cb) { - exportMediaTags(inner, function (toExport) { - cb(new Blob([ getHTML(toExport) ], { type: "text/html;charset=utf-8" })); - }); + framework.setFileExporter(Exporter.type, function (cb) { + Exporter.main(inner, cb); }, true); framework.setNormalizer(function (hjson) { @@ -837,7 +810,7 @@ define([ test.fail("No anchors found. Please adjust document"); } else { console.log(anchors.length + " anchors found."); - var exported = getHTML(window.inner); + var exported = Exporter.getHTML(window.inner); console.log("Obtained exported: " + exported); var allFound = true; for(var i=0; i