tmp commit
This commit is contained in:
parent
a0c9235a36
commit
b2b7b8c280
@ -18,7 +18,7 @@ export const getMovedCoords = (moved, tr) => {
|
||||
let end // this (exclusive) is the first item after start that is not part of the moved area
|
||||
if (moved.start.item) {
|
||||
if (moved.start.assoc < 0) {
|
||||
start = getItemCleanEnd(tr, moved.start.item)
|
||||
start = getItemCleanEnd(tr, moved.start.item) // @todo Try using getItem after all tests succeed again.
|
||||
start = start.right
|
||||
} else {
|
||||
start = getItemCleanStart(tr, moved.start.item)
|
||||
|
@ -152,11 +152,11 @@ export class YArray extends AbstractType {
|
||||
}
|
||||
if (this.doc !== null) {
|
||||
transact(this.doc, transaction => {
|
||||
const left = createRelativePositionFromTypeIndex(this, index, 1)
|
||||
const right = left.clone()
|
||||
right.assoc = -1
|
||||
const start = createRelativePositionFromTypeIndex(this, index, 1)
|
||||
const end = start.clone()
|
||||
end.assoc = -1
|
||||
useSearchMarker(transaction, this, target, walker => {
|
||||
walker.insertMove(transaction, left, right)
|
||||
walker.insertMove(transaction, [{ start, end }])
|
||||
})
|
||||
})
|
||||
} else {
|
||||
@ -165,6 +165,32 @@ export class YArray extends AbstractType {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} startIndex Inclusive move-start
|
||||
* @param {number} endIndex Inclusive move-end
|
||||
* @param {number} target
|
||||
* @param {number} assocStart >=0 if start should be associated with the right character. See relative-position assoc parameter.
|
||||
* @param {number} assocEnd >= 0 if end should be associated with the right character.
|
||||
*/
|
||||
moveRange (startIndex, endIndex, target, assocStart = 1, assocEnd = -1) {
|
||||
if (startIndex <= target && target <= endIndex) {
|
||||
// It doesn't make sense to move a range into the same range (it's basically a no-op).
|
||||
return
|
||||
}
|
||||
if (this.doc !== null) {
|
||||
transact(this.doc, transaction => {
|
||||
const start = createRelativePositionFromTypeIndex(this, startIndex, assocStart)
|
||||
const end = createRelativePositionFromTypeIndex(this, endIndex + 1, assocEnd)
|
||||
useSearchMarker(transaction, this, target, walker => {
|
||||
walker.insertMove(transaction, [{ start, end }])
|
||||
})
|
||||
})
|
||||
} else {
|
||||
const content = /** @type {Array<any>} */ (this._prelimContent).splice(startIndex, endIndex - startIndex + 1)
|
||||
;/** @type {Array<any>} */ (this._prelimContent).splice(target, 0, ...content)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} start Inclusive move-start
|
||||
* @param {number} end Inclusive move-end
|
||||
@ -172,17 +198,18 @@ export class YArray extends AbstractType {
|
||||
* @param {number} assocStart >=0 if start should be associated with the right character. See relative-position assoc parameter.
|
||||
* @param {number} assocEnd >= 0 if end should be associated with the right character.
|
||||
*/
|
||||
moveRange (start, end, target, assocStart = 1, assocEnd = -1) {
|
||||
moveRangeNew (start, end, target, assocStart = 1, assocEnd = -1) {
|
||||
if (start <= target && target <= end) {
|
||||
// It doesn't make sense to move a range into the same range (it's basically a no-op).
|
||||
return
|
||||
}
|
||||
if (this.doc !== null) {
|
||||
transact(this.doc, transaction => {
|
||||
const left = createRelativePositionFromTypeIndex(this, start, assocStart)
|
||||
const right = createRelativePositionFromTypeIndex(this, end + 1, assocEnd)
|
||||
const ranges = useSearchMarker(transaction, this, target, walker =>
|
||||
getMinimalListViewRanges(walker, start, end, assocStart, assocEnd)
|
||||
)
|
||||
useSearchMarker(transaction, this, target, walker => {
|
||||
walker.insertMove(transaction, left, right)
|
||||
walker.insertMove(transaction, ranges)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
|
@ -206,16 +206,36 @@ export class ListIterator {
|
||||
}
|
||||
|
||||
/**
|
||||
* We prefer to insert content outside of a moved range.
|
||||
* Try to escape the moved range by walking to the left over deleted items.
|
||||
*
|
||||
* @param {Transaction} tr
|
||||
*/
|
||||
reduceMoves (tr) {
|
||||
let item = this.nextItem
|
||||
if (item !== null) {
|
||||
while (item === this.currMoveStart) {
|
||||
item = /** @type {Item} */ (this.currMove) // we iterate to the left after the current condition
|
||||
popMovedStack(tr, this)
|
||||
reduceMoveDepth (tr) {
|
||||
let nextItem = this.nextItem
|
||||
if (nextItem !== null) {
|
||||
while (this.currMove) {
|
||||
if (nextItem === this.currMoveStart) {
|
||||
nextItem = /** @type {Item} */ (this.currMove) // we iterate to the left after the current condition
|
||||
popMovedStack(tr, this)
|
||||
continue
|
||||
}
|
||||
// check if we can iterate to the left while stepping over deleted items until we find an item === this.currMoveStart
|
||||
/**
|
||||
* @type {Item} nextItem
|
||||
*/
|
||||
let item = nextItem
|
||||
while (item.deleted && item.moved === this.currMove && item !== this.currMoveStart) {
|
||||
item = /** @type {Item} */ (item.left) // this must exist otherwise we miscalculated the move
|
||||
}
|
||||
if (item === this.currMoveStart) {
|
||||
// we only want to iterate over deleted items if we can escape a move
|
||||
nextItem = item
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
this.nextItem = item
|
||||
this.nextItem = nextItem
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,7 +411,7 @@ export class ListIterator {
|
||||
* @param {Array<AbstractContent>} content
|
||||
*/
|
||||
insertContents (tr, content) {
|
||||
this.reduceMoves(tr)
|
||||
this.reduceMoveDepth(tr)
|
||||
this._splitRel(tr)
|
||||
const parent = this.type
|
||||
const store = tr.doc.store
|
||||
@ -419,11 +439,10 @@ export class ListIterator {
|
||||
|
||||
/**
|
||||
* @param {Transaction} tr
|
||||
* @param {RelativePosition} start
|
||||
* @param {RelativePosition} end
|
||||
* @param {Array<{ start: RelativePosition, end: RelativePosition }>} ranges
|
||||
*/
|
||||
insertMove (tr, start, end) {
|
||||
this.insertContents(tr, [new ContentMove(start, end, -1)]) // @todo adjust priority
|
||||
insertMove (tr, ranges) {
|
||||
this.insertContents(tr, ranges.map(range => new ContentMove(range.start, range.end, -1)))
|
||||
// @todo is there a better alrogirthm to update searchmarkers? We could simply remove the markers that are in the updated range.
|
||||
// Also note that searchmarkers are updated in insertContents as well.
|
||||
const sm = this.type._searchMarker
|
||||
@ -563,3 +582,56 @@ const concatArrayContent = (content, added) => {
|
||||
content.push(...added)
|
||||
return content
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Transaction} tr
|
||||
* @param {ListIterator} walker
|
||||
* @param {number} len
|
||||
*/
|
||||
const getMinimalListViewRanges = (tr, walker, len) => {
|
||||
walker.reduceMoveDepth(tr)
|
||||
if (walker.index + len > walker.type._length) {
|
||||
throw lengthExceeded
|
||||
}
|
||||
walker.index += len
|
||||
/**
|
||||
* We store nextItem in a variable because this version cannot be null.
|
||||
*/
|
||||
let nextItem = /** @type {Item} */ (walker.nextItem)
|
||||
const ranges = []
|
||||
while (len > 0 && !walker.reachedEnd) {
|
||||
while (nextItem.countable && !walker.reachedEnd && len > 0 && nextItem !== walker.currMoveEnd) {
|
||||
if (!nextItem.deleted && nextItem.moved === walker.currMove) {
|
||||
const slicedContent = slice(nextItem.content, this.rel, len)
|
||||
len -= slicedContent.length
|
||||
value = concat(value, slicedContent)
|
||||
if (this.rel + slicedContent.length === nextItem.length) {
|
||||
this.rel = 0
|
||||
} else {
|
||||
this.rel += slicedContent.length
|
||||
continue // do not iterate to item.right
|
||||
}
|
||||
}
|
||||
if (nextItem.right) {
|
||||
nextItem = nextItem.right
|
||||
this.nextItem = nextItem
|
||||
} else {
|
||||
this.reachedEnd = true
|
||||
}
|
||||
}
|
||||
if ((!this.reachedEnd || this.currMove !== null) && len > 0) {
|
||||
// always set nextItem before any method call
|
||||
this.nextItem = nextItem
|
||||
this.forward(tr, 0)
|
||||
if (this.nextItem == null) {
|
||||
throw new Error('debug me') // @todo remove
|
||||
}
|
||||
nextItem = this.nextItem
|
||||
}
|
||||
}
|
||||
this.nextItem = nextItem
|
||||
if (len < 0) {
|
||||
this.index -= len
|
||||
}
|
||||
return ranges
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ const arrayTransactions = [
|
||||
const newPos = _newPosAdj + (_newPosAdj > yarray.length - len ? len : 0)
|
||||
const oldContent = yarray.toArray()
|
||||
yarray.moveRange(pos, pos + len - 1, newPos)
|
||||
console.log(`moving range ${pos}-${pos + len} to ${newPos}`)
|
||||
console.log(`moving range ${pos}-${pos + len - 1} to ${newPos}`)
|
||||
const movedValues = oldContent.splice(pos, len)
|
||||
oldContent.splice(pos < newPos ? newPos - len : newPos, 0, ...movedValues)
|
||||
t.compareArrays(yarray.toArray(), oldContent) // we want to make sure that fastSearch markers insert at the correct position
|
||||
|
Loading…
x
Reference in New Issue
Block a user