@textbus/collaborate 4.0.4 → 4.1.0-alpha.1

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