follow redone items to prevent some undo-redo issues. Fixes #162

This commit is contained in:
Kevin Jahns 2019-10-08 18:31:56 +02:00
parent 6d4f0c0cdd
commit aeb23dbaa9
3 changed files with 21 additions and 4 deletions

View File

@ -35,6 +35,8 @@ import * as set from 'lib0/set.js'
import * as binary from 'lib0/binary.js' import * as binary from 'lib0/binary.js'
/** /**
* @todo This should return several items
*
* @param {StructStore} store * @param {StructStore} store
* @param {ID} id * @param {ID} id
* @return {{item:Item, diff:number}} * @return {{item:Item, diff:number}}

View File

@ -75,15 +75,15 @@ const popStackItem = (undoManager, stack, eventType) => {
itemsToRedo.add(struct) itemsToRedo.add(struct)
} }
}) })
itemsToRedo.forEach(item => { itemsToRedo.forEach(struct => {
performedChange = redoItem(transaction, item, itemsToRedo) !== null || performedChange performedChange = redoItem(transaction, struct, itemsToRedo) !== null || performedChange
}) })
/** /**
* @type {Array<Item>} * @type {Array<Item>}
*/ */
const itemsToDelete = [] const itemsToDelete = []
iterateStructs(transaction, structs, stackStartClock, stackItem.len, struct => { iterateStructs(transaction, structs, stackStartClock, stackItem.len, struct => {
if (struct instanceof Item && !struct.deleted && scope.some(type => isParentOf(type, /** @type {Item} */ (struct)))) { if (struct instanceof Item) {
if (struct.redone !== null) { if (struct.redone !== null) {
let { item, diff } = followRedone(store, struct.id) let { item, diff } = followRedone(store, struct.id)
if (diff > 0) { if (diff > 0) {
@ -94,7 +94,9 @@ const popStackItem = (undoManager, stack, eventType) => {
} }
struct = item struct = item
} }
itemsToDelete.push(struct) if (!struct.deleted && scope.some(type => isParentOf(type, /** @type {Item} */ (struct)))) {
itemsToDelete.push(struct)
}
} }
}) })
// We want to delete in reverse order so that children are deleted before // We want to delete in reverse order so that children are deleted before

View File

@ -13,10 +13,23 @@ import * as t from 'lib0/testing.js'
export const testUndoText = tc => { export const testUndoText = tc => {
const { testConnector, text0, text1 } = init(tc, { users: 3 }) const { testConnector, text0, text1 } = init(tc, { users: 3 })
const undoManager = new UndoManager(text0) const undoManager = new UndoManager(text0)
// items that are added & deleted in the same transaction won't be undo
text0.insert(0, 'test') text0.insert(0, 'test')
text0.delete(0, 4) text0.delete(0, 4)
undoManager.undo() undoManager.undo()
t.assert(text0.toString() === '') t.assert(text0.toString() === '')
// follow redone items
text0.insert(0, 'a')
undoManager.stopCapturing()
text0.delete(0, 1)
undoManager.stopCapturing()
undoManager.undo()
t.assert(text0.toString() === 'a')
undoManager.undo()
t.assert(text0.toString() === '')
text0.insert(0, 'abc') text0.insert(0, 'abc')
text1.insert(0, 'xyz') text1.insert(0, 'xyz')
testConnector.syncAll() testConnector.syncAll()