[Undo] add UndoManager.currStackItem
This commit is contained in:
parent
917261a1ce
commit
29fa60ccf9
@ -12,9 +12,10 @@
|
|||||||
"url": "https://github.com/sponsors/dmonad"
|
"url": "https://github.com/sponsors/dmonad"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"clean": "rm -rf dist docs",
|
||||||
"test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
|
"test": "npm run dist && node ./dist/tests.cjs --repetition-time 50",
|
||||||
"test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
|
"test-extensive": "npm run lint && npm run dist && node ./dist/tests.cjs --production --repetition-time 10000",
|
||||||
"dist": "rm -rf dist && rollup -c && tsc",
|
"dist": "npm run clean && rollup -c && tsc",
|
||||||
"watch": "rollup -wc",
|
"watch": "rollup -wc",
|
||||||
"lint": "markdownlint README.md && standard && tsc",
|
"lint": "markdownlint README.md && standard && tsc",
|
||||||
"docs": "rm -rf docs; jsdoc --configure ./.jsdoc.json --verbose --readme ./README.md --package ./package.json || true",
|
"docs": "rm -rf docs; jsdoc --configure ./.jsdoc.json --verbose --readme ./README.md --package ./package.json || true",
|
||||||
|
@ -52,11 +52,6 @@ const clearUndoManagerStackItem = (tr, um, stackItem) => {
|
|||||||
* @return {StackItem?}
|
* @return {StackItem?}
|
||||||
*/
|
*/
|
||||||
const popStackItem = (undoManager, stack, eventType) => {
|
const popStackItem = (undoManager, stack, eventType) => {
|
||||||
/**
|
|
||||||
* Whether a change happened
|
|
||||||
* @type {StackItem?}
|
|
||||||
*/
|
|
||||||
let result = null
|
|
||||||
/**
|
/**
|
||||||
* Keep a reference to the transaction so we can fire the event with the changedParentTypes
|
* Keep a reference to the transaction so we can fire the event with the changedParentTypes
|
||||||
* @type {any}
|
* @type {any}
|
||||||
@ -65,7 +60,7 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
const doc = undoManager.doc
|
const doc = undoManager.doc
|
||||||
const scope = undoManager.scope
|
const scope = undoManager.scope
|
||||||
transact(doc, transaction => {
|
transact(doc, transaction => {
|
||||||
while (stack.length > 0 && result === null) {
|
while (stack.length > 0 && undoManager.currStackItem === null) {
|
||||||
const store = doc.store
|
const store = doc.store
|
||||||
const stackItem = /** @type {StackItem} */ (stack.pop())
|
const stackItem = /** @type {StackItem} */ (stack.pop())
|
||||||
/**
|
/**
|
||||||
@ -113,7 +108,7 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
performedChange = true
|
performedChange = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = performedChange ? stackItem : null
|
undoManager.currStackItem = performedChange ? stackItem : null
|
||||||
}
|
}
|
||||||
transaction.changed.forEach((subProps, type) => {
|
transaction.changed.forEach((subProps, type) => {
|
||||||
// destroy search marker if necessary
|
// destroy search marker if necessary
|
||||||
@ -123,11 +118,12 @@ const popStackItem = (undoManager, stack, eventType) => {
|
|||||||
})
|
})
|
||||||
_tr = transaction
|
_tr = transaction
|
||||||
}, undoManager)
|
}, undoManager)
|
||||||
if (result != null) {
|
if (undoManager.currStackItem != null) {
|
||||||
const changedParentTypes = _tr.changedParentTypes
|
const changedParentTypes = _tr.changedParentTypes
|
||||||
undoManager.emit('stack-item-popped', [{ stackItem: result, type: eventType, changedParentTypes }, undoManager])
|
undoManager.emit('stack-item-popped', [{ stackItem: undoManager.currStackItem, type: eventType, changedParentTypes }, undoManager])
|
||||||
|
undoManager.currStackItem = null
|
||||||
}
|
}
|
||||||
return result
|
return undoManager.currStackItem
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,7 +192,7 @@ export class UndoManager extends Observable {
|
|||||||
*
|
*
|
||||||
* @type {StackItem|null}
|
* @type {StackItem|null}
|
||||||
*/
|
*/
|
||||||
this.doingStackItem = null
|
this.currStackItem = null
|
||||||
this.lastChange = 0
|
this.lastChange = 0
|
||||||
this.ignoreRemoteMapChanges = ignoreRemoteMapChanges
|
this.ignoreRemoteMapChanges = ignoreRemoteMapChanges
|
||||||
this.captureTimeout = captureTimeout
|
this.captureTimeout = captureTimeout
|
||||||
@ -337,12 +333,10 @@ export class UndoManager extends Observable {
|
|||||||
*/
|
*/
|
||||||
undo () {
|
undo () {
|
||||||
this.undoing = true
|
this.undoing = true
|
||||||
this.doingStackItem = array.last(this.undoStack) ?? null
|
|
||||||
let res
|
let res
|
||||||
try {
|
try {
|
||||||
res = popStackItem(this, this.undoStack, 'undo')
|
res = popStackItem(this, this.undoStack, 'undo')
|
||||||
} finally {
|
} finally {
|
||||||
this.doingStackItem = null
|
|
||||||
this.undoing = false
|
this.undoing = false
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
@ -355,12 +349,10 @@ export class UndoManager extends Observable {
|
|||||||
*/
|
*/
|
||||||
redo () {
|
redo () {
|
||||||
this.redoing = true
|
this.redoing = true
|
||||||
this.doingStackItem = array.last(this.redoStack) ?? null
|
|
||||||
let res
|
let res
|
||||||
try {
|
try {
|
||||||
res = popStackItem(this, this.redoStack, 'redo')
|
res = popStackItem(this, this.redoStack, 'redo')
|
||||||
} finally {
|
} finally {
|
||||||
this.doingStackItem = null
|
|
||||||
this.redoing = false
|
this.redoing = false
|
||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
|
@ -719,62 +719,29 @@ export const testUndoDeleteInMap = (tc) => {
|
|||||||
/**
|
/**
|
||||||
* It should expose the StackItem being processed if undoing
|
* It should expose the StackItem being processed if undoing
|
||||||
*
|
*
|
||||||
* @param {t.TestCase} tc
|
* @param {t.TestCase} _tc
|
||||||
*/
|
*/
|
||||||
export const testUndoDoingStackItem = async (tc) => {
|
export const testUndoDoingStackItem = async (_tc) => {
|
||||||
const doc = new Y.Doc()
|
const doc = new Y.Doc()
|
||||||
const text = doc.getText('text')
|
const text = doc.getText('text')
|
||||||
const undoManager = new Y.UndoManager([text])
|
const undoManager = new Y.UndoManager([text])
|
||||||
|
|
||||||
undoManager.on('stack-item-added', /** @param {any} event */ event => {
|
undoManager.on('stack-item-added', /** @param {any} event */ event => {
|
||||||
event.stackItem.meta.set('str', '42')
|
event.stackItem.meta.set('str', '42')
|
||||||
})
|
})
|
||||||
|
let metaUndo = /** @type {any} */ (null)
|
||||||
const meta = new Promise((resolve) => {
|
let metaRedo = /** @type {any} */ (null)
|
||||||
setTimeout(() => resolve('ABORTED'), 50)
|
text.observe((event) => {
|
||||||
text.observe((event) => {
|
const /** @type {Y.UndoManager} */ origin = event.transaction.origin
|
||||||
const /** @type {Y.UndoManager} */ origin = event.transaction.origin
|
if (origin === undoManager && origin.undoing) {
|
||||||
if (origin === undoManager && origin.undoing) {
|
metaUndo = origin.currStackItem?.meta.get('str')
|
||||||
resolve(origin.doingStackItem?.meta.get('str'))
|
} else if (origin === undoManager && origin.redoing) {
|
||||||
}
|
metaRedo = origin.currStackItem?.meta.get('str')
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
text.insert(0, 'abc')
|
|
||||||
undoManager.undo()
|
|
||||||
|
|
||||||
t.compare(await meta, '42')
|
|
||||||
t.compare(undoManager.doingStackItem, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* It should expose the StackItem being processed if redoing
|
|
||||||
*
|
|
||||||
* @param {t.TestCase} tc
|
|
||||||
*/
|
|
||||||
export const testRedoDoingStackItem = async (tc) => {
|
|
||||||
const doc = new Y.Doc()
|
|
||||||
const text = doc.getText('text')
|
|
||||||
const undoManager = new Y.UndoManager([text])
|
|
||||||
|
|
||||||
undoManager.on('stack-item-added', /** @param {any} event */ event => {
|
|
||||||
event.stackItem.meta.set('str', '42')
|
|
||||||
})
|
|
||||||
|
|
||||||
const meta = new Promise(resolve => {
|
|
||||||
setTimeout(() => resolve('ABORTED'), 50)
|
|
||||||
text.observe((event) => {
|
|
||||||
const /** @type {Y.UndoManager} */ origin = event.transaction.origin
|
|
||||||
if (origin === undoManager && origin.redoing) {
|
|
||||||
resolve(origin.doingStackItem?.meta.get('str'))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
text.insert(0, 'abc')
|
text.insert(0, 'abc')
|
||||||
undoManager.undo()
|
undoManager.undo()
|
||||||
undoManager.redo()
|
undoManager.redo()
|
||||||
|
t.compare(metaUndo, '42', 'currStackItem is accessible while undoing')
|
||||||
t.compare(await meta, '42')
|
t.compare(metaRedo, '42', 'currStackItem is accessible while redoing')
|
||||||
t.compare(undoManager.doingStackItem, null)
|
t.compare(undoManager.currStackItem, null, 'currStackItem is null after observe/transaction')
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user