diff --git a/services/web/frontend/js/vendor/libs/sharejs.js b/services/web/frontend/js/vendor/libs/sharejs.js index e3bec4804e22..1749e61e6dfa 100644 --- a/services/web/frontend/js/vendor/libs/sharejs.js +++ b/services/web/frontend/js/vendor/libs/sharejs.js @@ -1048,6 +1048,24 @@ export const { Doc } = (() => { this.version = msg.v; } + // Overleaf: an inflight op that cancelled out against a remote op is + // empty; there is nothing to resend. Drop it (resolving its callbacks and + // clearing the dedup ids) so we do not resend an empty op. If there is no + // pending op either, the doc is fully in sync, so emit 'saved'; otherwise + // flush() below sends the pending op normally. + if (this.inflightOp && this.inflightOp.length === 0) { + this.inflightOp = null; + var inflightCallbacks = this.inflightCallbacks; + this.inflightCallbacks = []; + this.inflightSubmittedIds.length = 0; + inflightCallbacks.forEach(function (callback) { + callback(null); + }); + if (this.pendingOp === null) { + this.emit('saved'); + } + } + // Resend any previously queued operation. if (this.inflightOp) { var response = { @@ -1145,6 +1163,21 @@ export const { Doc } = (() => { this.pendingOp = _Array$from8[0]; undo = _Array$from8[1]; + + // Overleaf: a pending op fully reverted by the undo is a no-op. + // Drop it (rather than leaving an empty op list) so it is not + // flushed and sent as an empty op. Resolve its submit callbacks; the + // inflight op was already cleared above, so the doc is fully in + // sync: emit 'saved'. + if (this.pendingOp.length === 0) { + this.pendingOp = null; + var pendingCallbacks = this.pendingCallbacks; + this.pendingCallbacks = []; + pendingCallbacks.forEach(function (callback) { + callback(null); + }); + this.emit('saved'); + } } // ... and apply it locally, reverting the changes. @@ -1261,6 +1294,23 @@ export const { Doc } = (() => { this.pendingOp = _Array$from12[0]; docOp = _Array$from12[1]; + + // Overleaf: a pending op that fully cancels against the server op is a + // no-op. Drop it (rather than leaving an empty op list) so it is not + // flushed and sent to the server as an empty op. Resolve its submit + // callbacks (it completed as a no-op), and if nothing is inflight either + // the doc is fully in sync, so emit 'saved'. + if (this.pendingOp.length === 0) { + this.pendingOp = null; + var pendingCallbacks = this.pendingCallbacks; + this.pendingCallbacks = []; + pendingCallbacks.forEach(function (callback) { + callback(null); + }); + if (this.inflightOp === null) { + this.emit('saved'); + } + } } this.version++;