@textbus/collaborate 4.0.4 → 4.1.0-alpha.1

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