From 2d5ed81ac3006a38ad3ce54aa9422775af435b9c Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Sun, 8 Jun 2025 02:17:23 +0200 Subject: [PATCH] DiffAttributionManager supports accepting suggestions --- src/utils/AttributionManager.js | 48 +++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/src/utils/AttributionManager.js b/src/utils/AttributionManager.js index b8ca4b02..9e6cbc45 100644 --- a/src/utils/AttributionManager.js +++ b/src/utils/AttributionManager.js @@ -13,12 +13,14 @@ import { mergeIdMaps, createID, mergeIdSets, - IdSet, Item, Snapshot, Doc, AbstractContent, IdMap, // eslint-disable-line + ID, IdSet, Item, Snapshot, Doc, AbstractContent, IdMap, // eslint-disable-line applyUpdate, writeIdSet, UpdateEncoderV1, transact, - createMaybeAttrRange + createMaybeAttrRange, + createIdSet, + writeStructsFromIdSet } from '../internals.js' import * as error from 'lib0/error' @@ -327,6 +329,48 @@ export class DiffAttributionManager extends ObservableV2 { this._nextDoc.off('afterTransaction', this._afterTrListener) } + /** + * @param {ID} start + * @param {ID?} end + */ + acceptChanges (start, end = start) { + const encoder = new UpdateEncoderV1() + const store = this._nextDoc.store + const inserts = createIdSet() + const deletes = createIdSet() + /** + * @type {Item?} + */ + let item = getItem(store, start) + const endItem = start === end ? item : (end == null ? null : getItem(store, end)) + // walk to the left and find first un-attributed change that is rendered + while (item.left != null) { + item = item.left + if (!item.deleted) { + const slice = this.inserts.slice(item.id.client, item.id.clock, item.length) + if (slice.some(s => s.attrs === null)) { + break + } + } + } + let foundEndItem = false + while (item != null) { + inserts.add(item.id.client, item.id.clock, item.length) + if (item.deleted) { + deletes.add(item.id.client, item.id.clock, item.length) + } + foundEndItem ||= item === endItem + if (foundEndItem && !item.deleted && this.inserts.slice(item.id.client, item.id.clock, item.length).some(s => s.attrs === null)) { + break + } + item = item.right + } + writeStructsFromIdSet(encoder, this._nextDoc.store, inserts) + writeIdSet(encoder, deletes) + const acceptUpdate = encoder.toUint8Array() + applyUpdate(this._prevDoc, acceptUpdate) + } + /** * @param {Array>} contents - where to write the result * @param {number} client