From c304071492377a0bd87727796bd0b834cf9c7ddd Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle Date: Wed, 9 Aug 2017 17:37:55 +0200 Subject: [PATCH] wip --- www/common/common-userlist2.js | 112 ++++++++++ www/common/metadata-manager.js | 17 ++ www/common/sframe-boot2.js | 9 +- www/common/sframe-chainpad-netflux-inner.js | 24 +- www/common/sframe-chainpad-netflux-outer.js | 24 +- www/common/sframe-channel.js | 168 +++++++------- www/common/sframe-protocol.js | 5 + www/pad2/main.js | 232 ++++++++++---------- www/pad2/outer.js | 9 +- 9 files changed, 360 insertions(+), 240 deletions(-) create mode 100644 www/common/common-userlist2.js diff --git a/www/common/common-userlist2.js b/www/common/common-userlist2.js new file mode 100644 index 000000000..e7f2449fa --- /dev/null +++ b/www/common/common-userlist2.js @@ -0,0 +1,112 @@ +define(function () { + var module = {}; + + module.create = function (info, onLocal, Cryptget, Cryptpad) { + var exp = {}; + + var userData = exp.userData = {}; + var userList = exp.userList = info.userList; + var myData = exp.myData = {}; + exp.myUserName = info.myID; + exp.myNetfluxId = info.myID; + + var network = Cryptpad.getNetwork(); + + var parsed = Cryptpad.parsePadUrl(window.location.href); + var appType = parsed ? parsed.type : undefined; + + var addToUserData = exp.addToUserData = function(data) { + var users = userList.users; + for (var attrname in data) { userData[attrname] = data[attrname]; } + + if (users && users.length) { + for (var userKey in userData) { + if (users.indexOf(userKey) === -1) { + delete userData[userKey]; + } + } + } + + if(userList && typeof userList.onChange === "function") { + userList.onChange(userData); + } + }; + + exp.getToolbarConfig = function () { + return { + data: userData, + list: userList, + userNetfluxId: exp.myNetfluxId + }; + }; + + var setName = exp.setName = function (newName, cb) { + if (typeof(newName) !== 'string') { return; } + var myUserNameTemp = newName.trim(); + if(myUserNameTemp.length > 32) { + myUserNameTemp = myUserNameTemp.substr(0, 32); + } + exp.myUserName = myUserNameTemp; + myData = {}; + myData[exp.myNetfluxId] = { + name: exp.myUserName, + uid: Cryptpad.getUid(), + avatar: Cryptpad.getAvatarUrl(), + profile: Cryptpad.getProfileUrl(), + curvePublic: Cryptpad.getProxy().curvePublic + }; + addToUserData(myData); + /*Cryptpad.setAttribute('username', exp.myUserName, function (err) { + if (err) { + console.log("Couldn't set username"); + console.error(err); + return; + } + if (typeof cb === "function") { cb(); } + });*/ + if (typeof cb === "function") { cb(); } + }; + + exp.getLastName = function ($changeNameButton, isNew) { + Cryptpad.getLastName(function (err, lastName) { + if (err) { + console.log("Could not get previous name"); + console.error(err); + return; + } + // Update the toolbar list: + // Add the current user in the metadata + if (typeof(lastName) === 'string') { + setName(lastName, onLocal); + } else { + myData[exp.myNetfluxId] = { + name: "", + uid: Cryptpad.getUid(), + avatar: Cryptpad.getAvatarUrl(), + profile: Cryptpad.getProfileUrl(), + curvePublic: Cryptpad.getProxy().curvePublic + }; + addToUserData(myData); + onLocal(); + $changeNameButton.click(); + } + if (isNew && appType) { + Cryptpad.selectTemplate(appType, info.realtime, Cryptget); + } + }); + }; + + Cryptpad.onDisplayNameChanged(function (newName) { + setName(newName, onLocal); + }); + + network.on('reconnect', function (uid) { + exp.myNetfluxId = uid; + exp.setName(exp.myUserName); + }); + + return exp; + }; + + return module; +}); diff --git a/www/common/metadata-manager.js b/www/common/metadata-manager.js index e69de29bb..9d26d5588 100644 --- a/www/common/metadata-manager.js +++ b/www/common/metadata-manager.js @@ -0,0 +1,17 @@ +define([], function () { + var metadataChange = function (ctx, newMeta) { + + }; + var getMetadata = function (ctx) { + + }; + var create = function (sframeChan, cpNfInner) { + var ctx = { + sframeChan: sframeChan, + personalMetadata: {} + }; + + }; + return { create: create }; + +}); \ No newline at end of file diff --git a/www/common/sframe-boot2.js b/www/common/sframe-boot2.js index 94ec9d511..8285032d2 100644 --- a/www/common/sframe-boot2.js +++ b/www/common/sframe-boot2.js @@ -1,11 +1,8 @@ // This is stage 1, it can be changed but you must bump the version of the project. // Note: This must only be loaded from inside of a sandbox-iframe. -define([ - '/common/requireconfig.js', - '/common/sframe-channel.js' -], function (RequireConfig, SFrameChannel) { +define(['/common/requireconfig.js'], function (RequireConfig) { require.config(RequireConfig); -console.log('boot2'); + // most of CryptPad breaks if you don't support isArray if (!Array.isArray) { Array.isArray = function(arg) { // CRYPTPAD_SHIM @@ -23,7 +20,5 @@ console.log('boot2'); window.__defineGetter__('localStorage', function () { return mkFakeStore(); }); window.__defineGetter__('sessionStorage', function () { return mkFakeStore(); }); - SFrameChannel.init(window.top, function () { }); - require([document.querySelector('script[data-bootload]').getAttribute('data-bootload')]); }); diff --git a/www/common/sframe-chainpad-netflux-inner.js b/www/common/sframe-chainpad-netflux-inner.js index 32e1beb0f..efce47a91 100644 --- a/www/common/sframe-chainpad-netflux-inner.js +++ b/www/common/sframe-chainpad-netflux-inner.js @@ -15,9 +15,8 @@ * along with this program. If not, see . */ define([ - '/common/sframe-channel.js', '/bower_components/chainpad/chainpad.dist.js', -], function (SFrameChannel) { +], function () { var ChainPad = window.ChainPad; var module = { exports: {} }; @@ -81,6 +80,7 @@ define([ var avgSyncMilliseconds = config.avgSyncMilliseconds; var logLevel = typeof(config.logLevel) !== 'undefined'? config.logLevel : 1; var readOnly = config.readOnly || false; + var sframeChan = config.sframeChan; config = undefined; var chainpad; @@ -88,14 +88,14 @@ define([ var myID; var isReady = false; - SFrameChannel.on('EV_RT_JOIN', userList.onJoin); - SFrameChannel.on('EV_RT_LEAVE', userList.onLeave); - SFrameChannel.on('EV_RT_DISCONNECT', function () { + sframeChan.on('EV_RT_JOIN', userList.onJoin); + sframeChan.on('EV_RT_LEAVE', userList.onLeave); + sframeChan.on('EV_RT_DISCONNECT', function () { isReady = false; userList.onReset(); onConnectionChange({ state: false }); }); - SFrameChannel.on('EV_RT_CONNECT', function (content) { + sframeChan.on('EV_RT_CONNECT', function (content) { content.members.forEach(userList.onJoin); myID = content.myID; isReady = false; @@ -113,26 +113,26 @@ define([ logLevel: logLevel }); chainpad.onMessage(function(message, cb) { - SFrameChannel.query('Q_RT_MESSAGE', message, cb); + sframeChan.query('Q_RT_MESSAGE', message, cb); }); chainpad.onPatch(function () { onRemote({ realtime: chainpad }); }); onInit({ - myID: content.myID, + myID: myID, realtime: chainpad, userList: userList, readOnly: readOnly }); }); - SFrameChannel.on('Q_RT_MESSAGE', function (content, cb) { + sframeChan.on('Q_RT_MESSAGE', function (content, cb) { if (isReady) { onLocal(); // should be onBeforeMessage } chainpad.message(content); cb('OK'); }); - SFrameChannel.on('EV_RT_READY', function () { + sframeChan.on('EV_RT_READY', function () { if (isReady) { return; } isReady = true; chainpad.start(); @@ -141,7 +141,9 @@ define([ if (!readOnly) { userList.onJoin(myID); } onReady({ realtime: chainpad }); }); - return; + return { + getMyID: function () { return myID; } + }; }; return module.exports; }); \ No newline at end of file diff --git a/www/common/sframe-chainpad-netflux-outer.js b/www/common/sframe-chainpad-netflux-outer.js index d28fbe631..078a920e7 100644 --- a/www/common/sframe-chainpad-netflux-outer.js +++ b/www/common/sframe-chainpad-netflux-outer.js @@ -14,11 +14,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -define([ - '/common/sframe-channel.js', -], function (SFrameChannel) { +define([], function () { var USE_HISTORY = true; - var module = { exports: {} }; var verbose = function (x) { console.log(x); }; verbose = function () {}; // comment out to enable verbose logging @@ -31,6 +28,7 @@ define([ var validateKey = conf.validateKey; var readOnly = conf.readOnly || false; var network = conf.network; + var sframeChan = conf.sframeChan; conf = undefined; var initializing = true; @@ -38,15 +36,15 @@ define([ var queue = []; var messageFromInner = function (m, cb) { queue.push([ m, cb ]); }; - SFrameChannel.on('Q_RT_MESSAGE', function (message, cb) { + sframeChan.on('Q_RT_MESSAGE', function (message, cb) { messageFromInner(message, cb); }); - var onReady = function(wc) { + var onReady = function () { // Trigger onReady only if not ready yet. This is important because the history keeper sends a direct // message through "network" when it is synced, and it triggers onReady for each channel joined. if (!initializing) { return; } - SFrameChannel.event('EV_RT_READY', null); + sframeChan.event('EV_RT_READY', null); // we're fully synced initializing = false; }; @@ -122,7 +120,7 @@ define([ message = unBencode(message);//.slice(message.indexOf(':[') + 1); // pass the message into Chainpad - SFrameChannel.query('Q_RT_MESSAGE', message, function () { }); + sframeChan.query('Q_RT_MESSAGE', message, function () { }); }; // We use an object to store the webchannel so that we don't have to push new handlers to chainpad @@ -134,14 +132,14 @@ define([ channel = wc.id; // Add the existing peers in the userList - SFrameChannel.event('EV_RT_CONNECT', { myID: wc.myID, members: wc.members, readOnly: readOnly }); + sframeChan.event('EV_RT_CONNECT', { myID: wc.myID, members: wc.members, readOnly: readOnly }); // Add the handlers to the WebChannel wc.on('message', function (msg, sender) { //Channel msg onMessage(sender, msg, wc, network); }); - wc.on('join', function (m) { SFrameChannel.event('EV_RT_JOIN', m); }); - wc.on('leave', function (m) { SFrameChannel.event('EV_RT_LEAVE', m); }); + wc.on('join', function (m) { sframeChan.event('EV_RT_JOIN', m); }); + wc.on('leave', function (m) { sframeChan.event('EV_RT_LEAVE', m); }); if (firstConnection) { // Sending a message... @@ -210,7 +208,7 @@ define([ network.on('disconnect', function (reason) { if (isIntentionallyLeaving) { return; } if (reason === "network.disconnect() called") { return; } - SFrameChannel.event('EV_RT_DISCONNECT'); + sframeChan.event('EV_RT_DISCONNECT'); }); network.on('reconnect', function (uid) { @@ -230,7 +228,7 @@ define([ return { start: function (config) { - SFrameChannel.whenReg('EV_RT_READY', function () { start(config); }); + config.sframeChan.whenReg('EV_RT_READY', function () { start(config); }); } }; }); diff --git a/www/common/sframe-channel.js b/www/common/sframe-channel.js index 793906c5a..12b390fa7 100644 --- a/www/common/sframe-channel.js +++ b/www/common/sframe-channel.js @@ -2,22 +2,92 @@ define([ '/common/sframe-protocol.js' ], function (SFrameProtocol) { - var otherWindow; - var handlers = {}; - var queries = {}; - - // list of handlers which are registered from the other side... - var insideHandlers = []; - var callWhenRegistered = {}; - - var module = { exports: {} }; var mkTxid = function () { return Math.random().toString(16).replace('0.', '') + Math.random().toString(16).replace('0.', ''); }; - module.exports.init = function (ow, cb) { - if (otherWindow) { throw new Error('already initialized'); } + var create = function (ow, cb) { + var otherWindow; + var handlers = {}; + var queries = {}; + + // list of handlers which are registered from the other side... + var insideHandlers = []; + var callWhenRegistered = {}; + + var chan = {}; + + chan.query = function (q, content, cb) { + if (!otherWindow) { throw new Error('not yet initialized'); } + if (!SFrameProtocol[q]) { + throw new Error('please only make queries are defined in sframe-protocol.js'); + } + var txid = mkTxid(); + var timeout = setTimeout(function () { + delete queries[txid]; + console.log("Timeout making query " + q); + }, 30000); + queries[txid] = function (data, msg) { + clearTimeout(timeout); + delete queries[txid]; + cb(undefined, data.content, msg); + }; + otherWindow.postMessage(JSON.stringify({ + txid: txid, + content: content, + q: q + }), '*'); + }; + + var event = chan.event = function (e, content) { + if (!otherWindow) { throw new Error('not yet initialized'); } + if (!SFrameProtocol[e]) { + throw new Error('please only fire events that are defined in sframe-protocol.js'); + } + if (e.indexOf('EV_') !== 0) { + throw new Error('please only use events (starting with EV_) for event messages'); + } + otherWindow.postMessage(JSON.stringify({ content: content, q: e }), '*'); + }; + + chan.on = function (queryType, handler) { + if (!otherWindow) { throw new Error('not yet initialized'); } + if (typeof(handlers[queryType]) !== 'undefined') { throw new Error('already registered'); } + if (!SFrameProtocol[queryType]) { + throw new Error('please only register handlers which are defined in sframe-protocol.js'); + } + handlers[queryType] = function (data, msg) { + handler(data.content, function (replyContent) { + msg.source.postMessage(JSON.stringify({ + txid: data.txid, + content: replyContent + }), '*'); + }, msg); + }; + event('EV_REGISTER_HANDLER', queryType); + }; + + chan.whenReg = function (queryType, handler) { + if (!otherWindow) { throw new Error('not yet initialized'); } + if (!SFrameProtocol[queryType]) { + throw new Error('please only register handlers which are defined in sframe-protocol.js'); + } + if (insideHandlers.indexOf(queryType) > -1) { + handler(); + } else { + (callWhenRegistered[queryType] = callWhenRegistered[queryType] || []).push(handler); + } + }; + + handlers['EV_REGISTER_HANDLER'] = function (data) { + if (callWhenRegistered[data.content]) { + callWhenRegistered[data.content].forEach(function (f) { f(); }); + delete callWhenRegistered[data.content]; + } + insideHandlers.push(data.content); + }; + var intr; var txid; window.addEventListener('message', function (msg) { @@ -32,7 +102,7 @@ define([ } clearInterval(intr); otherWindow = ow; - cb(); + cb(chan); } else if (typeof(data.q) === 'string' && handlers[data.q]) { handlers[data.q](data, msg); } else if (typeof(data.q) === 'undefined' && queries[data.txid]) { @@ -48,7 +118,7 @@ define([ if (window !== window.top) { // we're in the sandbox otherWindow = ow; - cb(); + cb(chan); } else { require(['/common/requireconfig.js'], function (RequireConfig) { txid = mkTxid(); @@ -63,75 +133,5 @@ define([ } }; - module.exports.query = function (q, content, cb) { - if (!otherWindow) { throw new Error('not yet initialized'); } - if (!SFrameProtocol[q]) { - throw new Error('please only make queries are defined in sframe-protocol.js'); - } - var txid = mkTxid(); - var timeout = setTimeout(function () { - delete queries[txid]; - console.log("Timeout making query " + q); - }, 30000); - queries[txid] = function (data, msg) { - clearTimeout(timeout); - delete queries[txid]; - cb(undefined, data.content, msg); - }; - otherWindow.postMessage(JSON.stringify({ - txid: txid, - content: content, - q: q - }), '*'); - }; - - var event = module.exports.event = function (e, content) { - if (!otherWindow) { throw new Error('not yet initialized'); } - if (!SFrameProtocol[e]) { - throw new Error('please only fire events that are defined in sframe-protocol.js'); - } - if (e.indexOf('EV_') !== 0) { - throw new Error('please only use events (starting with EV_) for event messages'); - } - otherWindow.postMessage(JSON.stringify({ content: content, q: e }), '*'); - }; - - module.exports.on = function (queryType, handler) { - if (!otherWindow) { throw new Error('not yet initialized'); } - if (typeof(handlers[queryType]) !== 'undefined') { throw new Error('already registered'); } - if (!SFrameProtocol[queryType]) { - throw new Error('please only register handlers which are defined in sframe-protocol.js'); - } - handlers[queryType] = function (data, msg) { - handler(data.content, function (replyContent) { - msg.source.postMessage(JSON.stringify({ - txid: data.txid, - content: replyContent - }), '*'); - }, msg); - }; - event('EV_REGISTER_HANDLER', queryType); - }; - - module.exports.whenReg = function (queryType, handler) { - if (!otherWindow) { throw new Error('not yet initialized'); } - if (!SFrameProtocol[queryType]) { - throw new Error('please only register handlers which are defined in sframe-protocol.js'); - } - if (insideHandlers.indexOf(queryType) > -1) { - handler(); - } else { - (callWhenRegistered[queryType] = callWhenRegistered[queryType] || []).push(handler); - } - }; - - handlers['EV_REGISTER_HANDLER'] = function (data) { - if (callWhenRegistered[data.content]) { - callWhenRegistered[data.content].forEach(function (f) { f(); }); - delete callWhenRegistered[data.content]; - } - insideHandlers.push(data.content); - }; - - return module.exports; + return { create: create }; }); diff --git a/www/common/sframe-protocol.js b/www/common/sframe-protocol.js index 503dc2983..b6ab3f7b8 100644 --- a/www/common/sframe-protocol.js +++ b/www/common/sframe-protocol.js @@ -4,6 +4,11 @@ // Please document the queries and events you create, and please please avoid making generic // "do stuff" events/queries which are used for many different things because it makes the // protocol unclear. +// +// WARNING: At this point, this protocol is still EXPERIMENTAL. This is not it's final form. +// We need to define protocol one piece at a time and then when we are satisfied that we +// fully understand the problem, we will define the *right* protocol and this file will be dynomited. +// define({ // When the iframe first launches, this query is sent repeatedly by the controller // to wait for it to awake and give it the requirejs config to use. diff --git a/www/pad2/main.js b/www/pad2/main.js index bf92010e8..064153914 100644 --- a/www/pad2/main.js +++ b/www/pad2/main.js @@ -14,6 +14,7 @@ define([ '/common/cryptget.js', '/pad/links.js', '/bower_components/nthen/index.js', + '/common/sframe-channel.js', '/bower_components/file-saver/FileSaver.min.js', '/bower_components/diff-dom/diffDOM.js', @@ -21,8 +22,8 @@ define([ 'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'less!/customize/src/less/cryptpad.less', 'less!/customize/src/less/toolbar.less' -], function ($, Crypto, realtimeInput, Hyperjson, - Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher, Cryptpad, Cryptget, Links, nThen) { +], function ($, Crypto, CpNfInner, Hyperjson, + Toolbar, Cursor, JsonOT, TypingTest, JSONSortify, TextPatcher, Cryptpad, Cryptget, Links, nThen, SFrameChannel) { var saveAs = window.saveAs; var Messages = Cryptpad.Messages; var DiffDom = window.diffDOM; @@ -84,67 +85,48 @@ define([ Cryptpad.errorLoadingScreen(Messages.websocketError); }; - var andThen = function (editor) { - //var $iframe = $('#pad-iframe').contents(); - //var secret = Cryptpad.getSecrets(); - //var readOnly = secret.keys && !secret.keys.editKeyStr; - //if (!secret.keys) { - // secret.keys = secret.key; - //} - var readOnly = false; // TODO - - - var $bar = $('#cke_1_toolbox'); - - var $html = $bar.closest('html'); - var $faLink = $html.find('head link[href*="/bower_components/components-font-awesome/css/font-awesome.min.css"]'); - if ($faLink.length) { - $html.find('iframe').contents().find('head').append($faLink.clone()); - } - var isHistoryMode = false; - - if (readOnly) { - $('#cke_1_toolbox > .cke_toolbox_main').hide(); - } - - /* add a class to the magicline plugin so we can pick it out more easily */ - - var ml = window.CKEDITOR.instances.editor1.plugins.magicline.backdoor.that.line.$; - - [ml, ml.parentElement].forEach(function (el) { - el.setAttribute('class', 'non-realtime'); - }); - - var documentBody = $html.find('iframe')[0].contentWindow.document.body; + var domFromHTML = function (html) { + return new DOMParser().parseFromString(html, 'text/html'); + }; - var inner = window.inner = documentBody; + var forbiddenTags = [ + 'SCRIPT', + 'IFRAME', + 'OBJECT', + 'APPLET', + 'VIDEO', + 'AUDIO' + ]; + + var openLink = function (e) { + var el = e.currentTarget; + if (!el || el.nodeName !== 'A') { return; } + var href = el.getAttribute('href'); + if (href) { window.open(href, '_blank'); } + }; - var cursor = module.cursor = Cursor(inner); + var getHTML = function (inner) { + return ('\n' + '\n' + inner.innerHTML); + }; - var setEditable = module.setEditable = function (bool) { - if (bool) { - $(inner).css({ - color: '#333', - }); - } - if (!readOnly || !bool) { - inner.setAttribute('contenteditable', bool); + var CKEDITOR_CHECK_INTERVAL = 100; + var ckEditorAvailable = function (cb) { + var intr; + var check = function () { + if (window.CKEDITOR) { + clearTimeout(intr); + cb(window.CKEDITOR); } }; + intr = setInterval(function () { + console.log("Ckeditor was not defined. Trying again in %sms", CKEDITOR_CHECK_INTERVAL); + check(); + }, CKEDITOR_CHECK_INTERVAL); + check(); + }; - // don't let the user edit until the pad is ready - setEditable(false); - - var forbiddenTags = [ - 'SCRIPT', - 'IFRAME', - 'OBJECT', - 'APPLET', - 'VIDEO', - 'AUDIO' - ]; - - var diffOptions = { + var mkDiffOptions = function (cursor, readOnly) { + return { preDiffApply: function (info) { /* Don't accept attributes that begin with 'on' @@ -262,12 +244,69 @@ define([ } } }; + }; + + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////// + + var andThen = function (editor, Ckeditor, sframeChan) { + //var $iframe = $('#pad-iframe').contents(); + //var secret = Cryptpad.getSecrets(); + //var readOnly = secret.keys && !secret.keys.editKeyStr; + //if (!secret.keys) { + // secret.keys = secret.key; + //} + var readOnly = false; // TODO + + + var $bar = $('#cke_1_toolbox'); + + var $html = $bar.closest('html'); + var $faLink = $html.find('head link[href*="/bower_components/components-font-awesome/css/font-awesome.min.css"]'); + if ($faLink.length) { + $html.find('iframe').contents().find('head').append($faLink.clone()); + } + var isHistoryMode = false; + + if (readOnly) { + $('#cke_1_toolbox > .cke_toolbox_main').hide(); + } + + /* add a class to the magicline plugin so we can pick it out more easily */ + + var ml = Ckeditor.instances.editor1.plugins.magicline.backdoor.that.line.$; + [ml, ml.parentElement].forEach(function (el) { + el.setAttribute('class', 'non-realtime'); + }); + + var documentBody = $html.find('iframe')[0].contentWindow.document.body; + + var inner = window.inner = documentBody; + + var cursor = module.cursor = Cursor(inner); + + var setEditable = module.setEditable = function (bool) { + if (bool) { + $(inner).css({ + color: '#333', + }); + } + if (!readOnly || !bool) { + inner.setAttribute('contenteditable', bool); + } + }; + + // don't let the user edit until the pad is ready + setEditable(false); var initializing = true; - var Title; - var UserList; - var Metadata; + //var Title; + //var UserList; + //var Metadata; var getHeadingText = function () { var text; @@ -280,14 +319,7 @@ define([ })) { return text; } }; - var DD = new DiffDom(diffOptions); - - var openLink = function (e) { - var el = e.currentTarget; - if (!el || el.nodeName !== 'A') { return; } - var href = el.getAttribute('href'); - if (href) { window.open(href, '_blank'); } - }; + var DD = new DiffDom(mkDiffOptions(cursor, readOnly)); // apply patches, and try not to lose the cursor in the process! var applyHjson = function (shjson) { @@ -323,28 +355,12 @@ define([ }; var realtimeOptions = { - // the websocket URL - websocketURL: Cryptpad.getWebsocketURL(), - - // the channel we will communicate over - channel: 'x',//secret.channel, - - // the nework used for the file store if it exists - network: Cryptpad.getNetwork(), - - // our public key - validateKey: undefined,//secret.keys.validateKey || undefined, + sframeChan: sframeChan, readOnly: readOnly, - - // Pass in encrypt and decrypt methods - crypto: undefined,//Crypto.createEncryptor(secret.keys), - // really basic operational transform transformFunction : JsonOT.validate, - // cryptpad debug logging (default is 1) // logLevel: 0, - validateContent: function (content) { try { JSON.parse(content); @@ -440,16 +456,8 @@ define([ } }; - var getHTML = function () { - return ('\n' + '\n' + inner.innerHTML); - }; - - var domFromHTML = function (html) { - return new DOMParser().parseFromString(html, 'text/html'); - }; - var exportFile = function () { - var html = getHTML(); + var html = getHTML(inner); var suggestion = Title.suggestTitle('cryptpad-document'); Cryptpad.prompt(Messages.exportPrompt, Cryptpad.fixFileName(suggestion) + '.html', function (filename) { @@ -477,7 +485,8 @@ define([ Metadata = Cryptpad.createMetadata(UserList, Title, null, Cryptpad); var configTb = { - displayed: ['title', 'useradmin', 'spinner', 'lag', 'state', 'share', 'userlist', 'newpad', 'limit', 'upgrade'], + displayed: [ + 'title', 'useradmin', 'spinner', 'lag', 'state', 'share', 'userlist', 'newpad', 'limit', 'upgrade'], userList: UserList.getToolbarConfig(), share: { secret: secret, @@ -648,14 +657,6 @@ define([ cursor.setToStart(); } }; -/* unreachable - realtimeOptions.onAbort = function () { - console.log("Aborting the session!"); - // stop the user from continuing to edit - setEditable(false); - toolbar.failed(); - Cryptpad.alert(Messages.common_connectionLost, undefined, true); - }; */ realtimeOptions.onConnectionChange = function (info) { setEditable(info.state); @@ -685,7 +686,9 @@ define([ } }; - module.realtimeInput = realtimeInput.start(realtimeOptions); + var cpNfInner = CpNfInner.start(realtimeOptions); + + Cryptpad.onLogout(function () { setEditable(false); }); @@ -725,32 +728,17 @@ define([ }); }; - - var CKEDITOR_CHECK_INTERVAL = 100; - var ckEditorAvailable = function (cb) { - var intr; - var check = function () { - if (window.CKEDITOR) { - clearTimeout(intr); - cb(window.CKEDITOR); - } - }; - intr = setInterval(function () { - console.log("Ckeditor was not defined. Trying again in %sms", CKEDITOR_CHECK_INTERVAL); - check(); - }, CKEDITOR_CHECK_INTERVAL); - check(); - }; - var main = function () { var Ckeditor; var editor; + var sframeChan; nThen(function (waitFor) { ckEditorAvailable(waitFor(function (ck) { Ckeditor = ck; })); $(waitFor(function () { Cryptpad.addLoadingScreen(); })); + SFrameChannel.create(window.top, waitFor(function (sfc) { sframeChan = sfc; })); }).nThen(function (waitFor) { Ckeditor.config.toolbarCanCollapse = true; if (screen.height < 800) { @@ -770,7 +758,7 @@ define([ onConnectError(); } }); - andThen(editor); + andThen(editor, Ckeditor, sframeChan); }); }; main(); diff --git a/www/pad2/outer.js b/www/pad2/outer.js index 8e09a6ea0..e24a9a4b8 100644 --- a/www/pad2/outer.js +++ b/www/pad2/outer.js @@ -8,10 +8,12 @@ define([ '/bower_components/chainpad-crypto/crypto.js' ], function (SFrameChannel, $, CpNfOuter, nThen, Cryptpad, Crypto) { console.log('xxx'); + var sframeChan; nThen(function (waitFor) { $(waitFor()); }).nThen(function (waitFor) { - SFrameChannel.init($('#sbox-iframe')[0].contentWindow, waitFor(function () { + SFrameChannel.create($('#sbox-iframe')[0].contentWindow, waitFor(function (sfc) { + sframeChan = sfc; console.log('sframe initialized'); })); Cryptpad.ready(waitFor()); @@ -23,12 +25,13 @@ define([ //onConnectError(); } }); - }).nThen(function (waitFor) { + var secret = Cryptpad.getSecrets(); var readOnly = secret.keys && !secret.keys.editKeyStr; if (!secret.keys) { secret.keys = secret.key; } - var outer = CpNfOuter.start({ + CpNfOuter.start({ + sframeChan: sframeChan, channel: secret.channel, network: Cryptpad.getNetwork(), validateKey: secret.keys.validateKey || undefined,