diff --git a/NetfluxWebsocketSrv.js b/NetfluxWebsocketSrv.js index 2d894a5c0..b8c4f5a2a 100644 --- a/NetfluxWebsocketSrv.js +++ b/NetfluxWebsocketSrv.js @@ -118,7 +118,7 @@ dropUser = function (ctx, user) { }); }; -const getHistory = function (ctx, channelName, handler, cb) { +const getHistory = function (ctx, channelName, lastKnownHash, handler, cb) { var messageBuf = []; var messageKey; ctx.store.getMessages(channelName, function (msgStr) { @@ -137,21 +137,35 @@ const getHistory = function (ctx, channelName, handler, cb) { var startPoint; var cpCount = 0; var msgBuff2 = []; + var sendBuff2 = function () { + for (var x = msgBuff2.pop(); x; x = msgBuff2.pop()) { handler(x); } + }; + var hash = function (msg) { + return msg.slice(0,64); //Crypto.createHash('md5').update(msg).digest('hex'); + }; + var isSent = false; for (startPoint = messageBuf.length - 1; startPoint >= 0; startPoint--) { var msg = messageBuf[startPoint]; msgBuff2.push(msg); - if (msg[2] === 'MSG' && msg[4].indexOf('cp|') === 0) { + if (lastKnownHash) { + if (msg[2] === 'MSG' && hash(msg[4]) === lastKnownHash) { + msgBuff2.pop(); + sendBuff2(); + isSent = true; + break; + } + } else if (msg[2] === 'MSG' && msg[4].indexOf('cp|') === 0) { cpCount++; if (cpCount >= 2) { - for (var x = msgBuff2.pop(); x; x = msgBuff2.pop()) { handler(x); } + sendBuff2(); + isSent = true; break; } } - //console.log(messageBuf[startPoint]); } - if (cpCount < 2) { + if (!isSent) { // no checkpoints. - for (var x = msgBuff2.pop(); x; x = msgBuff2.pop()) { handler(x); } + sendBuff2(); } cb(messageBuf); }); @@ -196,11 +210,13 @@ const handleMessage = function (ctx, user, msg) { let parsed; try { parsed = JSON.parse(json[2]); } catch (err) { console.error(err); return; } if (parsed[0] === 'GET_HISTORY') { + // parsed[1] is the channel id + // parsed[2] is a validation key (optionnal) + // parsed[3] is the last known hash (optionnal) sendMsg(ctx, user, [seq, 'ACK']); - getHistory(ctx, parsed[1], function (msg) { + getHistory(ctx, parsed[1], parsed[3], function (msg) { sendMsg(ctx, user, [0, HISTORY_KEEPER_ID, 'MSG', user.id, JSON.stringify(msg)]); }, function (messages) { - // parsed[2] is a validation key if it exists if (messages.length === 0 && parsed[2] && !historyKeeperKeys[parsed[1]]) { var key = {channel: parsed[1], validateKey: parsed[2]}; storeMessage(ctx, ctx.channels[parsed[1]], JSON.stringify(key)); diff --git a/www/code/main.js b/www/code/main.js index a091b3f76..be2c49969 100644 --- a/www/code/main.js +++ b/www/code/main.js @@ -2,7 +2,7 @@ require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/J define([ '/bower_components/chainpad-crypto/crypto.js', '/bower_components/chainpad-netflux/chainpad-netflux.js', - '/bower_components/textpatcher/TextPatcher.amd.js', + '/bower_components/textpatcher/TextPatcher.js', '/common/toolbar.js', 'json.sortify', '/bower_components/chainpad-json-validator/json-ot.js', @@ -521,12 +521,14 @@ define([ }; var onReady = config.onReady = function (info) { - var realtime = module.realtime = info.realtime; module.users = info.userList.users; - module.patchText = TextPatcher.create({ - realtime: realtime, - //logging: true - }); + if (module.realtime !== info.realtime) { + var realtime = module.realtime = info.realtime; + module.patchText = TextPatcher.create({ + realtime: realtime, + //logging: true + }); + } var userDoc = module.realtime.getUserDoc(); diff --git a/www/common/toolbar.js b/www/common/toolbar.js index 4eaaf8ba6..297a4d857 100644 --- a/www/common/toolbar.js +++ b/www/common/toolbar.js @@ -407,8 +407,11 @@ define([ window.location = "/"; }; - $aTagBig.click(onClick); - $aTagSmall.click(onClick); + var onContext = function (e) { e.stopPropagation(); }; + + $aTagBig.click(onClick).contextmenu(onContext); + $aTagSmall.click(onClick).contextmenu(onContext); + $linkContainer.append($aTagSmall).append($aTagBig); }; diff --git a/www/drive/main.js b/www/drive/main.js index 02ba2238d..d1b381cd7 100644 --- a/www/drive/main.js +++ b/www/drive/main.js @@ -181,6 +181,7 @@ define([ var $tree = $iframe.find("#tree"); var $content = $iframe.find("#content"); + var $appContainer = $iframe.find(".app-container"); var $driveToolbar = $iframe.find("#driveToolbar"); var $contextMenu = $iframe.find("#treeContextMenu"); var $contentContextMenu = $iframe.find("#contentContextMenu"); @@ -1737,7 +1738,8 @@ define([ // Disable middle click in the context menu to avoid opening /drive/inner.html# in new tabs $(ifrw).click(function (e) { - if (e.which !== 3) { + if (!e.target || !$(e.target).parents('.cryptpad-dropdown').length) { return; } + if (e.which !== 1) { e.stopPropagation(); return false; } @@ -1900,21 +1902,21 @@ define([ module.hideMenu(); }); - $(ifrw).on('click', function (e) { + $appContainer.on('click', function (e) { if (e.which !== 1) { return ; } removeSelected(e); removeInput(); module.hideMenu(e); hideNewButton(); }); - $(ifrw).on('drag drop', function (e) { + $appContainer.on('drag drop', function (e) { removeInput(); module.hideMenu(e); }); - $(ifrw).on('mouseup drop', function (e) { + $appContainer.on('mouseup drop', function (e) { $iframe.find('.droppable').removeClass('droppable'); }); - $(ifrw).on('keydown', function (e) { + $appContainer.on('keydown', function (e) { // "Del" if (e.which === 46) { if (filesOp.isPathInFilesData(currentPath)) { return; } // We can't remove elements directly from filesData @@ -1948,7 +1950,7 @@ define([ moveElements(paths, [TRASH], false, refresh); } }); - $(ifrw).contextmenu(function () { + $appContainer.contextmenu(function () { module.hideMenu(); return false; }); @@ -2005,7 +2007,7 @@ define([ updatePathSize(); }, 100); }); - $(ifrw).mouseup(function (e) { + $appContainer.mouseup(function (e) { window.clearInterval(APP.resizeTree); APP.resizeTree = undefined; }); diff --git a/www/pad/main.js b/www/pad/main.js index 9c0cb6b7d..a5a135082 100644 --- a/www/pad/main.js +++ b/www/pad/main.js @@ -8,7 +8,7 @@ define([ '/bower_components/chainpad-json-validator/json-ot.js', '/common/TypingTests.js', 'json.sortify', - '/bower_components/textpatcher/TextPatcher.amd.js', + '/bower_components/textpatcher/TextPatcher.js', '/common/cryptpad-common.js', '/common/visible.js', '/common/notify.js', @@ -656,10 +656,12 @@ define([ } } - module.patchText = TextPatcher.create({ - realtime: info.realtime, - //logging: true, - }); + if (module.realtime !== info.realtime) { + module.patchText = TextPatcher.create({ + realtime: info.realtime, + //logging: true, + }); + } module.users = info.userList.users; module.realtime = info.realtime; diff --git a/www/poll/main.js b/www/poll/main.js index 237581713..95b540edf 100644 --- a/www/poll/main.js +++ b/www/poll/main.js @@ -589,7 +589,7 @@ define([ $description.val(proxy.info.description); } - $('#tableScroll').prepend($table); + $('#tableScroll').html('').prepend($table); updateDisplayedTable(); $table @@ -662,11 +662,17 @@ define([ var disconnect = function (info) { //setEditable(false); // TODO + APP.realtime.toolbar.failed(); Cryptpad.alert(Messages.common_connectionLost, undefined, true); }; + var reconnect = function (info) { + //setEditable(true); // TODO + APP.realtime.toolbar.reconnecting(info.myId); + Cryptpad.findOKButton().click(); + }; + var create = function (info) { - var realtime = APP.realtime = info.realtime; var myID = APP.myID = info.myID; var editHash; @@ -676,10 +682,13 @@ define([ editHash = Cryptpad.getEditHashFromKeys(info.channel, secret.keys); } - APP.patchText = TextPatcher.create({ - realtime: realtime, - logging: true, - }); + if (APP.realtime !== info.realtime) { + APP.realtime = info.realtime; + APP.patchText = TextPatcher.create({ + realtime: info.realtime, + logging: true, + }); + } userList = APP.userList = info.userList; @@ -766,7 +775,8 @@ define([ }); }); }) - .on('disconnect', disconnect); + .on('disconnect', disconnect) + .on('reconnect', reconnect); Cryptpad.getAttribute(HIDE_INTRODUCTION_TEXT, function (e, value) { if (e) { console.error(e); } diff --git a/www/slide/main.js b/www/slide/main.js index 2e1cca8a8..138aae9a7 100644 --- a/www/slide/main.js +++ b/www/slide/main.js @@ -2,7 +2,7 @@ require.config({ paths: { 'json.sortify': '/bower_components/json.sortify/dist/J define([ '/bower_components/chainpad-crypto/crypto.js', '/bower_components/chainpad-netflux/chainpad-netflux.js', - '/bower_components/textpatcher/TextPatcher.amd.js', + '/bower_components/textpatcher/TextPatcher.js', '/common/toolbar.js', 'json.sortify', '/bower_components/chainpad-json-validator/json-ot.js', @@ -678,12 +678,15 @@ define([ }; var onReady = config.onReady = function (info) { - var realtime = module.realtime = info.realtime; module.users = info.userList.users; - module.patchText = TextPatcher.create({ - realtime: realtime, - //logging: true - }); + + if (module.realtime !== info.realtime) { + var realtime = module.realtime = info.realtime; + module.patchText = TextPatcher.create({ + realtime: realtime, + //logging: true + }); + } var userDoc = module.realtime.getUserDoc();