2017-10-16 04:53:12 +02:00
|
|
|
import { getReference } from '../Util/structReferences.js'
|
2017-10-19 17:36:28 +02:00
|
|
|
import ID from '../Util/ID.js'
|
2017-10-26 19:12:33 +02:00
|
|
|
import { logID } from '../MessageHandler/messageToString.js'
|
2017-10-11 03:41:54 +02:00
|
|
|
|
2017-10-19 17:36:28 +02:00
|
|
|
/**
|
|
|
|
|
* Delete all items in an ID-range
|
|
|
|
|
* TODO: implement getItemCleanStartNode for better performance (only one lookup)
|
|
|
|
|
*/
|
2017-10-16 04:53:12 +02:00
|
|
|
export function deleteItemRange (y, user, clock, range) {
|
2017-10-19 17:36:28 +02:00
|
|
|
const createDelete = y.connector._forwardAppliedStructs
|
|
|
|
|
let item = y.os.getItemCleanStart(new ID(user, clock))
|
|
|
|
|
if (item !== null) {
|
|
|
|
|
if (!item._deleted) {
|
|
|
|
|
item._splitAt(y, range)
|
|
|
|
|
item._delete(y, createDelete)
|
|
|
|
|
}
|
|
|
|
|
let itemLen = item._length
|
|
|
|
|
range -= itemLen
|
|
|
|
|
clock += itemLen
|
|
|
|
|
if (range > 0) {
|
|
|
|
|
let node = y.os.findNode(new ID(user, clock))
|
|
|
|
|
while (node !== null && range > 0 && node.val._id.equals(new ID(user, clock))) {
|
|
|
|
|
const nodeVal = node.val
|
|
|
|
|
if (!nodeVal._deleted) {
|
|
|
|
|
nodeVal._splitAt(y, range)
|
|
|
|
|
nodeVal._delete(y, createDelete)
|
|
|
|
|
}
|
|
|
|
|
const nodeLen = nodeVal._length
|
|
|
|
|
range -= nodeLen
|
|
|
|
|
clock += nodeLen
|
|
|
|
|
node = node.next()
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-10-16 04:53:12 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete is not a real struct. It will not be saved in OS
|
|
|
|
|
*/
|
2017-10-11 03:41:54 +02:00
|
|
|
export default class Delete {
|
|
|
|
|
constructor () {
|
2017-10-16 04:53:12 +02:00
|
|
|
this._targetID = null
|
2017-10-11 03:41:54 +02:00
|
|
|
this._length = null
|
|
|
|
|
}
|
|
|
|
|
_fromBinary (y, decoder) {
|
2017-10-26 19:12:33 +02:00
|
|
|
// TODO: set target, and add it to missing if not found
|
|
|
|
|
// There is an edge case in p2p networks!
|
2017-10-16 04:53:12 +02:00
|
|
|
this._targetID = decoder.readID()
|
2017-10-11 03:41:54 +02:00
|
|
|
this._length = decoder.readVarUint()
|
2017-10-19 17:36:28 +02:00
|
|
|
return []
|
2017-10-11 03:41:54 +02:00
|
|
|
}
|
2017-10-16 04:53:12 +02:00
|
|
|
_toBinary (encoder) {
|
|
|
|
|
encoder.writeUint8(getReference(this.constructor))
|
|
|
|
|
encoder.writeID(this._targetID)
|
2017-10-11 03:41:54 +02:00
|
|
|
encoder.writeVarUint(this._length)
|
|
|
|
|
}
|
2017-10-16 04:53:12 +02:00
|
|
|
/**
|
|
|
|
|
* - If created remotely (a remote user deleted something),
|
|
|
|
|
* this Delete is applied to all structs in id-range.
|
|
|
|
|
* - If created lokally (e.g. when y-array deletes a range of elements),
|
|
|
|
|
* this struct is broadcasted only (it is already executed)
|
|
|
|
|
*/
|
|
|
|
|
_integrate (y, locallyCreated = false) {
|
|
|
|
|
if (!locallyCreated) {
|
|
|
|
|
// from remote
|
|
|
|
|
const id = this._targetID
|
|
|
|
|
deleteItemRange(y, id.user, id.clock, this._length)
|
|
|
|
|
} else {
|
|
|
|
|
// from local
|
|
|
|
|
y.connector.broadcastStruct(this)
|
2017-10-11 03:41:54 +02:00
|
|
|
}
|
|
|
|
|
if (y.persistence !== null) {
|
|
|
|
|
y.persistence.saveOperations(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_logString () {
|
2017-10-26 19:12:33 +02:00
|
|
|
return `Delete - target: ${logID(this._targetID)}, len: ${this._length}`
|
2017-10-11 03:41:54 +02:00
|
|
|
}
|
|
|
|
|
}
|