Port Undo/Redo approach with a clean API

This commit is contained in:
Kevin Jahns
2019-06-23 13:04:14 +02:00
parent 14df5b72af
commit 03458dc641
18 changed files with 793 additions and 290 deletions

View File

@@ -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