@fluidframework/sequence 2.30.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +506 -495
- package/api-report/sequence.legacy.alpha.api.md +67 -5
- package/dist/IntervalCollectionValues.d.ts +3 -51
- package/dist/IntervalCollectionValues.d.ts.map +1 -1
- package/dist/IntervalCollectionValues.js +6 -49
- package/dist/IntervalCollectionValues.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -8
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +292 -63
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +111 -193
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalCollectionMap.d.ts +11 -32
- package/dist/intervalCollectionMap.d.ts.map +1 -1
- package/dist/intervalCollectionMap.js +37 -90
- package/dist/intervalCollectionMap.js.map +1 -1
- package/dist/intervalCollectionMapInterfaces.d.ts +10 -83
- package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/dist/intervalCollectionMapInterfaces.js.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.d.ts +10 -11
- package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
- package/dist/intervalIndex/endpointInRangeIndex.js +4 -5
- package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -1
- package/dist/intervalIndex/endpointIndex.d.ts +12 -13
- package/dist/intervalIndex/endpointIndex.d.ts.map +1 -1
- package/dist/intervalIndex/endpointIndex.js +4 -5
- package/dist/intervalIndex/endpointIndex.js.map +1 -1
- package/dist/intervalIndex/idIntervalIndex.d.ts +6 -12
- package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -1
- package/dist/intervalIndex/idIntervalIndex.js +0 -3
- package/dist/intervalIndex/idIntervalIndex.js.map +1 -1
- package/dist/intervalIndex/index.d.ts +2 -2
- package/dist/intervalIndex/index.d.ts.map +1 -1
- package/dist/intervalIndex/index.js.map +1 -1
- package/dist/intervalIndex/intervalIndex.d.ts +28 -1
- package/dist/intervalIndex/intervalIndex.d.ts.map +1 -1
- package/dist/intervalIndex/intervalIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +30 -13
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.js +4 -5
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +1 -1
- package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +2 -2
- package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
- package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.d.ts +10 -11
- package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
- package/dist/intervalIndex/startpointInRangeIndex.js +4 -5
- package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -1
- package/dist/intervals/index.d.ts +2 -3
- package/dist/intervals/index.d.ts.map +1 -1
- package/dist/intervals/index.js +1 -6
- package/dist/intervals/index.js.map +1 -1
- package/dist/intervals/intervalUtils.d.ts +3 -25
- package/dist/intervals/intervalUtils.d.ts.map +1 -1
- package/dist/intervals/intervalUtils.js.map +1 -1
- package/dist/intervals/sequenceInterval.d.ts +3 -8
- package/dist/intervals/sequenceInterval.d.ts.map +1 -1
- package/dist/intervals/sequenceInterval.js +1 -9
- package/dist/intervals/sequenceInterval.js.map +1 -1
- package/dist/legacy.d.ts +4 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/sequence.d.ts +4 -6
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +3 -5
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +2 -63
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js +0 -113
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/dist/sharedString.d.ts.map +1 -1
- package/dist/sharedString.js +6 -6
- package/dist/sharedString.js.map +1 -1
- package/lib/IntervalCollectionValues.d.ts +3 -51
- package/lib/IntervalCollectionValues.d.ts.map +1 -1
- package/lib/IntervalCollectionValues.js +5 -47
- package/lib/IntervalCollectionValues.js.map +1 -1
- package/lib/index.d.ts +4 -4
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -3
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +292 -63
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +113 -191
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalCollectionMap.d.ts +11 -32
- package/lib/intervalCollectionMap.d.ts.map +1 -1
- package/lib/intervalCollectionMap.js +39 -92
- package/lib/intervalCollectionMap.js.map +1 -1
- package/lib/intervalCollectionMapInterfaces.d.ts +10 -83
- package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/lib/intervalCollectionMapInterfaces.js.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.d.ts +10 -11
- package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
- package/lib/intervalIndex/endpointInRangeIndex.js +5 -6
- package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -1
- package/lib/intervalIndex/endpointIndex.d.ts +12 -13
- package/lib/intervalIndex/endpointIndex.d.ts.map +1 -1
- package/lib/intervalIndex/endpointIndex.js +5 -6
- package/lib/intervalIndex/endpointIndex.js.map +1 -1
- package/lib/intervalIndex/idIntervalIndex.d.ts +6 -12
- package/lib/intervalIndex/idIntervalIndex.d.ts.map +1 -1
- package/lib/intervalIndex/idIntervalIndex.js +0 -3
- package/lib/intervalIndex/idIntervalIndex.js.map +1 -1
- package/lib/intervalIndex/index.d.ts +2 -2
- package/lib/intervalIndex/index.d.ts.map +1 -1
- package/lib/intervalIndex/index.js.map +1 -1
- package/lib/intervalIndex/intervalIndex.d.ts +28 -1
- package/lib/intervalIndex/intervalIndex.d.ts.map +1 -1
- package/lib/intervalIndex/intervalIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +30 -13
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js +5 -6
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +2 -2
- package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +2 -2
- package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
- package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.d.ts +10 -11
- package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
- package/lib/intervalIndex/startpointInRangeIndex.js +5 -6
- package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -1
- package/lib/intervals/index.d.ts +2 -3
- package/lib/intervals/index.d.ts.map +1 -1
- package/lib/intervals/index.js +1 -2
- package/lib/intervals/index.js.map +1 -1
- package/lib/intervals/intervalUtils.d.ts +3 -25
- package/lib/intervals/intervalUtils.d.ts.map +1 -1
- package/lib/intervals/intervalUtils.js.map +1 -1
- package/lib/intervals/sequenceInterval.d.ts +3 -8
- package/lib/intervals/sequenceInterval.d.ts.map +1 -1
- package/lib/intervals/sequenceInterval.js +0 -8
- package/lib/intervals/sequenceInterval.js.map +1 -1
- package/lib/legacy.d.ts +4 -0
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/sequence.d.ts +4 -6
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +3 -5
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +2 -63
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js +1 -110
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/lib/sharedString.d.ts.map +1 -1
- package/lib/sharedString.js +6 -6
- package/lib/sharedString.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +19 -22
- package/src/IntervalCollectionValues.ts +10 -93
- package/src/index.ts +6 -17
- package/src/intervalCollection.ts +524 -343
- package/src/intervalCollectionMap.ts +72 -140
- package/src/intervalCollectionMapInterfaces.ts +13 -104
- package/src/intervalIndex/endpointInRangeIndex.ts +17 -29
- package/src/intervalIndex/endpointIndex.ts +19 -31
- package/src/intervalIndex/idIntervalIndex.ts +15 -25
- package/src/intervalIndex/index.ts +2 -1
- package/src/intervalIndex/intervalIndex.ts +30 -1
- package/src/intervalIndex/overlappingIntervalsIndex.ts +50 -27
- package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +2 -3
- package/src/intervalIndex/sequenceIntervalIndexes.ts +2 -2
- package/src/intervalIndex/startpointInRangeIndex.ts +17 -29
- package/src/intervals/index.ts +0 -3
- package/src/intervals/intervalUtils.ts +3 -38
- package/src/intervals/sequenceInterval.ts +2 -12
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +8 -20
- package/src/sharedIntervalCollection.ts +5 -183
- package/src/sharedString.ts +6 -24
- package/dist/intervals/interval.d.ts +0 -76
- package/dist/intervals/interval.d.ts.map +0 -1
- package/dist/intervals/interval.js +0 -167
- package/dist/intervals/interval.js.map +0 -1
- package/lib/intervals/interval.d.ts +0 -76
- package/lib/intervals/interval.d.ts.map +0 -1
- package/lib/intervals/interval.js +0 -162
- package/lib/intervals/interval.js.map +0 -1
- package/prettier.config.cjs +0 -8
- package/src/intervals/interval.ts +0 -226
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/* eslint-disable no-bitwise */
|
|
7
|
-
/* eslint-disable import/no-deprecated */
|
|
8
7
|
|
|
9
8
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
10
9
|
import { IEvent } from "@fluidframework/core-interfaces";
|
|
@@ -21,7 +20,6 @@ import {
|
|
|
21
20
|
UnassignedSequenceNumber,
|
|
22
21
|
UniversalSequenceNumber,
|
|
23
22
|
addProperties,
|
|
24
|
-
createMap,
|
|
25
23
|
getSlideToSegoff,
|
|
26
24
|
refTypeIncludesFlag,
|
|
27
25
|
reservedRangeLabelsKey,
|
|
@@ -30,49 +28,49 @@ import {
|
|
|
30
28
|
endpointPosAndSide,
|
|
31
29
|
PropertiesManager,
|
|
32
30
|
type ISegmentInternal,
|
|
31
|
+
createMap,
|
|
33
32
|
} from "@fluidframework/merge-tree/internal";
|
|
34
33
|
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
35
34
|
import { v4 as uuid } from "uuid";
|
|
36
35
|
|
|
37
36
|
import {
|
|
38
|
-
IIntervalCollectionFactory,
|
|
39
37
|
IIntervalCollectionOperation,
|
|
40
|
-
IIntervalCollectionType,
|
|
41
38
|
IMapMessageLocalMetadata,
|
|
42
|
-
IValueOpEmitter,
|
|
43
39
|
SequenceOptions,
|
|
40
|
+
type IIntervalCollectionTypeOperationValue,
|
|
44
41
|
} from "./intervalCollectionMapInterfaces.js";
|
|
45
42
|
import {
|
|
43
|
+
createIdIntervalIndex,
|
|
46
44
|
EndpointIndex,
|
|
47
|
-
IEndpointIndex,
|
|
48
|
-
IIdIntervalIndex,
|
|
49
|
-
IOverlappingIntervalsIndex,
|
|
50
|
-
IntervalIndex,
|
|
51
45
|
OverlappingIntervalsIndex,
|
|
52
|
-
|
|
46
|
+
type IEndpointIndex,
|
|
47
|
+
type IIdIntervalIndex,
|
|
48
|
+
// eslint-disable-next-line import/no-deprecated
|
|
49
|
+
type IntervalIndex,
|
|
50
|
+
type ISequenceOverlappingIntervalsIndex,
|
|
51
|
+
type SequenceIntervalIndex,
|
|
53
52
|
} from "./intervalIndex/index.js";
|
|
54
53
|
import {
|
|
55
54
|
CompressedSerializedInterval,
|
|
56
|
-
IIntervalHelpers,
|
|
57
|
-
ISerializableInterval,
|
|
58
55
|
ISerializedInterval,
|
|
59
|
-
|
|
60
|
-
IntervalOpType,
|
|
56
|
+
IntervalDeltaOpType,
|
|
61
57
|
IntervalStickiness,
|
|
62
58
|
IntervalType,
|
|
63
59
|
SequenceInterval,
|
|
64
60
|
SequenceIntervalClass,
|
|
65
61
|
SerializedIntervalDelta,
|
|
66
|
-
createInterval,
|
|
67
62
|
createPositionReferenceFromSegoff,
|
|
63
|
+
createSequenceInterval,
|
|
68
64
|
endReferenceSlidingPreference,
|
|
69
|
-
sequenceIntervalHelpers,
|
|
70
65
|
startReferenceSlidingPreference,
|
|
66
|
+
type ISerializableInterval,
|
|
71
67
|
type ISerializableIntervalPrivate,
|
|
72
68
|
} from "./intervals/index.js";
|
|
73
69
|
|
|
74
70
|
export const reservedIntervalIdKey = "intervalId";
|
|
75
71
|
|
|
72
|
+
export type ISerializedIntervalCollectionV1 = ISerializedInterval[];
|
|
73
|
+
|
|
76
74
|
export interface ISerializedIntervalCollectionV2 {
|
|
77
75
|
label: string;
|
|
78
76
|
version: 2;
|
|
@@ -166,40 +164,26 @@ export function computeStickinessFromSide(
|
|
|
166
164
|
return stickiness as IntervalStickiness;
|
|
167
165
|
}
|
|
168
166
|
|
|
169
|
-
export
|
|
170
|
-
const helpers: IIntervalHelpers<Interval> = {
|
|
171
|
-
create: createInterval,
|
|
172
|
-
};
|
|
173
|
-
const lc = new LocalIntervalCollection<Interval>(
|
|
174
|
-
undefined as any as Client,
|
|
175
|
-
"",
|
|
176
|
-
helpers,
|
|
177
|
-
{},
|
|
178
|
-
);
|
|
179
|
-
return lc;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
167
|
+
export class LocalIntervalCollection {
|
|
183
168
|
private static readonly legacyIdPrefix = "legacy";
|
|
184
|
-
public readonly overlappingIntervalsIndex:
|
|
185
|
-
public readonly idIntervalIndex: IIdIntervalIndex
|
|
186
|
-
public readonly endIntervalIndex: IEndpointIndex
|
|
187
|
-
private readonly indexes: Set<
|
|
169
|
+
public readonly overlappingIntervalsIndex: ISequenceOverlappingIntervalsIndex;
|
|
170
|
+
public readonly idIntervalIndex: IIdIntervalIndex;
|
|
171
|
+
public readonly endIntervalIndex: IEndpointIndex;
|
|
172
|
+
private readonly indexes: Set<SequenceIntervalIndex>;
|
|
188
173
|
|
|
189
174
|
constructor(
|
|
190
175
|
private readonly client: Client,
|
|
191
176
|
private readonly label: string,
|
|
192
|
-
private readonly helpers: IIntervalHelpers<TInterval>,
|
|
193
177
|
private readonly options: Partial<SequenceOptions>,
|
|
194
178
|
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
195
179
|
private readonly onPositionChange?: (
|
|
196
|
-
interval:
|
|
197
|
-
previousInterval:
|
|
180
|
+
interval: SequenceIntervalClass,
|
|
181
|
+
previousInterval: SequenceIntervalClass,
|
|
198
182
|
) => void,
|
|
199
183
|
) {
|
|
200
|
-
this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client
|
|
201
|
-
this.idIntervalIndex = createIdIntervalIndex
|
|
202
|
-
this.endIntervalIndex = new EndpointIndex(client
|
|
184
|
+
this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client);
|
|
185
|
+
this.idIntervalIndex = createIdIntervalIndex();
|
|
186
|
+
this.endIntervalIndex = new EndpointIndex(client);
|
|
203
187
|
this.indexes = new Set([
|
|
204
188
|
this.overlappingIntervalsIndex,
|
|
205
189
|
this.idIntervalIndex,
|
|
@@ -245,21 +229,21 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
245
229
|
return id;
|
|
246
230
|
}
|
|
247
231
|
|
|
248
|
-
private removeIntervalFromIndexes(interval:
|
|
232
|
+
private removeIntervalFromIndexes(interval: SequenceIntervalClass) {
|
|
249
233
|
for (const index of this.indexes) {
|
|
250
234
|
index.remove(interval);
|
|
251
235
|
}
|
|
252
236
|
}
|
|
253
237
|
|
|
254
|
-
public appendIndex(index:
|
|
238
|
+
public appendIndex(index: SequenceIntervalIndex) {
|
|
255
239
|
this.indexes.add(index);
|
|
256
240
|
}
|
|
257
241
|
|
|
258
|
-
public removeIndex(index:
|
|
242
|
+
public removeIndex(index: SequenceIntervalIndex): boolean {
|
|
259
243
|
return this.indexes.delete(index);
|
|
260
244
|
}
|
|
261
245
|
|
|
262
|
-
public removeExistingInterval(interval:
|
|
246
|
+
public removeExistingInterval(interval: SequenceIntervalClass) {
|
|
263
247
|
this.removeIntervalFromIndexes(interval);
|
|
264
248
|
this.removeIntervalListeners(interval);
|
|
265
249
|
}
|
|
@@ -269,8 +253,8 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
269
253
|
end: SequencePlace,
|
|
270
254
|
intervalType: IntervalType,
|
|
271
255
|
op?: ISequencedDocumentMessage,
|
|
272
|
-
):
|
|
273
|
-
return
|
|
256
|
+
): SequenceIntervalClass {
|
|
257
|
+
return createSequenceInterval(
|
|
274
258
|
this.label,
|
|
275
259
|
start,
|
|
276
260
|
end,
|
|
@@ -289,7 +273,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
289
273
|
props?: PropertySet,
|
|
290
274
|
op?: ISequencedDocumentMessage,
|
|
291
275
|
) {
|
|
292
|
-
const interval:
|
|
276
|
+
const interval: SequenceIntervalClass = this.createInterval(start, end, intervalType, op);
|
|
293
277
|
if (interval) {
|
|
294
278
|
if (!interval.properties) {
|
|
295
279
|
interval.properties = createMap<any>();
|
|
@@ -315,27 +299,25 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
315
299
|
return interval;
|
|
316
300
|
}
|
|
317
301
|
|
|
318
|
-
private linkEndpointsToInterval(interval:
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
interval.end.addProperties({ interval });
|
|
322
|
-
}
|
|
302
|
+
private linkEndpointsToInterval(interval: SequenceIntervalClass): void {
|
|
303
|
+
interval.start.addProperties({ interval });
|
|
304
|
+
interval.end.addProperties({ interval });
|
|
323
305
|
}
|
|
324
306
|
|
|
325
|
-
private addIntervalToIndexes(interval:
|
|
307
|
+
private addIntervalToIndexes(interval: SequenceIntervalClass) {
|
|
326
308
|
for (const index of this.indexes) {
|
|
327
309
|
index.add(interval);
|
|
328
310
|
}
|
|
329
311
|
}
|
|
330
312
|
|
|
331
|
-
public add(interval:
|
|
313
|
+
public add(interval: SequenceIntervalClass): void {
|
|
332
314
|
this.linkEndpointsToInterval(interval);
|
|
333
315
|
this.addIntervalToIndexes(interval);
|
|
334
316
|
this.addIntervalListeners(interval);
|
|
335
317
|
}
|
|
336
318
|
|
|
337
319
|
public changeInterval(
|
|
338
|
-
interval:
|
|
320
|
+
interval: SequenceIntervalClass,
|
|
339
321
|
start: SequencePlace | undefined,
|
|
340
322
|
end: SequencePlace | undefined,
|
|
341
323
|
op?: ISequencedDocumentMessage,
|
|
@@ -348,7 +330,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
348
330
|
op,
|
|
349
331
|
localSeq,
|
|
350
332
|
this.options.mergeTreeReferencesCanSlideToEndpoint,
|
|
351
|
-
)
|
|
333
|
+
);
|
|
352
334
|
if (newInterval) {
|
|
353
335
|
this.removeExistingInterval(interval);
|
|
354
336
|
this.add(newInterval);
|
|
@@ -356,7 +338,12 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
356
338
|
return newInterval;
|
|
357
339
|
}
|
|
358
340
|
|
|
359
|
-
public serialize(
|
|
341
|
+
public serialize(
|
|
342
|
+
version: "1" | "2",
|
|
343
|
+
): ISerializedIntervalCollectionV1 | ISerializedIntervalCollectionV2 {
|
|
344
|
+
if (version === "1") {
|
|
345
|
+
return Array.from(this.idIntervalIndex, (interval) => interval.serialize());
|
|
346
|
+
}
|
|
360
347
|
return {
|
|
361
348
|
label: this.label,
|
|
362
349
|
intervals: Array.from(this.idIntervalIndex, (interval) =>
|
|
@@ -366,7 +353,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
366
353
|
};
|
|
367
354
|
}
|
|
368
355
|
|
|
369
|
-
private addIntervalListeners(interval:
|
|
356
|
+
private addIntervalListeners(interval: SequenceIntervalClass) {
|
|
370
357
|
const cloneRef = (ref: LocalReferencePosition) => {
|
|
371
358
|
const segment = ref.getSegment();
|
|
372
359
|
if (segment === undefined) {
|
|
@@ -385,193 +372,87 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
385
372
|
ref.canSlideToEndpoint,
|
|
386
373
|
);
|
|
387
374
|
};
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
(
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
},
|
|
414
|
-
);
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
private removeIntervalListeners(interval: TInterval) {
|
|
419
|
-
if (interval instanceof SequenceIntervalClass) {
|
|
420
|
-
interval.removePositionChangeListeners();
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
class SequenceIntervalCollectionFactory
|
|
426
|
-
implements IIntervalCollectionFactory<SequenceInterval>
|
|
427
|
-
{
|
|
428
|
-
public load(
|
|
429
|
-
emitter: IValueOpEmitter,
|
|
430
|
-
raw: ISerializedInterval[] | ISerializedIntervalCollectionV2 = [],
|
|
431
|
-
options?: Partial<SequenceOptions>,
|
|
432
|
-
): IntervalCollection<SequenceInterval> {
|
|
433
|
-
return new IntervalCollection<SequenceInterval>(
|
|
434
|
-
sequenceIntervalHelpers,
|
|
435
|
-
true,
|
|
436
|
-
emitter,
|
|
437
|
-
raw,
|
|
438
|
-
options,
|
|
375
|
+
let previousInterval: SequenceIntervalClass | undefined;
|
|
376
|
+
let pendingChanges = 0;
|
|
377
|
+
interval.addPositionChangeListeners(
|
|
378
|
+
() => {
|
|
379
|
+
pendingChanges++;
|
|
380
|
+
// Note: both start and end can change and invoke beforeSlide on each endpoint before afterSlide.
|
|
381
|
+
if (!previousInterval) {
|
|
382
|
+
previousInterval = interval.clone();
|
|
383
|
+
previousInterval.start = cloneRef(previousInterval.start);
|
|
384
|
+
previousInterval.end = cloneRef(previousInterval.end);
|
|
385
|
+
this.removeIntervalFromIndexes(interval);
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
() => {
|
|
389
|
+
assert(
|
|
390
|
+
previousInterval !== undefined,
|
|
391
|
+
0x3fa /* Invalid interleaving of before/after slide */,
|
|
392
|
+
);
|
|
393
|
+
pendingChanges--;
|
|
394
|
+
if (pendingChanges === 0) {
|
|
395
|
+
this.addIntervalToIndexes(interval);
|
|
396
|
+
this.onPositionChange?.(interval, previousInterval);
|
|
397
|
+
previousInterval = undefined;
|
|
398
|
+
}
|
|
399
|
+
},
|
|
439
400
|
);
|
|
440
401
|
}
|
|
441
402
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
): ISerializedInterval[] | ISerializedIntervalCollectionV2 {
|
|
445
|
-
return value.serializeInternal();
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
export class SequenceIntervalCollectionValueType
|
|
450
|
-
implements IIntervalCollectionType<SequenceInterval>
|
|
451
|
-
{
|
|
452
|
-
public static Name = "sharedStringIntervalCollection";
|
|
453
|
-
|
|
454
|
-
public get name(): string {
|
|
455
|
-
return SequenceIntervalCollectionValueType.Name;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
public get factory(): IIntervalCollectionFactory<SequenceInterval> {
|
|
459
|
-
return SequenceIntervalCollectionValueType._factory;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
public get ops(): Map<IntervalOpType, IIntervalCollectionOperation<SequenceInterval>> {
|
|
463
|
-
return SequenceIntervalCollectionValueType._ops;
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
private static readonly _factory: IIntervalCollectionFactory<SequenceInterval> =
|
|
467
|
-
new SequenceIntervalCollectionFactory();
|
|
468
|
-
|
|
469
|
-
private static readonly _ops = makeOpsMap<SequenceInterval>();
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
class IntervalCollectionFactory implements IIntervalCollectionFactory<Interval> {
|
|
473
|
-
public load(
|
|
474
|
-
emitter: IValueOpEmitter,
|
|
475
|
-
raw: ISerializedInterval[] | ISerializedIntervalCollectionV2 = [],
|
|
476
|
-
options?: Partial<SequenceOptions>,
|
|
477
|
-
): IntervalCollection<Interval> {
|
|
478
|
-
const helpers: IIntervalHelpers<Interval> = {
|
|
479
|
-
create: createInterval,
|
|
480
|
-
};
|
|
481
|
-
const collection = new IntervalCollection<Interval>(helpers, false, emitter, raw, options);
|
|
482
|
-
collection.attachGraph(undefined as any as Client, "");
|
|
483
|
-
return collection;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
public store(value: IntervalCollection<Interval>): ISerializedIntervalCollectionV2 {
|
|
487
|
-
return value.serializeInternal();
|
|
403
|
+
private removeIntervalListeners(interval: SequenceIntervalClass) {
|
|
404
|
+
interval.removePositionChangeListeners();
|
|
488
405
|
}
|
|
489
406
|
}
|
|
490
407
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
public get factory(): IIntervalCollectionFactory<Interval> {
|
|
499
|
-
return IntervalCollectionValueType._factory;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
public get ops(): Map<IntervalOpType, IIntervalCollectionOperation<Interval>> {
|
|
503
|
-
return IntervalCollectionValueType._ops;
|
|
408
|
+
const rebase: IIntervalCollectionOperation["rebase"] = (collection, op, localOpMetadata) => {
|
|
409
|
+
const { localSeq } = localOpMetadata;
|
|
410
|
+
const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
|
|
411
|
+
if (rebasedValue === undefined) {
|
|
412
|
+
return undefined;
|
|
504
413
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
{
|
|
548
|
-
process: (collection, params, local, op) => {
|
|
549
|
-
assert(op !== undefined, 0x3fc /* op should exist here */);
|
|
550
|
-
collection.ackDelete(params, local, op);
|
|
551
|
-
},
|
|
552
|
-
rebase: (collection, op, localOpMetadata) => {
|
|
553
|
-
// Deletion of intervals is based on id, so requires no rebasing.
|
|
554
|
-
return { rebasedOp: op, rebasedLocalOpMetadata: localOpMetadata };
|
|
555
|
-
},
|
|
556
|
-
},
|
|
557
|
-
],
|
|
558
|
-
[
|
|
559
|
-
IntervalOpType.CHANGE,
|
|
560
|
-
{
|
|
561
|
-
process: (collection, params, local, op, localOpMetadata) => {
|
|
562
|
-
// if params is undefined, the interval was deleted during
|
|
563
|
-
// rebasing
|
|
564
|
-
if (!params) {
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
assert(op !== undefined, 0x3fd /* op should exist here */);
|
|
568
|
-
collection.ackChange(params, local, op, localOpMetadata);
|
|
569
|
-
},
|
|
570
|
-
rebase,
|
|
571
|
-
},
|
|
572
|
-
],
|
|
573
|
-
]);
|
|
574
|
-
}
|
|
414
|
+
const rebasedOp = { ...op, value: rebasedValue };
|
|
415
|
+
return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
|
|
416
|
+
};
|
|
417
|
+
|
|
418
|
+
export const opsMap: Record<IntervalDeltaOpType, IIntervalCollectionOperation> = {
|
|
419
|
+
[IntervalDeltaOpType.ADD]: {
|
|
420
|
+
process: (collection, params, local, op, localOpMetadata) => {
|
|
421
|
+
// if params is undefined, the interval was deleted during
|
|
422
|
+
// rebasing
|
|
423
|
+
if (!params) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
assert(op !== undefined, 0x3fb /* op should exist here */);
|
|
427
|
+
collection.ackAdd(params, local, op, localOpMetadata);
|
|
428
|
+
},
|
|
429
|
+
rebase,
|
|
430
|
+
},
|
|
431
|
+
|
|
432
|
+
[IntervalDeltaOpType.DELETE]: {
|
|
433
|
+
process: (collection, params, local, op) => {
|
|
434
|
+
assert(op !== undefined, 0x3fc /* op should exist here */);
|
|
435
|
+
collection.ackDelete(params, local, op);
|
|
436
|
+
},
|
|
437
|
+
rebase: (collection, op, localOpMetadata) => {
|
|
438
|
+
// Deletion of intervals is based on id, so requires no rebasing.
|
|
439
|
+
return { rebasedOp: op, rebasedLocalOpMetadata: localOpMetadata };
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
|
|
443
|
+
[IntervalDeltaOpType.CHANGE]: {
|
|
444
|
+
process: (collection, params, local, op, localOpMetadata) => {
|
|
445
|
+
// if params is undefined, the interval was deleted during
|
|
446
|
+
// rebasing
|
|
447
|
+
if (!params) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
assert(op !== undefined, 0x3fd /* op should exist here */);
|
|
451
|
+
collection.ackChange(params, local, op, localOpMetadata);
|
|
452
|
+
},
|
|
453
|
+
rebase,
|
|
454
|
+
},
|
|
455
|
+
};
|
|
575
456
|
|
|
576
457
|
/**
|
|
577
458
|
* @legacy
|
|
@@ -579,14 +460,12 @@ export function makeOpsMap<T extends ISerializableInterval>(): Map<
|
|
|
579
460
|
*/
|
|
580
461
|
export type DeserializeCallback = (properties: PropertySet) => void;
|
|
581
462
|
|
|
582
|
-
class IntervalCollectionIterator
|
|
583
|
-
|
|
584
|
-
{
|
|
585
|
-
private readonly results: TInterval[];
|
|
463
|
+
class IntervalCollectionIterator implements Iterator<SequenceIntervalClass> {
|
|
464
|
+
private readonly results: SequenceIntervalClass[];
|
|
586
465
|
private index: number;
|
|
587
466
|
|
|
588
467
|
constructor(
|
|
589
|
-
collection: IntervalCollection
|
|
468
|
+
collection: IntervalCollection,
|
|
590
469
|
iteratesForward: boolean = true,
|
|
591
470
|
start?: number,
|
|
592
471
|
end?: number,
|
|
@@ -597,7 +476,7 @@ class IntervalCollectionIterator<TInterval extends ISerializableInterval>
|
|
|
597
476
|
collection.gatherIterationResults(this.results, iteratesForward, start, end);
|
|
598
477
|
}
|
|
599
478
|
|
|
600
|
-
public next(): IteratorResult<
|
|
479
|
+
public next(): IteratorResult<SequenceIntervalClass> {
|
|
601
480
|
if (this.index < this.results.length) {
|
|
602
481
|
return {
|
|
603
482
|
value: this.results[this.index++],
|
|
@@ -616,6 +495,7 @@ class IntervalCollectionIterator<TInterval extends ISerializableInterval>
|
|
|
616
495
|
* Change events emitted by `IntervalCollection`s
|
|
617
496
|
* @legacy
|
|
618
497
|
* @alpha
|
|
498
|
+
* @remarks The generic version of this interface is no longer used and will be removed. Use {@link ISequenceIntervalCollectionEvents} instead.
|
|
619
499
|
*/
|
|
620
500
|
export interface IIntervalCollectionEvent<TInterval extends ISerializableInterval>
|
|
621
501
|
extends IEvent {
|
|
@@ -697,11 +577,96 @@ export interface IIntervalCollectionEvent<TInterval extends ISerializableInterva
|
|
|
697
577
|
): void;
|
|
698
578
|
}
|
|
699
579
|
|
|
580
|
+
/**
|
|
581
|
+
* Change events emitted by `IntervalCollection`s
|
|
582
|
+
* @legacy
|
|
583
|
+
* @alpha
|
|
584
|
+
*/
|
|
585
|
+
export interface ISequenceIntervalCollectionEvents extends IEvent {
|
|
586
|
+
/**
|
|
587
|
+
* This event is invoked whenever the endpoints of an interval may have changed.
|
|
588
|
+
* This can happen on:
|
|
589
|
+
* - local endpoint modification
|
|
590
|
+
* - ack of a remote endpoint modification
|
|
591
|
+
* - position change due to segment sliding (slides due to mergeTree segment deletion will always appear local)
|
|
592
|
+
* The `interval` argument reflects the new values.
|
|
593
|
+
* `previousInterval` contains transient `ReferencePosition`s at the same location as the interval's original
|
|
594
|
+
* endpoints. These references should be used for position information only.
|
|
595
|
+
* `local` reflects whether the change originated locally.
|
|
596
|
+
* `op` is defined if and only if the server has acked this change.
|
|
597
|
+
* `slide` is true if the change is due to sliding on removal of position
|
|
598
|
+
*/
|
|
599
|
+
(
|
|
600
|
+
event: "changeInterval",
|
|
601
|
+
listener: (
|
|
602
|
+
interval: SequenceInterval,
|
|
603
|
+
previousInterval: SequenceInterval,
|
|
604
|
+
local: boolean,
|
|
605
|
+
op: ISequencedDocumentMessage | undefined,
|
|
606
|
+
slide: boolean,
|
|
607
|
+
) => void,
|
|
608
|
+
): void;
|
|
609
|
+
/**
|
|
610
|
+
* This event is invoked whenever an interval is added or removed from the collection.
|
|
611
|
+
* `local` reflects whether the change originated locally.
|
|
612
|
+
* `op` is defined if and only if the server has acked this change.
|
|
613
|
+
*/
|
|
614
|
+
(
|
|
615
|
+
event: "addInterval" | "deleteInterval",
|
|
616
|
+
listener: (
|
|
617
|
+
interval: SequenceInterval,
|
|
618
|
+
local: boolean,
|
|
619
|
+
op: ISequencedDocumentMessage | undefined,
|
|
620
|
+
) => void,
|
|
621
|
+
): void;
|
|
622
|
+
/**
|
|
623
|
+
* This event is invoked whenever an interval's properties have changed.
|
|
624
|
+
* `interval` reflects the state of the updated properties.
|
|
625
|
+
* `propertyDeltas` is a map-like whose keys contain all values that were changed, and whose
|
|
626
|
+
* values contain all previous values of the property set.
|
|
627
|
+
* This object can be used directly in a call to `changeProperties` to revert the property change if desired.
|
|
628
|
+
* `local` reflects whether the change originated locally.
|
|
629
|
+
* `op` is defined if and only if the server has acked this change.
|
|
630
|
+
*/
|
|
631
|
+
(
|
|
632
|
+
event: "propertyChanged",
|
|
633
|
+
listener: (
|
|
634
|
+
interval: SequenceInterval,
|
|
635
|
+
propertyDeltas: PropertySet,
|
|
636
|
+
local: boolean,
|
|
637
|
+
op: ISequencedDocumentMessage | undefined,
|
|
638
|
+
) => void,
|
|
639
|
+
): void;
|
|
640
|
+
/**
|
|
641
|
+
* This event is invoked whenever an interval's endpoints or properties (or both) have changed.
|
|
642
|
+
* `interval` reflects the state of the updated endpoints or properties.
|
|
643
|
+
* `propertyDeltas` is a map-like whose keys contain all values that were changed, and whose
|
|
644
|
+
* values contain all previous values of the property set.
|
|
645
|
+
* This object can be used directly in a call to `changeProperties` to revert the property change if desired.
|
|
646
|
+
* 'previousInterval' contains transient `ReferencePosition`s at the same location as the interval's original
|
|
647
|
+
* endpoints. These references should be used for position information only. In the case of a property change
|
|
648
|
+
* only, this argument should be undefined.
|
|
649
|
+
* `local` reflects whether the change originated locally.
|
|
650
|
+
* `slide` is true if the change is due to sliding on removal of position.
|
|
651
|
+
*/
|
|
652
|
+
(
|
|
653
|
+
event: "changed",
|
|
654
|
+
listener: (
|
|
655
|
+
interval: SequenceInterval,
|
|
656
|
+
propertyDeltas: PropertySet,
|
|
657
|
+
previousInterval: SequenceInterval | undefined,
|
|
658
|
+
local: boolean,
|
|
659
|
+
slide: boolean,
|
|
660
|
+
) => void,
|
|
661
|
+
): void;
|
|
662
|
+
}
|
|
663
|
+
|
|
700
664
|
/**
|
|
701
665
|
* Collection of intervals that supports addition, modification, removal, and efficient spatial querying.
|
|
702
666
|
* Changes to this collection will be incur updates on collaborating clients (i.e. they are not local-only).
|
|
703
667
|
* @legacy
|
|
704
668
|
* @alpha
|
|
669
|
+
* @deprecated The generic version of this interface is no longer used and will be removed. Use {@link ISequenceIntervalCollection} instead.
|
|
705
670
|
*/
|
|
706
671
|
export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
707
672
|
extends TypedEventEmitter<IIntervalCollectionEvent<TInterval>> {
|
|
@@ -714,6 +679,7 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
714
679
|
* @remarks After attaching an index to an interval collection, applications should typically store this
|
|
715
680
|
* index somewhere in their in-memory data model for future reference and querying.
|
|
716
681
|
*/
|
|
682
|
+
// eslint-disable-next-line import/no-deprecated
|
|
717
683
|
attachIndex(index: IntervalIndex<TInterval>): void;
|
|
718
684
|
/**
|
|
719
685
|
* Detaches an index from this collection.
|
|
@@ -722,6 +688,7 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
722
688
|
*
|
|
723
689
|
* @returns `false` if the target index cannot be found in the indexes, otherwise remove all intervals in the index and return `true`.
|
|
724
690
|
*/
|
|
691
|
+
// eslint-disable-next-line import/no-deprecated
|
|
725
692
|
detachIndex(index: IntervalIndex<TInterval>): boolean;
|
|
726
693
|
/**
|
|
727
694
|
* @returns the interval in this collection that has the provided `id`.
|
|
@@ -913,15 +880,231 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
|
|
|
913
880
|
nextInterval(pos: number): TInterval | undefined;
|
|
914
881
|
}
|
|
915
882
|
|
|
883
|
+
/**
|
|
884
|
+
* Collection of intervals that supports addition, modification, removal, and efficient spatial querying.
|
|
885
|
+
* Changes to this collection will be incur updates on collaborating clients (i.e. they are not local-only).
|
|
886
|
+
* @legacy
|
|
887
|
+
* @alpha
|
|
888
|
+
*/
|
|
889
|
+
export interface ISequenceIntervalCollection
|
|
890
|
+
extends TypedEventEmitter<ISequenceIntervalCollectionEvents> {
|
|
891
|
+
readonly attached: boolean;
|
|
892
|
+
/**
|
|
893
|
+
* Attaches an index to this collection.
|
|
894
|
+
* All intervals which are part of this collection will be added to the index, and the index will automatically
|
|
895
|
+
* be updated when this collection updates due to local or remote changes.
|
|
896
|
+
*
|
|
897
|
+
* @remarks After attaching an index to an interval collection, applications should typically store this
|
|
898
|
+
* index somewhere in their in-memory data model for future reference and querying.
|
|
899
|
+
*/
|
|
900
|
+
attachIndex(index: SequenceIntervalIndex): void;
|
|
901
|
+
/**
|
|
902
|
+
* Detaches an index from this collection.
|
|
903
|
+
* All intervals which are part of this collection will be removed from the index, and updates to this collection
|
|
904
|
+
* due to local or remote changes will no longer incur updates to the index.
|
|
905
|
+
*
|
|
906
|
+
* @returns `false` if the target index cannot be found in the indexes, otherwise remove all intervals in the index and return `true`.
|
|
907
|
+
*/
|
|
908
|
+
detachIndex(index: SequenceIntervalIndex): boolean;
|
|
909
|
+
/**
|
|
910
|
+
* @returns the interval in this collection that has the provided `id`.
|
|
911
|
+
* If no interval in the collection has this `id`, returns `undefined`.
|
|
912
|
+
*/
|
|
913
|
+
getIntervalById(id: string): SequenceInterval | undefined;
|
|
914
|
+
/**
|
|
915
|
+
* Creates a new interval and add it to the collection.
|
|
916
|
+
* @param start - interval start position (inclusive)
|
|
917
|
+
* @param end - interval end position (exclusive)
|
|
918
|
+
* @param props - properties of the interval
|
|
919
|
+
* @returns - the created interval
|
|
920
|
+
* @remarks See documentation on {@link SequenceInterval} for comments on
|
|
921
|
+
* interval endpoint semantics: there are subtleties with how the current
|
|
922
|
+
* half-open behavior is represented.
|
|
923
|
+
*
|
|
924
|
+
* Note that intervals may behave unexpectedly if the entire contents
|
|
925
|
+
* of the string are deleted. In this case, it is possible for one endpoint
|
|
926
|
+
* of the interval to become detached, while the other remains on the string.
|
|
927
|
+
*
|
|
928
|
+
* By adjusting the `side` and `pos` values of the `start` and `end` parameters,
|
|
929
|
+
* it is possible to control whether the interval expands to include content
|
|
930
|
+
* inserted at its start or end.
|
|
931
|
+
*
|
|
932
|
+
* See {@link @fluidframework/merge-tree#SequencePlace} for more details on the model.
|
|
933
|
+
*
|
|
934
|
+
* @example
|
|
935
|
+
*
|
|
936
|
+
* Given the string "ABCD":
|
|
937
|
+
*
|
|
938
|
+
*```typescript
|
|
939
|
+
* // Refers to "BC". If any content is inserted before B or after C, this
|
|
940
|
+
* // interval will include that content
|
|
941
|
+
* //
|
|
942
|
+
* // Picture:
|
|
943
|
+
* // \{start\} - A[- B - C -]D - \{end\}
|
|
944
|
+
* // \{start\} - A - B - C - D - \{end\}
|
|
945
|
+
* collection.add(\{ pos: 0, side: Side.After \}, \{ pos: 3, side: Side.Before \}, IntervalType.SlideOnRemove);
|
|
946
|
+
* // Equivalent to specifying the same positions and Side.Before.
|
|
947
|
+
* // Refers to "ABC". Content inserted after C will be included in the
|
|
948
|
+
* // interval, but content inserted before A will not.
|
|
949
|
+
* // \{start\} -[A - B - C -]D - \{end\}
|
|
950
|
+
* // \{start\} - A - B - C - D - \{end\}
|
|
951
|
+
* collection.add(0, 3, IntervalType.SlideOnRemove);
|
|
952
|
+
*```
|
|
953
|
+
*
|
|
954
|
+
* In the case of the first example, if text is deleted,
|
|
955
|
+
*
|
|
956
|
+
* ```typescript
|
|
957
|
+
* // Delete the character "B"
|
|
958
|
+
* string.removeRange(1, 2);
|
|
959
|
+
* ```
|
|
960
|
+
*
|
|
961
|
+
* The start point of the interval will slide to the position immediately
|
|
962
|
+
* before "C", and the same will be true.
|
|
963
|
+
*
|
|
964
|
+
* ```
|
|
965
|
+
* \{start\} - A[- C -]D - \{end\}
|
|
966
|
+
* ```
|
|
967
|
+
*
|
|
968
|
+
* In this case, text inserted immediately before "C" would be included in
|
|
969
|
+
* the interval.
|
|
970
|
+
*
|
|
971
|
+
* ```typescript
|
|
972
|
+
* string.insertText(1, "EFG");
|
|
973
|
+
* ```
|
|
974
|
+
*
|
|
975
|
+
* With the string now being,
|
|
976
|
+
*
|
|
977
|
+
* ```
|
|
978
|
+
* \{start\} - A[- E - F - G - C -]D - \{end\}
|
|
979
|
+
* ```
|
|
980
|
+
*
|
|
981
|
+
* @privateRemarks TODO: ADO:5205 the above comment regarding behavior in
|
|
982
|
+
* the case that the entire interval has been deleted should be resolved at
|
|
983
|
+
* the same time as this ticket
|
|
984
|
+
*/
|
|
985
|
+
add({
|
|
986
|
+
start,
|
|
987
|
+
end,
|
|
988
|
+
props,
|
|
989
|
+
}: {
|
|
990
|
+
start: SequencePlace;
|
|
991
|
+
end: SequencePlace;
|
|
992
|
+
props?: PropertySet;
|
|
993
|
+
}): SequenceInterval;
|
|
994
|
+
/**
|
|
995
|
+
* Removes an interval from the collection.
|
|
996
|
+
* @param id - Id of the interval to remove
|
|
997
|
+
* @returns the removed interval
|
|
998
|
+
*/
|
|
999
|
+
removeIntervalById(id: string): SequenceInterval | undefined;
|
|
1000
|
+
/**
|
|
1001
|
+
* Changes the endpoints, properties, or both of an existing interval.
|
|
1002
|
+
* @param id - Id of the Interval to change
|
|
1003
|
+
* @returns the interval that was changed, if it existed in the collection.
|
|
1004
|
+
* Pass the desired new start position, end position, and/or properties in an object. Start and end positions must be changed
|
|
1005
|
+
* simultaneously - they must either both be specified or both undefined. To only change the properties, leave both endpoints
|
|
1006
|
+
* undefined. To only change the endpoints, leave the properties undefined.
|
|
1007
|
+
*/
|
|
1008
|
+
change(
|
|
1009
|
+
id: string,
|
|
1010
|
+
{ start, end, props }: { start?: SequencePlace; end?: SequencePlace; props?: PropertySet },
|
|
1011
|
+
): SequenceInterval | undefined;
|
|
1012
|
+
|
|
1013
|
+
attachDeserializer(onDeserialize: DeserializeCallback): void;
|
|
1014
|
+
/**
|
|
1015
|
+
* @returns an iterator over all intervals in this collection.
|
|
1016
|
+
*/
|
|
1017
|
+
[Symbol.iterator](): Iterator<SequenceInterval>;
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* @returns a forward iterator over all intervals in this collection with start point equal to `startPosition`.
|
|
1021
|
+
*/
|
|
1022
|
+
CreateForwardIteratorWithStartPosition(startPosition: number): Iterator<SequenceInterval>;
|
|
1023
|
+
|
|
1024
|
+
/**
|
|
1025
|
+
* @returns a backward iterator over all intervals in this collection with start point equal to `startPosition`.
|
|
1026
|
+
*/
|
|
1027
|
+
CreateBackwardIteratorWithStartPosition(startPosition: number): Iterator<SequenceInterval>;
|
|
1028
|
+
|
|
1029
|
+
/**
|
|
1030
|
+
* @returns a forward iterator over all intervals in this collection with end point equal to `endPosition`.
|
|
1031
|
+
*/
|
|
1032
|
+
CreateForwardIteratorWithEndPosition(endPosition: number): Iterator<SequenceInterval>;
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* @returns a backward iterator over all intervals in this collection with end point equal to `endPosition`.
|
|
1036
|
+
*/
|
|
1037
|
+
CreateBackwardIteratorWithEndPosition(endPosition: number): Iterator<SequenceInterval>;
|
|
1038
|
+
|
|
1039
|
+
/**
|
|
1040
|
+
* Gathers iteration results that optionally match a start/end criteria into the provided array.
|
|
1041
|
+
* @param results - Array to gather the results into. In lieu of a return value, this array will be populated with
|
|
1042
|
+
* intervals matching the query upon edit.
|
|
1043
|
+
* @param iteratesForward - whether or not iteration should be in the forward direction
|
|
1044
|
+
* @param start - If provided, only match intervals whose start point is equal to `start`.
|
|
1045
|
+
* @param end - If provided, only match intervals whose end point is equal to `end`.
|
|
1046
|
+
*/
|
|
1047
|
+
gatherIterationResults(
|
|
1048
|
+
results: SequenceInterval[],
|
|
1049
|
+
iteratesForward: boolean,
|
|
1050
|
+
start?: number,
|
|
1051
|
+
end?: number,
|
|
1052
|
+
): void;
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* @deprecated - Users must manually attach the corresponding interval index to utilize this functionality, for instance:
|
|
1056
|
+
*
|
|
1057
|
+
* ```typescript
|
|
1058
|
+
* const overlappingIntervalsIndex = createOverlappingIntervalsIndex(sharedString);
|
|
1059
|
+
* collection.attachIndex(overlappingIntervalsIndex)
|
|
1060
|
+
* const result = overlappingIntervalsIndex.findOverlappingIntervals(start, end);
|
|
1061
|
+
* ```
|
|
1062
|
+
*
|
|
1063
|
+
* @returns an array of all intervals in this collection that overlap with the interval
|
|
1064
|
+
* `[startPosition, endPosition]`.
|
|
1065
|
+
*/
|
|
1066
|
+
findOverlappingIntervals(startPosition: number, endPosition: number): SequenceInterval[];
|
|
1067
|
+
|
|
1068
|
+
/**
|
|
1069
|
+
* Applies a function to each interval in this collection.
|
|
1070
|
+
*/
|
|
1071
|
+
map(fn: (interval: SequenceInterval) => void): void;
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* @deprecated - due to the forthcoming change where the endpointIndex will no longer be
|
|
1075
|
+
* automatically added to the collection. Users are advised to independently attach the
|
|
1076
|
+
* index to the collection and utilize the API accordingly, for instance:
|
|
1077
|
+
* ```typescript
|
|
1078
|
+
* const endpointIndex = createEndpointIndex(sharedString);
|
|
1079
|
+
* collection.attachIndex(endpointIndex);
|
|
1080
|
+
* const result1 = endpointIndex.previousInterval(pos);
|
|
1081
|
+
* ```
|
|
1082
|
+
* If an index is used repeatedly, applications should generally attach it once and store it in memory.
|
|
1083
|
+
*/
|
|
1084
|
+
previousInterval(pos: number): SequenceInterval | undefined;
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* @deprecated - due to the forthcoming change where the endpointIndex will no longer be
|
|
1088
|
+
* automatically added to the collection. Users are advised to independently attach the
|
|
1089
|
+
* index to the collection and utilize the API accordingly, for instance:
|
|
1090
|
+
* ```typescript
|
|
1091
|
+
* const endpointIndex = createEndpointIndex(sharedString);
|
|
1092
|
+
* collection.attachIndex(endpointIndex);
|
|
1093
|
+
* const result2 = endpointIndex.nextInterval(pos);
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
1096
|
+
nextInterval(pos: number): SequenceInterval | undefined;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
916
1099
|
/**
|
|
917
1100
|
* {@inheritdoc IIntervalCollection}
|
|
918
1101
|
*/
|
|
919
|
-
export class IntervalCollection
|
|
920
|
-
extends TypedEventEmitter<
|
|
921
|
-
implements
|
|
1102
|
+
export class IntervalCollection
|
|
1103
|
+
extends TypedEventEmitter<ISequenceIntervalCollectionEvents>
|
|
1104
|
+
implements ISequenceIntervalCollection
|
|
922
1105
|
{
|
|
923
|
-
private savedSerializedIntervals?:
|
|
924
|
-
private localCollection: LocalIntervalCollection
|
|
1106
|
+
private savedSerializedIntervals?: ISerializedIntervalCollectionV1;
|
|
1107
|
+
private localCollection: LocalIntervalCollection | undefined;
|
|
925
1108
|
private onDeserialize: DeserializeCallback | undefined;
|
|
926
1109
|
private client: Client | undefined;
|
|
927
1110
|
private readonly localSeqToSerializedInterval = new Map<
|
|
@@ -932,13 +1115,13 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
932
1115
|
number,
|
|
933
1116
|
ISerializedInterval | SerializedIntervalDelta
|
|
934
1117
|
>();
|
|
935
|
-
private readonly pendingChangesStart: Map<string,
|
|
1118
|
+
private readonly pendingChangesStart: Map<string, ISerializedIntervalCollectionV1> = new Map<
|
|
936
1119
|
string,
|
|
937
|
-
|
|
1120
|
+
ISerializedIntervalCollectionV1
|
|
938
1121
|
>();
|
|
939
|
-
private readonly pendingChangesEnd: Map<string,
|
|
1122
|
+
private readonly pendingChangesEnd: Map<string, ISerializedIntervalCollectionV1> = new Map<
|
|
940
1123
|
string,
|
|
941
|
-
|
|
1124
|
+
ISerializedIntervalCollectionV1
|
|
942
1125
|
>();
|
|
943
1126
|
|
|
944
1127
|
public get attached(): boolean {
|
|
@@ -946,10 +1129,11 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
946
1129
|
}
|
|
947
1130
|
|
|
948
1131
|
constructor(
|
|
949
|
-
private readonly
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
1132
|
+
private readonly submitDelta: (
|
|
1133
|
+
op: IIntervalCollectionTypeOperationValue,
|
|
1134
|
+
md: IMapMessageLocalMetadata,
|
|
1135
|
+
) => void,
|
|
1136
|
+
serializedIntervals: ISerializedIntervalCollectionV1 | ISerializedIntervalCollectionV2,
|
|
953
1137
|
private readonly options: Partial<SequenceOptions> = {},
|
|
954
1138
|
) {
|
|
955
1139
|
super();
|
|
@@ -964,7 +1148,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
964
1148
|
/**
|
|
965
1149
|
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
966
1150
|
*/
|
|
967
|
-
public attachIndex(index:
|
|
1151
|
+
public attachIndex(index: SequenceIntervalIndex): void {
|
|
968
1152
|
if (!this.attached) {
|
|
969
1153
|
throw new LoggingError("The local interval collection must exist");
|
|
970
1154
|
}
|
|
@@ -978,7 +1162,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
978
1162
|
/**
|
|
979
1163
|
* {@inheritdoc IIntervalCollection.detachIndex}
|
|
980
1164
|
*/
|
|
981
|
-
public detachIndex(index:
|
|
1165
|
+
public detachIndex(index: SequenceIntervalIndex): boolean {
|
|
982
1166
|
if (!this.attached) {
|
|
983
1167
|
throw new LoggingError("The local interval collection must exist");
|
|
984
1168
|
}
|
|
@@ -1068,7 +1252,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1068
1252
|
throw new LoggingError("Only supports one Sequence attach");
|
|
1069
1253
|
}
|
|
1070
1254
|
|
|
1071
|
-
if (client === undefined
|
|
1255
|
+
if (client === undefined) {
|
|
1072
1256
|
throw new LoggingError("Client required for this collection");
|
|
1073
1257
|
}
|
|
1074
1258
|
|
|
@@ -1082,10 +1266,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1082
1266
|
});
|
|
1083
1267
|
}
|
|
1084
1268
|
|
|
1085
|
-
this.localCollection = new LocalIntervalCollection
|
|
1269
|
+
this.localCollection = new LocalIntervalCollection(
|
|
1086
1270
|
client,
|
|
1087
1271
|
label,
|
|
1088
|
-
this.helpers,
|
|
1089
1272
|
this.options,
|
|
1090
1273
|
(interval, previousInterval) => this.emitChange(interval, previousInterval, true, true),
|
|
1091
1274
|
);
|
|
@@ -1108,7 +1291,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1108
1291
|
typeof endPos === "number" && endSide !== undefined
|
|
1109
1292
|
? { pos: endPos, side: endSide }
|
|
1110
1293
|
: endPos;
|
|
1111
|
-
const interval =
|
|
1294
|
+
const interval = createSequenceInterval(
|
|
1112
1295
|
label,
|
|
1113
1296
|
start,
|
|
1114
1297
|
end,
|
|
@@ -1139,8 +1322,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1139
1322
|
}
|
|
1140
1323
|
|
|
1141
1324
|
private emitChange(
|
|
1142
|
-
interval:
|
|
1143
|
-
previousInterval:
|
|
1325
|
+
interval: SequenceIntervalClass,
|
|
1326
|
+
previousInterval: SequenceIntervalClass,
|
|
1144
1327
|
local: boolean,
|
|
1145
1328
|
slide: boolean,
|
|
1146
1329
|
op?: ISequencedDocumentMessage,
|
|
@@ -1148,27 +1331,21 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1148
1331
|
// Temporarily make references transient so that positional queries work (non-transient refs
|
|
1149
1332
|
// on resolve to DetachedPosition on any segments that don't contain them). The original refType
|
|
1150
1333
|
// is restored as single-endpoint changes re-use previous references.
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
previousInterval.start.refType = startRefType;
|
|
1161
|
-
previousInterval.end.refType = endRefType;
|
|
1162
|
-
} else {
|
|
1163
|
-
this.emit("changeInterval", interval, previousInterval, local, op, slide);
|
|
1164
|
-
this.emit("changed", interval, undefined, previousInterval ?? undefined, local, slide);
|
|
1165
|
-
}
|
|
1334
|
+
|
|
1335
|
+
const startRefType = previousInterval.start.refType;
|
|
1336
|
+
const endRefType = previousInterval.end.refType;
|
|
1337
|
+
previousInterval.start.refType = ReferenceType.Transient;
|
|
1338
|
+
previousInterval.end.refType = ReferenceType.Transient;
|
|
1339
|
+
this.emit("changeInterval", interval, previousInterval, local, op, slide);
|
|
1340
|
+
this.emit("changed", interval, undefined, previousInterval ?? undefined, local, slide);
|
|
1341
|
+
previousInterval.start.refType = startRefType;
|
|
1342
|
+
previousInterval.end.refType = endRefType;
|
|
1166
1343
|
}
|
|
1167
1344
|
|
|
1168
1345
|
/**
|
|
1169
1346
|
* {@inheritdoc IIntervalCollection.getIntervalById}
|
|
1170
1347
|
*/
|
|
1171
|
-
public getIntervalById(id: string): ISerializableIntervalPrivate
|
|
1348
|
+
public getIntervalById(id: string): ISerializableIntervalPrivate | undefined {
|
|
1172
1349
|
if (!this.localCollection) {
|
|
1173
1350
|
throw new LoggingError("attach must be called before accessing intervals");
|
|
1174
1351
|
}
|
|
@@ -1197,7 +1374,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1197
1374
|
start: SequencePlace;
|
|
1198
1375
|
end: SequencePlace;
|
|
1199
1376
|
props?: PropertySet;
|
|
1200
|
-
}):
|
|
1377
|
+
}): SequenceIntervalClass {
|
|
1201
1378
|
if (!this.localCollection) {
|
|
1202
1379
|
throw new LoggingError("attach must be called prior to adding intervals");
|
|
1203
1380
|
}
|
|
@@ -1216,7 +1393,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1216
1393
|
|
|
1217
1394
|
this.assertStickinessEnabled(start, end);
|
|
1218
1395
|
|
|
1219
|
-
const interval:
|
|
1396
|
+
const interval: SequenceIntervalClass = this.localCollection.addInterval(
|
|
1220
1397
|
toSequencePlace(startPos, startSide),
|
|
1221
1398
|
toSequencePlace(endPos, endSide),
|
|
1222
1399
|
IntervalType.SlideOnRemove,
|
|
@@ -1224,7 +1401,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1224
1401
|
);
|
|
1225
1402
|
|
|
1226
1403
|
if (interval) {
|
|
1227
|
-
if (!this.isCollaborating
|
|
1404
|
+
if (!this.isCollaborating) {
|
|
1228
1405
|
setSlideOnRemove(interval.start);
|
|
1229
1406
|
setSlideOnRemove(interval.end);
|
|
1230
1407
|
}
|
|
@@ -1242,8 +1419,16 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1242
1419
|
if (this.isCollaborating) {
|
|
1243
1420
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
1244
1421
|
}
|
|
1245
|
-
|
|
1246
|
-
this.
|
|
1422
|
+
|
|
1423
|
+
this.submitDelta(
|
|
1424
|
+
{
|
|
1425
|
+
opName: "add",
|
|
1426
|
+
value: serializedInterval,
|
|
1427
|
+
},
|
|
1428
|
+
{
|
|
1429
|
+
localSeq,
|
|
1430
|
+
},
|
|
1431
|
+
);
|
|
1247
1432
|
}
|
|
1248
1433
|
|
|
1249
1434
|
this.emit("addInterval", interval, true, undefined);
|
|
@@ -1252,7 +1437,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1252
1437
|
}
|
|
1253
1438
|
|
|
1254
1439
|
private deleteExistingInterval(
|
|
1255
|
-
interval:
|
|
1440
|
+
interval: SequenceIntervalClass,
|
|
1256
1441
|
local: boolean,
|
|
1257
1442
|
op?: ISequencedDocumentMessage,
|
|
1258
1443
|
) {
|
|
@@ -1265,9 +1450,15 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1265
1450
|
if (interval) {
|
|
1266
1451
|
// Local ops get submitted to the server. Remote ops have the deserializer run.
|
|
1267
1452
|
if (local) {
|
|
1268
|
-
this.
|
|
1269
|
-
|
|
1270
|
-
|
|
1453
|
+
this.submitDelta(
|
|
1454
|
+
{
|
|
1455
|
+
opName: "delete",
|
|
1456
|
+
value: interval.serialize(),
|
|
1457
|
+
},
|
|
1458
|
+
{
|
|
1459
|
+
localSeq: this.getNextLocalSeq(),
|
|
1460
|
+
},
|
|
1461
|
+
);
|
|
1271
1462
|
} else {
|
|
1272
1463
|
if (this.onDeserialize) {
|
|
1273
1464
|
this.onDeserialize(interval);
|
|
@@ -1281,7 +1472,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1281
1472
|
/**
|
|
1282
1473
|
* {@inheritdoc IIntervalCollection.removeIntervalById}
|
|
1283
1474
|
*/
|
|
1284
|
-
public removeIntervalById(id: string):
|
|
1475
|
+
public removeIntervalById(id: string): SequenceIntervalClass | undefined {
|
|
1285
1476
|
if (!this.localCollection) {
|
|
1286
1477
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
1287
1478
|
}
|
|
@@ -1297,7 +1488,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1297
1488
|
public change(
|
|
1298
1489
|
id: string,
|
|
1299
1490
|
{ start, end, props }: { start?: SequencePlace; end?: SequencePlace; props?: PropertySet },
|
|
1300
|
-
):
|
|
1491
|
+
): SequenceIntervalClass | undefined {
|
|
1301
1492
|
if (!this.localCollection) {
|
|
1302
1493
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
1303
1494
|
}
|
|
@@ -1325,7 +1516,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1325
1516
|
const interval = this.getIntervalById(id);
|
|
1326
1517
|
if (interval) {
|
|
1327
1518
|
let deltaProps: PropertySet | undefined;
|
|
1328
|
-
let newInterval:
|
|
1519
|
+
let newInterval: SequenceIntervalClass | undefined;
|
|
1329
1520
|
if (props !== undefined) {
|
|
1330
1521
|
interval.propertyManager ??= new PropertiesManager();
|
|
1331
1522
|
deltaProps = interval.propertyManager.handleProperties(
|
|
@@ -1338,7 +1529,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1338
1529
|
}
|
|
1339
1530
|
if (start !== undefined && end !== undefined) {
|
|
1340
1531
|
newInterval = this.localCollection.changeInterval(interval, start, end);
|
|
1341
|
-
if (!this.isCollaborating && newInterval
|
|
1532
|
+
if (!this.isCollaborating && newInterval !== undefined) {
|
|
1342
1533
|
setSlideOnRemove(newInterval.start);
|
|
1343
1534
|
setSlideOnRemove(newInterval.end);
|
|
1344
1535
|
}
|
|
@@ -1361,7 +1552,15 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1361
1552
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
1362
1553
|
}
|
|
1363
1554
|
|
|
1364
|
-
this.
|
|
1555
|
+
this.submitDelta(
|
|
1556
|
+
{
|
|
1557
|
+
opName: "change",
|
|
1558
|
+
value: serializedInterval,
|
|
1559
|
+
},
|
|
1560
|
+
{
|
|
1561
|
+
localSeq,
|
|
1562
|
+
},
|
|
1563
|
+
);
|
|
1365
1564
|
if (deltaProps !== undefined) {
|
|
1366
1565
|
this.emit("propertyChanged", interval, deltaProps, true, undefined);
|
|
1367
1566
|
this.emit(
|
|
@@ -1376,10 +1575,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1376
1575
|
if (newInterval) {
|
|
1377
1576
|
this.addPendingChange(id, serializedInterval);
|
|
1378
1577
|
this.emitChange(newInterval, interval, true, false);
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
this.client?.removeLocalReferencePosition(interval.end);
|
|
1382
|
-
}
|
|
1578
|
+
this.client?.removeLocalReferencePosition(interval.start);
|
|
1579
|
+
this.client?.removeLocalReferencePosition(interval.end);
|
|
1383
1580
|
}
|
|
1384
1581
|
return newInterval;
|
|
1385
1582
|
}
|
|
@@ -1482,8 +1679,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1482
1679
|
// strip it out of the properties here.
|
|
1483
1680
|
const { [reservedIntervalIdKey]: id, ...newProps } = serializedInterval.properties ?? {};
|
|
1484
1681
|
assert(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1485
|
-
const interval: ISerializableIntervalPrivate
|
|
1486
|
-
this.getIntervalById(id);
|
|
1682
|
+
const interval: ISerializableIntervalPrivate | undefined = this.getIntervalById(id);
|
|
1487
1683
|
if (!interval) {
|
|
1488
1684
|
// The interval has been removed locally; no-op.
|
|
1489
1685
|
return;
|
|
@@ -1623,11 +1819,6 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1623
1819
|
}
|
|
1624
1820
|
|
|
1625
1821
|
if (localInterval !== undefined) {
|
|
1626
|
-
// we know we must be using `SequenceInterval` because `this.client` exists
|
|
1627
|
-
assert(
|
|
1628
|
-
localInterval instanceof SequenceIntervalClass,
|
|
1629
|
-
0x3a0 /* localInterval must be `SequenceInterval` when used with client */,
|
|
1630
|
-
);
|
|
1631
1822
|
// The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
|
|
1632
1823
|
// updates the local client's state to be consistent with the emitted op.
|
|
1633
1824
|
this.localCollection?.changeInterval(
|
|
@@ -1668,12 +1859,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1668
1859
|
return value;
|
|
1669
1860
|
}
|
|
1670
1861
|
|
|
1671
|
-
private ackInterval(interval:
|
|
1672
|
-
// Only SequenceIntervals need potential sliding
|
|
1673
|
-
if (!(interval instanceof SequenceIntervalClass)) {
|
|
1674
|
-
return;
|
|
1675
|
-
}
|
|
1676
|
-
|
|
1862
|
+
private ackInterval(interval: SequenceIntervalClass, op: ISequencedDocumentMessage): void {
|
|
1677
1863
|
if (
|
|
1678
1864
|
!refTypeIncludesFlag(interval.start, ReferenceType.StayOnRemove) &&
|
|
1679
1865
|
!refTypeIncludesFlag(interval.end, ReferenceType.StayOnRemove)
|
|
@@ -1711,7 +1897,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1711
1897
|
}
|
|
1712
1898
|
|
|
1713
1899
|
// `interval`'s endpoints will get modified in-place, so clone it prior to doing so for event emission.
|
|
1714
|
-
const oldInterval = interval.clone()
|
|
1900
|
+
const oldInterval = interval.clone();
|
|
1715
1901
|
|
|
1716
1902
|
// In this case, where we change the start or end of an interval,
|
|
1717
1903
|
// it is necessary to remove and re-add the interval listeners.
|
|
@@ -1764,7 +1950,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1764
1950
|
oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
|
|
1765
1951
|
}
|
|
1766
1952
|
this.localCollection.add(interval);
|
|
1767
|
-
this.emitChange(interval, oldInterval
|
|
1953
|
+
this.emitChange(interval, oldInterval, true, true, op);
|
|
1768
1954
|
}
|
|
1769
1955
|
}
|
|
1770
1956
|
|
|
@@ -1794,7 +1980,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1794
1980
|
|
|
1795
1981
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
1796
1982
|
|
|
1797
|
-
const interval:
|
|
1983
|
+
const interval: SequenceIntervalClass = this.localCollection.addInterval(
|
|
1798
1984
|
toSequencePlace(serializedInterval.start, serializedInterval.startSide ?? Side.Before),
|
|
1799
1985
|
toSequencePlace(serializedInterval.end, serializedInterval.endSide ?? Side.Before),
|
|
1800
1986
|
serializedInterval.intervalType,
|
|
@@ -1836,19 +2022,21 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1836
2022
|
}
|
|
1837
2023
|
}
|
|
1838
2024
|
|
|
1839
|
-
public serializeInternal(
|
|
2025
|
+
public serializeInternal(
|
|
2026
|
+
version: "1" | "2",
|
|
2027
|
+
): ISerializedIntervalCollectionV1 | ISerializedIntervalCollectionV2 {
|
|
1840
2028
|
if (!this.localCollection) {
|
|
1841
2029
|
throw new LoggingError("attachSequence must be called");
|
|
1842
2030
|
}
|
|
1843
2031
|
|
|
1844
|
-
return this.localCollection.serialize();
|
|
2032
|
+
return this.localCollection.serialize(version);
|
|
1845
2033
|
}
|
|
1846
2034
|
|
|
1847
2035
|
/**
|
|
1848
2036
|
* @returns an iterator over all intervals in this collection.
|
|
1849
2037
|
*/
|
|
1850
|
-
public [Symbol.iterator](): IntervalCollectionIterator
|
|
1851
|
-
const iterator = new IntervalCollectionIterator
|
|
2038
|
+
public [Symbol.iterator](): IntervalCollectionIterator {
|
|
2039
|
+
const iterator = new IntervalCollectionIterator(this);
|
|
1852
2040
|
return iterator;
|
|
1853
2041
|
}
|
|
1854
2042
|
|
|
@@ -1857,8 +2045,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1857
2045
|
*/
|
|
1858
2046
|
public CreateForwardIteratorWithStartPosition(
|
|
1859
2047
|
startPosition: number,
|
|
1860
|
-
): IntervalCollectionIterator
|
|
1861
|
-
const iterator = new IntervalCollectionIterator
|
|
2048
|
+
): IntervalCollectionIterator {
|
|
2049
|
+
const iterator = new IntervalCollectionIterator(this, true, startPosition);
|
|
1862
2050
|
return iterator;
|
|
1863
2051
|
}
|
|
1864
2052
|
|
|
@@ -1867,8 +2055,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1867
2055
|
*/
|
|
1868
2056
|
public CreateBackwardIteratorWithStartPosition(
|
|
1869
2057
|
startPosition: number,
|
|
1870
|
-
): IntervalCollectionIterator
|
|
1871
|
-
const iterator = new IntervalCollectionIterator
|
|
2058
|
+
): IntervalCollectionIterator {
|
|
2059
|
+
const iterator = new IntervalCollectionIterator(this, false, startPosition);
|
|
1872
2060
|
return iterator;
|
|
1873
2061
|
}
|
|
1874
2062
|
|
|
@@ -1877,13 +2065,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1877
2065
|
*/
|
|
1878
2066
|
public CreateForwardIteratorWithEndPosition(
|
|
1879
2067
|
endPosition: number,
|
|
1880
|
-
): IntervalCollectionIterator
|
|
1881
|
-
const iterator = new IntervalCollectionIterator
|
|
1882
|
-
this,
|
|
1883
|
-
true,
|
|
1884
|
-
undefined,
|
|
1885
|
-
endPosition,
|
|
1886
|
-
);
|
|
2068
|
+
): IntervalCollectionIterator {
|
|
2069
|
+
const iterator = new IntervalCollectionIterator(this, true, undefined, endPosition);
|
|
1887
2070
|
return iterator;
|
|
1888
2071
|
}
|
|
1889
2072
|
|
|
@@ -1892,13 +2075,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1892
2075
|
*/
|
|
1893
2076
|
public CreateBackwardIteratorWithEndPosition(
|
|
1894
2077
|
endPosition: number,
|
|
1895
|
-
): IntervalCollectionIterator
|
|
1896
|
-
const iterator = new IntervalCollectionIterator
|
|
1897
|
-
this,
|
|
1898
|
-
false,
|
|
1899
|
-
undefined,
|
|
1900
|
-
endPosition,
|
|
1901
|
-
);
|
|
2078
|
+
): IntervalCollectionIterator {
|
|
2079
|
+
const iterator = new IntervalCollectionIterator(this, false, undefined, endPosition);
|
|
1902
2080
|
return iterator;
|
|
1903
2081
|
}
|
|
1904
2082
|
|
|
@@ -1906,7 +2084,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1906
2084
|
* {@inheritdoc IIntervalCollection.gatherIterationResults}
|
|
1907
2085
|
*/
|
|
1908
2086
|
public gatherIterationResults(
|
|
1909
|
-
results:
|
|
2087
|
+
results: SequenceIntervalClass[],
|
|
1910
2088
|
iteratesForward: boolean,
|
|
1911
2089
|
start?: number,
|
|
1912
2090
|
end?: number,
|
|
@@ -1926,7 +2104,10 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1926
2104
|
/**
|
|
1927
2105
|
* {@inheritdoc IIntervalCollection.findOverlappingIntervals}
|
|
1928
2106
|
*/
|
|
1929
|
-
public findOverlappingIntervals(
|
|
2107
|
+
public findOverlappingIntervals(
|
|
2108
|
+
startPosition: number,
|
|
2109
|
+
endPosition: number,
|
|
2110
|
+
): SequenceInterval[] {
|
|
1930
2111
|
if (!this.localCollection) {
|
|
1931
2112
|
throw new LoggingError("attachSequence must be called");
|
|
1932
2113
|
}
|
|
@@ -1940,7 +2121,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1940
2121
|
/**
|
|
1941
2122
|
* {@inheritdoc IIntervalCollection.map}
|
|
1942
2123
|
*/
|
|
1943
|
-
public map(fn: (interval:
|
|
2124
|
+
public map(fn: (interval: SequenceIntervalClass) => void) {
|
|
1944
2125
|
if (!this.localCollection) {
|
|
1945
2126
|
throw new LoggingError("attachSequence must be called");
|
|
1946
2127
|
}
|
|
@@ -1953,7 +2134,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1953
2134
|
/**
|
|
1954
2135
|
* {@inheritdoc IIntervalCollection.previousInterval}
|
|
1955
2136
|
*/
|
|
1956
|
-
public previousInterval(pos: number):
|
|
2137
|
+
public previousInterval(pos: number): SequenceInterval | undefined {
|
|
1957
2138
|
if (!this.localCollection) {
|
|
1958
2139
|
throw new LoggingError("attachSequence must be called");
|
|
1959
2140
|
}
|
|
@@ -1964,7 +2145,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
|
|
|
1964
2145
|
/**
|
|
1965
2146
|
* {@inheritdoc IIntervalCollection.nextInterval}
|
|
1966
2147
|
*/
|
|
1967
|
-
public nextInterval(pos: number):
|
|
2148
|
+
public nextInterval(pos: number): SequenceInterval | undefined {
|
|
1968
2149
|
if (!this.localCollection) {
|
|
1969
2150
|
throw new LoggingError("attachSequence must be called");
|
|
1970
2151
|
}
|
|
@@ -1992,7 +2173,7 @@ export interface IntervalLocator {
|
|
|
1992
2173
|
/**
|
|
1993
2174
|
* Interval within that collection
|
|
1994
2175
|
*/
|
|
1995
|
-
interval:
|
|
2176
|
+
interval: SequenceIntervalClass;
|
|
1996
2177
|
}
|
|
1997
2178
|
|
|
1998
2179
|
/**
|