@textbus/collaborate 4.0.4 → 4.1.0-alpha.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/bundles/index.js CHANGED
@@ -114,6 +114,36 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
114
114
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
115
115
  };
116
116
 
117
+ const subModelLoaderErrorFn = core.makeError('subModelLoaderError');
118
+ /**
119
+ * 子文档加载器
120
+ */
121
+ class SubModelLoader {
122
+ }
123
+ exports.NonSubModelLoader = class NonSubModelLoader extends SubModelLoader {
124
+ createSubModelBySlot() {
125
+ throw subModelLoaderErrorFn('single document does not support async slot.');
126
+ }
127
+ createSubModelByComponent() {
128
+ throw subModelLoaderErrorFn('single document does not support async component.');
129
+ }
130
+ loadSubModelByComponent() {
131
+ throw subModelLoaderErrorFn('single document does not support async component.');
132
+ }
133
+ loadSubModelBySlot() {
134
+ throw subModelLoaderErrorFn('single document does not support async slot.');
135
+ }
136
+ getLoadedModelBySlot() {
137
+ throw subModelLoaderErrorFn('single document does not support async slot.');
138
+ }
139
+ getLoadedModelByComponent() {
140
+ throw subModelLoaderErrorFn('single document does not support async component.');
141
+ }
142
+ };
143
+ exports.NonSubModelLoader = __decorate([
144
+ core$1.Injectable()
145
+ ], exports.NonSubModelLoader);
146
+
117
147
  const collaborateErrorFn = core.makeError('Collaborate');
118
148
  class SlotMap {
119
149
  constructor() {
@@ -153,112 +183,41 @@ class SlotMap {
153
183
  }
154
184
  }
155
185
  }
156
- class CustomUndoManagerConfig {
157
- }
158
186
  exports.Collaborate = class Collaborate {
159
- get canBack() {
160
- var _a;
161
- return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canUndo()) || false;
162
- }
163
- get canForward() {
164
- var _a;
165
- return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canRedo()) || false;
166
- }
167
- constructor(stackSize, rootComponentRef, scheduler, registry, selection, undoManagerConfig) {
168
- this.stackSize = stackSize;
169
- this.rootComponentRef = rootComponentRef;
187
+ constructor(scheduler, registry, selection, subModelLoader) {
170
188
  this.scheduler = scheduler;
171
189
  this.registry = registry;
172
190
  this.selection = selection;
173
- this.undoManagerConfig = undoManagerConfig;
191
+ this.subModelLoader = subModelLoader;
174
192
  this.yDoc = new yjs.Doc();
175
- this.backEvent = new stream.Subject();
176
- this.forwardEvent = new stream.Subject();
177
- this.changeEvent = new stream.Subject();
178
- this.pushEvent = new stream.Subject();
179
- this.manager = null;
193
+ this.slotMap = new SlotMap();
180
194
  this.subscriptions = [];
181
195
  this.updateFromRemote = false;
182
- this.localChangesAppliedEvent = new stream.Subject();
183
- this.selectionChangeEvent = new stream.Subject();
184
- this.slotMap = new SlotMap();
185
- this.updateRemoteActions = [];
196
+ this.addSubModelEvent = new stream.Subject();
197
+ this.updateRemoteActions = new WeakMap();
186
198
  this.noRecord = {};
187
- this.historyItems = [];
188
- this.index = 0;
189
- this.onBack = this.backEvent.asObservable();
190
- this.onForward = this.forwardEvent.asObservable();
191
- this.onChange = this.changeEvent.asObservable();
192
- this.onPush = this.pushEvent.asObservable();
193
- this.onLocalChangesApplied = this.localChangesAppliedEvent.asObservable();
199
+ this.onAddSubModel = this.addSubModelEvent.asObservable();
194
200
  }
195
- listen() {
196
- const root = this.yDoc.getMap('RootComponent');
197
- const rootComponent = this.rootComponentRef.component;
198
- const undoManagerConfig = this.undoManagerConfig || {};
199
- const manager = new yjs.UndoManager(root, {
200
- trackedOrigins: new Set([this.yDoc]),
201
- captureTransaction(arg) {
202
- if (undoManagerConfig.captureTransaction) {
203
- return undoManagerConfig.captureTransaction(arg);
204
- }
205
- return true;
206
- },
207
- deleteFilter(item) {
208
- if (undoManagerConfig.deleteFilter) {
209
- return undoManagerConfig.deleteFilter(item);
210
- }
211
- return true;
212
- }
213
- });
214
- this.manager = manager;
215
- let beforePosition = null;
216
- this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
217
- beforePosition = this.getRelativeCursorLocation();
218
- }));
219
- manager.on('stack-item-added', (event) => {
220
- if (event.type === 'undo') {
221
- if (event.origin === manager) {
222
- this.index++;
223
- }
224
- else {
225
- this.historyItems.length = this.index;
226
- this.historyItems.push({
227
- before: beforePosition,
228
- after: this.getRelativeCursorLocation()
229
- });
230
- this.index++;
231
- }
232
- }
233
- else {
234
- this.index--;
235
- }
236
- if (manager.undoStack.length > this.stackSize) {
237
- this.historyItems.shift();
238
- manager.undoStack.shift();
239
- }
240
- if (event.origin === this.yDoc) {
241
- this.pushEvent.next();
242
- }
243
- this.changeEvent.next();
244
- });
245
- manager.on('stack-item-popped', (ev) => {
246
- const index = ev.type === 'undo' ? this.index : this.index - 1;
247
- const position = this.historyItems[index] || null;
248
- const p = ev.type === 'undo' ? position === null || position === void 0 ? void 0 : position.before : position === null || position === void 0 ? void 0 : position.after;
249
- if (p) {
250
- const selection = this.getAbstractSelection(p);
251
- if (selection) {
252
- this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
253
- return;
254
- }
255
- }
256
- this.selection.unSelect();
257
- });
258
- this.subscriptions.push(this.selection.onChange.subscribe(() => {
259
- const paths = this.selection.getPaths();
260
- this.selectionChangeEvent.next(paths);
261
- }), this.scheduler.onDocChanged.pipe(stream.map(item => {
201
+ syncRootComponent(yDoc, sharedComponent, localComponent) {
202
+ this.initSyncEvent(yDoc);
203
+ this.syncComponent(yDoc, sharedComponent, localComponent);
204
+ }
205
+ syncRootSlot(yDoc, sharedSlot, localSlot) {
206
+ if (sharedSlot.length) {
207
+ localSlot.retain(0);
208
+ localSlot.delete(localSlot.length);
209
+ localSlot.cleanAttributes();
210
+ localSlot.cleanFormats();
211
+ this.initLocalSlotBySharedSlot(sharedSlot, localSlot);
212
+ }
213
+ else {
214
+ this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
215
+ }
216
+ this.initSyncEvent(yDoc);
217
+ this.syncSlot(sharedSlot, localSlot);
218
+ }
219
+ initSyncEvent(yDoc) {
220
+ this.subscriptions.push(this.scheduler.onDocChanged.pipe(stream.map(item => {
262
221
  return item.filter(i => {
263
222
  return i.from !== core.ChangeOrigin.Remote;
264
223
  });
@@ -267,7 +226,8 @@ exports.Collaborate = class Collaborate {
267
226
  })).subscribe(() => {
268
227
  const updates = [];
269
228
  let update = null;
270
- for (const item of this.updateRemoteActions) {
229
+ const updateRemoteActions = this.updateRemoteActions.get(yDoc) || [];
230
+ for (const item of updateRemoteActions) {
271
231
  if (!update) {
272
232
  update = {
273
233
  record: item.record,
@@ -286,240 +246,54 @@ exports.Collaborate = class Collaborate {
286
246
  updates.push(update);
287
247
  }
288
248
  }
289
- this.updateRemoteActions = [];
249
+ this.updateRemoteActions.delete(yDoc);
290
250
  for (const item of updates) {
291
- this.yDoc.transact(() => {
251
+ yDoc.transact(() => {
292
252
  item.actions.forEach(fn => {
293
253
  fn();
294
254
  });
295
- }, item.record ? this.yDoc : this.noRecord);
255
+ }, item.record ? yDoc : this.noRecord);
296
256
  }
297
- this.localChangesAppliedEvent.next();
298
257
  }));
299
- this.syncRootComponent(root, rootComponent);
300
- }
301
- back() {
302
- var _a;
303
- if (this.canBack) {
304
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.undo();
305
- this.backEvent.next();
306
- }
307
- }
308
- forward() {
309
- var _a;
310
- if (this.canForward) {
311
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.redo();
312
- this.forwardEvent.next();
313
- }
314
- }
315
- clear() {
316
- var _a;
317
- const last = this.historyItems.pop();
318
- this.historyItems = last ? [last] : [];
319
- this.index = last ? 1 : 0;
320
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
321
- this.changeEvent.next();
322
- }
323
- destroy() {
324
- var _a;
325
- this.index = 0;
326
- this.historyItems = [];
327
- this.subscriptions.forEach(i => i.unsubscribe());
328
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
329
258
  }
330
- syncRootComponent(root, rootComponent) {
331
- let state = root.get('state');
259
+ syncComponent(yDoc, sharedComponent, localComponent) {
260
+ let state = sharedComponent.get('state');
332
261
  if (!state) {
333
262
  state = new yjs.Map();
334
- this.syncLocalMapToSharedMap(rootComponent.state, state);
335
- this.yDoc.transact(() => {
336
- root.set('state', state);
263
+ this.syncLocalMapToSharedMap(localComponent.state, state);
264
+ yDoc.transact(() => {
265
+ sharedComponent.set('state', state);
337
266
  });
338
267
  }
339
268
  else {
340
- Object.keys(rootComponent.state).forEach(key => {
341
- Reflect.deleteProperty(rootComponent.state, key);
269
+ Object.keys(localComponent.state).forEach(key => {
270
+ Reflect.deleteProperty(localComponent.state, key);
342
271
  });
343
- this.syncSharedMapToLocalMap(state, rootComponent.state);
272
+ this.syncSharedMapToLocalMap(state, localComponent.state);
344
273
  }
345
274
  }
346
- syncSharedMapToLocalMap(sharedMap, localMap) {
347
- sharedMap.forEach((value, key) => {
348
- localMap[key] = this.createLocalModelBySharedByModel(value);
349
- });
350
- this.syncObject(sharedMap, localMap);
351
- }
352
- createLocalMapBySharedMap(sharedMap) {
353
- const localMap = core.createObjectProxy({});
354
- this.syncSharedMapToLocalMap(sharedMap, localMap);
355
- return localMap;
356
- }
357
- createLocalArrayBySharedArray(sharedArray) {
358
- const localArray = core.createArrayProxy([]);
359
- localArray.push(...sharedArray.map(item => this.createLocalModelBySharedByModel(item)));
360
- this.syncArray(sharedArray, localArray);
361
- return localArray;
362
- }
363
- syncLocalMapToSharedMap(localMap, sharedMap) {
364
- Object.entries(localMap).forEach(([key, value]) => {
365
- sharedMap.set(key, this.createSharedModelByLocalModel(value));
366
- });
367
- this.syncObject(sharedMap, localMap);
368
- }
369
- createSharedMapByLocalMap(localMap) {
370
- const sharedMap = new yjs.Map();
371
- this.syncLocalMapToSharedMap(localMap, sharedMap);
372
- return sharedMap;
373
- }
374
- createSharedArrayByLocalArray(localArray) {
375
- const sharedArray = new yjs.Array();
376
- localArray.forEach(value => {
377
- sharedArray.push([this.createSharedModelByLocalModel(value)]);
378
- });
379
- this.syncArray(sharedArray, localArray);
380
- return sharedArray;
381
- }
382
- createSharedSlotByLocalSlot(localSlot) {
383
- const sharedSlot = new yjs.Text();
384
- sharedSlot.setAttribute('__schema__', [...localSlot.schema]);
385
- let offset = 0;
386
- localSlot.toDelta().forEach(i => {
387
- let formats = {};
388
- if (i.formats) {
389
- i.formats.forEach(item => {
390
- formats[item[0].name] = item[1];
391
- });
392
- }
393
- else {
394
- formats = null;
395
- }
396
- if (typeof i.insert === 'string') {
397
- sharedSlot.insert(offset, i.insert, formats);
398
- }
399
- else {
400
- const sharedComponent = this.createSharedComponentByLocalComponent(i.insert);
401
- sharedSlot.insertEmbed(offset, sharedComponent, formats);
402
- }
403
- offset += i.insert.length;
404
- });
405
- localSlot.getAttributes().forEach(item => {
406
- sharedSlot.setAttribute(item[0].name, item[1]);
407
- });
408
- this.syncSlot(sharedSlot, localSlot);
409
- return sharedSlot;
410
- }
411
- createLocalSlotBySharedSlot(sharedSlot) {
412
- const delta = sharedSlot.toDelta();
413
- const localSlot = new core.Slot(sharedSlot.getAttribute('__schema__') || []); // TODO 这里有潜在的问题
414
- const attrs = sharedSlot.getAttributes();
415
- Object.keys(attrs).forEach(key => {
416
- const attribute = this.registry.getAttribute(key);
417
- if (attribute) {
418
- localSlot.setAttribute(attribute, attrs[key]);
419
- }
420
- });
421
- for (const action of delta) {
422
- if (action.insert) {
423
- if (typeof action.insert === 'string') {
424
- const formats = remoteFormatsToLocal(this.registry, action.attributes);
425
- localSlot.insert(action.insert, formats);
426
- }
427
- else {
428
- const sharedComponent = action.insert;
429
- const component = this.createLocalComponentBySharedComponent(sharedComponent);
430
- localSlot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
431
- }
432
- }
433
- else {
434
- throw collaborateErrorFn('unexpected delta action.');
435
- }
436
- }
437
- this.syncSlot(sharedSlot, localSlot);
438
- return localSlot;
439
- }
440
- createSharedModelByLocalModel(localModel) {
441
- if (localModel instanceof core.Slot) {
442
- return this.createSharedSlotByLocalSlot(localModel);
443
- }
444
- if (Array.isArray(localModel)) {
445
- return this.createSharedArrayByLocalArray(localModel);
446
- }
447
- if (typeof localModel === 'object' && localModel !== null) {
448
- return this.createSharedMapByLocalMap(localModel);
449
- }
450
- return localModel;
451
- }
452
- createLocalModelBySharedByModel(sharedModel) {
453
- if (sharedModel instanceof yjs.Map) {
454
- return this.createLocalMapBySharedMap(sharedModel);
455
- }
456
- if (sharedModel instanceof yjs.Array) {
457
- return this.createLocalArrayBySharedArray(sharedModel);
458
- }
459
- if (sharedModel instanceof yjs.Text) {
460
- return this.createLocalSlotBySharedSlot(sharedModel);
461
- }
462
- return sharedModel;
463
- }
464
- getAbstractSelection(position) {
465
- const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
466
- const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
467
- if (anchorPosition && focusPosition) {
468
- const focusSlot = this.slotMap.get(focusPosition.type);
469
- const anchorSlot = this.slotMap.get(anchorPosition.type);
470
- if (focusSlot && anchorSlot) {
471
- return {
472
- anchorSlot,
473
- anchorOffset: anchorPosition.index,
474
- focusSlot,
475
- focusOffset: focusPosition.index
476
- };
477
- }
478
- }
479
- return null;
480
- }
481
- getRelativeCursorLocation() {
482
- const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
483
- if (anchorSlot) {
484
- const anchorYText = this.slotMap.get(anchorSlot);
485
- if (anchorYText) {
486
- const anchorPosition = yjs.createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
487
- if (focusSlot) {
488
- const focusYText = this.slotMap.get(focusSlot);
489
- if (focusYText) {
490
- const focusPosition = yjs.createRelativePositionFromTypeIndex(focusYText, focusOffset);
491
- return {
492
- focus: focusPosition,
493
- anchor: anchorPosition
494
- };
495
- }
496
- }
497
- }
498
- }
499
- return null;
500
- }
501
- syncSlot(sharedSlot, localSlot) {
502
- const syncRemote = (ev, tr) => {
503
- this.runRemoteUpdate(tr, () => {
504
- localSlot.retain(0);
505
- ev.keysChanged.forEach(key => {
506
- const change = ev.keys.get(key);
507
- if (!change) {
508
- return;
509
- }
510
- const updateType = change.action;
511
- if (updateType === 'update' || updateType === 'add') {
512
- const attribute = this.registry.getAttribute(key);
513
- if (attribute) {
514
- localSlot.setAttribute(attribute, sharedSlot.getAttribute(key));
515
- }
516
- }
517
- else if (updateType === 'delete') {
518
- const attribute = this.registry.getAttribute(key);
519
- if (attribute) {
520
- localSlot.removeAttribute(attribute);
521
- }
522
- }
275
+ syncSlot(sharedSlot, localSlot) {
276
+ const syncRemote = (ev, tr) => {
277
+ this.runRemoteUpdate(tr, () => {
278
+ localSlot.retain(0);
279
+ ev.keysChanged.forEach(key => {
280
+ const change = ev.keys.get(key);
281
+ if (!change) {
282
+ return;
283
+ }
284
+ const updateType = change.action;
285
+ if (updateType === 'update' || updateType === 'add') {
286
+ const attribute = this.registry.getAttribute(key);
287
+ if (attribute) {
288
+ localSlot.setAttribute(attribute, sharedSlot.getAttribute(key));
289
+ }
290
+ }
291
+ else if (updateType === 'delete') {
292
+ const attribute = this.registry.getAttribute(key);
293
+ if (attribute) {
294
+ localSlot.removeAttribute(attribute);
295
+ }
296
+ }
523
297
  });
524
298
  ev.delta.forEach(action => {
525
299
  if (Reflect.has(action, 'retain')) {
@@ -546,7 +320,7 @@ exports.Collaborate = class Collaborate {
546
320
  const component = this.createLocalComponentBySharedComponent(sharedComponent);
547
321
  localSlot.insert(component);
548
322
  }
549
- if (this.selection.isSelected && tr.origin !== this.manager) {
323
+ if (this.selection.isSelected && !(tr.origin instanceof yjs.UndoManager)) {
550
324
  if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
551
325
  this.selection.setAnchor(localSlot, this.selection.anchorOffset + length);
552
326
  }
@@ -558,7 +332,7 @@ exports.Collaborate = class Collaborate {
558
332
  else if (action.delete) {
559
333
  const index = localSlot.index;
560
334
  localSlot.delete(action.delete);
561
- if (this.selection.isSelected && tr.origin !== this.manager) {
335
+ if (this.selection.isSelected && !(tr.origin instanceof yjs.UndoManager)) {
562
336
  if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
563
337
  this.selection.setAnchor(localSlot, this.selection.startOffset - action.delete);
564
338
  }
@@ -572,7 +346,7 @@ exports.Collaborate = class Collaborate {
572
346
  };
573
347
  sharedSlot.observe(syncRemote);
574
348
  const sub = localSlot.onContentChange.subscribe(actions => {
575
- this.runLocalUpdate(() => {
349
+ this.runLocalUpdate(sharedSlot.doc, true, () => {
576
350
  var _a;
577
351
  let offset = 0;
578
352
  let length = 0;
@@ -630,7 +404,7 @@ exports.Collaborate = class Collaborate {
630
404
  sharedSlot.removeAttribute(action.name);
631
405
  }
632
406
  }
633
- }, true);
407
+ });
634
408
  });
635
409
  this.slotMap.set(localSlot, sharedSlot);
636
410
  localSlot.__changeMarker__.destroyCallbacks.push(() => {
@@ -639,18 +413,279 @@ exports.Collaborate = class Collaborate {
639
413
  sub.unsubscribe();
640
414
  });
641
415
  }
416
+ destroy() {
417
+ this.subscriptions.forEach(i => i.unsubscribe());
418
+ }
419
+ syncSharedMapToLocalMap(sharedMap, localMap) {
420
+ sharedMap.forEach((value, key) => {
421
+ localMap[key] = this.createLocalModelBySharedByModel(value);
422
+ });
423
+ this.syncObject(sharedMap, localMap);
424
+ }
425
+ createLocalMapBySharedMap(sharedMap) {
426
+ const localMap = core.createObjectProxy({});
427
+ this.syncSharedMapToLocalMap(sharedMap, localMap);
428
+ return localMap;
429
+ }
430
+ createLocalArrayBySharedArray(sharedArray) {
431
+ const localArray = core.createArrayProxy([]);
432
+ localArray.push(...sharedArray.map(item => this.createLocalModelBySharedByModel(item)));
433
+ this.syncArray(sharedArray, localArray);
434
+ return localArray;
435
+ }
436
+ syncLocalMapToSharedMap(localMap, sharedMap) {
437
+ Object.entries(localMap).forEach(([key, value]) => {
438
+ sharedMap.set(key, this.createSharedModelByLocalModel(value));
439
+ });
440
+ this.syncObject(sharedMap, localMap);
441
+ }
442
+ createSharedMapByLocalMap(localMap) {
443
+ const sharedMap = new yjs.Map();
444
+ this.syncLocalMapToSharedMap(localMap, sharedMap);
445
+ return sharedMap;
446
+ }
447
+ createSharedArrayByLocalArray(localArray) {
448
+ const sharedArray = new yjs.Array();
449
+ localArray.forEach(value => {
450
+ sharedArray.push([this.createSharedModelByLocalModel(value)]);
451
+ });
452
+ this.syncArray(sharedArray, localArray);
453
+ return sharedArray;
454
+ }
455
+ createSharedSlotByLocalSlot(localSlot) {
456
+ const sharedSlot = new yjs.Text();
457
+ const isAsyncSlot = localSlot instanceof core.AsyncSlot;
458
+ sharedSlot.setAttribute('schema', [...localSlot.schema]);
459
+ sharedSlot.setAttribute('type', isAsyncSlot ? 'async' : 'sync');
460
+ if (isAsyncSlot) {
461
+ let isDestroyed = false;
462
+ sharedSlot.setAttribute('metadata', localSlot.metadata);
463
+ this.subModelLoader.createSubModelBySlot(localSlot).then(subDocument => {
464
+ if (isDestroyed) {
465
+ return;
466
+ }
467
+ const content = subDocument.getText('content');
468
+ this.initSharedSlotByLocalSlot(content, localSlot);
469
+ this.syncSlot(content, localSlot);
470
+ this.addSubModelEvent.next({
471
+ yDoc: subDocument,
472
+ yType: content
473
+ });
474
+ localSlot.loader.markAsLoaded();
475
+ });
476
+ localSlot.__changeMarker__.destroyCallbacks.push(() => {
477
+ isDestroyed = true;
478
+ });
479
+ return sharedSlot;
480
+ }
481
+ const sharedContent = new yjs.Text();
482
+ this.initSharedSlotByLocalSlot(sharedContent, localSlot);
483
+ sharedSlot.insertEmbed(0, sharedContent);
484
+ this.syncSlot(sharedContent, localSlot);
485
+ return sharedSlot;
486
+ }
487
+ initSharedSlotByLocalSlot(sharedContent, localSlot) {
488
+ let offset = 0;
489
+ localSlot.toDelta().forEach(i => {
490
+ let formats = {};
491
+ if (i.formats) {
492
+ i.formats.forEach(item => {
493
+ formats[item[0].name] = item[1];
494
+ });
495
+ }
496
+ else {
497
+ formats = null;
498
+ }
499
+ if (typeof i.insert === 'string') {
500
+ sharedContent.insert(offset, i.insert, formats);
501
+ }
502
+ else {
503
+ const sharedComponent = this.createSharedComponentByLocalComponent(i.insert);
504
+ sharedContent.insertEmbed(offset, sharedComponent, formats);
505
+ }
506
+ offset += i.insert.length;
507
+ });
508
+ localSlot.getAttributes().forEach(item => {
509
+ sharedContent.setAttribute(item[0].name, item[1]);
510
+ });
511
+ }
512
+ createLocalSlotBySharedSlot(sharedSlot) {
513
+ var _a;
514
+ const type = sharedSlot.getAttribute('type');
515
+ const schema = sharedSlot.getAttribute('schema');
516
+ if (type === 'async') {
517
+ const metadata = sharedSlot.getAttribute('metadata');
518
+ const slot = new core.AsyncSlot(schema || [], metadata);
519
+ const loadedSubDocument = this.subModelLoader.getLoadedModelBySlot(slot);
520
+ if (loadedSubDocument) {
521
+ const subContent = loadedSubDocument.getText('content');
522
+ this.syncRootSlot(loadedSubDocument, subContent, slot);
523
+ this.addSubModelEvent.next({
524
+ yDoc: loadedSubDocument,
525
+ yType: subContent
526
+ });
527
+ slot.loader.markAsLoaded();
528
+ return slot;
529
+ }
530
+ let isDestroyed = false;
531
+ slot.loader.onRequestLoad.toPromise().then(() => {
532
+ return this.subModelLoader.loadSubModelBySlot(slot);
533
+ }).then(subDocument => {
534
+ if (isDestroyed) {
535
+ return;
536
+ }
537
+ slot.loader.markAsLoaded();
538
+ const subContent = subDocument.getText('content');
539
+ this.syncRootSlot(subDocument, subContent, slot);
540
+ this.addSubModelEvent.next({
541
+ yDoc: subDocument,
542
+ yType: subContent
543
+ });
544
+ });
545
+ slot.__changeMarker__.destroyCallbacks.push(() => {
546
+ isDestroyed = true;
547
+ });
548
+ return slot;
549
+ }
550
+ const contentDelta = sharedSlot.toDelta();
551
+ const content = (_a = contentDelta[0]) === null || _a === void 0 ? void 0 : _a.insert;
552
+ if (!(content instanceof yjs.Text)) {
553
+ throw collaborateErrorFn('shared slot content type is not `YText`.');
554
+ }
555
+ const localSlot = new core.Slot(schema || []);
556
+ this.initLocalSlotBySharedSlot(content, localSlot);
557
+ this.syncSlot(content, localSlot);
558
+ return localSlot;
559
+ }
560
+ initLocalSlotBySharedSlot(content, localSlot) {
561
+ const delta = content.toDelta();
562
+ const attrs = content.getAttributes();
563
+ Object.keys(attrs).forEach(key => {
564
+ const attribute = this.registry.getAttribute(key);
565
+ if (attribute) {
566
+ localSlot.setAttribute(attribute, attrs[key]);
567
+ }
568
+ });
569
+ for (const action of delta) {
570
+ if (action.insert) {
571
+ if (typeof action.insert === 'string') {
572
+ const formats = remoteFormatsToLocal(this.registry, action.attributes);
573
+ localSlot.insert(action.insert, formats);
574
+ }
575
+ else {
576
+ const sharedComponent = action.insert;
577
+ const component = this.createLocalComponentBySharedComponent(sharedComponent);
578
+ localSlot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
579
+ }
580
+ }
581
+ else {
582
+ throw collaborateErrorFn('unexpected delta action.');
583
+ }
584
+ }
585
+ }
586
+ createSharedModelByLocalModel(localModel) {
587
+ if (localModel instanceof core.Slot) {
588
+ return this.createSharedSlotByLocalSlot(localModel);
589
+ }
590
+ if (Array.isArray(localModel)) {
591
+ return this.createSharedArrayByLocalArray(localModel);
592
+ }
593
+ if (typeof localModel === 'object' && localModel !== null) {
594
+ return this.createSharedMapByLocalMap(localModel);
595
+ }
596
+ return localModel;
597
+ }
598
+ createLocalModelBySharedByModel(sharedModel) {
599
+ if (sharedModel instanceof yjs.Map) {
600
+ return this.createLocalMapBySharedMap(sharedModel);
601
+ }
602
+ if (sharedModel instanceof yjs.Array) {
603
+ return this.createLocalArrayBySharedArray(sharedModel);
604
+ }
605
+ if (sharedModel instanceof yjs.Text) {
606
+ return this.createLocalSlotBySharedSlot(sharedModel);
607
+ }
608
+ return sharedModel;
609
+ }
642
610
  createSharedComponentByLocalComponent(component) {
643
611
  const sharedComponent = new yjs.Map();
644
- const sharedState = this.createSharedMapByLocalMap(component.state);
645
612
  sharedComponent.set('name', component.name);
613
+ if (component instanceof core.AsyncComponent) {
614
+ sharedComponent.set('type', 'async');
615
+ sharedComponent.set('metadata', component.getMetadata());
616
+ const state = component.state;
617
+ let isDestroyed = false;
618
+ state.__changeMarker__.destroyCallbacks.push(() => {
619
+ isDestroyed = true;
620
+ });
621
+ this.subModelLoader.createSubModelByComponent(component).then(subDocument => {
622
+ if (isDestroyed) {
623
+ return;
624
+ }
625
+ const state = subDocument.getMap('state');
626
+ this.syncComponent(subDocument, state, component);
627
+ this.addSubModelEvent.next({
628
+ yType: state,
629
+ yDoc: subDocument
630
+ });
631
+ component.loader.markAsLoaded();
632
+ });
633
+ return sharedComponent;
634
+ }
635
+ const sharedState = this.createSharedMapByLocalMap(component.state);
646
636
  sharedComponent.set('state', sharedState);
637
+ sharedComponent.set('type', 'sync');
647
638
  return sharedComponent;
648
639
  }
649
640
  createLocalComponentBySharedComponent(yMap) {
650
641
  const componentName = yMap.get('name');
651
- const sharedState = yMap.get('state');
652
- const state = this.createLocalMapBySharedMap(sharedState);
653
- const instance = this.registry.createComponentByData(componentName, state);
642
+ const type = yMap.get('type');
643
+ let instance;
644
+ if (type === 'async') {
645
+ instance = this.registry.createComponentByData(componentName, {});
646
+ if (instance instanceof core.AsyncComponent) {
647
+ instance.setMetadata(yMap.get('metadata'));
648
+ const loadedSubDocument = this.subModelLoader.getLoadedModelByComponent(instance);
649
+ if (loadedSubDocument) {
650
+ const state = loadedSubDocument.getMap('state');
651
+ this.syncComponent(loadedSubDocument, state, instance);
652
+ this.addSubModelEvent.next({
653
+ yType: state,
654
+ yDoc: loadedSubDocument
655
+ });
656
+ instance.loader.markAsLoaded();
657
+ return instance;
658
+ }
659
+ const state = instance.state;
660
+ let isDestroyed = false;
661
+ instance.loader.onRequestLoad.toPromise().then(() => {
662
+ return this.subModelLoader.loadSubModelByComponent(instance);
663
+ })
664
+ .then(subDocument => {
665
+ if (isDestroyed) {
666
+ return;
667
+ }
668
+ instance.loader.markAsLoaded();
669
+ const state = subDocument.getMap('state');
670
+ this.syncComponent(subDocument, state, instance);
671
+ this.addSubModelEvent.next({
672
+ yType: state,
673
+ yDoc: subDocument
674
+ });
675
+ });
676
+ state.__changeMarker__.destroyCallbacks.push(() => {
677
+ isDestroyed = true;
678
+ });
679
+ }
680
+ else if (instance instanceof core.Component) {
681
+ throw collaborateErrorFn(`component name \`${componentName}\` is not a async component.`);
682
+ }
683
+ }
684
+ else {
685
+ const sharedState = yMap.get('state');
686
+ const state = this.createLocalMapBySharedMap(sharedState);
687
+ instance = this.registry.createComponentByData(componentName, state);
688
+ }
654
689
  if (instance) {
655
690
  return instance;
656
691
  }
@@ -664,7 +699,7 @@ exports.Collaborate = class Collaborate {
664
699
  */
665
700
  syncArray(sharedArray, localArray) {
666
701
  const sub = localArray.__changeMarker__.onSelfChange.subscribe((actions) => {
667
- this.runLocalUpdate(() => {
702
+ this.runLocalUpdate(sharedArray.doc, !localArray.__changeMarker__.irrevocableUpdate, () => {
668
703
  let index = 0;
669
704
  for (const action of actions) {
670
705
  switch (action.type) {
@@ -695,7 +730,7 @@ exports.Collaborate = class Collaborate {
695
730
  break;
696
731
  }
697
732
  }
698
- }, !localArray.__changeMarker__.irrevocableUpdate);
733
+ });
699
734
  });
700
735
  const syncRemote = (ev, tr) => {
701
736
  this.runRemoteUpdate(tr, () => {
@@ -745,7 +780,7 @@ exports.Collaborate = class Collaborate {
745
780
  };
746
781
  sharedObject.observe(syncRemote);
747
782
  const sub = localObject.__changeMarker__.onSelfChange.subscribe((actions) => {
748
- this.runLocalUpdate(() => {
783
+ this.runLocalUpdate(sharedObject.doc, !localObject.__changeMarker__.irrevocableUpdate, () => {
749
784
  for (const action of actions) {
750
785
  switch (action.type) {
751
786
  case 'propSet':
@@ -756,28 +791,33 @@ exports.Collaborate = class Collaborate {
756
791
  break;
757
792
  }
758
793
  }
759
- }, !localObject.__changeMarker__.irrevocableUpdate);
794
+ });
760
795
  });
761
796
  localObject.__changeMarker__.destroyCallbacks.push(function () {
762
797
  sharedObject.unobserve(syncRemote);
763
798
  sub.unsubscribe();
764
799
  });
765
800
  }
766
- runLocalUpdate(fn, record) {
767
- if (this.updateFromRemote) {
801
+ runLocalUpdate(yDoc, record, fn) {
802
+ if (this.updateFromRemote || !yDoc) {
768
803
  return;
769
804
  }
770
- this.updateRemoteActions.push({
805
+ let changeList = this.updateRemoteActions.get(yDoc);
806
+ if (!changeList) {
807
+ changeList = [];
808
+ this.updateRemoteActions.set(yDoc, changeList);
809
+ }
810
+ changeList.push({
771
811
  record,
772
812
  action: fn
773
813
  });
774
814
  }
775
815
  runRemoteUpdate(tr, fn) {
776
- if (tr.origin === this.yDoc) {
816
+ if (tr.origin === tr.doc) {
777
817
  return;
778
818
  }
779
819
  this.updateFromRemote = true;
780
- if (tr.origin === this.manager) {
820
+ if (tr.origin instanceof yjs.UndoManager) {
781
821
  this.scheduler.historyApplyTransact(fn);
782
822
  }
783
823
  else {
@@ -788,13 +828,10 @@ exports.Collaborate = class Collaborate {
788
828
  };
789
829
  exports.Collaborate = __decorate([
790
830
  core$1.Injectable(),
791
- __param(0, core$1.Inject(core.HISTORY_STACK_SIZE)),
792
- __param(5, core$1.Optional()),
793
- __metadata("design:paramtypes", [Number, core.RootComponentRef,
794
- core.Scheduler,
831
+ __metadata("design:paramtypes", [core.Scheduler,
795
832
  core.Registry,
796
833
  core.Selection,
797
- CustomUndoManagerConfig])
834
+ SubModelLoader])
798
835
  ], exports.Collaborate);
799
836
  function remoteFormatsToLocal(registry, attrs) {
800
837
  const formats = [];
@@ -809,6 +846,182 @@ function remoteFormatsToLocal(registry, attrs) {
809
846
  return formats;
810
847
  }
811
848
 
849
+ class CustomUndoManagerConfig {
850
+ }
851
+ const collabHistoryErrorFn = core.makeError('CollabHistory');
852
+ exports.CollabHistory = class CollabHistory {
853
+ get canBack() {
854
+ var _a;
855
+ return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canUndo()) || false;
856
+ }
857
+ get canForward() {
858
+ var _a;
859
+ return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canRedo()) || false;
860
+ }
861
+ constructor(rootComponentRef, collaborate, scheduler, selection, stackSize, undoManagerConfig) {
862
+ this.rootComponentRef = rootComponentRef;
863
+ this.collaborate = collaborate;
864
+ this.scheduler = scheduler;
865
+ this.selection = selection;
866
+ this.stackSize = stackSize;
867
+ this.undoManagerConfig = undoManagerConfig;
868
+ this.manager = null;
869
+ this.historyItems = [];
870
+ this.index = 0;
871
+ this.subscriptions = [];
872
+ this.backEvent = new stream.Subject();
873
+ this.forwardEvent = new stream.Subject();
874
+ this.changeEvent = new stream.Subject();
875
+ this.pushEvent = new stream.Subject();
876
+ this.onBack = this.backEvent.asObservable();
877
+ this.onForward = this.forwardEvent.asObservable();
878
+ this.onChange = this.changeEvent.asObservable();
879
+ this.onPush = this.pushEvent.asObservable();
880
+ }
881
+ listen() {
882
+ const root = this.collaborate.yDoc.getMap('RootComponent');
883
+ const rootComponent = this.rootComponentRef.component;
884
+ this.collaborate.syncRootComponent(this.collaborate.yDoc, root, rootComponent);
885
+ const undoManagerConfig = this.undoManagerConfig || {};
886
+ const manager = new yjs.UndoManager(root, {
887
+ trackedOrigins: new Set([this.collaborate.yDoc]),
888
+ captureTransaction(arg) {
889
+ if (undoManagerConfig.captureTransaction) {
890
+ return undoManagerConfig.captureTransaction(arg);
891
+ }
892
+ return true;
893
+ },
894
+ deleteFilter(item) {
895
+ if (undoManagerConfig.deleteFilter) {
896
+ return undoManagerConfig.deleteFilter(item);
897
+ }
898
+ return true;
899
+ }
900
+ });
901
+ this.manager = manager;
902
+ let beforePosition = null;
903
+ this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
904
+ beforePosition = this.getRelativeCursorLocation();
905
+ }), this.collaborate.onAddSubModel.subscribe(() => {
906
+ throw collabHistoryErrorFn('single document does not support submodels.');
907
+ }));
908
+ manager.on('stack-item-added', (event) => {
909
+ if (event.type === 'undo') {
910
+ if (event.origin === manager) {
911
+ this.index++;
912
+ }
913
+ else {
914
+ this.historyItems.length = this.index;
915
+ this.historyItems.push({
916
+ before: beforePosition,
917
+ after: this.getRelativeCursorLocation()
918
+ });
919
+ this.index++;
920
+ }
921
+ }
922
+ else {
923
+ this.index--;
924
+ }
925
+ if (manager.undoStack.length > this.stackSize) {
926
+ this.historyItems.shift();
927
+ manager.undoStack.shift();
928
+ }
929
+ if (event.origin === this.collaborate.yDoc) {
930
+ this.pushEvent.next();
931
+ }
932
+ this.changeEvent.next();
933
+ });
934
+ manager.on('stack-item-popped', (ev) => {
935
+ const index = ev.type === 'undo' ? this.index : this.index - 1;
936
+ const position = this.historyItems[index] || null;
937
+ const p = ev.type === 'undo' ? position === null || position === void 0 ? void 0 : position.before : position === null || position === void 0 ? void 0 : position.after;
938
+ if (p) {
939
+ const selection = this.getAbstractSelection(p);
940
+ if (selection) {
941
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
942
+ return;
943
+ }
944
+ }
945
+ this.selection.unSelect();
946
+ });
947
+ }
948
+ back() {
949
+ var _a;
950
+ if (this.canBack) {
951
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.undo();
952
+ this.backEvent.next();
953
+ }
954
+ }
955
+ forward() {
956
+ var _a;
957
+ if (this.canForward) {
958
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.redo();
959
+ this.forwardEvent.next();
960
+ }
961
+ }
962
+ clear() {
963
+ var _a;
964
+ const last = this.historyItems.pop();
965
+ this.historyItems = last ? [last] : [];
966
+ this.index = last ? 1 : 0;
967
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
968
+ this.changeEvent.next();
969
+ }
970
+ destroy() {
971
+ var _a;
972
+ this.index = 0;
973
+ this.historyItems = [];
974
+ this.subscriptions.forEach(i => i.unsubscribe());
975
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
976
+ }
977
+ getAbstractSelection(position) {
978
+ const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor, this.collaborate.yDoc);
979
+ const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus, this.collaborate.yDoc);
980
+ if (anchorPosition && focusPosition) {
981
+ const focusSlot = this.collaborate.slotMap.get(focusPosition.type);
982
+ const anchorSlot = this.collaborate.slotMap.get(anchorPosition.type);
983
+ if (focusSlot && anchorSlot) {
984
+ return {
985
+ anchorSlot,
986
+ anchorOffset: anchorPosition.index,
987
+ focusSlot,
988
+ focusOffset: focusPosition.index
989
+ };
990
+ }
991
+ }
992
+ return null;
993
+ }
994
+ getRelativeCursorLocation() {
995
+ const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
996
+ if (anchorSlot) {
997
+ const anchorYText = this.collaborate.slotMap.get(anchorSlot);
998
+ if (anchorYText) {
999
+ const anchorPosition = yjs.createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
1000
+ if (focusSlot) {
1001
+ const focusYText = this.collaborate.slotMap.get(focusSlot);
1002
+ if (focusYText) {
1003
+ const focusPosition = yjs.createRelativePositionFromTypeIndex(focusYText, focusOffset);
1004
+ return {
1005
+ focus: focusPosition,
1006
+ anchor: anchorPosition
1007
+ };
1008
+ }
1009
+ }
1010
+ }
1011
+ }
1012
+ return null;
1013
+ }
1014
+ };
1015
+ exports.CollabHistory = __decorate([
1016
+ core$1.Injectable(),
1017
+ __param(4, core$1.Inject(core.HISTORY_STACK_SIZE)),
1018
+ __param(5, core$1.Optional()),
1019
+ __metadata("design:paramtypes", [core.RootComponentRef,
1020
+ exports.Collaborate,
1021
+ core.Scheduler,
1022
+ core.Selection, Number, CustomUndoManagerConfig])
1023
+ ], exports.CollabHistory);
1024
+
812
1025
  exports.UserActivity = class UserActivity {
813
1026
  constructor(syncConnector, selection) {
814
1027
  this.syncConnector = syncConnector;
@@ -857,15 +1070,219 @@ class CollaborateModule {
857
1070
  this.providers = [
858
1071
  exports.Collaborate,
859
1072
  exports.UserActivity,
1073
+ exports.CollabHistory,
1074
+ {
1075
+ provide: core.History,
1076
+ useExisting: exports.CollabHistory
1077
+ }, {
1078
+ provide: SyncConnector,
1079
+ useFactory: (collab) => {
1080
+ return this.config.createConnector(collab.yDoc);
1081
+ },
1082
+ deps: [exports.Collaborate]
1083
+ }, {
1084
+ provide: SubModelLoader,
1085
+ useClass: exports.NonSubModelLoader
1086
+ }
1087
+ ];
1088
+ }
1089
+ setup(textbus) {
1090
+ const connector = textbus.get(SyncConnector);
1091
+ const userActivity = textbus.get(exports.UserActivity);
1092
+ userActivity.init(this.config.userinfo);
1093
+ return connector.onLoad.toPromise();
1094
+ }
1095
+ onDestroy(textbus) {
1096
+ textbus.get(exports.Collaborate).destroy();
1097
+ textbus.get(core.History).destroy();
1098
+ textbus.get(exports.UserActivity).destroy();
1099
+ textbus.get(SyncConnector).onDestroy();
1100
+ }
1101
+ }
1102
+
1103
+ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1104
+ get canBack() {
1105
+ return this.actionStack.length > 0 && this.index > 0;
1106
+ }
1107
+ get canForward() {
1108
+ return this.actionStack.length > 0 && this.index < this.actionStack.length;
1109
+ }
1110
+ constructor(collaborate, rootComponentRef, stackSize, undoManagerConfig) {
1111
+ this.collaborate = collaborate;
1112
+ this.rootComponentRef = rootComponentRef;
1113
+ this.stackSize = stackSize;
1114
+ this.undoManagerConfig = undoManagerConfig;
1115
+ this.isListen = false;
1116
+ this.changeEvent = new stream.Subject();
1117
+ this.backEvent = new stream.Subject();
1118
+ this.forwardEvent = new stream.Subject();
1119
+ this.pushEvent = new stream.Subject();
1120
+ this.actionStack = [];
1121
+ this.index = 0;
1122
+ this.stackItem = null;
1123
+ this.timer = null;
1124
+ this.subscription = new stream.Subscription();
1125
+ this.subDocs = new Set();
1126
+ this.listenerCaches = new Set();
1127
+ this.onChange = this.changeEvent.asObservable();
1128
+ this.onBack = this.backEvent.asObservable();
1129
+ this.onForward = this.forwardEvent.asObservable();
1130
+ this.onPush = this.pushEvent.asObservable();
1131
+ }
1132
+ listen() {
1133
+ this.isListen = true;
1134
+ const root = this.collaborate.yDoc.getMap('RootComponent');
1135
+ const rootComponent = this.rootComponentRef.component;
1136
+ this.collaborate.syncRootComponent(this.collaborate.yDoc, root, rootComponent);
1137
+ this.listenItem(root, this.collaborate.yDoc);
1138
+ this.subscription.add(this.collaborate.onAddSubModel.subscribe(({ yType, yDoc }) => {
1139
+ if (this.subDocs.has(yType)) {
1140
+ return;
1141
+ }
1142
+ this.subDocs.add(yType);
1143
+ if (this.isListen) {
1144
+ this.listenItem(yType, yDoc);
1145
+ }
1146
+ }));
1147
+ }
1148
+ forward() {
1149
+ if (!this.canForward) {
1150
+ return;
1151
+ }
1152
+ clearTimeout(this.timer);
1153
+ const item = this.actionStack[this.index];
1154
+ if (item) {
1155
+ for (const i of item) {
1156
+ i.redo();
1157
+ }
1158
+ }
1159
+ this.index++;
1160
+ this.forwardEvent.next();
1161
+ this.changeEvent.next();
1162
+ }
1163
+ back() {
1164
+ if (!this.canBack) {
1165
+ return;
1166
+ }
1167
+ clearTimeout(this.timer);
1168
+ let actions;
1169
+ if (this.stackItem) {
1170
+ actions = this.stackItem;
1171
+ this.stackItem = null;
1172
+ }
1173
+ else {
1174
+ this.index--;
1175
+ actions = this.actionStack[this.index];
1176
+ }
1177
+ let len = actions.length;
1178
+ while (len > 0) {
1179
+ len--;
1180
+ actions[len].undo();
1181
+ }
1182
+ if (actions) {
1183
+ this.backEvent.next();
1184
+ this.changeEvent.next();
1185
+ }
1186
+ }
1187
+ clear() {
1188
+ this.actionStack = [];
1189
+ this.stackItem = [];
1190
+ this.index = 0;
1191
+ clearTimeout(this.timer);
1192
+ this.listenerCaches.forEach((undoManager) => {
1193
+ undoManager.clear();
1194
+ });
1195
+ this.changeEvent.next();
1196
+ }
1197
+ destroy() {
1198
+ this.clear();
1199
+ this.subscription.unsubscribe();
1200
+ this.listenerCaches.forEach((undoManager) => {
1201
+ undoManager.destroy();
1202
+ });
1203
+ this.subDocs.clear();
1204
+ this.listenerCaches.clear();
1205
+ }
1206
+ listenItem(yType, yDoc) {
1207
+ const undoManagerConfig = this.undoManagerConfig || {};
1208
+ const undoManager = new yjs.UndoManager(yType, {
1209
+ trackedOrigins: new Set([yDoc]),
1210
+ captureTimeout: 0,
1211
+ captureTransaction(arg) {
1212
+ if (undoManagerConfig.captureTransaction) {
1213
+ return undoManagerConfig.captureTransaction(arg);
1214
+ }
1215
+ return true;
1216
+ },
1217
+ deleteFilter(item) {
1218
+ if (undoManagerConfig.deleteFilter) {
1219
+ return undoManagerConfig.deleteFilter(item);
1220
+ }
1221
+ return true;
1222
+ }
1223
+ });
1224
+ undoManager.on('stack-item-added', (event) => {
1225
+ if (event.type === 'undo' && !(event.origin instanceof yjs.UndoManager)) {
1226
+ if (this.index != this.actionStack.length) {
1227
+ const redoStack = this.actionStack.slice(this.index);
1228
+ redoStack.forEach(item => {
1229
+ item.forEach(i => {
1230
+ i.clear(false, true);
1231
+ });
1232
+ });
1233
+ this.actionStack.length = this.index;
1234
+ this.changeEvent.next();
1235
+ }
1236
+ if (this.stackItem === null) {
1237
+ this.stackItem = [];
1238
+ this.timer = setTimeout(() => {
1239
+ if (this.actionStack.length >= this.stackSize) {
1240
+ this.actionStack.shift();
1241
+ }
1242
+ else {
1243
+ this.index++;
1244
+ }
1245
+ this.actionStack.push(this.stackItem);
1246
+ this.stackItem = null;
1247
+ this.pushEvent.next();
1248
+ this.changeEvent.next();
1249
+ }, 500);
1250
+ }
1251
+ this.stackItem.push(undoManager);
1252
+ }
1253
+ });
1254
+ this.listenerCaches.add(undoManager);
1255
+ }
1256
+ };
1257
+ exports.MultipleDocCollabHistory = __decorate([
1258
+ core$1.Injectable(),
1259
+ __param(2, core$1.Inject(core.HISTORY_STACK_SIZE)),
1260
+ __param(3, core$1.Optional()),
1261
+ __metadata("design:paramtypes", [exports.Collaborate,
1262
+ core.RootComponentRef, Number, CustomUndoManagerConfig])
1263
+ ], exports.MultipleDocCollabHistory);
1264
+
1265
+ class MultipleDocumentCollaborateModule {
1266
+ constructor(config) {
1267
+ this.config = config;
1268
+ this.providers = [
1269
+ exports.Collaborate,
1270
+ exports.UserActivity,
1271
+ exports.MultipleDocCollabHistory,
860
1272
  {
861
1273
  provide: core.History,
862
- useExisting: exports.Collaborate
1274
+ useExisting: exports.MultipleDocCollabHistory
863
1275
  }, {
864
1276
  provide: SyncConnector,
865
1277
  useFactory: (collab) => {
866
1278
  return this.config.createConnector(collab.yDoc);
867
1279
  },
868
1280
  deps: [exports.Collaborate]
1281
+ }, {
1282
+ provide: SubModelLoader,
1283
+ useFactory: () => {
1284
+ return this.config.subModelLoader;
1285
+ }
869
1286
  }
870
1287
  ];
871
1288
  }
@@ -876,6 +1293,8 @@ class CollaborateModule {
876
1293
  return connector.onLoad.toPromise();
877
1294
  }
878
1295
  onDestroy(textbus) {
1296
+ textbus.get(exports.Collaborate).destroy();
1297
+ textbus.get(core.History).destroy();
879
1298
  textbus.get(exports.UserActivity).destroy();
880
1299
  textbus.get(SyncConnector).onDestroy();
881
1300
  }
@@ -884,5 +1303,7 @@ class CollaborateModule {
884
1303
  exports.CollaborateModule = CollaborateModule;
885
1304
  exports.CustomUndoManagerConfig = CustomUndoManagerConfig;
886
1305
  exports.HocuspocusConnector = HocuspocusConnector;
1306
+ exports.MultipleDocumentCollaborateModule = MultipleDocumentCollaborateModule;
1307
+ exports.SubModelLoader = SubModelLoader;
887
1308
  exports.SyncConnector = SyncConnector;
888
1309
  exports.YWebsocketConnector = YWebsocketConnector;