Port Undo/Redo approach with a clean API
This commit is contained in:
@@ -4,7 +4,8 @@ import {
|
||||
createID,
|
||||
getState,
|
||||
splitItem,
|
||||
Item, AbstractStruct, StructStore, Transaction, ID // eslint-disable-line
|
||||
iterateStructs,
|
||||
Item, GC, StructStore, Transaction, ID // eslint-disable-line
|
||||
} from '../internals.js'
|
||||
|
||||
import * as math from 'lib0/math.js'
|
||||
@@ -47,29 +48,21 @@ export class DeleteSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over all structs that were deleted.
|
||||
*
|
||||
* This function expects that the deletes structs are not merged. Hence, you can
|
||||
* probably only use it in type observes and `afterTransaction` events. But not
|
||||
* in `afterTransactionCleanup`.
|
||||
* Iterate over all structs that the DeleteSet gc's.
|
||||
*
|
||||
* @param {Transaction} transaction
|
||||
* @param {DeleteSet} ds
|
||||
* @param {StructStore} store
|
||||
* @param {function(AbstractStruct):void} f
|
||||
* @param {function(GC|Item):void} f
|
||||
*
|
||||
* @function
|
||||
*/
|
||||
export const iterateDeletedStructs = (ds, store, f) =>
|
||||
export const iterateDeletedStructs = (transaction, ds, store, f) =>
|
||||
ds.clients.forEach((deletes, clientid) => {
|
||||
const structs = /** @type {Array<AbstractStruct>} */ (store.clients.get(clientid))
|
||||
const structs = /** @type {Array<GC|Item>} */ (store.clients.get(clientid))
|
||||
for (let i = 0; i < deletes.length; i++) {
|
||||
const del = deletes[i]
|
||||
let index = findIndexSS(structs, del.clock)
|
||||
let struct
|
||||
do {
|
||||
struct = structs[index++]
|
||||
f(struct)
|
||||
} while (index < structs.length && structs[index].id.clock < del.clock + del.len)
|
||||
iterateStructs(transaction, structs, del.clock, del.len, f)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -143,6 +136,27 @@ export const sortAndMergeDeleteSet = ds => {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DeleteSet} ds1
|
||||
* @param {DeleteSet} ds2
|
||||
* @return {DeleteSet} A fresh DeleteSet
|
||||
*/
|
||||
export const mergeDeleteSets = (ds1, ds2) => {
|
||||
const merged = new DeleteSet()
|
||||
// Write all keys from ds1 to merged. If ds2 has the same key, combine the sets.
|
||||
ds1.clients.forEach((dels1, client) =>
|
||||
merged.clients.set(client, dels1.concat(ds2.clients.get(client) || []))
|
||||
)
|
||||
// Write all missing keys from ds2 to merged.
|
||||
ds2.clients.forEach((dels2, client) => {
|
||||
if (!merged.clients.has(client)) {
|
||||
merged.clients.set(client, dels2)
|
||||
}
|
||||
})
|
||||
sortAndMergeDeleteSet(merged)
|
||||
return merged
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DeleteSet} ds
|
||||
* @param {ID} id
|
||||
|
||||
Reference in New Issue
Block a user