@textbus/collaborate 4.0.0-alpha.23 → 4.0.0-alpha.26

Sign up to get free protection for your applications and to get access to all the features.
package/bundles/index.js CHANGED
@@ -43,7 +43,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
43
43
  };
44
44
 
45
45
  const collaborateErrorFn = core.makeError('Collaborate');
46
- class ContentMap {
46
+ class SlotMap {
47
47
  constructor() {
48
48
  this.slotAndYTextMap = new WeakMap();
49
49
  this.yTextAndSLotMap = new WeakMap();
@@ -107,13 +107,9 @@ exports.Collaborate = class Collaborate {
107
107
  this.manager = null;
108
108
  this.subscriptions = [];
109
109
  this.updateFromRemote = false;
110
- this.contentSyncCaches = new WeakMap();
111
- this.slotStateSyncCaches = new WeakMap();
112
- this.slotsSyncCaches = new WeakMap();
113
- this.componentStateSyncCaches = new WeakMap();
114
110
  this.localChangesAppliedEvent = new stream.Subject();
115
111
  this.selectionChangeEvent = new stream.Subject();
116
- this.contentMap = new ContentMap();
112
+ this.slotMap = new SlotMap();
117
113
  this.updateRemoteActions = [];
118
114
  this.noRecord = {};
119
115
  this.historyItems = [];
@@ -148,7 +144,7 @@ exports.Collaborate = class Collaborate {
148
144
  this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
149
145
  beforePosition = this.getRelativeCursorLocation();
150
146
  }));
151
- manager.on('stack-item-added', event => {
147
+ manager.on('stack-item-added', (event) => {
152
148
  if (event.type === 'undo') {
153
149
  if (event.origin === manager) {
154
150
  this.index++;
@@ -260,50 +256,153 @@ exports.Collaborate = class Collaborate {
260
256
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
261
257
  }
262
258
  syncRootComponent(root, rootComponent) {
263
- let slots = root.get('slots');
264
- if (!slots) {
265
- slots = new yjs.Array();
266
- rootComponent.slots.toArray().forEach(i => {
267
- const sharedSlot = this.createSharedSlotBySlot(i);
268
- slots.push([sharedSlot]);
269
- });
259
+ let state = root.get('state');
260
+ if (!state) {
261
+ state = new yjs.Map();
262
+ this.syncLocalMapToSharedMap(rootComponent.state, state, rootComponent);
270
263
  this.yDoc.transact(() => {
271
- root.set('state', rootComponent.state);
272
- root.set('slots', slots);
264
+ root.set('state', state);
273
265
  });
274
266
  }
275
- else if (slots.length === 0) {
276
- rootComponent.updateState(() => {
277
- return root.get('state');
278
- });
279
- this.yDoc.transact(() => {
280
- rootComponent.slots.toArray().forEach(i => {
281
- const sharedSlot = this.createSharedSlotBySlot(i);
282
- slots.push([sharedSlot]);
267
+ else {
268
+ rootComponent.state.clean();
269
+ this.syncSharedMapToLocalMap(state, rootComponent.state, rootComponent);
270
+ }
271
+ }
272
+ syncSharedMapToLocalMap(sharedMap, localMap, parent) {
273
+ sharedMap.forEach((value, key) => {
274
+ localMap.set(key, this.createLocalModelBySharedByModel(value, parent));
275
+ });
276
+ this.syncObject(sharedMap, localMap, parent);
277
+ }
278
+ createLocalMapBySharedMap(sharedMap, parent) {
279
+ const localMap = new core.MapModel(parent);
280
+ this.syncSharedMapToLocalMap(sharedMap, localMap, parent);
281
+ return localMap;
282
+ }
283
+ createLocalArrayBySharedArray(sharedArray, parent) {
284
+ const localArray = new core.ArrayModel(parent);
285
+ sharedArray.forEach(item => {
286
+ localArray.insert(this.createLocalModelBySharedByModel(item, parent));
287
+ });
288
+ this.syncArray(sharedArray, localArray, parent);
289
+ return localArray;
290
+ }
291
+ syncLocalMapToSharedMap(localMap, sharedMap, parent) {
292
+ localMap.forEach((value, key) => {
293
+ sharedMap.set(key, this.createSharedModelByLocalModel(value, parent));
294
+ });
295
+ this.syncObject(sharedMap, localMap, parent);
296
+ }
297
+ createSharedMapByLocalMap(localMap, parent) {
298
+ const sharedMap = new yjs.Map();
299
+ this.syncLocalMapToSharedMap(localMap, sharedMap, parent);
300
+ return sharedMap;
301
+ }
302
+ createSharedArrayByLocalArray(localArray, parent) {
303
+ const sharedArray = new yjs.Array();
304
+ localArray.forEach(value => {
305
+ sharedArray.push([this.createSharedModelByLocalModel(value, parent)]);
306
+ });
307
+ this.syncArray(sharedArray, localArray, parent);
308
+ return sharedArray;
309
+ }
310
+ createSharedSlotByLocalSlot(localSlot) {
311
+ const sharedSlot = new yjs.Text();
312
+ sharedSlot.setAttribute('__schema__', [...localSlot.schema]);
313
+ let offset = 0;
314
+ localSlot.toDelta().forEach(i => {
315
+ let formats = {};
316
+ if (i.formats) {
317
+ i.formats.forEach(item => {
318
+ formats[item[0].name] = item[1];
283
319
  });
284
- });
320
+ }
321
+ else {
322
+ formats = null;
323
+ }
324
+ if (typeof i.insert === 'string') {
325
+ sharedSlot.insert(offset, i.insert, formats);
326
+ }
327
+ else {
328
+ const sharedComponent = this.createSharedComponentByLocalComponent(i.insert);
329
+ sharedSlot.insertEmbed(offset, sharedComponent, formats);
330
+ }
331
+ offset += i.insert.length;
332
+ });
333
+ localSlot.getAttributes().forEach(item => {
334
+ sharedSlot.setAttribute(item[0].name, item[1]);
335
+ });
336
+ this.syncSlot(sharedSlot, localSlot);
337
+ return sharedSlot;
338
+ }
339
+ createLocalSlotBySharedSlot(sharedSlot) {
340
+ const delta = sharedSlot.toDelta();
341
+ const localSlot = new core.Slot(sharedSlot.getAttribute('__schema__') || []); // TODO 这里有潜在的问题
342
+ const attrs = sharedSlot.getAttributes();
343
+ Object.keys(attrs).forEach(key => {
344
+ const attribute = this.registry.getAttribute(key);
345
+ if (attribute) {
346
+ localSlot.setAttribute(attribute, attrs[key]);
347
+ }
348
+ });
349
+ for (const action of delta) {
350
+ if (action.insert) {
351
+ if (typeof action.insert === 'string') {
352
+ const formats = remoteFormatsToLocal(this.registry, action.attributes);
353
+ localSlot.insert(action.insert, formats);
354
+ }
355
+ else {
356
+ const sharedComponent = action.insert;
357
+ const component = this.createLocalComponentBySharedComponent(sharedComponent);
358
+ localSlot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
359
+ }
360
+ }
361
+ else {
362
+ throw collaborateErrorFn('unexpected delta action.');
363
+ }
285
364
  }
286
- else {
287
- rootComponent.updateState(() => {
288
- return root.get('state');
289
- });
290
- rootComponent.slots.clean();
291
- slots.forEach(sharedSlot => {
292
- const slot = this.createSlotBySharedSlot(sharedSlot);
293
- this.syncSlotContent(sharedSlot.get('content'), slot);
294
- this.syncSlotState(sharedSlot, slot);
295
- rootComponent.slots.insert(slot);
296
- });
365
+ this.syncSlot(sharedSlot, localSlot);
366
+ return localSlot;
367
+ }
368
+ // private createSharedModelByLocalModel(sharedModel: YMap<any>, parent: Component<any>): MapModel<any>
369
+ // private createSharedModelByLocalModel(sharedModel: YArray<any>, parent: Component<any>): ArrayModel<any>
370
+ // private createSharedModelByLocalModel(sharedModel: YText, parent: Component<any>): Slot
371
+ // private createSharedModelByLocalModel(sharedModel: any, parent: Component<any>): any
372
+ createSharedModelByLocalModel(sharedModel, parent) {
373
+ if (sharedModel instanceof core.MapModel) {
374
+ return this.createSharedMapByLocalMap(sharedModel, parent);
375
+ }
376
+ if (sharedModel instanceof core.ArrayModel) {
377
+ return this.createSharedArrayByLocalArray(sharedModel, parent);
378
+ }
379
+ if (sharedModel instanceof core.Slot) {
380
+ return this.createSharedSlotByLocalSlot(sharedModel);
297
381
  }
298
- this.syncComponentState(root, rootComponent);
299
- this.syncComponentSlots(slots, rootComponent);
382
+ return sharedModel;
383
+ }
384
+ // private createLocalModelBySharedByModel(localModel: MapModel<any>, parent: Component<any>): MapModel<any>
385
+ // private createLocalModelBySharedByModel(localModel: ArrayModel<any>, parent: Component<any>): YArray<any>
386
+ // private createLocalModelBySharedByModel(localModel: Slot, parent: Component<any>): YText
387
+ // private createLocalModelBySharedByModel(localModel: any, parent: Component<any>): any
388
+ createLocalModelBySharedByModel(localModel, parent) {
389
+ if (localModel instanceof yjs.Map) {
390
+ return this.createLocalMapBySharedMap(localModel, parent);
391
+ }
392
+ if (localModel instanceof yjs.Array) {
393
+ return this.createLocalArrayBySharedArray(localModel, parent);
394
+ }
395
+ if (localModel instanceof yjs.Text) {
396
+ return this.createLocalSlotBySharedSlot(localModel);
397
+ }
398
+ return localModel;
300
399
  }
301
400
  getAbstractSelection(position) {
302
401
  const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
303
402
  const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
304
403
  if (anchorPosition && focusPosition) {
305
- const focusSlot = this.contentMap.get(focusPosition.type);
306
- const anchorSlot = this.contentMap.get(anchorPosition.type);
404
+ const focusSlot = this.slotMap.get(focusPosition.type);
405
+ const anchorSlot = this.slotMap.get(anchorPosition.type);
307
406
  if (focusSlot && anchorSlot) {
308
407
  return {
309
408
  anchorSlot,
@@ -318,11 +417,11 @@ exports.Collaborate = class Collaborate {
318
417
  getRelativeCursorLocation() {
319
418
  const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
320
419
  if (anchorSlot) {
321
- const anchorYText = this.contentMap.get(anchorSlot);
420
+ const anchorYText = this.slotMap.get(anchorSlot);
322
421
  if (anchorYText) {
323
422
  const anchorPosition = yjs.createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
324
423
  if (focusSlot) {
325
- const focusYText = this.contentMap.get(focusSlot);
424
+ const focusYText = this.slotMap.get(focusSlot);
326
425
  if (focusYText) {
327
426
  const focusPosition = yjs.createRelativePositionFromTypeIndex(focusYText, focusOffset);
328
427
  return {
@@ -335,11 +434,10 @@ exports.Collaborate = class Collaborate {
335
434
  }
336
435
  return null;
337
436
  }
338
- syncSlotContent(content, slot) {
339
- this.contentMap.set(slot, content);
437
+ syncSlot(sharedSlot, localSlot) {
340
438
  const syncRemote = (ev, tr) => {
341
439
  this.runRemoteUpdate(tr, () => {
342
- slot.retain(0);
440
+ localSlot.retain(0);
343
441
  ev.keysChanged.forEach(key => {
344
442
  const change = ev.keys.get(key);
345
443
  if (!change) {
@@ -349,13 +447,13 @@ exports.Collaborate = class Collaborate {
349
447
  if (updateType === 'update' || updateType === 'add') {
350
448
  const attribute = this.registry.getAttribute(key);
351
449
  if (attribute) {
352
- slot.setAttribute(attribute, content.getAttribute(key));
450
+ localSlot.setAttribute(attribute, sharedSlot.getAttribute(key));
353
451
  }
354
452
  }
355
453
  else if (updateType === 'delete') {
356
454
  const attribute = this.registry.getAttribute(key);
357
455
  if (attribute) {
358
- slot.removeAttribute(attribute);
456
+ localSlot.removeAttribute(attribute);
359
457
  }
360
458
  }
361
459
  });
@@ -364,54 +462,52 @@ exports.Collaborate = class Collaborate {
364
462
  if (action.attributes) {
365
463
  const formats = remoteFormatsToLocal(this.registry, action.attributes);
366
464
  if (formats.length) {
367
- slot.retain(action.retain, formats);
465
+ localSlot.retain(action.retain, formats);
368
466
  }
369
- slot.retain(slot.index + action.retain);
467
+ localSlot.retain(localSlot.index + action.retain);
370
468
  }
371
469
  else {
372
- slot.retain(action.retain);
470
+ localSlot.retain(action.retain);
373
471
  }
374
472
  }
375
473
  else if (action.insert) {
376
- const index = slot.index;
474
+ const index = localSlot.index;
377
475
  let length = 1;
378
476
  if (typeof action.insert === 'string') {
379
477
  length = action.insert.length;
380
- slot.insert(action.insert, remoteFormatsToLocal(this.registry, action.attributes));
478
+ localSlot.insert(action.insert, remoteFormatsToLocal(this.registry, action.attributes));
381
479
  }
382
480
  else {
383
481
  const sharedComponent = action.insert;
384
- const component = this.createComponentBySharedComponent(sharedComponent);
385
- this.syncComponentSlots(sharedComponent.get('slots'), component);
386
- this.syncComponentState(sharedComponent, component);
387
- slot.insert(component);
482
+ const component = this.createLocalComponentBySharedComponent(sharedComponent);
483
+ localSlot.insert(component);
388
484
  }
389
485
  if (this.selection.isSelected && tr.origin !== this.manager) {
390
- if (slot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
391
- this.selection.setAnchor(slot, this.selection.anchorOffset + length);
486
+ if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
487
+ this.selection.setAnchor(localSlot, this.selection.anchorOffset + length);
392
488
  }
393
- if (slot === this.selection.focusSlot && this.selection.focusOffset > index) {
394
- this.selection.setFocus(slot, this.selection.focusOffset + length);
489
+ if (localSlot === this.selection.focusSlot && this.selection.focusOffset > index) {
490
+ this.selection.setFocus(localSlot, this.selection.focusOffset + length);
395
491
  }
396
492
  }
397
493
  }
398
494
  else if (action.delete) {
399
- const index = slot.index;
400
- slot.delete(action.delete);
495
+ const index = localSlot.index;
496
+ localSlot.delete(action.delete);
401
497
  if (this.selection.isSelected && tr.origin !== this.manager) {
402
- if (slot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
403
- this.selection.setAnchor(slot, this.selection.startOffset - action.delete);
498
+ if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
499
+ this.selection.setAnchor(localSlot, this.selection.startOffset - action.delete);
404
500
  }
405
- if (slot === this.selection.focusSlot && this.selection.focusOffset >= index) {
406
- this.selection.setFocus(slot, this.selection.focusOffset - action.delete);
501
+ if (localSlot === this.selection.focusSlot && this.selection.focusOffset >= index) {
502
+ this.selection.setFocus(localSlot, this.selection.focusOffset - action.delete);
407
503
  }
408
504
  }
409
505
  }
410
506
  });
411
507
  });
412
508
  };
413
- content.observe(syncRemote);
414
- const sub = slot.onContentChange.subscribe(actions => {
509
+ sharedSlot.observe(syncRemote);
510
+ const sub = localSlot.onContentChange.subscribe(actions => {
415
511
  this.runLocalUpdate(() => {
416
512
  var _a;
417
513
  let offset = 0;
@@ -430,170 +526,169 @@ exports.Collaborate = class Collaborate {
430
526
  }
431
527
  });
432
528
  if (length) {
433
- content.format(offset, action.offset, formats);
529
+ sharedSlot.format(offset, action.offset, formats);
434
530
  }
435
531
  }
436
532
  else {
437
533
  offset = action.offset;
438
534
  }
439
535
  }
440
- else if (action.type === 'insert') {
441
- const delta = content.toDelta();
536
+ else if (action.type === 'contentInsert') {
537
+ const delta = sharedSlot.toDelta();
442
538
  const isEmpty = delta.length === 1 && delta[0].insert === core.Slot.emptyPlaceholder;
443
539
  if (typeof action.content === 'string') {
444
540
  length = action.content.length;
445
- content.insert(offset, action.content, action.formats || {});
541
+ sharedSlot.insert(offset, action.content, action.formats || {});
446
542
  }
447
543
  else {
448
544
  length = 1;
449
- const sharedComponent = this.createSharedComponentByComponent(action.ref);
450
- content.insertEmbed(offset, sharedComponent, action.formats || {});
545
+ const sharedComponent = this.createSharedComponentByLocalComponent(action.ref);
546
+ sharedSlot.insertEmbed(offset, sharedComponent, action.formats || {});
451
547
  }
452
548
  if (isEmpty && offset === 0) {
453
- content.delete(content.length - 1, 1);
549
+ sharedSlot.delete(sharedSlot.length - 1, 1);
454
550
  }
455
551
  offset += length;
456
552
  }
457
553
  else if (action.type === 'delete') {
458
- const delta = content.toDelta();
459
- if (content.length) {
460
- content.delete(offset, action.count);
554
+ const delta = sharedSlot.toDelta();
555
+ if (sharedSlot.length) {
556
+ sharedSlot.delete(offset, action.count);
461
557
  }
462
- if (content.length === 0) {
463
- content.insert(0, '\n', (_a = delta[0]) === null || _a === void 0 ? void 0 : _a.attributes);
558
+ if (sharedSlot.length === 0) {
559
+ sharedSlot.insert(0, '\n', (_a = delta[0]) === null || _a === void 0 ? void 0 : _a.attributes);
464
560
  }
465
561
  }
466
562
  else if (action.type === 'attrSet') {
467
- content.setAttribute(action.name, action.value);
563
+ sharedSlot.setAttribute(action.name, action.value);
468
564
  }
469
- else if (action.type === 'attrRemove') {
470
- content.removeAttribute(action.name);
565
+ else if (action.type === 'attrDelete') {
566
+ sharedSlot.removeAttribute(action.name);
471
567
  }
472
568
  }
473
569
  });
474
570
  });
475
- sub.add(slot.onChildComponentRemove.subscribe(components => {
476
- components.forEach(c => {
477
- this.cleanSubscriptionsByComponent(c);
478
- });
479
- }));
480
- this.contentSyncCaches.set(slot, () => {
481
- content.unobserve(syncRemote);
571
+ this.slotMap.set(localSlot, sharedSlot);
572
+ localSlot.destroyCallbacks.push(() => {
573
+ this.slotMap.delete(localSlot);
574
+ sharedSlot.unobserve(syncRemote);
482
575
  sub.unsubscribe();
483
576
  });
484
577
  }
485
- syncSlotState(remoteSlot, slot) {
486
- const syncRemote = (ev, tr) => {
487
- this.runRemoteUpdate(tr, () => {
488
- ev.keysChanged.forEach(key => {
489
- if (key === 'state') {
490
- const state = ev.target.get('state');
491
- slot.updateState(draft => {
492
- if (typeof draft === 'object' && draft !== null) {
493
- Object.assign(draft, state);
494
- }
495
- else {
496
- return state;
578
+ createSharedComponentByLocalComponent(component) {
579
+ const sharedComponent = new yjs.Map();
580
+ const sharedState = this.createSharedMapByLocalMap(component.state, component);
581
+ sharedComponent.set('name', component.name);
582
+ sharedComponent.set('state', sharedState);
583
+ return sharedComponent;
584
+ }
585
+ createLocalComponentBySharedComponent(yMap) {
586
+ const componentName = yMap.get('name');
587
+ const sharedState = yMap.get('state');
588
+ const instance = this.registry.createComponentByData(componentName, (component) => {
589
+ return this.createLocalMapBySharedMap(sharedState, component);
590
+ });
591
+ if (instance) {
592
+ return instance;
593
+ }
594
+ throw collaborateErrorFn(`cannot find component factory \`${componentName}\`.`);
595
+ }
596
+ /**
597
+ * 双向同步数组
598
+ * @param sharedArray
599
+ * @param localArray
600
+ * @param parent
601
+ * @private
602
+ */
603
+ syncArray(sharedArray, localArray, parent) {
604
+ const sub = localArray.changeMarker.onChange.subscribe((op) => {
605
+ this.runLocalUpdate(() => {
606
+ let index = 0;
607
+ for (const action of op.apply) {
608
+ switch (action.type) {
609
+ case 'retain':
610
+ index = action.offset;
611
+ break;
612
+ case 'insert':
613
+ {
614
+ const data = this.createSharedModelByLocalModel(action.ref, parent);
615
+ sharedArray.insert(index, [data]);
497
616
  }
498
- });
617
+ break;
618
+ case 'delete':
619
+ sharedArray.delete(index, 1);
620
+ break;
499
621
  }
500
- });
622
+ }
501
623
  });
502
- };
503
- remoteSlot.observe(syncRemote);
504
- const sub = slot.onStateChange.subscribe(change => {
505
- this.runLocalUpdate(() => {
506
- remoteSlot.set('state', change.newState);
507
- }, change.record);
508
624
  });
509
- this.slotStateSyncCaches.set(slot, () => {
510
- remoteSlot.unobserve(syncRemote);
511
- sub.unsubscribe();
512
- });
513
- }
514
- syncComponentSlots(remoteSlots, component) {
515
- const slots = component.slots;
516
625
  const syncRemote = (ev, tr) => {
517
626
  this.runRemoteUpdate(tr, () => {
518
627
  let index = 0;
519
- slots.retain(index);
520
- ev.delta.forEach(action => {
628
+ localArray.retain(index);
629
+ ev.delta.forEach((action) => {
521
630
  if (Reflect.has(action, 'retain')) {
522
631
  index += action.retain;
523
- slots.retain(index);
632
+ localArray.retain(index);
524
633
  }
525
634
  else if (action.insert) {
526
- action.insert.forEach(item => {
527
- const slot = this.createSlotBySharedSlot(item);
528
- slots.insert(slot);
529
- this.syncSlotContent(item.get('content'), slot);
530
- this.syncSlotState(item, slot);
635
+ action.insert.forEach((item) => {
636
+ const value = this.createLocalModelBySharedByModel(item, parent);
637
+ localArray.insert(value);
531
638
  index++;
532
639
  });
533
640
  }
534
641
  else if (action.delete) {
535
- slots.retain(index);
536
- slots.delete(action.delete);
642
+ localArray.retain(index);
643
+ localArray.delete(action.delete);
537
644
  }
538
645
  });
539
646
  });
540
647
  };
541
- remoteSlots.observe(syncRemote);
542
- const sub = slots.onChange.subscribe(operations => {
543
- this.runLocalUpdate(() => {
544
- const applyActions = operations.apply;
545
- let index;
546
- applyActions.forEach(action => {
547
- if (action.type === 'retain') {
548
- index = action.offset;
549
- }
550
- else if (action.type === 'insertSlot') {
551
- const sharedSlot = this.createSharedSlotBySlot(action.ref);
552
- remoteSlots.insert(index, [sharedSlot]);
553
- index++;
554
- }
555
- else if (action.type === 'delete') {
556
- remoteSlots.delete(index, action.count);
557
- }
558
- });
559
- });
560
- });
561
- sub.add(slots.onChildSlotRemove.subscribe(slots => {
562
- slots.forEach(slot => {
563
- this.cleanSubscriptionsBySlot(slot);
564
- });
565
- }));
566
- this.slotsSyncCaches.set(component, () => {
567
- remoteSlots.unobserve(syncRemote);
648
+ sharedArray.observe(syncRemote);
649
+ localArray.destroyCallbacks.push(() => {
568
650
  sub.unsubscribe();
651
+ sharedArray.unobserve(syncRemote);
569
652
  });
570
653
  }
571
- syncComponentState(remoteComponent, component) {
654
+ /**
655
+ * 双向同步对象
656
+ * @param sharedObject
657
+ * @param localObject
658
+ * @param parent
659
+ * @private
660
+ */
661
+ syncObject(sharedObject, localObject, parent) {
572
662
  const syncRemote = (ev, tr) => {
573
663
  this.runRemoteUpdate(tr, () => {
574
- ev.keysChanged.forEach(key => {
575
- if (key === 'state') {
576
- const state = ev.target.get('state');
577
- component.updateState(draft => {
578
- if (typeof draft === 'object' && draft !== null) {
579
- Object.assign(draft, state);
580
- }
581
- else {
582
- return state;
583
- }
584
- });
664
+ ev.changes.keys.forEach((item, key) => {
665
+ if (item.action === 'add' || item.action === 'update') {
666
+ const value = sharedObject.get(key);
667
+ localObject.set(key, this.createLocalModelBySharedByModel(value, parent));
668
+ }
669
+ else {
670
+ localObject.remove(key);
585
671
  }
586
672
  });
587
673
  });
588
674
  };
589
- remoteComponent.observe(syncRemote);
590
- const sub = component.onStateChange.subscribe(change => {
675
+ sharedObject.observe(syncRemote);
676
+ const sub = localObject.changeMarker.onChange.subscribe((op) => {
591
677
  this.runLocalUpdate(() => {
592
- remoteComponent.set('state', change.newState);
593
- }, change.record);
678
+ for (const action of op.apply) {
679
+ switch (action.type) {
680
+ case 'propSet':
681
+ sharedObject.set(action.key, this.createSharedModelByLocalModel(action.value, parent));
682
+ break;
683
+ case 'propDelete':
684
+ sharedObject.delete(action.key);
685
+ break;
686
+ }
687
+ }
688
+ });
594
689
  });
595
- this.componentStateSyncCaches.set(component, () => {
596
- remoteComponent.unobserve(syncRemote);
690
+ localObject.destroyCallbacks.push(function () {
691
+ sharedObject.unobserve(syncRemote);
597
692
  sub.unsubscribe();
598
693
  });
599
694
  }
@@ -619,140 +714,6 @@ exports.Collaborate = class Collaborate {
619
714
  }
620
715
  this.updateFromRemote = false;
621
716
  }
622
- createSharedComponentByComponent(component) {
623
- const sharedComponent = new yjs.Map();
624
- sharedComponent.set('state', component.state);
625
- sharedComponent.set('name', component.name);
626
- const sharedSlots = new yjs.Array();
627
- sharedComponent.set('slots', sharedSlots);
628
- component.slots.toArray().forEach(slot => {
629
- const sharedSlot = this.createSharedSlotBySlot(slot);
630
- sharedSlots.push([sharedSlot]);
631
- });
632
- this.syncComponentSlots(sharedSlots, component);
633
- this.syncComponentState(sharedComponent, component);
634
- return sharedComponent;
635
- }
636
- createSharedSlotBySlot(slot) {
637
- const sharedSlot = new yjs.Map();
638
- sharedSlot.set('schema', slot.schema);
639
- sharedSlot.set('state', slot.state);
640
- const sharedContent = new yjs.Text();
641
- sharedSlot.set('content', sharedContent);
642
- let offset = 0;
643
- slot.toDelta().forEach(i => {
644
- let formats = {};
645
- if (i.formats) {
646
- i.formats.forEach(item => {
647
- formats[item[0].name] = item[1];
648
- });
649
- }
650
- else {
651
- formats = null;
652
- }
653
- if (typeof i.insert === 'string') {
654
- sharedContent.insert(offset, i.insert, formats);
655
- }
656
- else {
657
- const sharedComponent = this.createSharedComponentByComponent(i.insert);
658
- sharedContent.insertEmbed(offset, sharedComponent, formats);
659
- }
660
- offset += i.insert.length;
661
- });
662
- slot.getAttributes().forEach(item => {
663
- sharedContent.setAttribute(item[0].name, item[1]);
664
- });
665
- this.syncSlotContent(sharedContent, slot);
666
- this.syncSlotState(sharedSlot, slot);
667
- return sharedSlot;
668
- }
669
- createComponentBySharedComponent(yMap) {
670
- const sharedSlots = yMap.get('slots');
671
- const slots = [];
672
- sharedSlots.forEach(sharedSlot => {
673
- const slot = this.createSlotBySharedSlot(sharedSlot);
674
- slots.push(slot);
675
- });
676
- const name = yMap.get('name');
677
- const state = yMap.get('state');
678
- const instance = this.registry.createComponentByData(name, {
679
- state,
680
- slots
681
- });
682
- if (instance) {
683
- instance.slots.toArray().forEach((slot, index) => {
684
- let sharedSlot = sharedSlots.get(index);
685
- if (!sharedSlot) {
686
- sharedSlot = this.createSharedSlotBySlot(slot);
687
- sharedSlots.push([sharedSlot]);
688
- }
689
- this.syncSlotState(sharedSlot, slot);
690
- this.syncSlotContent(sharedSlot.get('content'), slot);
691
- });
692
- return instance;
693
- }
694
- throw collaborateErrorFn(`cannot find component factory \`${name}\`.`);
695
- }
696
- createSlotBySharedSlot(sharedSlot) {
697
- const content = sharedSlot.get('content');
698
- const delta = content.toDelta();
699
- const slot = this.registry.createSlot({
700
- schema: sharedSlot.get('schema'),
701
- state: sharedSlot.get('state'),
702
- attributes: {},
703
- formats: {},
704
- content: []
705
- });
706
- const attrs = content.getAttributes();
707
- Object.keys(attrs).forEach(key => {
708
- const attribute = this.registry.getAttribute(key);
709
- if (attribute) {
710
- slot.setAttribute(attribute, attrs[key]);
711
- }
712
- });
713
- for (const action of delta) {
714
- if (action.insert) {
715
- if (typeof action.insert === 'string') {
716
- const formats = remoteFormatsToLocal(this.registry, action.attributes);
717
- slot.insert(action.insert, formats);
718
- }
719
- else {
720
- const sharedComponent = action.insert;
721
- const component = this.createComponentBySharedComponent(sharedComponent);
722
- slot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
723
- this.syncComponentSlots(sharedComponent.get('slots'), component);
724
- this.syncComponentState(sharedComponent, component);
725
- }
726
- }
727
- else {
728
- throw collaborateErrorFn('unexpected delta action.');
729
- }
730
- }
731
- return slot;
732
- }
733
- cleanSubscriptionsBySlot(slot) {
734
- this.contentMap.delete(slot);
735
- [this.contentSyncCaches.get(slot), this.slotStateSyncCaches.get(slot)].forEach(fn => {
736
- if (fn) {
737
- fn();
738
- }
739
- });
740
- slot.sliceContent().forEach(i => {
741
- if (typeof i !== 'string') {
742
- this.cleanSubscriptionsByComponent(i);
743
- }
744
- });
745
- }
746
- cleanSubscriptionsByComponent(component) {
747
- [this.slotsSyncCaches.get(component), this.componentStateSyncCaches.get(component)].forEach(fn => {
748
- if (fn) {
749
- fn();
750
- }
751
- });
752
- component.slots.toArray().forEach(slot => {
753
- this.cleanSubscriptionsBySlot(slot);
754
- });
755
- }
756
717
  };
757
718
  exports.Collaborate = __decorate([
758
719
  core$1.Injectable(),