@textbus/collaborate 4.0.4 → 4.1.0-alpha.1

Sign up to get free protection for your applications and to get access to all the features.
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,96 @@ 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();
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
+ yDoc.transact(() => {
215
+ this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
216
+ });
217
+ }
218
+ this.initSyncEvent(yDoc);
219
+ this.syncSlot(sharedSlot, localSlot);
220
+ }
221
+ getAbstractSelection(position) {
222
+ const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor.position, position.anchor.doc);
223
+ const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus.position, position.focus.doc);
224
+ if (anchorPosition && focusPosition) {
225
+ const focusSlot = this.slotMap.get(focusPosition.type);
226
+ const anchorSlot = this.slotMap.get(anchorPosition.type);
227
+ if (focusSlot && anchorSlot) {
228
+ return {
229
+ anchorSlot,
230
+ anchorOffset: anchorPosition.index,
231
+ focusSlot,
232
+ focusOffset: focusPosition.index
233
+ };
242
234
  }
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;
235
+ }
236
+ return null;
237
+ }
238
+ getRelativeCursorLocation() {
239
+ const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
240
+ if (anchorSlot) {
241
+ const anchorYText = this.slotMap.get(anchorSlot);
242
+ if (anchorYText) {
243
+ const anchorPosition = yjs.createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
244
+ if (focusSlot) {
245
+ const focusYText = this.slotMap.get(focusSlot);
246
+ if (focusYText) {
247
+ const focusPosition = yjs.createRelativePositionFromTypeIndex(focusYText, focusOffset);
248
+ return {
249
+ focus: {
250
+ doc: focusYText.doc,
251
+ position: focusPosition
252
+ },
253
+ anchor: {
254
+ doc: anchorYText.doc,
255
+ position: anchorPosition
256
+ }
257
+ };
258
+ }
254
259
  }
255
260
  }
261
+ }
262
+ return null;
263
+ }
264
+ restoreCursorPosition(position) {
265
+ if (!position) {
256
266
  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 => {
267
+ return;
268
+ }
269
+ const selection = this.getAbstractSelection(position);
270
+ if (selection) {
271
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
272
+ }
273
+ }
274
+ initSyncEvent(yDoc) {
275
+ this.subscriptions.push(this.scheduler.onDocChanged.pipe(stream.map(item => {
262
276
  return item.filter(i => {
263
277
  return i.from !== core.ChangeOrigin.Remote;
264
278
  });
@@ -267,7 +281,8 @@ exports.Collaborate = class Collaborate {
267
281
  })).subscribe(() => {
268
282
  const updates = [];
269
283
  let update = null;
270
- for (const item of this.updateRemoteActions) {
284
+ const updateRemoteActions = this.updateRemoteActions.get(yDoc) || [];
285
+ for (const item of updateRemoteActions) {
271
286
  if (!update) {
272
287
  update = {
273
288
  record: item.record,
@@ -286,218 +301,32 @@ exports.Collaborate = class Collaborate {
286
301
  updates.push(update);
287
302
  }
288
303
  }
289
- this.updateRemoteActions = [];
304
+ this.updateRemoteActions.delete(yDoc);
290
305
  for (const item of updates) {
291
- this.yDoc.transact(() => {
306
+ yDoc.transact(() => {
292
307
  item.actions.forEach(fn => {
293
308
  fn();
294
309
  });
295
- }, item.record ? this.yDoc : this.noRecord);
310
+ }, item.record ? yDoc : this.noRecord);
296
311
  }
297
- this.localChangesAppliedEvent.next();
298
312
  }));
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
313
  }
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
- }
330
- syncRootComponent(root, rootComponent) {
331
- let state = root.get('state');
314
+ syncComponent(yDoc, sharedComponent, localComponent) {
315
+ let state = sharedComponent.get('state');
332
316
  if (!state) {
333
317
  state = new yjs.Map();
334
- this.syncLocalMapToSharedMap(rootComponent.state, state);
335
- this.yDoc.transact(() => {
336
- root.set('state', state);
318
+ this.syncLocalMapToSharedMap(localComponent.state, state);
319
+ yDoc.transact(() => {
320
+ sharedComponent.set('state', state);
337
321
  });
338
322
  }
339
323
  else {
340
- Object.keys(rootComponent.state).forEach(key => {
341
- Reflect.deleteProperty(rootComponent.state, key);
324
+ Object.keys(localComponent.state).forEach(key => {
325
+ Reflect.deleteProperty(localComponent.state, key);
342
326
  });
343
- this.syncSharedMapToLocalMap(state, rootComponent.state);
327
+ this.syncSharedMapToLocalMap(state, localComponent.state);
344
328
  }
345
329
  }
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
330
  syncSlot(sharedSlot, localSlot) {
502
331
  const syncRemote = (ev, tr) => {
503
332
  this.runRemoteUpdate(tr, () => {
@@ -546,7 +375,7 @@ exports.Collaborate = class Collaborate {
546
375
  const component = this.createLocalComponentBySharedComponent(sharedComponent);
547
376
  localSlot.insert(component);
548
377
  }
549
- if (this.selection.isSelected && tr.origin !== this.manager) {
378
+ if (this.selection.isSelected && !(tr.origin instanceof yjs.UndoManager)) {
550
379
  if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
551
380
  this.selection.setAnchor(localSlot, this.selection.anchorOffset + length);
552
381
  }
@@ -558,7 +387,7 @@ exports.Collaborate = class Collaborate {
558
387
  else if (action.delete) {
559
388
  const index = localSlot.index;
560
389
  localSlot.delete(action.delete);
561
- if (this.selection.isSelected && tr.origin !== this.manager) {
390
+ if (this.selection.isSelected && !(tr.origin instanceof yjs.UndoManager)) {
562
391
  if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
563
392
  this.selection.setAnchor(localSlot, this.selection.startOffset - action.delete);
564
393
  }
@@ -572,7 +401,7 @@ exports.Collaborate = class Collaborate {
572
401
  };
573
402
  sharedSlot.observe(syncRemote);
574
403
  const sub = localSlot.onContentChange.subscribe(actions => {
575
- this.runLocalUpdate(() => {
404
+ this.runLocalUpdate(sharedSlot.doc, true, () => {
576
405
  var _a;
577
406
  let offset = 0;
578
407
  let length = 0;
@@ -630,7 +459,7 @@ exports.Collaborate = class Collaborate {
630
459
  sharedSlot.removeAttribute(action.name);
631
460
  }
632
461
  }
633
- }, true);
462
+ });
634
463
  });
635
464
  this.slotMap.set(localSlot, sharedSlot);
636
465
  localSlot.__changeMarker__.destroyCallbacks.push(() => {
@@ -639,18 +468,281 @@ exports.Collaborate = class Collaborate {
639
468
  sub.unsubscribe();
640
469
  });
641
470
  }
471
+ destroy() {
472
+ this.subscriptions.forEach(i => i.unsubscribe());
473
+ }
474
+ syncSharedMapToLocalMap(sharedMap, localMap) {
475
+ sharedMap.forEach((value, key) => {
476
+ localMap[key] = this.createLocalModelBySharedByModel(value);
477
+ });
478
+ this.syncObject(sharedMap, localMap);
479
+ }
480
+ createLocalMapBySharedMap(sharedMap) {
481
+ const localMap = core.createObjectProxy({});
482
+ this.syncSharedMapToLocalMap(sharedMap, localMap);
483
+ return localMap;
484
+ }
485
+ createLocalArrayBySharedArray(sharedArray) {
486
+ const localArray = core.createArrayProxy([]);
487
+ localArray.push(...sharedArray.map(item => this.createLocalModelBySharedByModel(item)));
488
+ this.syncArray(sharedArray, localArray);
489
+ return localArray;
490
+ }
491
+ syncLocalMapToSharedMap(localMap, sharedMap) {
492
+ Object.entries(localMap).forEach(([key, value]) => {
493
+ sharedMap.set(key, this.createSharedModelByLocalModel(value));
494
+ });
495
+ this.syncObject(sharedMap, localMap);
496
+ }
497
+ createSharedMapByLocalMap(localMap) {
498
+ const sharedMap = new yjs.Map();
499
+ this.syncLocalMapToSharedMap(localMap, sharedMap);
500
+ return sharedMap;
501
+ }
502
+ createSharedArrayByLocalArray(localArray) {
503
+ const sharedArray = new yjs.Array();
504
+ localArray.forEach(value => {
505
+ sharedArray.push([this.createSharedModelByLocalModel(value)]);
506
+ });
507
+ this.syncArray(sharedArray, localArray);
508
+ return sharedArray;
509
+ }
510
+ createSharedSlotByLocalSlot(localSlot) {
511
+ const sharedSlot = new yjs.Text();
512
+ const isAsyncSlot = localSlot instanceof core.AsyncSlot;
513
+ sharedSlot.setAttribute('schema', [...localSlot.schema]);
514
+ sharedSlot.setAttribute('type', isAsyncSlot ? 'async' : 'sync');
515
+ if (isAsyncSlot) {
516
+ let isDestroyed = false;
517
+ sharedSlot.setAttribute('metadata', localSlot.metadata);
518
+ this.subModelLoader.createSubModelBySlot(localSlot).then(subDocument => {
519
+ if (isDestroyed) {
520
+ return;
521
+ }
522
+ const content = subDocument.getText('content');
523
+ this.initSharedSlotByLocalSlot(content, localSlot);
524
+ this.syncSlot(content, localSlot);
525
+ this.addSubModelEvent.next({
526
+ yDoc: subDocument,
527
+ yType: content
528
+ });
529
+ this.initSyncEvent(subDocument);
530
+ localSlot.loader.markAsLoaded();
531
+ });
532
+ localSlot.__changeMarker__.destroyCallbacks.push(() => {
533
+ isDestroyed = true;
534
+ });
535
+ return sharedSlot;
536
+ }
537
+ const sharedContent = new yjs.Text();
538
+ this.initSharedSlotByLocalSlot(sharedContent, localSlot);
539
+ sharedSlot.insertEmbed(0, sharedContent);
540
+ this.syncSlot(sharedContent, localSlot);
541
+ return sharedSlot;
542
+ }
543
+ initSharedSlotByLocalSlot(sharedContent, localSlot) {
544
+ let offset = 0;
545
+ localSlot.toDelta().forEach(i => {
546
+ let formats = {};
547
+ if (i.formats) {
548
+ i.formats.forEach(item => {
549
+ formats[item[0].name] = item[1];
550
+ });
551
+ }
552
+ else {
553
+ formats = null;
554
+ }
555
+ if (typeof i.insert === 'string') {
556
+ sharedContent.insert(offset, i.insert, formats);
557
+ }
558
+ else {
559
+ const sharedComponent = this.createSharedComponentByLocalComponent(i.insert);
560
+ sharedContent.insertEmbed(offset, sharedComponent, formats);
561
+ }
562
+ offset += i.insert.length;
563
+ });
564
+ localSlot.getAttributes().forEach(item => {
565
+ sharedContent.setAttribute(item[0].name, item[1]);
566
+ });
567
+ }
568
+ createLocalSlotBySharedSlot(sharedSlot) {
569
+ var _a;
570
+ const type = sharedSlot.getAttribute('type');
571
+ const schema = sharedSlot.getAttribute('schema');
572
+ if (type === 'async') {
573
+ const metadata = sharedSlot.getAttribute('metadata');
574
+ const slot = new core.AsyncSlot(schema || [], metadata);
575
+ const loadedSubDocument = this.subModelLoader.getLoadedModelBySlot(slot);
576
+ if (loadedSubDocument) {
577
+ const subContent = loadedSubDocument.getText('content');
578
+ this.syncRootSlot(loadedSubDocument, subContent, slot);
579
+ this.addSubModelEvent.next({
580
+ yDoc: loadedSubDocument,
581
+ yType: subContent
582
+ });
583
+ slot.loader.markAsLoaded();
584
+ return slot;
585
+ }
586
+ let isDestroyed = false;
587
+ slot.loader.onRequestLoad.toPromise().then(() => {
588
+ return this.subModelLoader.loadSubModelBySlot(slot);
589
+ }).then(subDocument => {
590
+ if (isDestroyed) {
591
+ return;
592
+ }
593
+ slot.loader.markAsLoaded();
594
+ const subContent = subDocument.getText('content');
595
+ this.syncRootSlot(subDocument, subContent, slot);
596
+ this.addSubModelEvent.next({
597
+ yDoc: subDocument,
598
+ yType: subContent
599
+ });
600
+ });
601
+ slot.__changeMarker__.destroyCallbacks.push(() => {
602
+ isDestroyed = true;
603
+ });
604
+ return slot;
605
+ }
606
+ const contentDelta = sharedSlot.toDelta();
607
+ const content = (_a = contentDelta[0]) === null || _a === void 0 ? void 0 : _a.insert;
608
+ if (!(content instanceof yjs.Text)) {
609
+ throw collaborateErrorFn('shared slot content type is not `YText`.');
610
+ }
611
+ const localSlot = new core.Slot(schema || []);
612
+ this.initLocalSlotBySharedSlot(content, localSlot);
613
+ this.syncSlot(content, localSlot);
614
+ return localSlot;
615
+ }
616
+ initLocalSlotBySharedSlot(content, localSlot) {
617
+ const delta = content.toDelta();
618
+ const attrs = content.getAttributes();
619
+ Object.keys(attrs).forEach(key => {
620
+ const attribute = this.registry.getAttribute(key);
621
+ if (attribute) {
622
+ localSlot.setAttribute(attribute, attrs[key]);
623
+ }
624
+ });
625
+ for (const action of delta) {
626
+ if (action.insert) {
627
+ if (typeof action.insert === 'string') {
628
+ const formats = remoteFormatsToLocal(this.registry, action.attributes);
629
+ localSlot.insert(action.insert, formats);
630
+ }
631
+ else {
632
+ const sharedComponent = action.insert;
633
+ const component = this.createLocalComponentBySharedComponent(sharedComponent);
634
+ localSlot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
635
+ }
636
+ }
637
+ else {
638
+ throw collaborateErrorFn('unexpected delta action.');
639
+ }
640
+ }
641
+ }
642
+ createSharedModelByLocalModel(localModel) {
643
+ if (localModel instanceof core.Slot) {
644
+ return this.createSharedSlotByLocalSlot(localModel);
645
+ }
646
+ if (Array.isArray(localModel)) {
647
+ return this.createSharedArrayByLocalArray(localModel);
648
+ }
649
+ if (typeof localModel === 'object' && localModel !== null) {
650
+ return this.createSharedMapByLocalMap(localModel);
651
+ }
652
+ return localModel;
653
+ }
654
+ createLocalModelBySharedByModel(sharedModel) {
655
+ if (sharedModel instanceof yjs.Map) {
656
+ return this.createLocalMapBySharedMap(sharedModel);
657
+ }
658
+ if (sharedModel instanceof yjs.Array) {
659
+ return this.createLocalArrayBySharedArray(sharedModel);
660
+ }
661
+ if (sharedModel instanceof yjs.Text) {
662
+ return this.createLocalSlotBySharedSlot(sharedModel);
663
+ }
664
+ return sharedModel;
665
+ }
642
666
  createSharedComponentByLocalComponent(component) {
643
667
  const sharedComponent = new yjs.Map();
644
- const sharedState = this.createSharedMapByLocalMap(component.state);
645
668
  sharedComponent.set('name', component.name);
669
+ if (component instanceof core.AsyncComponent) {
670
+ sharedComponent.set('type', 'async');
671
+ sharedComponent.set('metadata', component.getMetadata());
672
+ const state = component.state;
673
+ let isDestroyed = false;
674
+ state.__changeMarker__.destroyCallbacks.push(() => {
675
+ isDestroyed = true;
676
+ });
677
+ this.subModelLoader.createSubModelByComponent(component).then(subDocument => {
678
+ if (isDestroyed) {
679
+ return;
680
+ }
681
+ const state = subDocument.getMap('state');
682
+ this.syncComponent(subDocument, state, component);
683
+ this.addSubModelEvent.next({
684
+ yType: state,
685
+ yDoc: subDocument
686
+ });
687
+ this.initSyncEvent(subDocument);
688
+ component.loader.markAsLoaded();
689
+ });
690
+ return sharedComponent;
691
+ }
692
+ const sharedState = this.createSharedMapByLocalMap(component.state);
646
693
  sharedComponent.set('state', sharedState);
694
+ sharedComponent.set('type', 'sync');
647
695
  return sharedComponent;
648
696
  }
649
697
  createLocalComponentBySharedComponent(yMap) {
650
698
  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);
699
+ const type = yMap.get('type');
700
+ let instance;
701
+ if (type === 'async') {
702
+ instance = this.registry.createComponentByData(componentName, {});
703
+ if (instance instanceof core.AsyncComponent) {
704
+ instance.setMetadata(yMap.get('metadata'));
705
+ const loadedSubDocument = this.subModelLoader.getLoadedModelByComponent(instance);
706
+ if (loadedSubDocument) {
707
+ const state = loadedSubDocument.getMap('state');
708
+ this.syncComponent(loadedSubDocument, state, instance);
709
+ this.addSubModelEvent.next({
710
+ yType: state,
711
+ yDoc: loadedSubDocument
712
+ });
713
+ instance.loader.markAsLoaded();
714
+ return instance;
715
+ }
716
+ const state = instance.state;
717
+ let isDestroyed = false;
718
+ instance.loader.onRequestLoad.toPromise().then(() => {
719
+ return this.subModelLoader.loadSubModelByComponent(instance);
720
+ })
721
+ .then(subDocument => {
722
+ if (isDestroyed) {
723
+ return;
724
+ }
725
+ instance.loader.markAsLoaded();
726
+ const state = subDocument.getMap('state');
727
+ this.syncComponent(subDocument, state, instance);
728
+ this.addSubModelEvent.next({
729
+ yType: state,
730
+ yDoc: subDocument
731
+ });
732
+ });
733
+ state.__changeMarker__.destroyCallbacks.push(() => {
734
+ isDestroyed = true;
735
+ });
736
+ }
737
+ else if (instance instanceof core.Component) {
738
+ throw collaborateErrorFn(`component name \`${componentName}\` is not a async component.`);
739
+ }
740
+ }
741
+ else {
742
+ const sharedState = yMap.get('state');
743
+ const state = this.createLocalMapBySharedMap(sharedState);
744
+ instance = this.registry.createComponentByData(componentName, state);
745
+ }
654
746
  if (instance) {
655
747
  return instance;
656
748
  }
@@ -664,7 +756,7 @@ exports.Collaborate = class Collaborate {
664
756
  */
665
757
  syncArray(sharedArray, localArray) {
666
758
  const sub = localArray.__changeMarker__.onSelfChange.subscribe((actions) => {
667
- this.runLocalUpdate(() => {
759
+ this.runLocalUpdate(sharedArray.doc, !localArray.__changeMarker__.irrevocableUpdate, () => {
668
760
  let index = 0;
669
761
  for (const action of actions) {
670
762
  switch (action.type) {
@@ -695,7 +787,7 @@ exports.Collaborate = class Collaborate {
695
787
  break;
696
788
  }
697
789
  }
698
- }, !localArray.__changeMarker__.irrevocableUpdate);
790
+ });
699
791
  });
700
792
  const syncRemote = (ev, tr) => {
701
793
  this.runRemoteUpdate(tr, () => {
@@ -745,7 +837,7 @@ exports.Collaborate = class Collaborate {
745
837
  };
746
838
  sharedObject.observe(syncRemote);
747
839
  const sub = localObject.__changeMarker__.onSelfChange.subscribe((actions) => {
748
- this.runLocalUpdate(() => {
840
+ this.runLocalUpdate(sharedObject.doc, !localObject.__changeMarker__.irrevocableUpdate, () => {
749
841
  for (const action of actions) {
750
842
  switch (action.type) {
751
843
  case 'propSet':
@@ -756,28 +848,33 @@ exports.Collaborate = class Collaborate {
756
848
  break;
757
849
  }
758
850
  }
759
- }, !localObject.__changeMarker__.irrevocableUpdate);
851
+ });
760
852
  });
761
853
  localObject.__changeMarker__.destroyCallbacks.push(function () {
762
854
  sharedObject.unobserve(syncRemote);
763
855
  sub.unsubscribe();
764
856
  });
765
857
  }
766
- runLocalUpdate(fn, record) {
767
- if (this.updateFromRemote) {
858
+ runLocalUpdate(yDoc, record, fn) {
859
+ if (this.updateFromRemote || !yDoc) {
768
860
  return;
769
861
  }
770
- this.updateRemoteActions.push({
862
+ let changeList = this.updateRemoteActions.get(yDoc);
863
+ if (!changeList) {
864
+ changeList = [];
865
+ this.updateRemoteActions.set(yDoc, changeList);
866
+ }
867
+ changeList.push({
771
868
  record,
772
869
  action: fn
773
870
  });
774
871
  }
775
872
  runRemoteUpdate(tr, fn) {
776
- if (tr.origin === this.yDoc) {
873
+ if (tr.origin === tr.doc) {
777
874
  return;
778
875
  }
779
876
  this.updateFromRemote = true;
780
- if (tr.origin === this.manager) {
877
+ if (tr.origin instanceof yjs.UndoManager) {
781
878
  this.scheduler.historyApplyTransact(fn);
782
879
  }
783
880
  else {
@@ -788,13 +885,10 @@ exports.Collaborate = class Collaborate {
788
885
  };
789
886
  exports.Collaborate = __decorate([
790
887
  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,
888
+ __metadata("design:paramtypes", [core.Scheduler,
795
889
  core.Registry,
796
890
  core.Selection,
797
- CustomUndoManagerConfig])
891
+ SubModelLoader])
798
892
  ], exports.Collaborate);
799
893
  function remoteFormatsToLocal(registry, attrs) {
800
894
  const formats = [];
@@ -809,6 +903,138 @@ function remoteFormatsToLocal(registry, attrs) {
809
903
  return formats;
810
904
  }
811
905
 
906
+ class CustomUndoManagerConfig {
907
+ }
908
+ const collabHistoryErrorFn = core.makeError('CollabHistory');
909
+ exports.CollabHistory = class CollabHistory {
910
+ get canBack() {
911
+ var _a;
912
+ return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canUndo()) || false;
913
+ }
914
+ get canForward() {
915
+ var _a;
916
+ return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canRedo()) || false;
917
+ }
918
+ constructor(rootComponentRef, collaborate, scheduler, selection, stackSize, undoManagerConfig) {
919
+ this.rootComponentRef = rootComponentRef;
920
+ this.collaborate = collaborate;
921
+ this.scheduler = scheduler;
922
+ this.selection = selection;
923
+ this.stackSize = stackSize;
924
+ this.undoManagerConfig = undoManagerConfig;
925
+ this.manager = null;
926
+ this.historyItems = [];
927
+ this.index = 0;
928
+ this.subscriptions = [];
929
+ this.backEvent = new stream.Subject();
930
+ this.forwardEvent = new stream.Subject();
931
+ this.changeEvent = new stream.Subject();
932
+ this.pushEvent = new stream.Subject();
933
+ this.onBack = this.backEvent.asObservable();
934
+ this.onForward = this.forwardEvent.asObservable();
935
+ this.onChange = this.changeEvent.asObservable();
936
+ this.onPush = this.pushEvent.asObservable();
937
+ }
938
+ listen() {
939
+ const root = this.collaborate.yDoc.getMap('RootComponent');
940
+ const rootComponent = this.rootComponentRef.component;
941
+ this.collaborate.syncRootComponent(this.collaborate.yDoc, root, rootComponent);
942
+ const undoManagerConfig = this.undoManagerConfig || {};
943
+ const manager = new yjs.UndoManager(root, {
944
+ trackedOrigins: new Set([this.collaborate.yDoc]),
945
+ captureTransaction(arg) {
946
+ if (undoManagerConfig.captureTransaction) {
947
+ return undoManagerConfig.captureTransaction(arg);
948
+ }
949
+ return true;
950
+ },
951
+ deleteFilter(item) {
952
+ if (undoManagerConfig.deleteFilter) {
953
+ return undoManagerConfig.deleteFilter(item);
954
+ }
955
+ return true;
956
+ }
957
+ });
958
+ this.manager = manager;
959
+ let beforePosition = null;
960
+ this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
961
+ beforePosition = this.collaborate.getRelativeCursorLocation();
962
+ }), this.collaborate.onAddSubModel.subscribe(() => {
963
+ throw collabHistoryErrorFn('single document does not support submodels.');
964
+ }));
965
+ manager.on('stack-item-added', (event) => {
966
+ if (event.type === 'undo') {
967
+ if (event.origin === manager) {
968
+ this.index++;
969
+ }
970
+ else {
971
+ this.historyItems.length = this.index;
972
+ this.historyItems.push({
973
+ before: beforePosition,
974
+ after: this.collaborate.getRelativeCursorLocation()
975
+ });
976
+ this.index++;
977
+ }
978
+ }
979
+ else {
980
+ this.index--;
981
+ }
982
+ if (manager.undoStack.length > this.stackSize) {
983
+ this.historyItems.shift();
984
+ manager.undoStack.shift();
985
+ }
986
+ if (event.origin === this.collaborate.yDoc) {
987
+ this.pushEvent.next();
988
+ }
989
+ this.changeEvent.next();
990
+ });
991
+ manager.on('stack-item-popped', (ev) => {
992
+ const index = ev.type === 'undo' ? this.index : this.index - 1;
993
+ const position = this.historyItems[index] || null;
994
+ const p = ev.type === 'undo' ? position === null || position === void 0 ? void 0 : position.before : position === null || position === void 0 ? void 0 : position.after;
995
+ this.collaborate.restoreCursorPosition(p);
996
+ });
997
+ }
998
+ back() {
999
+ var _a;
1000
+ if (this.canBack) {
1001
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.undo();
1002
+ this.backEvent.next();
1003
+ }
1004
+ }
1005
+ forward() {
1006
+ var _a;
1007
+ if (this.canForward) {
1008
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.redo();
1009
+ this.forwardEvent.next();
1010
+ }
1011
+ }
1012
+ clear() {
1013
+ var _a;
1014
+ const last = this.historyItems.pop();
1015
+ this.historyItems = last ? [last] : [];
1016
+ this.index = last ? 1 : 0;
1017
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
1018
+ this.changeEvent.next();
1019
+ }
1020
+ destroy() {
1021
+ var _a;
1022
+ this.index = 0;
1023
+ this.historyItems = [];
1024
+ this.subscriptions.forEach(i => i.unsubscribe());
1025
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
1026
+ }
1027
+ };
1028
+ exports.CollabHistory = __decorate([
1029
+ core$1.Injectable(),
1030
+ __param(4, core$1.Inject(core.HISTORY_STACK_SIZE)),
1031
+ __param(5, core$1.Optional()),
1032
+ __metadata("design:paramtypes", [core.RootComponentRef,
1033
+ exports.Collaborate,
1034
+ core.Scheduler,
1035
+ core.Selection, Number, CustomUndoManagerConfig])
1036
+ ], exports.CollabHistory);
1037
+
812
1038
  exports.UserActivity = class UserActivity {
813
1039
  constructor(syncConnector, selection) {
814
1040
  this.syncConnector = syncConnector;
@@ -857,15 +1083,235 @@ class CollaborateModule {
857
1083
  this.providers = [
858
1084
  exports.Collaborate,
859
1085
  exports.UserActivity,
1086
+ exports.CollabHistory,
1087
+ {
1088
+ provide: core.History,
1089
+ useExisting: exports.CollabHistory
1090
+ }, {
1091
+ provide: SyncConnector,
1092
+ useFactory: (collab) => {
1093
+ return this.config.createConnector(collab.yDoc);
1094
+ },
1095
+ deps: [exports.Collaborate]
1096
+ }, {
1097
+ provide: SubModelLoader,
1098
+ useClass: exports.NonSubModelLoader
1099
+ }
1100
+ ];
1101
+ }
1102
+ setup(textbus) {
1103
+ const connector = textbus.get(SyncConnector);
1104
+ const userActivity = textbus.get(exports.UserActivity);
1105
+ userActivity.init(this.config.userinfo);
1106
+ return connector.onLoad.toPromise();
1107
+ }
1108
+ onDestroy(textbus) {
1109
+ textbus.get(exports.Collaborate).destroy();
1110
+ textbus.get(core.History).destroy();
1111
+ textbus.get(exports.UserActivity).destroy();
1112
+ textbus.get(SyncConnector).onDestroy();
1113
+ }
1114
+ }
1115
+
1116
+ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1117
+ get canBack() {
1118
+ return this.actionStack.length > 0 && this.index > 0;
1119
+ }
1120
+ get canForward() {
1121
+ return this.actionStack.length > 0 && this.index < this.actionStack.length;
1122
+ }
1123
+ constructor(collaborate, scheduler, rootComponentRef, stackSize, undoManagerConfig) {
1124
+ this.collaborate = collaborate;
1125
+ this.scheduler = scheduler;
1126
+ this.rootComponentRef = rootComponentRef;
1127
+ this.stackSize = stackSize;
1128
+ this.undoManagerConfig = undoManagerConfig;
1129
+ this.isListen = false;
1130
+ this.changeEvent = new stream.Subject();
1131
+ this.backEvent = new stream.Subject();
1132
+ this.forwardEvent = new stream.Subject();
1133
+ this.pushEvent = new stream.Subject();
1134
+ this.actionStack = [];
1135
+ this.index = 0;
1136
+ this.stackItem = null;
1137
+ this.timer = null;
1138
+ this.beforePosition = null;
1139
+ this.subscription = new stream.Subscription();
1140
+ this.subDocs = new Set();
1141
+ this.listenerCaches = new Set();
1142
+ this.onChange = this.changeEvent.asObservable();
1143
+ this.onBack = this.backEvent.asObservable();
1144
+ this.onForward = this.forwardEvent.asObservable();
1145
+ this.onPush = this.pushEvent.asObservable();
1146
+ }
1147
+ listen() {
1148
+ this.isListen = true;
1149
+ const root = this.collaborate.yDoc.getMap('RootComponent');
1150
+ const rootComponent = this.rootComponentRef.component;
1151
+ this.collaborate.syncRootComponent(this.collaborate.yDoc, root, rootComponent);
1152
+ this.listenItem(root, this.collaborate.yDoc);
1153
+ this.subscription.add(this.collaborate.onAddSubModel.subscribe(({ yType, yDoc }) => {
1154
+ if (this.subDocs.has(yType)) {
1155
+ return;
1156
+ }
1157
+ this.subDocs.add(yType);
1158
+ if (this.isListen) {
1159
+ this.listenItem(yType, yDoc);
1160
+ }
1161
+ }), this.scheduler.onLocalChangeBefore.subscribe(() => {
1162
+ this.beforePosition = this.collaborate.getRelativeCursorLocation();
1163
+ }));
1164
+ }
1165
+ forward() {
1166
+ if (!this.canForward) {
1167
+ return;
1168
+ }
1169
+ clearTimeout(this.timer);
1170
+ const item = this.actionStack[this.index];
1171
+ if (item) {
1172
+ for (const i of item.undoManagers) {
1173
+ i.redo();
1174
+ }
1175
+ this.collaborate.restoreCursorPosition(item.after);
1176
+ }
1177
+ this.index++;
1178
+ this.forwardEvent.next();
1179
+ this.changeEvent.next();
1180
+ }
1181
+ back() {
1182
+ if (!this.canBack) {
1183
+ return;
1184
+ }
1185
+ clearTimeout(this.timer);
1186
+ let historyStackItem;
1187
+ if (this.stackItem) {
1188
+ historyStackItem = this.stackItem;
1189
+ this.stackItem = null;
1190
+ }
1191
+ else {
1192
+ this.index--;
1193
+ historyStackItem = this.actionStack[this.index];
1194
+ }
1195
+ let len = historyStackItem.undoManagers.length;
1196
+ while (len > 0) {
1197
+ len--;
1198
+ historyStackItem.undoManagers[len].undo();
1199
+ }
1200
+ if (historyStackItem) {
1201
+ const beforePosition = historyStackItem.before;
1202
+ this.collaborate.restoreCursorPosition(beforePosition);
1203
+ this.backEvent.next();
1204
+ this.changeEvent.next();
1205
+ }
1206
+ }
1207
+ clear() {
1208
+ this.actionStack = [];
1209
+ this.stackItem = null;
1210
+ this.index = 0;
1211
+ this.beforePosition = null;
1212
+ clearTimeout(this.timer);
1213
+ this.listenerCaches.forEach((undoManager) => {
1214
+ undoManager.clear();
1215
+ });
1216
+ this.changeEvent.next();
1217
+ }
1218
+ destroy() {
1219
+ this.clear();
1220
+ this.beforePosition = this.stackItem = null;
1221
+ this.subscription.unsubscribe();
1222
+ this.listenerCaches.forEach((undoManager) => {
1223
+ undoManager.destroy();
1224
+ });
1225
+ this.subDocs.clear();
1226
+ this.listenerCaches.clear();
1227
+ }
1228
+ listenItem(yType, yDoc) {
1229
+ const undoManagerConfig = this.undoManagerConfig || {};
1230
+ const undoManager = new yjs.UndoManager(yType, {
1231
+ trackedOrigins: new Set([yDoc]),
1232
+ captureTimeout: 0,
1233
+ captureTransaction(arg) {
1234
+ if (undoManagerConfig.captureTransaction) {
1235
+ return undoManagerConfig.captureTransaction(arg);
1236
+ }
1237
+ return true;
1238
+ },
1239
+ deleteFilter(item) {
1240
+ if (undoManagerConfig.deleteFilter) {
1241
+ return undoManagerConfig.deleteFilter(item);
1242
+ }
1243
+ return true;
1244
+ }
1245
+ });
1246
+ undoManager.on('stack-item-added', (event) => {
1247
+ if (event.type === 'undo' && !(event.origin instanceof yjs.UndoManager)) {
1248
+ if (this.index != this.actionStack.length) {
1249
+ const redoStack = this.actionStack.slice(this.index);
1250
+ redoStack.forEach(item => {
1251
+ item.undoManagers.forEach(i => {
1252
+ i.clear(false, true);
1253
+ });
1254
+ });
1255
+ this.actionStack.length = this.index;
1256
+ this.changeEvent.next();
1257
+ }
1258
+ if (this.stackItem === null) {
1259
+ this.stackItem = {
1260
+ before: this.beforePosition,
1261
+ after: null,
1262
+ undoManagers: []
1263
+ };
1264
+ this.timer = setTimeout(() => {
1265
+ if (this.actionStack.length >= this.stackSize) {
1266
+ this.actionStack.shift();
1267
+ }
1268
+ else {
1269
+ this.index++;
1270
+ }
1271
+ // this.beforePosition = this.collaborate.getRelativeCursorLocation()
1272
+ this.stackItem.after = this.beforePosition;
1273
+ this.actionStack.push(this.stackItem);
1274
+ this.stackItem = null;
1275
+ this.pushEvent.next();
1276
+ this.changeEvent.next();
1277
+ }, 500);
1278
+ }
1279
+ this.stackItem.undoManagers.push(undoManager);
1280
+ }
1281
+ });
1282
+ this.listenerCaches.add(undoManager);
1283
+ }
1284
+ };
1285
+ exports.MultipleDocCollabHistory = __decorate([
1286
+ core$1.Injectable(),
1287
+ __param(3, core$1.Inject(core.HISTORY_STACK_SIZE)),
1288
+ __param(4, core$1.Optional()),
1289
+ __metadata("design:paramtypes", [exports.Collaborate,
1290
+ core.Scheduler,
1291
+ core.RootComponentRef, Number, CustomUndoManagerConfig])
1292
+ ], exports.MultipleDocCollabHistory);
1293
+
1294
+ class MultipleDocumentCollaborateModule {
1295
+ constructor(config) {
1296
+ this.config = config;
1297
+ this.providers = [
1298
+ exports.Collaborate,
1299
+ exports.UserActivity,
1300
+ exports.MultipleDocCollabHistory,
860
1301
  {
861
1302
  provide: core.History,
862
- useExisting: exports.Collaborate
1303
+ useExisting: exports.MultipleDocCollabHistory
863
1304
  }, {
864
1305
  provide: SyncConnector,
865
1306
  useFactory: (collab) => {
866
1307
  return this.config.createConnector(collab.yDoc);
867
1308
  },
868
1309
  deps: [exports.Collaborate]
1310
+ }, {
1311
+ provide: SubModelLoader,
1312
+ useFactory: () => {
1313
+ return this.config.subModelLoader;
1314
+ }
869
1315
  }
870
1316
  ];
871
1317
  }
@@ -876,6 +1322,8 @@ class CollaborateModule {
876
1322
  return connector.onLoad.toPromise();
877
1323
  }
878
1324
  onDestroy(textbus) {
1325
+ textbus.get(exports.Collaborate).destroy();
1326
+ textbus.get(core.History).destroy();
879
1327
  textbus.get(exports.UserActivity).destroy();
880
1328
  textbus.get(SyncConnector).onDestroy();
881
1329
  }
@@ -884,5 +1332,7 @@ class CollaborateModule {
884
1332
  exports.CollaborateModule = CollaborateModule;
885
1333
  exports.CustomUndoManagerConfig = CustomUndoManagerConfig;
886
1334
  exports.HocuspocusConnector = HocuspocusConnector;
1335
+ exports.MultipleDocumentCollaborateModule = MultipleDocumentCollaborateModule;
1336
+ exports.SubModelLoader = SubModelLoader;
887
1337
  exports.SyncConnector = SyncConnector;
888
1338
  exports.YWebsocketConnector = YWebsocketConnector;