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