From 6aa598bb187551f3033bfc0364db763ceac4eb10 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 12 Jun 2023 14:50:27 +0200 Subject: [PATCH] fix(sync): Save even if versions match Fixes #3404. Apply saves even if the client and server version match. The client version only reflects the steps which the client has received back from the server. It may leave out the steps the client just send itself. So if the versions match - save the file to be sure to include changes from the client. Signed-off-by: Max --- cypress/e2e/directediting.spec.js | 15 --------------- lib/Service/DocumentService.php | 8 ++++++-- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/cypress/e2e/directediting.spec.js b/cypress/e2e/directediting.spec.js index 35e2333641..c59a7a8abe 100644 --- a/cypress/e2e/directediting.spec.js +++ b/cypress/e2e/directediting.spec.js @@ -61,16 +61,11 @@ describe('direct editing', function() { }) const closeRequestAlias = 'closeRequest' cy.intercept({ method: 'POST', url: '**/session/close' }).as(closeRequestAlias) - cy.intercept({ method: 'POST', url: '**/apps/text/session/sync' }).as('sync') cy.getContent().type('# This is a headline') cy.getContent().type('{enter}') cy.getContent().type('Some text') cy.getContent().type('{enter}') - // ensure we have received our own steps - cy.wait('@sync', { timeout: 7000 }) - cy.wait('@sync', { timeout: 7000 }) - cy.get('button.icon-close').click() cy.wait(`@${closeRequestAlias}`).then(() => { cy.getFileContent('empty.md').then((content) => { @@ -87,17 +82,12 @@ describe('direct editing', function() { }) const closeRequestAlias = 'closeRequest' cy.intercept({ method: 'POST', url: '**/session/close' }).as(closeRequestAlias) - cy.intercept({ method: 'POST', url: '**/apps/text/session/sync' }).as('sync') cy.getContent().type('# This is a headline') cy.getContent().type('{enter}') cy.getContent().type('Some text') cy.getContent().type('{enter}') - // ensure we have received our own steps - cy.wait('@sync', { timeout: 7000 }) - cy.wait('@sync', { timeout: 7000 }) - cy.get('button.icon-close').click() cy.wait(`@${closeRequestAlias}`).then(() => { cy.getFileContent('newfile.md').then((content) => { @@ -114,17 +104,12 @@ describe('direct editing', function() { }) const closeRequestAlias = 'closeRequest' cy.intercept({ method: 'POST', url: '**/session/close' }).as(closeRequestAlias) - cy.intercept({ method: 'POST', url: '**/apps/text/session/sync' }).as('sync') cy.getContent().type('# This is a headline') cy.getContent().type('{enter}') cy.getContent().type('Some text') cy.getContent().type('{enter}') - // ensure we have received our own steps - cy.wait('@sync', { timeout: 7000 }) - cy.wait('@sync', { timeout: 7000 }) - cy.get('button.icon-close').click() cy.wait(`@${closeRequestAlias}`).then(() => { cy.getFileContent('empty.txt').then((content) => { diff --git a/lib/Service/DocumentService.php b/lib/Service/DocumentService.php index 1bf5f8b1fe..aadfc825c6 100644 --- a/lib/Service/DocumentService.php +++ b/lib/Service/DocumentService.php @@ -339,9 +339,13 @@ public function autosave(?File $file, int $documentId, int $version, ?string $au if ($autoSaveDocument === null) { return $document; } - // Do not save if version already saved + // Do not save if newer version already saved + // Note that $version is the version of the steps the client has fetched. + // It may have added steps on top of that - so if the versions match we still save. $stepsVersion = $this->stepMapper->getLatestVersion($documentId); - if (!$force && ($version <= (string)$document->getLastSavedVersion() || $version > (string)$stepsVersion)) { + $savedVersion = $document->getLastSavedVersion(); + $outdated = $savedVersion > 0 && $savedVersion > $version; + if (!$force && ($outdated || $version > (string)$stepsVersion)) { return $document; }