@textbus/collaborate 3.0.0-alpha.50 → 3.0.0-alpha.53

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