Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SharedString DDS annotateAdjustRange #22751

Open
wants to merge 164 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 160 commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
2cc6221
Remove Exposure of Client
anthony-murphy Sep 17, 2024
2129908
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Sep 25, 2024
1c687be
update type tests
anthony-murphy Sep 25, 2024
8d7ef70
fix tests
anthony-murphy Sep 25, 2024
620f950
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Sep 27, 2024
5e747b4
MergeTree: Separate Segment Interfaces Based on Visibility
anthony-murphy Sep 30, 2024
d59ee81
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Sep 30, 2024
319e1d4
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 1, 2024
6905f27
remove deprecations
anthony-murphy Oct 1, 2024
00be065
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 1, 2024
e11b49c
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 1, 2024
fb201de
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 2, 2024
d251c2a
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 2, 2024
2ae3b9e
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 2, 2024
47bdab0
fix tests
anthony-murphy Oct 2, 2024
19691c2
Merge branch 'main' into test/internal-merge-tree-client
anthony-murphy Oct 3, 2024
3993dfc
Merge branch 'main' into test/remove-ISegment-deprecations
anthony-murphy Oct 3, 2024
558c9fb
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 3, 2024
bcffd48
Add Adjust to Annotate
anthony-murphy Oct 3, 2024
29386e2
move to object based annotate
anthony-murphy Oct 3, 2024
1fc1c13
conflict farm passing
anthony-murphy Oct 4, 2024
ef8add8
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 4, 2024
8b0ecb3
Merge branch 'main' into test/internal-merge-tree-client
anthony-murphy Oct 4, 2024
37f754c
Merge branch 'main' into test/remove-ISegment-deprecations
anthony-murphy Oct 4, 2024
74571c3
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 4, 2024
396d12e
remove unused method
anthony-murphy Oct 4, 2024
d664a5c
fix delta handling
anthony-murphy Oct 4, 2024
b557003
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 4, 2024
e374f9a
Merge branch 'main' into test/internal-merge-tree-client
anthony-murphy Oct 4, 2024
f1586dc
Merge branch 'main' into test/remove-ISegment-deprecations
anthony-murphy Oct 4, 2024
21f55a1
handle rollback
anthony-murphy Oct 4, 2024
b123f73
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 4, 2024
9dc1d27
more rollback fixes
anthony-murphy Oct 5, 2024
c112816
Merge branch 'main' into test/remove-ISegment-deprecations
anthony-murphy Oct 7, 2024
1cb5de6
Merge branch 'main' into test/internal-merge-tree-client
anthony-murphy Oct 7, 2024
da2d4ff
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 7, 2024
488b0d2
Merge branch 'main' into test/internal-merge-tree-client
anthony-murphy Oct 7, 2024
cb1c19f
Merge branch 'main' into test/remove-ISegment-deprecations
anthony-murphy Oct 7, 2024
e980833
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 7, 2024
6d27559
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 7, 2024
a9fe86c
move from object to map
anthony-murphy Oct 8, 2024
ad238be
tests passing
anthony-murphy Oct 8, 2024
441a6a9
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 8, 2024
f75264d
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 8, 2024
bf57b68
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 8, 2024
8eb582a
Apply suggestions from code review
anthony-murphy Oct 8, 2024
117902d
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 8, 2024
36ae191
remove some deprecations
anthony-murphy Oct 8, 2024
c5d6026
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 8, 2024
a3c4896
remove missed method
anthony-murphy Oct 8, 2024
b1fc8cd
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 8, 2024
0fb303e
remove client args changes
anthony-murphy Oct 8, 2024
bc72f79
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 8, 2024
704f29f
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 8, 2024
e795deb
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 8, 2024
20eb3df
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 10, 2024
f4cf507
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 10, 2024
615ce18
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 10, 2024
f1d2579
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 15, 2024
34d54ad
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 15, 2024
19c6537
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 15, 2024
aaaad13
fix intervals
anthony-murphy Oct 15, 2024
a740c45
add config
anthony-murphy Oct 15, 2024
c3cb067
expose in sequence
anthony-murphy Oct 16, 2024
adc7a99
gen docs and tests
anthony-murphy Oct 16, 2024
7f1f78d
add config to tests
anthony-murphy Oct 16, 2024
6444ced
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 17, 2024
74eda59
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 17, 2024
4b70996
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 17, 2024
887dfca
Add IMergeTreeOptionsInternal
anthony-murphy Oct 17, 2024
6575577
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 17, 2024
a6b267b
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 17, 2024
525b316
fix merge
anthony-murphy Oct 17, 2024
f096b9c
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 18, 2024
802a21f
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 18, 2024
8db3d0d
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 18, 2024
966a8cd
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 25, 2024
0663c9b
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 25, 2024
a11a3f9
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 25, 2024
ac52ee6
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 29, 2024
684644b
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 29, 2024
6989db8
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 29, 2024
c32cefb
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 29, 2024
393f5de
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 29, 2024
4852dfb
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 29, 2024
08433f5
remove new snapshot format
anthony-murphy Oct 29, 2024
1966a1c
Move msn forward in mocks to fix fuzz snapshoting
anthony-murphy Oct 29, 2024
6495a81
Merge branch 'fuzz-msn' into test/merge-tree-adjust
anthony-murphy Oct 29, 2024
1b3b263
fix legacy snapshotting
anthony-murphy Oct 30, 2024
45bada7
only track remotes with adjusts
anthony-murphy Oct 30, 2024
a898922
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 30, 2024
f2e2e8d
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 30, 2024
eb6b3f5
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 30, 2024
f0a1b41
fix some test issues
anthony-murphy Oct 30, 2024
9b443b7
fix some imports
anthony-murphy Oct 31, 2024
636b4de
fix up event typing
anthony-murphy Oct 31, 2024
25c42b4
improve the sequence interval interface
anthony-murphy Oct 31, 2024
45b0bc8
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Oct 31, 2024
bfeab60
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 31, 2024
da858c0
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 31, 2024
ffc81d4
generate docs
anthony-murphy Oct 31, 2024
525cea2
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 31, 2024
3dbbb23
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 31, 2024
541b635
re-enable type tests
anthony-murphy Oct 31, 2024
65fd710
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 31, 2024
62564f0
add missing file
anthony-murphy Oct 31, 2024
e3d1a48
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Oct 31, 2024
c4c78ab
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 31, 2024
5fc4397
enable type tests
anthony-murphy Oct 31, 2024
d83a655
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Oct 31, 2024
6d62edc
refactor IMergeTreeAnnotateAdjustMsg
anthony-murphy Oct 31, 2024
b04b44b
more type tests
anthony-murphy Nov 1, 2024
37134cc
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 1, 2024
b27ba4c
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 1, 2024
7a02704
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Nov 1, 2024
ebe5c6b
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 2, 2024
f182673
add changeset
anthony-murphy Nov 2, 2024
86c7a6e
improve change set
anthony-murphy Nov 2, 2024
2d00a7d
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 2, 2024
24b3d66
re-add local references
anthony-murphy Nov 2, 2024
7b3ab8d
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 4, 2024
014c15d
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 4, 2024
8107dbe
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 4, 2024
19711d4
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Nov 4, 2024
4b3721b
initial changeset
anthony-murphy Nov 4, 2024
eabb66e
split import to work around autofix bug
anthony-murphy Nov 4, 2024
fbdc77d
fix test import
anthony-murphy Nov 4, 2024
1c798e5
PR feedback
anthony-murphy Nov 4, 2024
e019bb2
fix assignment typo
anthony-murphy Nov 4, 2024
e99be8b
make propertyManager's optional on interval classes
anthony-murphy Nov 4, 2024
019c329
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 4, 2024
e90a846
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Nov 4, 2024
eedd524
fix bad merge
anthony-murphy Nov 4, 2024
72b0fa3
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 5, 2024
62e1381
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 5, 2024
1528d00
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Nov 5, 2024
d2fdec1
Update .changeset/rude-views-bake.md
anthony-murphy Nov 5, 2024
02adda5
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 5, 2024
0cc8954
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 5, 2024
5c752ed
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Nov 5, 2024
af62cb7
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 5, 2024
7f4d879
Merge branch 'test/internal-merge-tree-client' into test/remove-ISegm…
anthony-murphy Nov 5, 2024
03ca3a7
revert build change
anthony-murphy Nov 5, 2024
03a5cf0
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 7, 2024
35b8567
Merge branch 'test/remove-ISegment-deprecations' into test/merge-tree…
anthony-murphy Nov 7, 2024
8152afc
clean up adjust types
anthony-murphy Nov 7, 2024
d2108aa
revert annotate method signatures
anthony-murphy Nov 7, 2024
27e9d85
type tests
anthony-murphy Nov 7, 2024
3e42239
some unit tests
anthony-murphy Nov 8, 2024
0e26579
more tests
anthony-murphy Nov 8, 2024
b8e3f93
js docs
anthony-murphy Nov 8, 2024
0904132
more docs and changeset
anthony-murphy Nov 8, 2024
948252d
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 8, 2024
3122f69
Update .changeset/ninety-dragons-fold.md
anthony-murphy Nov 8, 2024
82e35a7
Update packages/dds/sequence/src/sequence.ts
anthony-murphy Nov 8, 2024
995f4eb
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 12, 2024
f69533b
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 13, 2024
964d2a4
Update packages/dds/sequence/src/sequence.ts
anthony-murphy Nov 14, 2024
7ba6b92
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 14, 2024
d358ab2
add min max validation
anthony-murphy Nov 14, 2024
b42c8d2
tests
anthony-murphy Nov 15, 2024
bd274c6
Update packages/dds/sequence/src/sequence.ts
anthony-murphy Nov 15, 2024
4d0af64
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
anthony-murphy Nov 15, 2024
3a23e84
Merge branch 'test/merge-tree-adjust' of https://github.com/microsoft…
anthony-murphy Nov 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .changeset/ninety-dragons-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
"fluid-framework": minor
"@fluidframework/merge-tree": minor
"@fluidframework/sequence": minor
"@fluidframework/undo-redo": minor
---
---
"section": feature
---

### SharedString DDS annotateAdjustRange

This update introduces a new feature to the `SharedString` DDS, allowing for the adjustment of properties over a specified range. The `annotateAdjustRange` method enables users to apply adjustments to properties within a given range, providing more flexibility and control over property modifications.

An adjustment is a modification applied to a property value within a specified range. Adjustments can be used to increment or decrement property values dynamically. They are particularly useful in scenarios where property values need to be updated based on user interactions or other events. For example, in a rich text editor, adjustments can be used for modifying indentation levels or font sizes, where multiple users could apply differing numerical adjustments.

### Key Features and Use Cases:
- **Adjustments with Constraints**: Adjustments can include optional minimum and maximum constraints to ensure the final value falls within specified bounds. This is particularly useful for maintaining consistent formatting in rich text editors.
- **Consistent Property Changes**: The feature ensures that property changes are consistent, managing both local and remote changes effectively. This is essential for collaborative rich text editing where multiple users may be making adjustments simultaneously.
- **Rich Text Formatting**: Adjustments can be used to modify text properties such as font size, indentation, or other formatting attributes dynamically based on user actions.

### Configuration and Compatibility Requirements:
This feature is only available when the configuration `Fluid.Sequence.mergeTreeEnableAnnotateAdjust` is set to `true`. Additionally, all collaborating clients must have this feature enabled to use it. If any client does not have this feature enabled, it will lead to the client exiting collaboration. A future major version of Fluid will enable this feature by default.

### Usage Example:
```typescript
sharedString.annotateAdjustRange(start, end, {
key: { value: 5, min: 0, max: 10 }
});
```
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ export interface IMergeTreeDeltaCallbackArgs<TOperationType extends MergeTreeDel
}

// @alpha (undocumented)
export type IMergeTreeDeltaOp = IMergeTreeInsertMsg | IMergeTreeRemoveMsg | IMergeTreeAnnotateMsg | IMergeTreeObliterateMsg | IMergeTreeObliterateSidedMsg;
export type IMergeTreeDeltaOp = IMergeTreeInsertMsg | IMergeTreeRemoveMsg | IMergeTreeAnnotateMsg | IMergeTreeAnnotateAdjustMsg | IMergeTreeObliterateMsg | IMergeTreeObliterateSidedMsg;

// @alpha (undocumented)
export interface IMergeTreeDeltaOpArgs {
Expand Down Expand Up @@ -290,6 +290,7 @@ export type IMergeTreeOp = IMergeTreeDeltaOp | IMergeTreeGroupMsg;
export interface IMergeTreeOptions {
// (undocumented)
catchUpBlobName?: string;
mergeTreeEnableAnnotateAdjust?: boolean;
mergeTreeEnableObliterate?: boolean;
mergeTreeEnableObliterateReconnect?: boolean;
mergeTreeEnableSidedObliterate?: boolean;
Expand Down
3 changes: 3 additions & 0 deletions packages/dds/merge-tree/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@
"TypeAlias_Trackable": {
"backCompat": false
},
"Class_Client": {
"forwardCompat": false
},
"Class_PropertiesManager": {
"forwardCompat": false,
"backCompat": false
Expand Down
2 changes: 1 addition & 1 deletion packages/dds/merge-tree/src/attributionPolicy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ function createPropertyTrackingMergeTreeCallbacks(
const shouldAttributeAnnotate =
op.type === MergeTreeDeltaType.ANNOTATE &&
// Only attribute annotations which change the tracked property
op.props[propName] !== undefined &&
(op.props?.[propName] !== undefined || op.adjust?.[propName] !== undefined) &&
(isLocal || (propertyDeltas !== undefined && propName in propertyDeltas));

if (shouldAttributeInsert || shouldAttributeAnnotate) {
Expand Down
54 changes: 41 additions & 13 deletions packages/dds/merge-tree/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
toMoveInfo,
} from "./mergeTreeNodes.js";
import {
createAdjustRangeOp,
createAnnotateMarkerOp,
createAnnotateRangeOp,
// eslint-disable-next-line import/no-deprecated
Expand All @@ -77,9 +78,11 @@ import {
IRelativePosition,
MergeTreeDeltaType,
ReferenceType,
type AdjustParams,
type IMergeTreeAnnotateAdjustMsg,
type IMergeTreeObliterateSidedMsg,
} from "./ops.js";
import { PropertySet } from "./properties.js";
import { PropertySet, type MapLike } from "./properties.js";
import { DetachedReferencePosition, ReferencePosition } from "./referencePositions.js";
import { Side, type InteriorSequencePlace } from "./sequencePlace.js";
import { SnapshotLoader } from "./snapshotLoader.js";
Expand Down Expand Up @@ -245,6 +248,26 @@ export class Client extends TypedEventEmitter<IClientEvents> {
return annotateOp;
}

/**
* adjusts a value
*/
public annotateAdjustRangeLocal(
start: number,
end: number,
adjust: MapLike<AdjustParams>,
): IMergeTreeAnnotateAdjustMsg | undefined {
const annotateOp = createAdjustRangeOp(start, end, adjust);

for (const [key, value] of Object.entries(adjust)) {
if (value.min !== undefined && value.max !== undefined && value.min > value.max) {
throw new UsageError(`min is greater than max for ${key}`);
}
}

this.applyAnnotateRangeOp({ op: annotateOp });
return annotateOp;
}

/**
* Removes the range
*
Expand Down Expand Up @@ -564,7 +587,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
this._mergeTree.annotateRange(
range.start,
range.end,
op.props,
op,
clientArgs.referenceSequenceNumber,
clientArgs.clientId,
clientArgs.sequenceNumber,
Expand Down Expand Up @@ -686,6 +709,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
private getValidOpRange(
op:
| IMergeTreeAnnotateMsg
| IMergeTreeAnnotateAdjustMsg
| IMergeTreeInsertMsg
| IMergeTreeRemoveMsg
// eslint-disable-next-line import/no-deprecated
Expand Down Expand Up @@ -767,11 +791,7 @@ export class Client extends TypedEventEmitter<IClientEvents> {
| ISequencedDocumentMessage
| Pick<ISequencedDocumentMessage, "referenceSequenceNumber" | "clientId">
| undefined,
): {
clientId: number;
referenceSequenceNumber: number;
sequenceNumber: number;
} {
): IMergeTreeClientSequenceArgs {
// If there this no sequenced message, then the op is local
// and unacked, so use this clients sequenced args
//
Expand Down Expand Up @@ -907,7 +927,8 @@ export class Client extends TypedEventEmitter<IClientEvents> {
switch (resetOp.type) {
case MergeTreeDeltaType.ANNOTATE: {
assert(
segment.propertyManager?.hasPendingProperties(resetOp.props) === true,
segment.propertyManager?.hasPendingProperties(resetOp.props ?? resetOp.adjust) ===
true,
0x036 /* "Segment has no pending properties" */,
);
// if the segment has been removed or obliterated, there's no need to send the annotate op
Expand All @@ -921,11 +942,18 @@ export class Client extends TypedEventEmitter<IClientEvents> {
(segment.localMovedSeq !== undefined &&
segment.movedSeq === UnassignedSequenceNumber))
) {
newOp = createAnnotateRangeOp(
segmentPosition,
segmentPosition + segment.cachedLength,
resetOp.props,
);
newOp =
resetOp.props === undefined
? createAdjustRangeOp(
segmentPosition,
segmentPosition + segment.cachedLength,
resetOp.adjust,
)
: createAnnotateRangeOp(
segmentPosition,
segmentPosition + segment.cachedLength,
resetOp.props,
);
}
break;
}
Expand Down
28 changes: 20 additions & 8 deletions packages/dds/merge-tree/src/mergeTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ import {
copyPropertiesAndManager,
PropertiesManager,
PropertiesRollback,
type PropsOrAdjust,
} from "./segmentPropertiesManager.js";
import { Side, type InteriorSequencePlace } from "./sequencePlace.js";
import { SortedSegmentSet } from "./sortedSegmentSet.js";
Expand Down Expand Up @@ -277,6 +278,14 @@ export interface IMergeTreeOptions {
* @defaultValue `false`
*/
mergeTreeEnableSidedObliterate?: boolean;

/**
* Enables support for annotate adjust operations, which allow for specifying
* a summand which is summed with the current value to compute the new value.
*
* @defaultValue `false`
*/
mergeTreeEnableAnnotateAdjust?: boolean;
}

/**
Expand Down Expand Up @@ -1895,7 +1904,7 @@ export class MergeTree {
* Annotate a range with properties
* @param start - The inclusive start position of the range to annotate
* @param end - The exclusive end position of the range to annotate
* @param props - The properties to annotate the range with
* @param propsOrAdjust - The properties or adjustments to annotate the range with
* @param refSeq - The reference sequence number to use to apply the annotate
* @param clientId - The id of the client making the annotate
* @param seq - The sequence number of the annotate operation
Expand All @@ -1905,33 +1914,37 @@ export class MergeTree {
public annotateRange(
start: number,
end: number,
props: PropertySet,
propsOrAdjust: PropsOrAdjust,
refSeq: number,
clientId: number,
seq: number,
opArgs: IMergeTreeDeltaOpArgs,

// eslint-disable-next-line import/no-deprecated
rollback: PropertiesRollback = PropertiesRollback.None,
): void {
if (propsOrAdjust.adjust !== undefined) {
errorIfOptionNotTrue(this.options, "mergeTreeEnableAnnotateAdjust");
}

this.ensureIntervalBoundary(start, refSeq, clientId);
this.ensureIntervalBoundary(end, refSeq, clientId);
const deltaSegments: IMergeTreeSegmentDelta[] = [];
const localSeq =
seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
// eslint-disable-next-line import/no-deprecated
let segmentGroup: SegmentGroup | undefined;
const opObj = propsOrAdjust.props ?? propsOrAdjust.adjust;
const annotateSegment = (segment: ISegmentLeaf): boolean => {
assert(
!Marker.is(segment) ||
!(reservedMarkerIdKey in props) ||
props.markerId === segment.properties?.markerId,
!(reservedMarkerIdKey in opObj) ||
opObj.markerId === segment.properties?.markerId,
0x5ad /* Cannot change the markerId of an existing marker */,
);

const propertyManager = (segment.propertyManager ??= new PropertiesManager());
const propertyDeltas = propertyManager.handleProperties(
{ props },
propsOrAdjust,
segment,
seq,
this.collabWindow.minSeq,
Expand Down Expand Up @@ -2409,12 +2422,11 @@ export class MergeTree {
this.annotateRange(
start,
start + segment.cachedLength,
props,
{ props },
UniversalSequenceNumber,
this.collabWindow.clientId,
UniversalSequenceNumber,
{ op: annotateOp },

PropertiesRollback.Rollback,
);
i++;
Expand Down
26 changes: 25 additions & 1 deletion packages/dds/merge-tree/src/opBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import {
IMergeTreeObliterateMsg,
IMergeTreeRemoveMsg,
MergeTreeDeltaType,
type AdjustParams,
type IMergeTreeAnnotateAdjustMsg,
type IMergeTreeObliterateSidedMsg,
} from "./ops.js";
import { PropertySet } from "./properties.js";
import { PropertySet, type MapLike } from "./properties.js";
import { normalizePlace, Side, type SequencePlace } from "./sequencePlace.js";

/**
Expand Down Expand Up @@ -66,6 +68,28 @@ export function createAnnotateRangeOp(
};
}

/**
* Creates the op for annotating the range with the provided properties
* @param start - The inclusive start position of the range to annotate
* @param end - The exclusive end position of the range to annotate
* @param props - The properties to annotate the range with
* @returns The annotate op
*
* @internal
*/
export function createAdjustRangeOp(
start: number,
end: number,
adjust: MapLike<AdjustParams>,
): IMergeTreeAnnotateAdjustMsg {
return {
pos1: start,
pos2: end,
adjust: { ...adjust },
type: MergeTreeDeltaType.ANNOTATE,
};
}

/**
* Creates the op to remove a range
*
Expand Down
1 change: 1 addition & 0 deletions packages/dds/merge-tree/src/ops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ export type IMergeTreeDeltaOp =
| IMergeTreeInsertMsg
| IMergeTreeRemoveMsg
| IMergeTreeAnnotateMsg
| IMergeTreeAnnotateAdjustMsg
| IMergeTreeObliterateMsg
| IMergeTreeObliterateSidedMsg;

Expand Down
27 changes: 12 additions & 15 deletions packages/dds/merge-tree/src/snapshotlegacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {

import { NonCollabClient, UnassignedSequenceNumber } from "./constants.js";
import { MergeTree } from "./mergeTree.js";
import { ISegment } from "./mergeTreeNodes.js";
import { ISegment, type ISegmentLeaf } from "./mergeTreeNodes.js";
import { matchProperties } from "./properties.js";
import {
JsonSegmentSpecs,
Expand Down Expand Up @@ -193,7 +193,7 @@ export class SnapshotLegacy {

extractSync(): ISegment[] {
const collabWindow = this.mergeTree.collabWindow;
this.seq = collabWindow.minSeq;
const seq = (this.seq = collabWindow.minSeq);
this.header = {
segmentsTotalLength: this.mergeTree.getLength(
this.mergeTree.collabWindow.minSeq,
Expand All @@ -205,9 +205,9 @@ export class SnapshotLegacy {
let originalSegments = 0;

const segs: ISegment[] = [];
let prev: ISegment | undefined;
let prev: ISegmentLeaf | undefined;
const extractSegment = (
segment: ISegment,
segment: ISegmentLeaf,
pos: number,
refSeq: number,
clientId: number,
Expand All @@ -216,29 +216,26 @@ export class SnapshotLegacy {
): boolean => {
if (
segment.seq !== UnassignedSequenceNumber &&
segment.seq! <= this.seq! &&
segment.seq! <= seq &&
(segment.removedSeq === undefined ||
segment.removedSeq === UnassignedSequenceNumber ||
segment.removedSeq > this.seq!)
segment.removedSeq > seq)
) {
originalSegments += 1;
if (prev?.canAppend(segment) && matchProperties(prev.properties, segment.properties)) {
prev = prev.clone();
const properties =
segment.propertyManager?.getAtSeq(segment.properties, seq) ?? segment.properties;
if (prev?.canAppend(segment) && matchProperties(prev.properties, properties)) {
prev.append(segment.clone());
} else {
if (prev) {
segs.push(prev);
}
prev = segment;
prev = segment.clone();
prev.properties = properties;
segs.push(prev);
}
}
return true;
};

this.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);
if (prev) {
segs.push(prev);
}

this.segments = [];
let totalLength: number = 0;
Expand Down
Loading
Loading