diff --git a/www/text/main.js b/www/text/main.js index 65f654cf8..0143a0f10 100644 --- a/www/text/main.js +++ b/www/text/main.js @@ -1,11 +1,12 @@ define([ '/api/config?cb=' + Math.random().toString(16).substring(2), - '/common/realtime-textarea.js', + '/common/RealtimeTextarea.js', '/common/messages.js', '/common/crypto.js', + '/common/TextPatcher.js', '/bower_components/jquery/dist/jquery.min.js', '/customize/pad.js' -], function (Config, Realtime, Messages, Crypto) { +], function (Config, Realtime, Messages, Crypto, TextPatcher) { var $ = window.jQuery; $(window).on('hashchange', function() { window.location.reload(); @@ -15,28 +16,58 @@ define([ return; } + var module = window.APP = {}; var key = Crypto.parseKey(window.location.hash.substring(1)); var initializing = true; var $textarea = $('textarea'); - var config = { + var config = module.config = { textarea: $textarea[0], - websocketURL: Config.websocketURL, + websocketURL: Config.websocketURL + '_old', userName: Crypto.rand64(8), channel: key.channel, cryptKey: key.cryptKey }; + var setEditable = function (bool) { $textarea.attr('disabled', !bool); }; + var canonicalize = function (text) { return text.replace(/\r\n/g, '\n'); }; + + setEditable(false); + var onInit = config.onInit = function (info) { }; - var onRemote = config.onRemote = function (contents) { + var onRemote = config.onRemote = function (info) { if (initializing) { return; } - // TODO... + var userDoc = module.realtime.getUserDoc(); + var content = canonicalize($textarea.val()); + + var op = TextPatcher.diff(content, userDoc); + var elem = $textarea[0]; + + var selects = ['selectionStart', 'selectionEnd'].map(function (attr) { + return TextPatcher.transformCursor(elem[attr], op); + }); + + $textarea.val(userDoc); + elem.selectionStart = selects[0]; + elem.selectionEnd = selects[1]; + }; + + var onLocal = config.onLocal = function () { + if (initializing) { return; } + module.patchText(canonicalize($textarea.val())); }; var onReady = config.onReady = function (info) { + var realtime = module.realtime = info.realtime; + module.patchText = TextPatcher.create({ + realtime: realtime + }); + + $textarea.val(realtime.getUserDoc()); + + setEditable(true); initializing = false; - $textarea.attr('disabled', false); }; var onAbort = config.onAbort = function (info) { @@ -45,4 +76,9 @@ define([ }; var rt = Realtime.start(config); + + ['cut', 'paste', 'change', 'keyup', 'keydown', 'select', 'textInput'] + .forEach(function (evt) { + $textarea.on(evt, onLocal); + }); });