@textbus/collaborate 3.0.0-alpha.22 → 3.0.0-alpha.24

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