[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