From abc342dfd8ef877c8b2f97a3f837867c2f697b4a 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 35e23336411..c59a7a8abec 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 f2d9ebb790d..19f445acf4c 100644 --- a/lib/Service/DocumentService.php +++ b/lib/Service/DocumentService.php @@ -330,9 +330,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; }