more utility around Y.UndoManager

This commit is contained in:
Kevin Jahns 2022-03-20 22:41:33 +01:00
parent 239703fe5c
commit 46fbce0de8
2 changed files with 53 additions and 24 deletions

12
package-lock.json generated
View File

@ -2210,9 +2210,9 @@
} }
}, },
"node_modules/lib0": { "node_modules/lib0": {
"version": "0.2.46", "version": "0.2.47",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.46.tgz", "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.47.tgz",
"integrity": "sha512-U8V4Nc91EUSXLewvlJb0uSm9JI5rbiZKXBKHqWwPHX4g5cHx09dWAeD//UEZplm96xCrZ1BKDh5QaFHUIsnGIg==", "integrity": "sha512-RXprIyaflw7OmFNMpb8HmvDhuRVUFXYCXrmynQN8OGbGevgMx9u6tjQG/yB0dOoDcuB1XXgqFn8Oy3RlKF/Qhg==",
"dependencies": { "dependencies": {
"isomorphic.js": "^0.2.4" "isomorphic.js": "^0.2.4"
}, },
@ -5591,9 +5591,9 @@
} }
}, },
"lib0": { "lib0": {
"version": "0.2.46", "version": "0.2.47",
"resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.46.tgz", "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.47.tgz",
"integrity": "sha512-U8V4Nc91EUSXLewvlJb0uSm9JI5rbiZKXBKHqWwPHX4g5cHx09dWAeD//UEZplm96xCrZ1BKDh5QaFHUIsnGIg==", "integrity": "sha512-RXprIyaflw7OmFNMpb8HmvDhuRVUFXYCXrmynQN8OGbGevgMx9u6tjQG/yB0dOoDcuB1XXgqFn8Oy3RlKF/Qhg==",
"requires": { "requires": {
"isomorphic.js": "^0.2.4" "isomorphic.js": "^0.2.4"
} }

View File

@ -14,6 +14,7 @@ import {
} from '../internals.js' } from '../internals.js'
import * as time from 'lib0/time' import * as time from 'lib0/time'
import * as array from 'lib0/array'
import { Observable } from 'lib0/observable' import { Observable } from 'lib0/observable'
class StackItem { class StackItem {
@ -30,6 +31,18 @@ class StackItem {
this.meta = new Map() this.meta = new Map()
} }
} }
/**
* @param {Transaction} tr
* @param {UndoManager} um
* @param {StackItem} stackItem
*/
const clearUndoManagerStackItem = (tr, um, stackItem) => {
iterateDeletedStructs(tr, stackItem.deletions, item => {
if (item instanceof Item && um.scope.some(type => isParentOf(type, item))) {
keepItem(item, false)
}
})
}
/** /**
* @param {UndoManager} undoManager * @param {UndoManager} undoManager
@ -133,7 +146,7 @@ const popStackItem = (undoManager, stack, eventType) => {
* Fires 'stack-item-popped' event when a stack item was popped from either the * Fires 'stack-item-popped' event when a stack item was popped from either the
* undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`. * undo- or the redo-stack. You may restore the saved stack information from `event.stackItem.meta`.
* *
* @extends {Observable<'stack-item-added'|'stack-item-popped'>} * @extends {Observable<'stack-item-added'|'stack-item-popped'|'stack-cleared'>}
*/ */
export class UndoManager extends Observable { export class UndoManager extends Observable {
/** /**
@ -142,7 +155,11 @@ export class UndoManager extends Observable {
*/ */
constructor (typeScope, { captureTimeout = 500, deleteFilter = () => true, trackedOrigins = new Set([null]) } = {}) { constructor (typeScope, { captureTimeout = 500, deleteFilter = () => true, trackedOrigins = new Set([null]) } = {}) {
super() super()
this.scope = typeScope instanceof Array ? typeScope : [typeScope] /**
* @type {Array<AbstractType<any>>}
*/
this.scope = []
this.addToScope(typeScope)
this.deleteFilter = deleteFilter this.deleteFilter = deleteFilter
trackedOrigins.add(this) trackedOrigins.add(this)
this.trackedOrigins = trackedOrigins this.trackedOrigins = trackedOrigins
@ -175,7 +192,7 @@ export class UndoManager extends Observable {
this.stopCapturing() // next undo should not be appended to last stack item this.stopCapturing() // next undo should not be appended to last stack item
} else if (!redoing) { } else if (!redoing) {
// neither undoing nor redoing: delete redoStack // neither undoing nor redoing: delete redoStack
this.redoStack = [] this.clear(false, true)
} }
const insertions = new DeleteSet() const insertions = new DeleteSet()
transaction.afterState.forEach((endClock, client) => { transaction.afterState.forEach((endClock, client) => {
@ -210,25 +227,37 @@ export class UndoManager extends Observable {
this.emit('stack-item-added', [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this]) this.emit('stack-item-added', [{ stackItem: stack[stack.length - 1], origin: transaction.origin, type: undoing ? 'redo' : 'undo', changedParentTypes: transaction.changedParentTypes }, this])
} }
}) })
this.doc.on('destroy', () => {
this.destroy()
})
} }
clear () { /**
this.doc.transact(transaction => { * @param {Array<AbstractType<any>> | AbstractType<any>} ytypes
/** */
* @param {StackItem} stackItem addToScope (ytypes) {
*/ ytypes = array.isArray(ytypes) ? ytypes : [ytypes]
const clearItem = stackItem => { ytypes.forEach(ytype => {
iterateDeletedStructs(transaction, stackItem.deletions, item => { if (this.scope.every(yt => yt !== ytype)) {
if (item instanceof Item && this.scope.some(type => isParentOf(type, item))) { this.scope.push(ytype)
keepItem(item, false)
}
})
} }
this.undoStack.forEach(clearItem)
this.redoStack.forEach(clearItem)
}) })
this.undoStack = [] }
this.redoStack = []
clear (clearUndoStack = true, clearRedoStack = true) {
if ((clearUndoStack && this.canUndo()) || (clearRedoStack && this.canRedo())) {
this.doc.transact(tr => {
if (clearUndoStack) {
this.undoStack.forEach(item => clearUndoManagerStackItem(tr, this, item))
this.undoStack = []
}
if (clearRedoStack) {
this.redoStack.forEach(item => clearUndoManagerStackItem(tr, this, item))
this.redoStack = []
}
this.emit('stack-cleared', [{ undoStackCleared: clearUndoStack, redoStackCleared: clearRedoStack }])
})
}
} }
/** /**