[UndoManager] support global undo
This commit is contained in:
		
							parent
							
								
									cc9a857441
								
							
						
					
					
						commit
						69d4a5c821
					
				| @ -39,7 +39,7 @@ export class StackItem { | ||||
|  */ | ||||
| const clearUndoManagerStackItem = (tr, um, stackItem) => { | ||||
|   iterateDeletedStructs(tr, stackItem.deletions, item => { | ||||
|     if (item instanceof Item && um.scope.some(type => isParentOf(type, item))) { | ||||
|     if (item instanceof Item && um.scope.some(type => type === tr.doc || isParentOf(/** @type {AbstractType<any>} */ (type), item))) { | ||||
|       keepItem(item, false) | ||||
|     } | ||||
|   }) | ||||
| @ -81,7 +81,7 @@ const popStackItem = (undoManager, stack, eventType) => { | ||||
|             } | ||||
|             struct = item | ||||
|           } | ||||
|           if (!struct.deleted && scope.some(type => isParentOf(type, /** @type {Item} */ (struct)))) { | ||||
|           if (!struct.deleted && scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), /** @type {Item} */ (struct)))) { | ||||
|             itemsToDelete.push(struct) | ||||
|           } | ||||
|         } | ||||
| @ -89,7 +89,7 @@ const popStackItem = (undoManager, stack, eventType) => { | ||||
|       iterateDeletedStructs(transaction, stackItem.deletions, struct => { | ||||
|         if ( | ||||
|           struct instanceof Item && | ||||
|           scope.some(type => isParentOf(type, struct)) && | ||||
|           scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), struct)) && | ||||
|           // Never redo structs in stackItem.insertions because they were created and deleted in the same capture interval.
 | ||||
|           !isDeleted(stackItem.insertions, struct.id) | ||||
|         ) { | ||||
| @ -159,7 +159,7 @@ const popStackItem = (undoManager, stack, eventType) => { | ||||
|  */ | ||||
| export class UndoManager extends ObservableV2 { | ||||
|   /** | ||||
|    * @param {AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types | ||||
|    * @param {Doc|AbstractType<any>|Array<AbstractType<any>>} typeScope Accepts either a single type, or an array of types | ||||
|    * @param {UndoManagerOptions} options | ||||
|    */ | ||||
|   constructor (typeScope, { | ||||
| @ -168,11 +168,11 @@ export class UndoManager extends ObservableV2 { | ||||
|     deleteFilter = () => true, | ||||
|     trackedOrigins = new Set([null]), | ||||
|     ignoreRemoteMapChanges = false, | ||||
|     doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope.doc) | ||||
|     doc = /** @type {Doc} */ (array.isArray(typeScope) ? typeScope[0].doc : typeScope instanceof Doc ? typeScope : typeScope.doc) | ||||
|   } = {}) { | ||||
|     super() | ||||
|     /** | ||||
|      * @type {Array<AbstractType<any>>} | ||||
|      * @type {Array<AbstractType<any> | Doc>} | ||||
|      */ | ||||
|     this.scope = [] | ||||
|     this.doc = doc | ||||
| @ -212,7 +212,7 @@ export class UndoManager extends ObservableV2 { | ||||
|       // Only track certain transactions
 | ||||
|       if ( | ||||
|         !this.captureTransaction(transaction) || | ||||
|         !this.scope.some(type => transaction.changedParentTypes.has(type)) || | ||||
|         !this.scope.some(type => transaction.changedParentTypes.has(/** @type {AbstractType<any>} */ (type)) || type === this.doc) || | ||||
|         (!this.trackedOrigins.has(transaction.origin) && (!transaction.origin || !this.trackedOrigins.has(transaction.origin.constructor))) | ||||
|       ) { | ||||
|         return | ||||
| @ -251,7 +251,7 @@ export class UndoManager extends ObservableV2 { | ||||
|       } | ||||
|       // make sure that deleted structs are not gc'd
 | ||||
|       iterateDeletedStructs(transaction, transaction.deleteSet, /** @param {Item|GC} item */ item => { | ||||
|         if (item instanceof Item && this.scope.some(type => isParentOf(type, item))) { | ||||
|         if (item instanceof Item && this.scope.some(type => type === transaction.doc || isParentOf(/** @type {AbstractType<any>} */ (type), item))) { | ||||
|           keepItem(item, true) | ||||
|         } | ||||
|       }) | ||||
| @ -272,13 +272,15 @@ export class UndoManager extends ObservableV2 { | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * @param {Array<AbstractType<any>> | AbstractType<any>} ytypes | ||||
|    * @param {Array<AbstractType<any> | Doc> | AbstractType<any> | Doc} ytypes | ||||
|    */ | ||||
|   addToScope (ytypes) { | ||||
|     const tmpSet = new Set(this.scope) | ||||
|     ytypes = array.isArray(ytypes) ? ytypes : [ytypes] | ||||
|     ytypes.forEach(ytype => { | ||||
|       if (this.scope.every(yt => yt !== ytype)) { | ||||
|         if (ytype.doc !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
 | ||||
|       if (!tmpSet.has(ytype)) { | ||||
|         tmpSet.add(ytype) | ||||
|         if (ytype instanceof AbstractType ? ytype.doc !== this.doc : ytype !== this.doc) logging.warn('[yjs#509] Not same Y.Doc') // use MultiDocUndoManager instead. also see https://github.com/yjs/yjs/issues/509
 | ||||
|         this.scope.push(ytype) | ||||
|       } | ||||
|     }) | ||||
|  | ||||
| @ -116,6 +116,19 @@ export const testEmptyTypeScope = _tc => { | ||||
|   t.assert(yarray.length === 0) | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Test case to fix #241 | ||||
|  * @param {t.TestCase} _tc | ||||
|  */ | ||||
| export const testGlobalScope = _tc => { | ||||
|   const ydoc = new Y.Doc() | ||||
|   const um = new Y.UndoManager(ydoc) | ||||
|   const yarray = ydoc.getArray() | ||||
|   yarray.insert(0, [1]) | ||||
|   um.undo() | ||||
|   t.assert(yarray.length === 0) | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Test case to fix #241 | ||||
|  * @param {t.TestCase} _tc | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user