@textbus/collaborate 3.1.7 → 3.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,743 +33,753 @@ function __metadata(metadataKey, metadataValue) {
33
33
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
34
34
  }
35
35
 
36
- const collaborateErrorFn = makeError('Collaborate');
37
- class ContentMap {
38
- constructor() {
39
- this.slotAndYTextMap = new WeakMap();
40
- this.yTextAndSLotMap = new WeakMap();
41
- }
42
- set(key, value) {
43
- if (key instanceof Slot) {
44
- this.slotAndYTextMap.set(key, value);
45
- this.yTextAndSLotMap.set(value, key);
46
- }
47
- else {
48
- this.slotAndYTextMap.set(value, key);
49
- this.yTextAndSLotMap.set(key, value);
50
- }
51
- }
52
- get(key) {
53
- if (key instanceof Slot) {
54
- return this.slotAndYTextMap.get(key) || null;
55
- }
56
- return this.yTextAndSLotMap.get(key) || null;
57
- }
58
- delete(key) {
59
- if (key instanceof Slot) {
60
- const v = this.slotAndYTextMap.get(key);
61
- this.slotAndYTextMap.delete(key);
62
- if (v) {
63
- this.yTextAndSLotMap.delete(v);
64
- }
65
- }
66
- else {
67
- const v = this.yTextAndSLotMap.get(key);
68
- this.yTextAndSLotMap.delete(key);
69
- if (v) {
70
- this.slotAndYTextMap.delete(v);
71
- }
72
- }
73
- }
74
- }
75
- class CustomUndoManagerConfig {
76
- }
77
- let Collaborate = class Collaborate {
78
- get canBack() {
79
- var _a;
80
- return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canUndo()) || false;
81
- }
82
- get canForward() {
83
- var _a;
84
- return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canRedo()) || false;
85
- }
86
- constructor(stackSize, rootComponentRef, controller, scheduler, registry, selection, starter, undoManagerConfig) {
87
- this.stackSize = stackSize;
88
- this.rootComponentRef = rootComponentRef;
89
- this.controller = controller;
90
- this.scheduler = scheduler;
91
- this.registry = registry;
92
- this.selection = selection;
93
- this.starter = starter;
94
- this.undoManagerConfig = undoManagerConfig;
95
- this.yDoc = new Doc();
96
- this.backEvent = new Subject();
97
- this.forwardEvent = new Subject();
98
- this.changeEvent = new Subject();
99
- this.pushEvent = new Subject();
100
- this.manager = null;
101
- this.subscriptions = [];
102
- this.updateFromRemote = false;
103
- this.contentSyncCaches = new WeakMap();
104
- this.slotStateSyncCaches = new WeakMap();
105
- this.slotsSyncCaches = new WeakMap();
106
- this.componentStateSyncCaches = new WeakMap();
107
- this.localChangesAppliedEvent = new Subject();
108
- this.selectionChangeEvent = new Subject();
109
- this.contentMap = new ContentMap();
110
- this.updateRemoteActions = [];
111
- this.noRecord = {};
112
- this.historyItems = [];
113
- this.index = 0;
114
- this.onBack = this.backEvent.asObservable();
115
- this.onForward = this.forwardEvent.asObservable();
116
- this.onChange = this.changeEvent.asObservable();
117
- this.onPush = this.pushEvent.asObservable();
118
- this.onLocalChangesApplied = this.localChangesAppliedEvent.asObservable();
119
- }
120
- listen() {
121
- const root = this.yDoc.getMap('RootComponent');
122
- const rootComponent = this.rootComponentRef.component;
123
- const undoManagerConfig = this.undoManagerConfig || {};
124
- const manager = new UndoManager(root, {
125
- trackedOrigins: new Set([this.yDoc]),
126
- captureTransaction(arg) {
127
- if (undoManagerConfig.captureTransaction) {
128
- return undoManagerConfig.captureTransaction(arg);
129
- }
130
- return true;
131
- },
132
- deleteFilter(item) {
133
- if (undoManagerConfig.deleteFilter) {
134
- return undoManagerConfig.deleteFilter(item);
135
- }
136
- return true;
137
- }
138
- });
139
- this.manager = manager;
140
- manager.on('stack-item-added', event => {
141
- if (event.type === 'undo') {
142
- if (event.origin === manager) {
143
- this.index++;
144
- }
145
- else {
146
- this.historyItems.length = this.index;
147
- this.historyItems.push(this.getRelativeCursorLocation());
148
- this.index++;
149
- }
150
- }
151
- else {
152
- this.index--;
153
- }
154
- if (manager.undoStack.length > this.stackSize) {
155
- this.historyItems.shift();
156
- manager.undoStack.shift();
157
- }
158
- if (event.origin === this.yDoc) {
159
- this.pushEvent.next();
160
- }
161
- this.changeEvent.next();
162
- });
163
- manager.on('stack-item-popped', () => {
164
- const position = this.historyItems[this.index - 1];
165
- if (position) {
166
- const selection = this.getAbstractSelection(position);
167
- if (selection) {
168
- this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
169
- return;
170
- }
171
- }
172
- this.selection.unSelect();
173
- });
174
- this.subscriptions.push(this.selection.onChange.subscribe(() => {
175
- const paths = this.selection.getPaths();
176
- this.selectionChangeEvent.next(paths);
177
- }), this.scheduler.onDocChanged.pipe(map(item => {
178
- return item.filter(i => {
179
- return i.from !== ChangeOrigin.Remote;
180
- });
181
- }), filter(item => {
182
- return item.length;
183
- })).subscribe(() => {
184
- const updates = [];
185
- let update = null;
186
- for (const item of this.updateRemoteActions) {
187
- if (!update) {
188
- update = {
189
- record: item.record,
190
- actions: []
191
- };
192
- updates.push(update);
193
- }
194
- if (update.record === item.record) {
195
- update.actions.push(item.action);
196
- }
197
- else {
198
- update = {
199
- record: item.record,
200
- actions: [item.action]
201
- };
202
- updates.push(update);
203
- }
204
- }
205
- this.updateRemoteActions = [];
206
- for (const item of updates) {
207
- this.yDoc.transact(() => {
208
- item.actions.forEach(fn => {
209
- fn();
210
- });
211
- }, item.record ? this.yDoc : this.noRecord);
212
- }
213
- this.localChangesAppliedEvent.next();
214
- }));
215
- this.syncRootComponent(root, rootComponent);
216
- }
217
- back() {
218
- var _a;
219
- if (this.canBack) {
220
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.undo();
221
- this.backEvent.next();
222
- }
223
- }
224
- forward() {
225
- var _a;
226
- if (this.canForward) {
227
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.redo();
228
- this.forwardEvent.next();
229
- }
230
- }
231
- clear() {
232
- var _a;
233
- this.index = 0;
234
- this.historyItems = [];
235
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
236
- this.changeEvent.next();
237
- }
238
- destroy() {
239
- var _a;
240
- this.index = 0;
241
- this.historyItems = [];
242
- this.subscriptions.forEach(i => i.unsubscribe());
243
- (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
244
- }
245
- syncRootComponent(root, rootComponent) {
246
- let slots = root.get('slots');
247
- if (!slots) {
248
- slots = new Array();
249
- rootComponent.slots.toArray().forEach(i => {
250
- const sharedSlot = this.createSharedSlotBySlot(i);
251
- slots.push([sharedSlot]);
252
- });
253
- this.yDoc.transact(() => {
254
- root.set('state', rootComponent.state);
255
- root.set('slots', slots);
256
- });
257
- }
258
- else if (slots.length === 0) {
259
- rootComponent.updateState(() => {
260
- return root.get('state');
261
- });
262
- this.yDoc.transact(() => {
263
- rootComponent.slots.toArray().forEach(i => {
264
- const sharedSlot = this.createSharedSlotBySlot(i);
265
- slots.push([sharedSlot]);
266
- });
267
- });
268
- }
269
- else {
270
- rootComponent.updateState(() => {
271
- return root.get('state');
272
- });
273
- rootComponent.slots.clean();
274
- slots.forEach(sharedSlot => {
275
- const slot = this.createSlotBySharedSlot(sharedSlot);
276
- this.syncSlotContent(sharedSlot.get('content'), slot);
277
- this.syncSlotState(sharedSlot, slot);
278
- rootComponent.slots.insert(slot);
279
- });
280
- }
281
- this.syncComponentState(root, rootComponent);
282
- this.syncComponentSlots(slots, rootComponent);
283
- }
284
- getAbstractSelection(position) {
285
- const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
286
- const focusPosition = createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
287
- if (anchorPosition && focusPosition) {
288
- const focusSlot = this.contentMap.get(focusPosition.type);
289
- const anchorSlot = this.contentMap.get(anchorPosition.type);
290
- if (focusSlot && anchorSlot) {
291
- return {
292
- anchorSlot,
293
- anchorOffset: anchorPosition.index,
294
- focusSlot,
295
- focusOffset: focusPosition.index
296
- };
297
- }
298
- }
299
- return null;
300
- }
301
- getRelativeCursorLocation() {
302
- const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
303
- if (anchorSlot) {
304
- const anchorYText = this.contentMap.get(anchorSlot);
305
- if (anchorYText) {
306
- const anchorPosition = createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
307
- if (focusSlot) {
308
- const focusYText = this.contentMap.get(focusSlot);
309
- if (focusYText) {
310
- const focusPosition = createRelativePositionFromTypeIndex(focusYText, focusOffset);
311
- return {
312
- focus: focusPosition,
313
- anchor: anchorPosition
314
- };
315
- }
316
- }
317
- }
318
- }
319
- return null;
320
- }
321
- syncSlotContent(content, slot) {
322
- this.contentMap.set(slot, content);
323
- const syncRemote = (ev, tr) => {
324
- this.runRemoteUpdate(tr, () => {
325
- slot.retain(0);
326
- ev.keysChanged.forEach(key => {
327
- const change = ev.keys.get(key);
328
- if (!change) {
329
- return;
330
- }
331
- const updateType = change.action;
332
- if (updateType === 'update' || updateType === 'add') {
333
- const attribute = this.registry.getAttribute(key);
334
- if (attribute) {
335
- slot.setAttribute(attribute, content.getAttribute(key));
336
- }
337
- }
338
- else if (updateType === 'delete') {
339
- const attribute = this.registry.getAttribute(key);
340
- if (attribute) {
341
- slot.removeAttribute(attribute);
342
- }
343
- }
344
- });
345
- ev.delta.forEach(action => {
346
- if (Reflect.has(action, 'retain')) {
347
- if (action.attributes) {
348
- const formats = remoteFormatsToLocal(this.registry, action.attributes);
349
- if (formats.length) {
350
- slot.retain(action.retain, formats);
351
- }
352
- slot.retain(slot.index + action.retain);
353
- }
354
- else {
355
- slot.retain(action.retain);
356
- }
357
- }
358
- else if (action.insert) {
359
- const index = slot.index;
360
- let length = 1;
361
- if (typeof action.insert === 'string') {
362
- length = action.insert.length;
363
- slot.insert(action.insert, remoteFormatsToLocal(this.registry, action.attributes));
364
- }
365
- else {
366
- const sharedComponent = action.insert;
367
- const component = this.createComponentBySharedComponent(sharedComponent);
368
- this.syncComponentSlots(sharedComponent.get('slots'), component);
369
- this.syncComponentState(sharedComponent, component);
370
- slot.insert(component);
371
- }
372
- if (this.selection.isSelected && tr.origin !== this.manager) {
373
- if (slot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
374
- this.selection.setAnchor(slot, this.selection.anchorOffset + length);
375
- }
376
- if (slot === this.selection.focusSlot && this.selection.focusOffset > index) {
377
- this.selection.setFocus(slot, this.selection.focusOffset + length);
378
- }
379
- }
380
- }
381
- else if (action.delete) {
382
- const index = slot.index;
383
- slot.delete(action.delete);
384
- if (this.selection.isSelected && tr.origin !== this.manager) {
385
- if (slot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
386
- this.selection.setAnchor(slot, this.selection.startOffset - action.delete);
387
- }
388
- if (slot === this.selection.focusSlot && this.selection.focusOffset >= index) {
389
- this.selection.setFocus(slot, this.selection.focusOffset - action.delete);
390
- }
391
- }
392
- }
393
- });
394
- });
395
- };
396
- content.observe(syncRemote);
397
- const sub = slot.onContentChange.subscribe(actions => {
398
- this.runLocalUpdate(() => {
399
- var _a;
400
- let offset = 0;
401
- let length = 0;
402
- for (const action of actions) {
403
- if (action.type === 'retain') {
404
- const formats = action.formats;
405
- if (formats) {
406
- const keys = Object.keys(formats);
407
- let length = keys.length;
408
- keys.forEach(key => {
409
- const formatter = this.registry.getFormatter(key);
410
- if (!formatter) {
411
- length--;
412
- Reflect.deleteProperty(formats, key);
413
- }
414
- });
415
- if (length) {
416
- content.format(offset, action.offset, formats);
417
- }
418
- }
419
- else {
420
- offset = action.offset;
421
- }
422
- }
423
- else if (action.type === 'insert') {
424
- const delta = content.toDelta();
425
- const isEmpty = delta.length === 1 && delta[0].insert === Slot.emptyPlaceholder;
426
- if (typeof action.content === 'string') {
427
- length = action.content.length;
428
- content.insert(offset, action.content, action.formats || {});
429
- }
430
- else {
431
- length = 1;
432
- const sharedComponent = this.createSharedComponentByComponent(action.ref);
433
- content.insertEmbed(offset, sharedComponent, action.formats || {});
434
- }
435
- if (isEmpty && offset === 0) {
436
- content.delete(content.length - 1, 1);
437
- }
438
- offset += length;
439
- }
440
- else if (action.type === 'delete') {
441
- const delta = content.toDelta();
442
- if (content.length) {
443
- content.delete(offset, action.count);
444
- }
445
- if (content.length === 0) {
446
- content.insert(0, '\n', (_a = delta[0]) === null || _a === void 0 ? void 0 : _a.attributes);
447
- }
448
- }
449
- else if (action.type === 'attrSet') {
450
- content.setAttribute(action.name, action.value);
451
- }
452
- else if (action.type === 'attrRemove') {
453
- content.removeAttribute(action.name);
454
- }
455
- }
456
- });
457
- });
458
- sub.add(slot.onChildComponentRemove.subscribe(components => {
459
- components.forEach(c => {
460
- this.cleanSubscriptionsByComponent(c);
461
- });
462
- }));
463
- this.contentSyncCaches.set(slot, () => {
464
- content.unobserve(syncRemote);
465
- sub.unsubscribe();
466
- });
467
- }
468
- syncSlotState(remoteSlot, slot) {
469
- const syncRemote = (ev, tr) => {
470
- this.runRemoteUpdate(tr, () => {
471
- ev.keysChanged.forEach(key => {
472
- if (key === 'state') {
473
- const state = ev.target.get('state');
474
- slot.updateState(draft => {
475
- if (typeof draft === 'object' && draft !== null) {
476
- Object.assign(draft, state);
477
- }
478
- else {
479
- return state;
480
- }
481
- });
482
- }
483
- });
484
- });
485
- };
486
- remoteSlot.observe(syncRemote);
487
- const sub = slot.onStateChange.subscribe(change => {
488
- this.runLocalUpdate(() => {
489
- remoteSlot.set('state', change.newState);
490
- }, change.record);
491
- });
492
- this.slotStateSyncCaches.set(slot, () => {
493
- remoteSlot.unobserve(syncRemote);
494
- sub.unsubscribe();
495
- });
496
- }
497
- syncComponentSlots(remoteSlots, component) {
498
- const slots = component.slots;
499
- const syncRemote = (ev, tr) => {
500
- this.runRemoteUpdate(tr, () => {
501
- let index = 0;
502
- slots.retain(index);
503
- ev.delta.forEach(action => {
504
- if (Reflect.has(action, 'retain')) {
505
- index += action.retain;
506
- slots.retain(index);
507
- }
508
- else if (action.insert) {
509
- action.insert.forEach(item => {
510
- const slot = this.createSlotBySharedSlot(item);
511
- slots.insert(slot);
512
- this.syncSlotContent(item.get('content'), slot);
513
- this.syncSlotState(item, slot);
514
- index++;
515
- });
516
- }
517
- else if (action.delete) {
518
- slots.retain(index);
519
- slots.delete(action.delete);
520
- }
521
- });
522
- });
523
- };
524
- remoteSlots.observe(syncRemote);
525
- const sub = slots.onChange.subscribe(operations => {
526
- this.runLocalUpdate(() => {
527
- const applyActions = operations.apply;
528
- let index;
529
- applyActions.forEach(action => {
530
- if (action.type === 'retain') {
531
- index = action.offset;
532
- }
533
- else if (action.type === 'insertSlot') {
534
- const sharedSlot = this.createSharedSlotBySlot(action.ref);
535
- remoteSlots.insert(index, [sharedSlot]);
536
- index++;
537
- }
538
- else if (action.type === 'delete') {
539
- remoteSlots.delete(index, action.count);
540
- }
541
- });
542
- });
543
- });
544
- sub.add(slots.onChildSlotRemove.subscribe(slots => {
545
- slots.forEach(slot => {
546
- this.cleanSubscriptionsBySlot(slot);
547
- });
548
- }));
549
- this.slotsSyncCaches.set(component, () => {
550
- remoteSlots.unobserve(syncRemote);
551
- sub.unsubscribe();
552
- });
553
- }
554
- syncComponentState(remoteComponent, component) {
555
- const syncRemote = (ev, tr) => {
556
- this.runRemoteUpdate(tr, () => {
557
- ev.keysChanged.forEach(key => {
558
- if (key === 'state') {
559
- const state = ev.target.get('state');
560
- component.updateState(draft => {
561
- if (typeof draft === 'object' && draft !== null) {
562
- Object.assign(draft, state);
563
- }
564
- else {
565
- return state;
566
- }
567
- });
568
- }
569
- });
570
- });
571
- };
572
- remoteComponent.observe(syncRemote);
573
- const sub = component.onStateChange.subscribe(change => {
574
- this.runLocalUpdate(() => {
575
- remoteComponent.set('state', change.newState);
576
- }, change.record);
577
- });
578
- this.componentStateSyncCaches.set(component, () => {
579
- remoteComponent.unobserve(syncRemote);
580
- sub.unsubscribe();
581
- });
582
- }
583
- runLocalUpdate(fn, record = true) {
584
- if (this.updateFromRemote || this.controller.readonly) {
585
- return;
586
- }
587
- this.updateRemoteActions.push({
588
- record,
589
- action: fn
590
- });
591
- }
592
- runRemoteUpdate(tr, fn) {
593
- if (tr.origin === this.yDoc) {
594
- return;
595
- }
596
- this.updateFromRemote = true;
597
- if (tr.origin === this.manager) {
598
- this.scheduler.historyApplyTransact(fn);
599
- }
600
- else {
601
- this.scheduler.remoteUpdateTransact(fn);
602
- }
603
- this.updateFromRemote = false;
604
- }
605
- createSharedComponentByComponent(component) {
606
- const sharedComponent = new Map();
607
- sharedComponent.set('state', component.state);
608
- sharedComponent.set('name', component.name);
609
- const sharedSlots = new Array();
610
- sharedComponent.set('slots', sharedSlots);
611
- component.slots.toArray().forEach(slot => {
612
- const sharedSlot = this.createSharedSlotBySlot(slot);
613
- sharedSlots.push([sharedSlot]);
614
- });
615
- this.syncComponentSlots(sharedSlots, component);
616
- this.syncComponentState(sharedComponent, component);
617
- return sharedComponent;
618
- }
619
- createSharedSlotBySlot(slot) {
620
- const sharedSlot = new Map();
621
- sharedSlot.set('schema', slot.schema);
622
- sharedSlot.set('state', slot.state);
623
- const sharedContent = new Text();
624
- sharedSlot.set('content', sharedContent);
625
- let offset = 0;
626
- slot.toDelta().forEach(i => {
627
- let formats = {};
628
- if (i.formats) {
629
- i.formats.forEach(item => {
630
- formats[item[0].name] = item[1];
631
- });
632
- }
633
- else {
634
- formats = null;
635
- }
636
- if (typeof i.insert === 'string') {
637
- sharedContent.insert(offset, i.insert, formats);
638
- }
639
- else {
640
- const sharedComponent = this.createSharedComponentByComponent(i.insert);
641
- sharedContent.insertEmbed(offset, sharedComponent, formats);
642
- }
643
- offset += i.insert.length;
644
- });
645
- slot.getAttributes().forEach(item => {
646
- sharedContent.setAttribute(item[0].name, item[1]);
647
- });
648
- this.syncSlotContent(sharedContent, slot);
649
- this.syncSlotState(sharedSlot, slot);
650
- return sharedSlot;
651
- }
652
- createComponentBySharedComponent(yMap) {
653
- const sharedSlots = yMap.get('slots');
654
- const slots = [];
655
- sharedSlots.forEach(sharedSlot => {
656
- const slot = this.createSlotBySharedSlot(sharedSlot);
657
- slots.push(slot);
658
- });
659
- const name = yMap.get('name');
660
- const state = yMap.get('state');
661
- const instance = this.registry.createComponentByData(name, {
662
- state,
663
- slots
664
- });
665
- if (instance) {
666
- instance.slots.toArray().forEach((slot, index) => {
667
- let sharedSlot = sharedSlots.get(index);
668
- if (!sharedSlot) {
669
- sharedSlot = this.createSharedSlotBySlot(slot);
670
- sharedSlots.push([sharedSlot]);
671
- }
672
- this.syncSlotState(sharedSlot, slot);
673
- this.syncSlotContent(sharedSlot.get('content'), slot);
674
- });
675
- return instance;
676
- }
677
- throw collaborateErrorFn(`cannot find component factory \`${name}\`.`);
678
- }
679
- createSlotBySharedSlot(sharedSlot) {
680
- const content = sharedSlot.get('content');
681
- const delta = content.toDelta();
682
- const slot = this.registry.createSlot({
683
- schema: sharedSlot.get('schema'),
684
- state: sharedSlot.get('state'),
685
- attributes: {},
686
- formats: {},
687
- content: []
688
- });
689
- const attrs = content.getAttributes();
690
- Object.keys(attrs).forEach(key => {
691
- const attribute = this.registry.getAttribute(key);
692
- if (attribute) {
693
- slot.setAttribute(attribute, attrs[key]);
694
- }
695
- });
696
- for (const action of delta) {
697
- if (action.insert) {
698
- if (typeof action.insert === 'string') {
699
- const formats = remoteFormatsToLocal(this.registry, action.attributes);
700
- slot.insert(action.insert, formats);
701
- }
702
- else {
703
- const sharedComponent = action.insert;
704
- const component = this.createComponentBySharedComponent(sharedComponent);
705
- slot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
706
- this.syncComponentSlots(sharedComponent.get('slots'), component);
707
- this.syncComponentState(sharedComponent, component);
708
- }
709
- }
710
- else {
711
- throw collaborateErrorFn('unexpected delta action.');
712
- }
713
- }
714
- return slot;
715
- }
716
- cleanSubscriptionsBySlot(slot) {
717
- this.contentMap.delete(slot);
718
- [this.contentSyncCaches.get(slot), this.slotStateSyncCaches.get(slot)].forEach(fn => {
719
- if (fn) {
720
- fn();
721
- }
722
- });
723
- slot.sliceContent().forEach(i => {
724
- if (typeof i !== 'string') {
725
- this.cleanSubscriptionsByComponent(i);
726
- }
727
- });
728
- }
729
- cleanSubscriptionsByComponent(component) {
730
- [this.slotsSyncCaches.get(component), this.componentStateSyncCaches.get(component)].forEach(fn => {
731
- if (fn) {
732
- fn();
733
- }
734
- });
735
- component.slots.toArray().forEach(slot => {
736
- this.cleanSubscriptionsBySlot(slot);
737
- });
738
- }
739
- };
740
- Collaborate = __decorate([
741
- Injectable(),
742
- __param(0, Inject(HISTORY_STACK_SIZE)),
743
- __param(7, Optional()),
744
- __metadata("design:paramtypes", [Number, RootComponentRef,
745
- Controller,
746
- Scheduler,
747
- Registry,
748
- Selection,
749
- Starter,
750
- CustomUndoManagerConfig])
751
- ], Collaborate);
752
- function remoteFormatsToLocal(registry, attrs) {
753
- const formats = [];
754
- if (attrs) {
755
- Object.keys(attrs).forEach(key => {
756
- const formatter = registry.getFormatter(key);
757
- if (formatter) {
758
- formats.push([formatter, attrs[key]]);
759
- }
760
- });
761
- }
762
- return formats;
36
+ const collaborateErrorFn = makeError('Collaborate');
37
+ class ContentMap {
38
+ constructor() {
39
+ this.slotAndYTextMap = new WeakMap();
40
+ this.yTextAndSLotMap = new WeakMap();
41
+ }
42
+ set(key, value) {
43
+ if (key instanceof Slot) {
44
+ this.slotAndYTextMap.set(key, value);
45
+ this.yTextAndSLotMap.set(value, key);
46
+ }
47
+ else {
48
+ this.slotAndYTextMap.set(value, key);
49
+ this.yTextAndSLotMap.set(key, value);
50
+ }
51
+ }
52
+ get(key) {
53
+ if (key instanceof Slot) {
54
+ return this.slotAndYTextMap.get(key) || null;
55
+ }
56
+ return this.yTextAndSLotMap.get(key) || null;
57
+ }
58
+ delete(key) {
59
+ if (key instanceof Slot) {
60
+ const v = this.slotAndYTextMap.get(key);
61
+ this.slotAndYTextMap.delete(key);
62
+ if (v) {
63
+ this.yTextAndSLotMap.delete(v);
64
+ }
65
+ }
66
+ else {
67
+ const v = this.yTextAndSLotMap.get(key);
68
+ this.yTextAndSLotMap.delete(key);
69
+ if (v) {
70
+ this.slotAndYTextMap.delete(v);
71
+ }
72
+ }
73
+ }
74
+ }
75
+ class CustomUndoManagerConfig {
76
+ }
77
+ let Collaborate = class Collaborate {
78
+ get canBack() {
79
+ var _a;
80
+ return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canUndo()) || false;
81
+ }
82
+ get canForward() {
83
+ var _a;
84
+ return ((_a = this.manager) === null || _a === void 0 ? void 0 : _a.canRedo()) || false;
85
+ }
86
+ constructor(stackSize, rootComponentRef, controller, scheduler, registry, selection, starter, undoManagerConfig) {
87
+ this.stackSize = stackSize;
88
+ this.rootComponentRef = rootComponentRef;
89
+ this.controller = controller;
90
+ this.scheduler = scheduler;
91
+ this.registry = registry;
92
+ this.selection = selection;
93
+ this.starter = starter;
94
+ this.undoManagerConfig = undoManagerConfig;
95
+ this.yDoc = new Doc();
96
+ this.backEvent = new Subject();
97
+ this.forwardEvent = new Subject();
98
+ this.changeEvent = new Subject();
99
+ this.pushEvent = new Subject();
100
+ this.manager = null;
101
+ this.subscriptions = [];
102
+ this.updateFromRemote = false;
103
+ this.contentSyncCaches = new WeakMap();
104
+ this.slotStateSyncCaches = new WeakMap();
105
+ this.slotsSyncCaches = new WeakMap();
106
+ this.componentStateSyncCaches = new WeakMap();
107
+ this.localChangesAppliedEvent = new Subject();
108
+ this.selectionChangeEvent = new Subject();
109
+ this.contentMap = new ContentMap();
110
+ this.updateRemoteActions = [];
111
+ this.noRecord = {};
112
+ this.historyItems = [];
113
+ this.index = 0;
114
+ this.onBack = this.backEvent.asObservable();
115
+ this.onForward = this.forwardEvent.asObservable();
116
+ this.onChange = this.changeEvent.asObservable();
117
+ this.onPush = this.pushEvent.asObservable();
118
+ this.onLocalChangesApplied = this.localChangesAppliedEvent.asObservable();
119
+ }
120
+ listen() {
121
+ const root = this.yDoc.getMap('RootComponent');
122
+ const rootComponent = this.rootComponentRef.component;
123
+ const undoManagerConfig = this.undoManagerConfig || {};
124
+ const manager = new UndoManager(root, {
125
+ trackedOrigins: new Set([this.yDoc]),
126
+ captureTransaction(arg) {
127
+ if (undoManagerConfig.captureTransaction) {
128
+ return undoManagerConfig.captureTransaction(arg);
129
+ }
130
+ return true;
131
+ },
132
+ deleteFilter(item) {
133
+ if (undoManagerConfig.deleteFilter) {
134
+ return undoManagerConfig.deleteFilter(item);
135
+ }
136
+ return true;
137
+ }
138
+ });
139
+ this.manager = manager;
140
+ let beforePosition = null;
141
+ this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
142
+ beforePosition = this.getRelativeCursorLocation();
143
+ }));
144
+ manager.on('stack-item-added', event => {
145
+ if (event.type === 'undo') {
146
+ if (event.origin === manager) {
147
+ this.index++;
148
+ }
149
+ else {
150
+ this.historyItems.length = this.index;
151
+ this.historyItems.push({
152
+ before: beforePosition,
153
+ after: this.getRelativeCursorLocation()
154
+ });
155
+ this.index++;
156
+ }
157
+ }
158
+ else {
159
+ this.index--;
160
+ }
161
+ if (manager.undoStack.length > this.stackSize) {
162
+ this.historyItems.shift();
163
+ manager.undoStack.shift();
164
+ }
165
+ if (event.origin === this.yDoc) {
166
+ this.pushEvent.next();
167
+ }
168
+ this.changeEvent.next();
169
+ });
170
+ manager.on('stack-item-popped', (ev) => {
171
+ const index = ev.type === 'undo' ? this.index : this.index - 1;
172
+ const position = this.historyItems[index] || null;
173
+ const p = ev.type === 'undo' ? position === null || position === void 0 ? void 0 : position.before : position === null || position === void 0 ? void 0 : position.after;
174
+ if (p) {
175
+ const selection = this.getAbstractSelection(p);
176
+ if (selection) {
177
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
178
+ return;
179
+ }
180
+ }
181
+ this.selection.unSelect();
182
+ });
183
+ this.subscriptions.push(this.selection.onChange.subscribe(() => {
184
+ const paths = this.selection.getPaths();
185
+ this.selectionChangeEvent.next(paths);
186
+ }), this.scheduler.onDocChanged.pipe(map(item => {
187
+ return item.filter(i => {
188
+ return i.from !== ChangeOrigin.Remote;
189
+ });
190
+ }), filter(item => {
191
+ return item.length;
192
+ })).subscribe(() => {
193
+ const updates = [];
194
+ let update = null;
195
+ for (const item of this.updateRemoteActions) {
196
+ if (!update) {
197
+ update = {
198
+ record: item.record,
199
+ actions: []
200
+ };
201
+ updates.push(update);
202
+ }
203
+ if (update.record === item.record) {
204
+ update.actions.push(item.action);
205
+ }
206
+ else {
207
+ update = {
208
+ record: item.record,
209
+ actions: [item.action]
210
+ };
211
+ updates.push(update);
212
+ }
213
+ }
214
+ this.updateRemoteActions = [];
215
+ for (const item of updates) {
216
+ this.yDoc.transact(() => {
217
+ item.actions.forEach(fn => {
218
+ fn();
219
+ });
220
+ }, item.record ? this.yDoc : this.noRecord);
221
+ }
222
+ this.localChangesAppliedEvent.next();
223
+ }));
224
+ this.syncRootComponent(root, rootComponent);
225
+ }
226
+ back() {
227
+ var _a;
228
+ if (this.canBack) {
229
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.undo();
230
+ this.backEvent.next();
231
+ }
232
+ }
233
+ forward() {
234
+ var _a;
235
+ if (this.canForward) {
236
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.redo();
237
+ this.forwardEvent.next();
238
+ }
239
+ }
240
+ clear() {
241
+ var _a;
242
+ const last = this.historyItems.pop();
243
+ this.historyItems = last ? [last] : [];
244
+ this.index = last ? 1 : 0;
245
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
246
+ this.changeEvent.next();
247
+ }
248
+ destroy() {
249
+ var _a;
250
+ this.index = 0;
251
+ this.historyItems = [];
252
+ this.subscriptions.forEach(i => i.unsubscribe());
253
+ (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
254
+ }
255
+ syncRootComponent(root, rootComponent) {
256
+ let slots = root.get('slots');
257
+ if (!slots) {
258
+ slots = new Array();
259
+ rootComponent.slots.toArray().forEach(i => {
260
+ const sharedSlot = this.createSharedSlotBySlot(i);
261
+ slots.push([sharedSlot]);
262
+ });
263
+ this.yDoc.transact(() => {
264
+ root.set('state', rootComponent.state);
265
+ root.set('slots', slots);
266
+ });
267
+ }
268
+ else if (slots.length === 0) {
269
+ rootComponent.updateState(() => {
270
+ return root.get('state');
271
+ });
272
+ this.yDoc.transact(() => {
273
+ rootComponent.slots.toArray().forEach(i => {
274
+ const sharedSlot = this.createSharedSlotBySlot(i);
275
+ slots.push([sharedSlot]);
276
+ });
277
+ });
278
+ }
279
+ else {
280
+ rootComponent.updateState(() => {
281
+ return root.get('state');
282
+ });
283
+ rootComponent.slots.clean();
284
+ slots.forEach(sharedSlot => {
285
+ const slot = this.createSlotBySharedSlot(sharedSlot);
286
+ this.syncSlotContent(sharedSlot.get('content'), slot);
287
+ this.syncSlotState(sharedSlot, slot);
288
+ rootComponent.slots.insert(slot);
289
+ });
290
+ }
291
+ this.syncComponentState(root, rootComponent);
292
+ this.syncComponentSlots(slots, rootComponent);
293
+ }
294
+ getAbstractSelection(position) {
295
+ const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
296
+ const focusPosition = createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
297
+ if (anchorPosition && focusPosition) {
298
+ const focusSlot = this.contentMap.get(focusPosition.type);
299
+ const anchorSlot = this.contentMap.get(anchorPosition.type);
300
+ if (focusSlot && anchorSlot) {
301
+ return {
302
+ anchorSlot,
303
+ anchorOffset: anchorPosition.index,
304
+ focusSlot,
305
+ focusOffset: focusPosition.index
306
+ };
307
+ }
308
+ }
309
+ return null;
310
+ }
311
+ getRelativeCursorLocation() {
312
+ const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
313
+ if (anchorSlot) {
314
+ const anchorYText = this.contentMap.get(anchorSlot);
315
+ if (anchorYText) {
316
+ const anchorPosition = createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
317
+ if (focusSlot) {
318
+ const focusYText = this.contentMap.get(focusSlot);
319
+ if (focusYText) {
320
+ const focusPosition = createRelativePositionFromTypeIndex(focusYText, focusOffset);
321
+ return {
322
+ focus: focusPosition,
323
+ anchor: anchorPosition
324
+ };
325
+ }
326
+ }
327
+ }
328
+ }
329
+ return null;
330
+ }
331
+ syncSlotContent(content, slot) {
332
+ this.contentMap.set(slot, content);
333
+ const syncRemote = (ev, tr) => {
334
+ this.runRemoteUpdate(tr, () => {
335
+ slot.retain(0);
336
+ ev.keysChanged.forEach(key => {
337
+ const change = ev.keys.get(key);
338
+ if (!change) {
339
+ return;
340
+ }
341
+ const updateType = change.action;
342
+ if (updateType === 'update' || updateType === 'add') {
343
+ const attribute = this.registry.getAttribute(key);
344
+ if (attribute) {
345
+ slot.setAttribute(attribute, content.getAttribute(key));
346
+ }
347
+ }
348
+ else if (updateType === 'delete') {
349
+ const attribute = this.registry.getAttribute(key);
350
+ if (attribute) {
351
+ slot.removeAttribute(attribute);
352
+ }
353
+ }
354
+ });
355
+ ev.delta.forEach(action => {
356
+ if (Reflect.has(action, 'retain')) {
357
+ if (action.attributes) {
358
+ const formats = remoteFormatsToLocal(this.registry, action.attributes);
359
+ if (formats.length) {
360
+ slot.retain(action.retain, formats);
361
+ }
362
+ slot.retain(slot.index + action.retain);
363
+ }
364
+ else {
365
+ slot.retain(action.retain);
366
+ }
367
+ }
368
+ else if (action.insert) {
369
+ const index = slot.index;
370
+ let length = 1;
371
+ if (typeof action.insert === 'string') {
372
+ length = action.insert.length;
373
+ slot.insert(action.insert, remoteFormatsToLocal(this.registry, action.attributes));
374
+ }
375
+ else {
376
+ const sharedComponent = action.insert;
377
+ const component = this.createComponentBySharedComponent(sharedComponent);
378
+ this.syncComponentSlots(sharedComponent.get('slots'), component);
379
+ this.syncComponentState(sharedComponent, component);
380
+ slot.insert(component);
381
+ }
382
+ if (this.selection.isSelected && tr.origin !== this.manager) {
383
+ if (slot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
384
+ this.selection.setAnchor(slot, this.selection.anchorOffset + length);
385
+ }
386
+ if (slot === this.selection.focusSlot && this.selection.focusOffset > index) {
387
+ this.selection.setFocus(slot, this.selection.focusOffset + length);
388
+ }
389
+ }
390
+ }
391
+ else if (action.delete) {
392
+ const index = slot.index;
393
+ slot.delete(action.delete);
394
+ if (this.selection.isSelected && tr.origin !== this.manager) {
395
+ if (slot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
396
+ this.selection.setAnchor(slot, this.selection.startOffset - action.delete);
397
+ }
398
+ if (slot === this.selection.focusSlot && this.selection.focusOffset >= index) {
399
+ this.selection.setFocus(slot, this.selection.focusOffset - action.delete);
400
+ }
401
+ }
402
+ }
403
+ });
404
+ });
405
+ };
406
+ content.observe(syncRemote);
407
+ const sub = slot.onContentChange.subscribe(actions => {
408
+ this.runLocalUpdate(() => {
409
+ var _a;
410
+ let offset = 0;
411
+ let length = 0;
412
+ for (const action of actions) {
413
+ if (action.type === 'retain') {
414
+ const formats = action.formats;
415
+ if (formats) {
416
+ const keys = Object.keys(formats);
417
+ let length = keys.length;
418
+ keys.forEach(key => {
419
+ const formatter = this.registry.getFormatter(key);
420
+ if (!formatter) {
421
+ length--;
422
+ Reflect.deleteProperty(formats, key);
423
+ }
424
+ });
425
+ if (length) {
426
+ content.format(offset, action.offset, formats);
427
+ }
428
+ }
429
+ else {
430
+ offset = action.offset;
431
+ }
432
+ }
433
+ else if (action.type === 'insert') {
434
+ const delta = content.toDelta();
435
+ const isEmpty = delta.length === 1 && delta[0].insert === Slot.emptyPlaceholder;
436
+ if (typeof action.content === 'string') {
437
+ length = action.content.length;
438
+ content.insert(offset, action.content, action.formats || {});
439
+ }
440
+ else {
441
+ length = 1;
442
+ const sharedComponent = this.createSharedComponentByComponent(action.ref);
443
+ content.insertEmbed(offset, sharedComponent, action.formats || {});
444
+ }
445
+ if (isEmpty && offset === 0) {
446
+ content.delete(content.length - 1, 1);
447
+ }
448
+ offset += length;
449
+ }
450
+ else if (action.type === 'delete') {
451
+ const delta = content.toDelta();
452
+ if (content.length) {
453
+ content.delete(offset, action.count);
454
+ }
455
+ if (content.length === 0) {
456
+ content.insert(0, '\n', (_a = delta[0]) === null || _a === void 0 ? void 0 : _a.attributes);
457
+ }
458
+ }
459
+ else if (action.type === 'attrSet') {
460
+ content.setAttribute(action.name, action.value);
461
+ }
462
+ else if (action.type === 'attrRemove') {
463
+ content.removeAttribute(action.name);
464
+ }
465
+ }
466
+ });
467
+ });
468
+ sub.add(slot.onChildComponentRemove.subscribe(components => {
469
+ components.forEach(c => {
470
+ this.cleanSubscriptionsByComponent(c);
471
+ });
472
+ }));
473
+ this.contentSyncCaches.set(slot, () => {
474
+ content.unobserve(syncRemote);
475
+ sub.unsubscribe();
476
+ });
477
+ }
478
+ syncSlotState(remoteSlot, slot) {
479
+ const syncRemote = (ev, tr) => {
480
+ this.runRemoteUpdate(tr, () => {
481
+ ev.keysChanged.forEach(key => {
482
+ if (key === 'state') {
483
+ const state = ev.target.get('state');
484
+ slot.updateState(draft => {
485
+ if (typeof draft === 'object' && draft !== null) {
486
+ Object.assign(draft, state);
487
+ }
488
+ else {
489
+ return state;
490
+ }
491
+ });
492
+ }
493
+ });
494
+ });
495
+ };
496
+ remoteSlot.observe(syncRemote);
497
+ const sub = slot.onStateChange.subscribe(change => {
498
+ this.runLocalUpdate(() => {
499
+ remoteSlot.set('state', change.newState);
500
+ }, change.record);
501
+ });
502
+ this.slotStateSyncCaches.set(slot, () => {
503
+ remoteSlot.unobserve(syncRemote);
504
+ sub.unsubscribe();
505
+ });
506
+ }
507
+ syncComponentSlots(remoteSlots, component) {
508
+ const slots = component.slots;
509
+ const syncRemote = (ev, tr) => {
510
+ this.runRemoteUpdate(tr, () => {
511
+ let index = 0;
512
+ slots.retain(index);
513
+ ev.delta.forEach(action => {
514
+ if (Reflect.has(action, 'retain')) {
515
+ index += action.retain;
516
+ slots.retain(index);
517
+ }
518
+ else if (action.insert) {
519
+ action.insert.forEach(item => {
520
+ const slot = this.createSlotBySharedSlot(item);
521
+ slots.insert(slot);
522
+ this.syncSlotContent(item.get('content'), slot);
523
+ this.syncSlotState(item, slot);
524
+ index++;
525
+ });
526
+ }
527
+ else if (action.delete) {
528
+ slots.retain(index);
529
+ slots.delete(action.delete);
530
+ }
531
+ });
532
+ });
533
+ };
534
+ remoteSlots.observe(syncRemote);
535
+ const sub = slots.onChange.subscribe(operations => {
536
+ this.runLocalUpdate(() => {
537
+ const applyActions = operations.apply;
538
+ let index;
539
+ applyActions.forEach(action => {
540
+ if (action.type === 'retain') {
541
+ index = action.offset;
542
+ }
543
+ else if (action.type === 'insertSlot') {
544
+ const sharedSlot = this.createSharedSlotBySlot(action.ref);
545
+ remoteSlots.insert(index, [sharedSlot]);
546
+ index++;
547
+ }
548
+ else if (action.type === 'delete') {
549
+ remoteSlots.delete(index, action.count);
550
+ }
551
+ });
552
+ });
553
+ });
554
+ sub.add(slots.onChildSlotRemove.subscribe(slots => {
555
+ slots.forEach(slot => {
556
+ this.cleanSubscriptionsBySlot(slot);
557
+ });
558
+ }));
559
+ this.slotsSyncCaches.set(component, () => {
560
+ remoteSlots.unobserve(syncRemote);
561
+ sub.unsubscribe();
562
+ });
563
+ }
564
+ syncComponentState(remoteComponent, component) {
565
+ const syncRemote = (ev, tr) => {
566
+ this.runRemoteUpdate(tr, () => {
567
+ ev.keysChanged.forEach(key => {
568
+ if (key === 'state') {
569
+ const state = ev.target.get('state');
570
+ component.updateState(draft => {
571
+ if (typeof draft === 'object' && draft !== null) {
572
+ Object.assign(draft, state);
573
+ }
574
+ else {
575
+ return state;
576
+ }
577
+ });
578
+ }
579
+ });
580
+ });
581
+ };
582
+ remoteComponent.observe(syncRemote);
583
+ const sub = component.onStateChange.subscribe(change => {
584
+ this.runLocalUpdate(() => {
585
+ remoteComponent.set('state', change.newState);
586
+ }, change.record);
587
+ });
588
+ this.componentStateSyncCaches.set(component, () => {
589
+ remoteComponent.unobserve(syncRemote);
590
+ sub.unsubscribe();
591
+ });
592
+ }
593
+ runLocalUpdate(fn, record = true) {
594
+ if (this.updateFromRemote || this.controller.readonly) {
595
+ return;
596
+ }
597
+ this.updateRemoteActions.push({
598
+ record,
599
+ action: fn
600
+ });
601
+ }
602
+ runRemoteUpdate(tr, fn) {
603
+ if (tr.origin === this.yDoc) {
604
+ return;
605
+ }
606
+ this.updateFromRemote = true;
607
+ if (tr.origin === this.manager) {
608
+ this.scheduler.historyApplyTransact(fn);
609
+ }
610
+ else {
611
+ this.scheduler.remoteUpdateTransact(fn);
612
+ }
613
+ this.updateFromRemote = false;
614
+ }
615
+ createSharedComponentByComponent(component) {
616
+ const sharedComponent = new Map();
617
+ sharedComponent.set('state', component.state);
618
+ sharedComponent.set('name', component.name);
619
+ const sharedSlots = new Array();
620
+ sharedComponent.set('slots', sharedSlots);
621
+ component.slots.toArray().forEach(slot => {
622
+ const sharedSlot = this.createSharedSlotBySlot(slot);
623
+ sharedSlots.push([sharedSlot]);
624
+ });
625
+ this.syncComponentSlots(sharedSlots, component);
626
+ this.syncComponentState(sharedComponent, component);
627
+ return sharedComponent;
628
+ }
629
+ createSharedSlotBySlot(slot) {
630
+ const sharedSlot = new Map();
631
+ sharedSlot.set('schema', slot.schema);
632
+ sharedSlot.set('state', slot.state);
633
+ const sharedContent = new Text();
634
+ sharedSlot.set('content', sharedContent);
635
+ let offset = 0;
636
+ slot.toDelta().forEach(i => {
637
+ let formats = {};
638
+ if (i.formats) {
639
+ i.formats.forEach(item => {
640
+ formats[item[0].name] = item[1];
641
+ });
642
+ }
643
+ else {
644
+ formats = null;
645
+ }
646
+ if (typeof i.insert === 'string') {
647
+ sharedContent.insert(offset, i.insert, formats);
648
+ }
649
+ else {
650
+ const sharedComponent = this.createSharedComponentByComponent(i.insert);
651
+ sharedContent.insertEmbed(offset, sharedComponent, formats);
652
+ }
653
+ offset += i.insert.length;
654
+ });
655
+ slot.getAttributes().forEach(item => {
656
+ sharedContent.setAttribute(item[0].name, item[1]);
657
+ });
658
+ this.syncSlotContent(sharedContent, slot);
659
+ this.syncSlotState(sharedSlot, slot);
660
+ return sharedSlot;
661
+ }
662
+ createComponentBySharedComponent(yMap) {
663
+ const sharedSlots = yMap.get('slots');
664
+ const slots = [];
665
+ sharedSlots.forEach(sharedSlot => {
666
+ const slot = this.createSlotBySharedSlot(sharedSlot);
667
+ slots.push(slot);
668
+ });
669
+ const name = yMap.get('name');
670
+ const state = yMap.get('state');
671
+ const instance = this.registry.createComponentByData(name, {
672
+ state,
673
+ slots
674
+ });
675
+ if (instance) {
676
+ instance.slots.toArray().forEach((slot, index) => {
677
+ let sharedSlot = sharedSlots.get(index);
678
+ if (!sharedSlot) {
679
+ sharedSlot = this.createSharedSlotBySlot(slot);
680
+ sharedSlots.push([sharedSlot]);
681
+ }
682
+ this.syncSlotState(sharedSlot, slot);
683
+ this.syncSlotContent(sharedSlot.get('content'), slot);
684
+ });
685
+ return instance;
686
+ }
687
+ throw collaborateErrorFn(`cannot find component factory \`${name}\`.`);
688
+ }
689
+ createSlotBySharedSlot(sharedSlot) {
690
+ const content = sharedSlot.get('content');
691
+ const delta = content.toDelta();
692
+ const slot = this.registry.createSlot({
693
+ schema: sharedSlot.get('schema'),
694
+ state: sharedSlot.get('state'),
695
+ attributes: {},
696
+ formats: {},
697
+ content: []
698
+ });
699
+ const attrs = content.getAttributes();
700
+ Object.keys(attrs).forEach(key => {
701
+ const attribute = this.registry.getAttribute(key);
702
+ if (attribute) {
703
+ slot.setAttribute(attribute, attrs[key]);
704
+ }
705
+ });
706
+ for (const action of delta) {
707
+ if (action.insert) {
708
+ if (typeof action.insert === 'string') {
709
+ const formats = remoteFormatsToLocal(this.registry, action.attributes);
710
+ slot.insert(action.insert, formats);
711
+ }
712
+ else {
713
+ const sharedComponent = action.insert;
714
+ const component = this.createComponentBySharedComponent(sharedComponent);
715
+ slot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
716
+ this.syncComponentSlots(sharedComponent.get('slots'), component);
717
+ this.syncComponentState(sharedComponent, component);
718
+ }
719
+ }
720
+ else {
721
+ throw collaborateErrorFn('unexpected delta action.');
722
+ }
723
+ }
724
+ return slot;
725
+ }
726
+ cleanSubscriptionsBySlot(slot) {
727
+ this.contentMap.delete(slot);
728
+ [this.contentSyncCaches.get(slot), this.slotStateSyncCaches.get(slot)].forEach(fn => {
729
+ if (fn) {
730
+ fn();
731
+ }
732
+ });
733
+ slot.sliceContent().forEach(i => {
734
+ if (typeof i !== 'string') {
735
+ this.cleanSubscriptionsByComponent(i);
736
+ }
737
+ });
738
+ }
739
+ cleanSubscriptionsByComponent(component) {
740
+ [this.slotsSyncCaches.get(component), this.componentStateSyncCaches.get(component)].forEach(fn => {
741
+ if (fn) {
742
+ fn();
743
+ }
744
+ });
745
+ component.slots.toArray().forEach(slot => {
746
+ this.cleanSubscriptionsBySlot(slot);
747
+ });
748
+ }
749
+ };
750
+ Collaborate = __decorate([
751
+ Injectable(),
752
+ __param(0, Inject(HISTORY_STACK_SIZE)),
753
+ __param(7, Optional()),
754
+ __metadata("design:paramtypes", [Number, RootComponentRef,
755
+ Controller,
756
+ Scheduler,
757
+ Registry,
758
+ Selection,
759
+ Starter,
760
+ CustomUndoManagerConfig])
761
+ ], Collaborate);
762
+ function remoteFormatsToLocal(registry, attrs) {
763
+ const formats = [];
764
+ if (attrs) {
765
+ Object.keys(attrs).forEach(key => {
766
+ const formatter = registry.getFormatter(key);
767
+ if (formatter) {
768
+ formats.push([formatter, attrs[key]]);
769
+ }
770
+ });
771
+ }
772
+ return formats;
763
773
  }
764
774
 
765
- const collaborateModule = {
766
- providers: [
767
- Collaborate,
768
- {
769
- provide: History,
770
- useExisting: Collaborate
771
- }
772
- ]
775
+ const collaborateModule = {
776
+ providers: [
777
+ Collaborate,
778
+ {
779
+ provide: History,
780
+ useExisting: Collaborate
781
+ }
782
+ ]
773
783
  };
774
784
 
775
785
  export { Collaborate, CustomUndoManagerConfig, collaborateModule };