From f087837e675d9ecaaa7e0057a113506415a3959d Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 5 May 2020 14:03:30 +0200 Subject: [PATCH 1/5] Loop over all oo checkpoints until you find one available --- www/common/onlyoffice/inner.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index b65aac99d..0a42f79f3 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -221,10 +221,12 @@ define([ var now = function () { return +new Date(); }; - var getLastCp = function (old) { + var getLastCp = function (old, i) { var hashes = old ? oldHashes : content.hashes; if (!hashes || !Object.keys(hashes).length) { return {}; } - var lastIndex = Math.max.apply(null, Object.keys(hashes).map(Number)); + i = i || 0; + var idx = Object.keys(hashes).map(Number).sort(); + var lastIndex = idx[idx.length - 1 - i]; var last = JSON.parse(JSON.stringify(hashes[lastIndex])); return last; }; @@ -1365,9 +1367,7 @@ define([ }, 100); }; - var loadLastDocument = function () { - var lastCp = getLastCp(); - if (!lastCp) { return; } + var loadLastDocument = function (lastCp, onCpError) { ooChannel.cpIndex = lastCp.index || 0; var parsed = Hash.parsePadUrl(lastCp.file); var secret = Hash.getSecrets('file', parsed.hash); @@ -1381,6 +1381,7 @@ define([ xhr.responseType = 'arraybuffer'; xhr.onload = function () { if (/^4/.test('' + this.status)) { + onCpError(); return void console.error('XHR error', this.status); } var arrayBuffer = xhr.response; @@ -1393,15 +1394,25 @@ define([ }); } }; + xhr.onerror = function () { + onCpError(); + }; xhr.send(null); }; - var loadDocument = function (noCp, useNewDefault) { + var loadDocument = function (noCp, useNewDefault, i) { if (ooLoaded) { return; } var type = common.getMetadataMgr().getPrivateData().ooType; var file = getFileType(); if (!noCp) { + var lastCp = getLastCp(false, i); + // If the last checkpoint is empty, load the "initial" doc instead + if (!lastCp || !lastCp.file) { return void loadDocument(true, useNewDefault); } // Load latest checkpoint - return void loadLastDocument(); + return void loadLastDocument(lastCp, function () { + // Checkpoint error: load the previous one + i = i || 0; + loadDocument(noCp, useNewDefault, ++i); + }); } var newText; switch (type) { From 84b5741cdffdf6587245b217b55b00975a6d70ba Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 5 May 2020 14:41:02 +0200 Subject: [PATCH 2/5] Reload when a checkpoint has drawings --- www/common/onlyoffice/inner.js | 57 +++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index 0a42f79f3..f0884f918 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -346,6 +346,21 @@ define([ }; APP.FM = common.createFileManager(fmConfig); + var checkDrawings = function () { + var editor = getEditor(); + if (!editor) { return false; } + var s = editor.GetSheets(); + var hasDrawings = false; + s.forEach(function (obj, i) { + obj.worksheet.Drawings.forEach(function (d) { + console.log(d.graphicObject, d.graphicObject.Id); + }); + }); + return s.some(function (obj, i) { + return obj.worksheet.Drawings.length; + }); + }; + var saveToServer = function () { var text = getContent(); var blob = new Blob([text], {type: 'plain/text'}); @@ -356,6 +371,19 @@ define([ index: ooChannel.cpIndex }; fixSheets(); + +var hasDrawings = checkDrawings(); +console.log(hasDrawings); + +if (hasDrawings) { + data.callback = function () { + console.error('reload'); + $('iframe[name="frameEditor"]').after(h('div#cp-app-oo-placeholder')).remove();// XXX + startOO(blob, file, true); // XXX + }; +} + + APP.FM.handleFile(blob, data); }; @@ -841,8 +869,8 @@ define([ }; var ooLoaded = false; - var startOO = function (blob, file) { - if (APP.ooconfig) { return void console.error('already started'); } + var startOO = function (blob, file, force) { + if (APP.ooconfig && !force) { return void console.error('already started'); } var url = URL.createObjectURL(blob); var lock = readOnly || APP.migrate; @@ -1367,7 +1395,7 @@ define([ }, 100); }; - var loadLastDocument = function (lastCp, onCpError) { + var loadLastDocument = function (lastCp, onCpError, cb) { ooChannel.cpIndex = lastCp.index || 0; var parsed = Hash.parsePadUrl(lastCp.file); var secret = Hash.getSecrets('file', parsed.hash); @@ -1390,6 +1418,9 @@ define([ FileCrypto.decrypt(u8, key, function (err, decrypted) { if (err) { return void console.error(err); } var blob = new Blob([decrypted.content], {type: 'plain/text'}); + if (cb) { + return cb(blob, getFileType()); + } startOO(blob, getFileType()); }); } @@ -1670,6 +1701,21 @@ define([ var reloadPopup = false; + var checkNewCheckpoint = function () { + var hasDrawings = checkDrawings(); + if (hasDrawings) { + console.error('reload'); + var lastCp = getLastCp(); + loadLastDocument(lastCp, function () { + // On error, do nothing + }, function (blob, type) { + $('iframe[name="frameEditor"]').after(h('div#cp-app-oo-placeholder')) + .remove();// XXX + startOO(blob, type, true); + }); + } + }; + config.onRemote = function () { if (initializing) { return; } var userDoc = APP.realtime.getUserDoc(); @@ -1695,10 +1741,13 @@ define([ var latest = getLastCp(true); var newLatest = getLastCp(); if (newLatest.index > latest.index) { + // New checkpoint sframeChan.query('Q_OO_SAVE', { hash: newLatest.hash, url: newLatest.file - }, function () { }); + }, function () { + checkNewCheckpoint(); + }); } oldHashes = JSON.parse(JSON.stringify(content.hashes)); } From 6edbe019d66b5629adee2214a41be96de4f2c2df Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 5 May 2020 15:03:20 +0200 Subject: [PATCH 3/5] Fix fixSheets --- www/common/onlyoffice/inner.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index f0884f918..18275f414 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -269,6 +269,8 @@ define([ // so that the messages we send to the realtime channel are // loadable by users joining after the checkpoint var fixSheets = function () { + var hasDrawings = checkDrawings(); + if (hasDrawings) { return; } // XXX we need a migration for old sheets... try { var editor = getEditor(); // if we are not in the sheet app From 091192b69741fa45712adc43bc27b2c66a00a2fb Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 12 May 2020 13:21:56 +0200 Subject: [PATCH 4/5] Fix userID issues with the reload script and add reload modal --- www/common/onlyoffice/inner.js | 46 ++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index 18275f414..ed29c58ad 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -76,6 +76,7 @@ define([ var privateData = metadataMgr.getPrivateData(); var readOnly = false; var offline = false; + var ooLoaded = false; var pendingChanges = {}; var config = {}; var content = { @@ -302,6 +303,11 @@ define([ index: ev.index }; oldHashes = JSON.parse(JSON.stringify(content.hashes)); + var hasDrawings = checkDrawings(); + if (hasDrawings) { + content.locks = {}; + content.ids = {}; + } // If this is a migration, set the new version if (APP.migrate) { delete content.migration; @@ -363,6 +369,23 @@ define([ }); }; + var resetData = function (blob, type) { + if (!isLockedModal.modal) { + isLockedModal.modal = UI.openCustomModal(isLockedModal.content); + } + myUniqueOOId = undefined; + setMyId(); + APP.docEditor.destroyEditor(); // Kill the old editor + $('iframe[name="frameEditor"]').after(h('div#cp-app-oo-placeholder')).remove(); + ooLoaded = false; + oldLocks = {}; + Object.keys(pendingChanges).forEach(function (key) { + clearTimeout(pendingChanges[key]); + delete pendingChanges[key]; + }); + startOO(blob, type, true); + }; + var saveToServer = function () { var text = getContent(); var blob = new Blob([text], {type: 'plain/text'}); @@ -378,10 +401,11 @@ var hasDrawings = checkDrawings(); console.log(hasDrawings); if (hasDrawings) { + ooChannel.ready = false; + ooChannel.queue = []; data.callback = function () { console.error('reload'); - $('iframe[name="frameEditor"]').after(h('div#cp-app-oo-placeholder')).remove();// XXX - startOO(blob, file, true); // XXX + resetData(blob, file); }; } @@ -500,6 +524,7 @@ if (hasDrawings) { var getParticipants = function () { var users = metadataMgr.getMetadata().users; var i = 1; + var myIdx = false; var p = Object.keys(content.ids || {}).map(function (id) { var nId = id.slice(0,32); var ooId = content.ids[id].ooid; @@ -870,7 +895,6 @@ if (hasDrawings) { }); }; - var ooLoaded = false; var startOO = function (blob, file, force) { if (APP.ooconfig && !force) { return void console.error('already started'); } var url = URL.createObjectURL(blob); @@ -942,7 +966,6 @@ if (hasDrawings) { } }, "onDocumentReady": function () { - // The doc is ready, fix the worksheets IDs and push the queue fixSheets(); // Push changes since last cp @@ -960,6 +983,12 @@ if (hasDrawings) { // Allow edition setEditable(true); + if (isLockedModal.modal && force) { + isLockedModal.modal.closeModal(); + delete isLockedModal.modal; + $('#cp-app-oo-editor > iframe')[0].contentWindow.focus(); + } + if (APP.migrate && !readOnly) { var div = h('div.cp-oo-x2tXls', [ h('span.fa.fa-spin.fa-spinner'), @@ -1711,9 +1740,7 @@ if (hasDrawings) { loadLastDocument(lastCp, function () { // On error, do nothing }, function (blob, type) { - $('iframe[name="frameEditor"]').after(h('div#cp-app-oo-placeholder')) - .remove();// XXX - startOO(blob, type, true); + resetData(blob, type); }); } }; @@ -1743,6 +1770,11 @@ if (hasDrawings) { var latest = getLastCp(true); var newLatest = getLastCp(); if (newLatest.index > latest.index) { + var hasDrawings = checkDrawings(); + if (hasDrawings) { + ooChannel.ready = false; + ooChannel.queue = []; + } // New checkpoint sframeChan.query('Q_OO_SAVE', { hash: newLatest.hash, From 0018f71175e6363f110fde88f8031d706837387d Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 12 May 2020 13:46:09 +0200 Subject: [PATCH 5/5] Bump cp interval in onlyoffice to 100 --- www/common/onlyoffice/inner.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index ed29c58ad..89c5acf01 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -52,7 +52,7 @@ define([ $: $ }; - var CHECKPOINT_INTERVAL = 50; + var CHECKPOINT_INTERVAL = 100; var DISPLAY_RESTORE_BUTTON = false; var NEW_VERSION = 2; var PENDING_TIMEOUT = 30000; @@ -296,7 +296,13 @@ define([ console.error(err); return void UI.alert(Messages.oo_saveError); } - var i = Math.floor(ev.index / CHECKPOINT_INTERVAL); + // Get the last cp idx + var all = Object.keys(content.hashes || {}).map(Number).sort(); + var current = all[all.length - 1] || 0; + // Get the expected cp idx + var _i = Math.floor(ev.index / CHECKPOINT_INTERVAL); + // Take the max of both + var i = Math.max(_i, current); content.hashes[i] = { file: data.url, hash: ev.hash,