[relative-positions] add option to configure whether to follow redon insertions - #638
This commit is contained in:
parent
927c2369aa
commit
ce43124ad0
@ -8,6 +8,7 @@ import {
|
|||||||
createID,
|
createID,
|
||||||
ContentType,
|
ContentType,
|
||||||
followRedone,
|
followRedone,
|
||||||
|
getItem,
|
||||||
ID, Doc, AbstractType // eslint-disable-line
|
ID, Doc, AbstractType // eslint-disable-line
|
||||||
} from '../internals.js'
|
} from '../internals.js'
|
||||||
|
|
||||||
@ -256,13 +257,24 @@ export const readRelativePosition = decoder => {
|
|||||||
export const decodeRelativePosition = uint8Array => readRelativePosition(decoding.createDecoder(uint8Array))
|
export const decodeRelativePosition = uint8Array => readRelativePosition(decoding.createDecoder(uint8Array))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Transform a relative position to an absolute position.
|
||||||
|
*
|
||||||
|
* If you want to share the relative position with other users, you should set
|
||||||
|
* `followUndoneDeletions` to false to get consistent results across all clients.
|
||||||
|
*
|
||||||
|
* When calculating the absolute position, we try to follow the "undone deletions". This yields
|
||||||
|
* better results for the user who performed undo. However, only the user who performed the undo
|
||||||
|
* will get the better results, the other users don't know which operations recreated a deleted
|
||||||
|
* range of content. There is more information in this ticket: https://github.com/yjs/yjs/issues/638
|
||||||
|
*
|
||||||
* @param {RelativePosition} rpos
|
* @param {RelativePosition} rpos
|
||||||
* @param {Doc} doc
|
* @param {Doc} doc
|
||||||
|
* @param {boolean} followUndoneDeletions - whether to follow undone deletions - see https://github.com/yjs/yjs/issues/638
|
||||||
* @return {AbsolutePosition|null}
|
* @return {AbsolutePosition|null}
|
||||||
*
|
*
|
||||||
* @function
|
* @function
|
||||||
*/
|
*/
|
||||||
export const createAbsolutePositionFromRelativePosition = (rpos, doc) => {
|
export const createAbsolutePositionFromRelativePosition = (rpos, doc, followUndoneDeletions = true) => {
|
||||||
const store = doc.store
|
const store = doc.store
|
||||||
const rightID = rpos.item
|
const rightID = rpos.item
|
||||||
const typeID = rpos.type
|
const typeID = rpos.type
|
||||||
@ -274,7 +286,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc) => {
|
|||||||
if (getState(store, rightID.client) <= rightID.clock) {
|
if (getState(store, rightID.client) <= rightID.clock) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const res = followRedone(store, rightID)
|
const res = followUndoneDeletions ? followRedone(store, rightID) : { item: getItem(store, rightID), diff: 0 }
|
||||||
const right = res.item
|
const right = res.item
|
||||||
if (!(right instanceof Item)) {
|
if (!(right instanceof Item)) {
|
||||||
return null
|
return null
|
||||||
@ -298,7 +310,7 @@ export const createAbsolutePositionFromRelativePosition = (rpos, doc) => {
|
|||||||
// type does not exist yet
|
// type does not exist yet
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const { item } = followRedone(store, typeID)
|
const { item } = followUndoneDeletions ? followRedone(store, typeID) : { item: getItem(store, typeID) }
|
||||||
if (item instanceof Item && item.content instanceof ContentType) {
|
if (item instanceof Item && item.content instanceof ContentType) {
|
||||||
type = item.content.type
|
type = item.content.type
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,3 +101,25 @@ export const testRelativePositionAssociationDifference = tc => {
|
|||||||
t.assert(posRight != null && posRight.index === 2)
|
t.assert(posRight != null && posRight.index === 2)
|
||||||
t.assert(posLeft != null && posLeft.index === 1)
|
t.assert(posLeft != null && posLeft.index === 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {t.TestCase} tc
|
||||||
|
*/
|
||||||
|
export const testRelativePositionWithUndo = tc => {
|
||||||
|
const ydoc = new Y.Doc()
|
||||||
|
const ytext = ydoc.getText()
|
||||||
|
ytext.insert(0, 'hello world')
|
||||||
|
const rpos = Y.createRelativePositionFromTypeIndex(ytext, 1)
|
||||||
|
const um = new Y.UndoManager(ytext)
|
||||||
|
ytext.delete(0, 6)
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydoc)?.index === 0)
|
||||||
|
um.undo()
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydoc)?.index === 1)
|
||||||
|
const posWithoutFollow = Y.createAbsolutePositionFromRelativePosition(rpos, ydoc, false)
|
||||||
|
console.log({ posWithoutFollow })
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydoc, false)?.index === 6)
|
||||||
|
const ydocClone = new Y.Doc()
|
||||||
|
Y.applyUpdate(ydocClone, Y.encodeStateAsUpdate(ydoc))
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydocClone)?.index === 6)
|
||||||
|
t.assert(Y.createAbsolutePositionFromRelativePosition(rpos, ydocClone, false)?.index === 6)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user