@textbus/collaborate 4.0.4 → 4.1.0-alpha.0

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, 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 };