diff --git a/www/common/TypingTests.js b/www/common/TypingTests.js index af09c72c8..16db8c0d5 100644 --- a/www/common/TypingTests.js +++ b/www/common/TypingTests.js @@ -33,7 +33,7 @@ define(function () { interval = setRandomizedInterval(function () { cb(); try { - el.replaceData(j, 0, input.charAt(i)); + el.replaceData(Math.min(j, el.length), 0, input.charAt(i)); } catch (err) { errors++; if (errors >= max_errors) { diff --git a/www/common/netflux-client.js b/www/common/netflux-client.js index 902abb483..e6567229a 100644 --- a/www/common/netflux-client.js +++ b/www/common/netflux-client.js @@ -4,7 +4,7 @@ define(() => { const MAX_LAG_BEFORE_PING = 15000; const MAX_LAG_BEFORE_DISCONNECT = 30000; const PING_CYCLE = 5000; -const REQUEST_TIMEOUT = 5000; +const REQUEST_TIMEOUT = 30000; const now = () => new Date().getTime(); @@ -133,7 +133,7 @@ const onMessage = (ctx, evt) => { return; } if (msg[2] === 'PING') { - msg[1] = 'PONG'; + msg[2] = 'PONG'; ctx.ws.send(JSON.stringify(msg)); return; } @@ -205,7 +205,7 @@ const connect = (websocketURL) => { const req = ctx.requests[id]; if (now() - req.time > REQUEST_TIMEOUT) { delete ctx.requests[id]; - req.reject({ type: 'TIMEOUT', message: 'waited ' + now() - req.time + 'ms' }); + if(typeof req.reject === "function") { req.reject({ type: 'TIMEOUT', message: 'waited ' + now() - req.time + 'ms' }); } } } }, 5000); diff --git a/www/common/realtime-input.js b/www/common/realtime-input.js index bf173263d..3fd00231d 100644 --- a/www/common/realtime-input.js +++ b/www/common/realtime-input.js @@ -14,17 +14,15 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -window.Reflect = { has: function (x,y) { return (y in x); } }; define([ '/common/messages.js', '/common/netflux-client.js', '/common/crypto.js', - '/common/toolbar.js', '/common/TextPatcher.js', '/common/es6-promise.min.js', '/common/chainpad.js', '/bower_components/jquery/dist/jquery.min.js', -], function (Messages, Netflux, Crypto, Toolbar, TextPatcher) { +], function (Messages, Netflux, Crypto, TextPatcher) { var $ = window.jQuery; var ChainPad = window.ChainPad; var PARANOIA = true; @@ -41,37 +39,6 @@ define([ verbose = function (x) { console.log(x); }; verbose = function () {}; // comment out to enable verbose logging - // ------------------ Trapping Keyboard Events ---------------------- // - - var bindEvents = function (element, events, callback, unbind) { - for (var i = 0; i < events.length; i++) { - var e = events[i]; - if (element.addEventListener) { - if (unbind) { - element.removeEventListener(e, callback, false); - } else { - element.addEventListener(e, callback, false); - } - } else { - if (unbind) { - element.detachEvent('on' + e, callback); - } else { - element.attachEvent('on' + e, callback); - } - } - } - }; - - var getParameterByName = function (name, url) { - if (!url) { url = window.location.href; } - name = name.replace(/[\[\]]/g, "\\$&"); - var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), - results = regex.exec(url); - if (!results) { return null; } - if (!results[2]) { return ''; } - return decodeURIComponent(results[2].replace(/\+/g, " ")); - }; - var start = module.exports.start = function (config) { diff --git a/www/pad/main.js b/www/pad/main.js index 91b9d009c..59c9de2ae 100644 --- a/www/pad/main.js +++ b/www/pad/main.js @@ -32,7 +32,8 @@ define([ }; var module = window.REALTIME_MODULE = { - localChangeInProgress: 0 + Hyperjson: Hyperjson, + Hyperscript: Hyperscript }; var userName = Crypto.rand64(8), @@ -104,8 +105,7 @@ define([ var cursor = window.cursor = Cursor(inner); var setEditable = function (bool) { - inner.setAttribute('contenteditable', - (typeof (bool) !== 'undefined'? bool : true)); + inner.setAttribute('contenteditable', bool); }; // don't let the user edit until the pad is ready @@ -113,25 +113,53 @@ define([ var diffOptions = { preDiffApply: function (info) { - /* Don't remove local instances of the magicline plugin */ + /* DiffDOM will filter out magicline plugin elements + in practice this will make it impossible to use it + while someone else is typing, which could be annoying. + + we should check when such an element is going to be + removed, and prevent that from happening. */ if (info.node && info.node.tagName === 'SPAN' && - info.node.getAttribute('contentEditable') === 'false') { - return true; + info.node.getAttribute('contentEditable') === "false") { + // it seems to be a magicline plugin element... + if (info.diff.action === 'removeElement') { + // and you're about to remove it... + // this probably isn't what you want + + /* + I have never seen this in the console, but the + magic line is still getting removed on remote + edits. This suggests that it's getting removed + by something other than diffDom. + */ + console.log("preventing removal of the magic line!"); + + // return true to prevent diff application + return true; + } } + // no use trying to recover the cursor if it doesn't exist if (!cursor.exists()) { return; } + + /* frame is either 0, 1, 2, or 3, depending on which + cursor frames were affected: none, first, last, or both + */ var frame = info.frame = cursor.inNode(info.node); + if (!frame) { return; } - if (typeof info.diff.oldValue === 'string' && - typeof info.diff.newValue === 'string') { - var pushes = cursor.pushDelta(info.diff.oldValue, - info.diff.newValue); + + if (typeof info.diff.oldValue === 'string' && typeof info.diff.newValue === 'string') { + var pushes = cursor.pushDelta(info.diff.oldValue, info.diff.newValue); + if (frame & 1) { + // push cursor start if necessary if (pushes.commonStart < cursor.Range.start.offset) { cursor.Range.start.offset += pushes.delta; } } if (frame & 2) { + // push cursor end if necessary if (pushes.commonStart < cursor.Range.end.offset) { cursor.Range.end.offset += pushes.delta; } @@ -143,7 +171,7 @@ define([ if (info.node) { if (info.frame & 1) { cursor.fixStart(info.node); } if (info.frame & 2) { cursor.fixEnd(info.node); } - } else { console.log("info.node did not exist"); } + } else { console.error("info.node did not exist"); } var sel = cursor.makeSelection(); var range = cursor.makeRange();