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