diff --git a/package.json b/package.json index f87caf8b8..0d23ca0c1 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "dev": "DEV=1 node server.js", "fresh": "FRESH=1 node server.js", "offline": "FRESH=1 OFFLINE=1 node server.js", + "offlinedev": "DEV=1 OFFLINE=1 node server.js", "package": "PACKAGE=1 node server.js", "lint": "jshint --config .jshintrc --exclude-path .jshintignore . && ./node_modules/lesshint/bin/lesshint -c ./.lesshintrc ./customize.dist/src/less2/", "lint:js": "jshint --config .jshintrc --exclude-path .jshintignore .", diff --git a/scripts/tests/test-rpc.js b/scripts/tests/test-rpc.js index ce432408c..0fd0abc37 100644 --- a/scripts/tests/test-rpc.js +++ b/scripts/tests/test-rpc.js @@ -299,7 +299,7 @@ nThen(function (w) { oscar.edKeys.edPublic ], keys: rosterKeys, - anon_rpc: oscar.anonRpc, + store: oscar, lastKnownHash: void 0, }, w(function (err, roster) { if (err) { @@ -514,7 +514,7 @@ nThen(function (w) { channel: rosterKeys.channel, //owners: [], // Alice doesn't know who the owners might be... keys: rosterKeys, - anon_rpc: alice.anonRpc, + store: alice, lastKnownHash: void 0, // alice should fetch everything from the beginning of time... }, w(function (err, roster) { if (err) { @@ -742,7 +742,7 @@ nThen(function (w) { network: bob.network, channel: rosterKeys.channel, keys: rosterKeys, - anon_rpc: bob.anonRpc, + store: bob, //lastKnownHash: oscar.lastRosterCheckpointHash //lastKnownHash: oscar.lastKnownHash, // FIXME this doesn't work. off-by-one? }, w(function (err, roster) { diff --git a/www/common/onlyoffice/inner.js b/www/common/onlyoffice/inner.js index 577c1d286..95d5b872e 100644 --- a/www/common/onlyoffice/inner.js +++ b/www/common/onlyoffice/inner.js @@ -73,6 +73,11 @@ define([ return JSONSortify(obj); }; + var supportsXLSX = function () { + return !(typeof(Atomics) === "undefined" || typeof (SharedArrayBuffer) === "undefined"); + }; + + var toolbar; @@ -208,6 +213,19 @@ define([ } }; + // Make sure a former tab on the same worker doesn't have remaining locks + var checkClients = function (clients) { + Object.keys(content.ids).forEach(function (id) { + var tabId = Number(id.slice(33)); // remove the netflux ID and the "-" + if (clients.indexOf(tabId) === -1) { + removeClient({ + id: tabId + }); + } + }); + }; + + var getFileType = function () { var type = common.getMetadataMgr().getPrivateData().ooType; var title = common.getMetadataMgr().getMetadataLazy().title; @@ -723,6 +741,7 @@ define([ sframeChan.on('EV_OO_EVENT', function (obj) { switch (obj.ev) { case 'READY': + checkClients(obj.data); cb(); break; case 'LEAVE': @@ -984,6 +1003,12 @@ define([ deleteOfflineLocks(); // Prepare callback if (cpNfInner) { + var waitLock = APP.waitLock = Util.mkEvent(true); + setTimeout(function () { + // Make sure the waitLock is never stuck + waitLock.fire(); + if (waitLock === APP.waitLock) { delete APP.waitLock; } + }, 5000); var onPatchSent = function (again) { if (!again) { cpNfInner.offPatchSent(onPatchSent); } // Answer to our onlyoffice @@ -999,6 +1024,8 @@ define([ type: "getLock", locks: getLock() }); + waitLock.fire(); + if (waitLock === APP.waitLock) { delete APP.waitLock; } } else { if (!isLockedModal.modal) { isLockedModal.modal = UI.openCustomModal(isLockedModal.content); @@ -1107,7 +1134,8 @@ define([ Channel.create(msgEv, postMsg, function (chan) { APP.chan = chan; - var send = ooChannel.send = function (obj) { + var send = ooChannel.send = function (obj, force) { + if (APP.onStrictSaveChanges && !force) { return; } // can't push to OO before reloading cp debug(obj, 'toOO'); chan.event('CMD', obj); }; @@ -1121,10 +1149,19 @@ define([ case "isSaveLock": // TODO ping the server to check if we're online first? if (!offline) { - send({ - type: "saveLock", - saveLock: false - }); + if (APP.waitLock) { + APP.waitLock.reg(function () { + send({ + type: "saveLock", + saveLock: false + }, true); + }); + } else { + send({ + type: "saveLock", + saveLock: false + }, true); + } } break; case "getLock": @@ -1135,6 +1172,18 @@ define([ send({ type: "message" }); break; case "saveChanges": + // If we have unsaved data before reloading for a checkpoint... + if (APP.onStrictSaveChanges) { + APP.unsavedChanges = { + type: "saveChanges", + changes: parseChanges(obj.changes), + changesIndex: ooChannel.cpIndex || 0, + locks: getUserLock(getId()), + excelAdditionalInfo: null + }; + APP.onStrictSaveChanges(); + return; + } // We're sending our changes to netflux handleChanges(obj, send); // If we're alone, clean up the medias @@ -1223,27 +1272,29 @@ define([ $iframe.prop('tabindex', '-1'); var $tb = $iframe.find('head'); var css = // Old OO - '#id-toolbar-full .toolbar-group:nth-child(2), #id-toolbar-full .separator:nth-child(3) { display: none; }' + - '#fm-btn-save { display: none !important; }' + + //'#id-toolbar-full .toolbar-group:nth-child(2), #id-toolbar-full .separator:nth-child(3) { display: none; }' + + //'#fm-btn-save { display: none !important; }' + '#panel-settings-general tr.autosave { display: none !important; }' + '#panel-settings-general tr.coauth { display: none !important; }' + - '#header { display: none !important; }' + + //'#header { display: none !important; }' + '#title-doc-name { display: none !important; }' + + '#title-user-name { display: none !important; }' + + (supportsXLSX() ? '' : '#slot-btn-dt-print { display: none !important; }') + // New OO: '#asc-gen566 { display: none !important; }' + // Insert image from url 'section[data-tab="ins"] .separator:nth-last-child(2) { display: none !important; }' + // separator '#slot-btn-insequation { display: none !important; }' + // Insert equation - '.toolbar .tabs .ribtab:not(.canedit) { display: none !important; }' + // Switch collaborative mode - '#app-title { display: none !important; }' + // OnlyOffice logo + doc title + //'.toolbar .tabs .ribtab:not(.canedit) { display: none !important; }' + // Switch collaborative mode '#fm-btn-info { display: none !important; }' + // Author name, doc title, etc. in "File" (menu entry) '#panel-info { display: none !important; }' + // Same but content '#image-button-from-url { display: none !important; }' + // Inline image settings: replace with url '#file-menu-panel .devider { display: none !important; }' + // separator in the "File" menu - '#file-menu-panel { top: 28px !important; }' + // Position of the "File" menu '#left-btn-spellcheck, #left-btn-about { display: none !important; }'+ 'div.btn-users.dropdown-toggle { display: none; !important }'; if (readOnly) { css += '#toolbar { display: none !important; }'; + //css += '#app-title { display: none !important; }'; // OnlyOffice logo + doc title + //css += '#file-menu-panel { top: 28px !important; }'; // Position of the "File" menu } $('