From f113b201885a6a64321391a278b684a6902c9ea5 Mon Sep 17 00:00:00 2001 From: Yifeng Wang Date: Sat, 25 Dec 2021 23:37:10 +0800 Subject: [PATCH] fix continuous paired undo redo of arbitrary length --- src/structs/Item.js | 15 +++++++++++++-- tests/undo-redo.tests.js | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/structs/Item.js b/src/structs/Item.js index 656f5e5b..79f800ae 100644 --- a/src/structs/Item.js +++ b/src/structs/Item.js @@ -210,10 +210,21 @@ export const redoItem = (transaction, item, redoitems, itemsToDelete) => { } right = right.right } + + /** + * @type {Item|null} + */ + let leftTrace = left // Iterate right while right is in itemsToDelete // If it is intended to delete right while item is redone, we can expect that item should replace right. - while (left !== null && left.right !== null && left.right !== right && itemsToDelete.findIndex(d => d === /** @type {Item} */ (left).right) >= 0) { - left = left.right + while (leftTrace !== null && leftTrace.right !== null && leftTrace.right !== right) { + if (itemsToDelete.findIndex(d => d === /** @type {Item} */ leftTrace) >= 0) { + break + } + leftTrace = leftTrace.right + } + if (leftTrace !== null) { + left = leftTrace } } const nextClock = getState(store, ownClientID) diff --git a/tests/undo-redo.tests.js b/tests/undo-redo.tests.js index 991225ca..c29c5a52 100644 --- a/tests/undo-redo.tests.js +++ b/tests/undo-redo.tests.js @@ -358,6 +358,26 @@ export const testUndoNestedUndoIssue = tc => { text.set('blocks', blocks3block) }) + const blocks4 = new Y.Array() + const blocks4block = new Y.Map() + doc.transact(() => { + blocks4block.set('text', 'Something Else 2') + blocks4.push([blocks4block]) + text.set('blocks', blocks4block) + }) + + const blocks5 = new Y.Array() + const blocks5block = new Y.Map() + doc.transact(() => { + blocks5block.set('text', 'Something Else 3') + blocks5.push([blocks5block]) + text.set('blocks', blocks5block) + }) + + t.compare(design.toJSON(), { text: { blocks: { text: 'Something Else 3' } } }) + undoManager.undo() + t.compare(design.toJSON(), { text: { blocks: { text: 'Something Else 2' } } }) + undoManager.undo() t.compare(design.toJSON(), { text: { blocks: { text: 'Something Else' } } }) undoManager.undo() t.compare(design.toJSON(), { text: { blocks: { text: 'Something' } } }) @@ -371,4 +391,8 @@ export const testUndoNestedUndoIssue = tc => { t.compare(design.toJSON(), { text: { blocks: { text: 'Something' } } }) undoManager.redo() t.compare(design.toJSON(), { text: { blocks: { text: 'Something Else' } } }) + undoManager.redo() + t.compare(design.toJSON(), { text: { blocks: { text: 'Something Else 2' } } }) + undoManager.redo() + t.compare(design.toJSON(), { text: { blocks: { text: 'Something Else 3' } } }) }