feat: append changes to previous stack item

This commit is contained in:
Matias Arola 2024-12-19 18:15:54 +02:00
parent 1b0f2e5463
commit 26209526b3
2 changed files with 30 additions and 1 deletions

View File

@ -131,6 +131,7 @@ const popStackItem = (undoManager, stack, eventType) => {
* @typedef {Object} UndoManagerOptions
* @property {number} [UndoManagerOptions.captureTimeout=500]
* @property {function(Transaction):boolean} [UndoManagerOptions.captureTransaction] Do not capture changes of a Transaction if result false.
* @property {function(Transaction):boolean} [UndoManagerOptions.appendToLatestStackItem] Append changes to the previous stack item if result true (regardless of captureTimeout).
* @property {function(Item):boolean} [UndoManagerOptions.deleteFilter=()=>true] Sometimes
* it is necessary to filter what an Undo/Redo operation can delete. If this
* filter returns false, the type/item won't be deleted even it is in the
@ -165,6 +166,7 @@ export class UndoManager extends ObservableV2 {
constructor (typeScope, {
captureTimeout = 500,
captureTransaction = _tr => true,
appendToLatestStackItem = _tr => false,
deleteFilter = () => true,
trackedOrigins = new Set([null]),
ignoreRemoteMapChanges = false,
@ -181,6 +183,7 @@ export class UndoManager extends ObservableV2 {
trackedOrigins.add(this)
this.trackedOrigins = trackedOrigins
this.captureTransaction = captureTransaction
this.appendToLatestStackItem = appendToLatestStackItem
/**
* @type {Array<StackItem>}
*/
@ -236,7 +239,10 @@ export class UndoManager extends ObservableV2 {
})
const now = time.getUnixTime()
let didAdd = false
if (this.lastChange > 0 && now - this.lastChange < this.captureTimeout && stack.length > 0 && !undoing && !redoing) {
if (this.lastChange > 0 &&
(now - this.lastChange < this.captureTimeout || this.appendToLatestStackItem(transaction)) &&
stack.length > 0 && !undoing && !redoing
) {
// append change to last stack op
const lastOp = stack[stack.length - 1]
lastOp.deletions = mergeDeleteSets([lastOp.deletions, transaction.deleteSet])

View File

@ -745,3 +745,26 @@ export const testUndoDoingStackItem = async (_tc) => {
t.compare(metaRedo, '42', 'currStackItem is accessible while redoing')
t.compare(undoManager.currStackItem, null, 'currStackItem is null after observe/transaction')
}
/**
* @param {t.TestCase} tc
*/
export const testAppendToLatestStackItem = tc => {
const { array0, array1 } = init(tc, { users: 2 })
const undoManager0 = new Y.UndoManager(array0, { captureTimeout: 0, appendToLatestStackItem: (_transaction) => true})
const undoManager1 = new Y.UndoManager(array1, { captureTimeout: 0, appendToLatestStackItem: (_transaction) => false})
array0.push([1, 2, 3])
undoManager0.stopCapturing()
array0.push([4, 5, 6])
array0.push([7, 8, 9])
undoManager0.undo()
t.compare(array0.toArray(), [1, 2, 3])
array1.push([1, 2, 3])
undoManager0.stopCapturing()
array1.push([4, 5, 6])
array1.push([7, 8, 9])
undoManager1.undo()
t.compare(array1.toArray(), [1, 2, 3, 4, 5, 6])
}