@textbus/collaborate 2.5.9 → 2.5.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  import { Observable, Subject, Subscription } from '@tanbo/stream';
2
- import { ComponentInstance, Controller, History, Registry, RootComponentRef, Scheduler, Selection, SelectionPaths, Slot, Starter, Translator } from '@textbus/core';
2
+ import { AbstractSelection, ComponentInstance, Controller, History, Registry, RootComponentRef, Scheduler, Selection, SelectionPaths, Slot, Starter, Translator } from '@textbus/core';
3
3
  import { Array as YArray, Doc as YDoc, Map as YMap, RelativePosition, Text as YText, Transaction, UndoManager } from 'yjs';
4
4
  import { CollaborateCursor, RemoteSelection } from './collaborate-cursor';
5
5
  interface CursorPosition {
@@ -54,6 +54,8 @@ export declare class Collaborate implements History {
54
54
  protected contentMap: ContentMap;
55
55
  protected updateRemoteActions: Array<UpdateItem>;
56
56
  protected noRecord: {};
57
+ protected historyItems: Array<CursorPosition | null>;
58
+ protected index: number;
57
59
  constructor(stackSize: number, rootComponentRef: RootComponentRef, collaborateCursor: CollaborateCursor, controller: Controller, scheduler: Scheduler, translator: Translator, registry: Registry, selection: Selection, starter: Starter);
58
60
  listen(): void;
59
61
  updateRemoteSelection(paths: RemoteSelection[]): void;
@@ -62,7 +64,7 @@ export declare class Collaborate implements History {
62
64
  clear(): void;
63
65
  destroy(): void;
64
66
  protected syncRootComponent(root: YMap<any>, rootComponent: ComponentInstance): void;
65
- protected restoreCursorLocation(position: CursorPosition): void;
67
+ protected getAbstractSelection(position: CursorPosition): AbstractSelection | null;
66
68
  protected getRelativeCursorLocation(): CursorPosition | null;
67
69
  protected syncContent(content: YText, slot: Slot): void;
68
70
  protected syncSlot(remoteSlot: YMap<any>, slot: Slot): void;
@@ -371,6 +371,8 @@ let Collaborate = class Collaborate {
371
371
  this.contentMap = new ContentMap();
372
372
  this.updateRemoteActions = [];
373
373
  this.noRecord = {};
374
+ this.historyItems = [];
375
+ this.index = 0;
374
376
  this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(delay());
375
377
  this.onBack = this.backEvent.asObservable();
376
378
  this.onForward = this.forwardEvent.asObservable();
@@ -389,25 +391,43 @@ let Collaborate = class Collaborate {
389
391
  listen() {
390
392
  const root = this.yDoc.getMap('RootComponent');
391
393
  const rootComponent = this.rootComponentRef.component;
392
- this.manager = new UndoManager(root, {
394
+ const manager = new UndoManager(root, {
393
395
  trackedOrigins: new Set([this.yDoc])
394
396
  });
395
- const cursorKey = 'cursor-position';
396
- this.manager.on('stack-item-added', event => {
397
- event.stackItem.meta.set(cursorKey, this.getRelativeCursorLocation());
398
- if (this.manager.undoStack.length > this.stackSize) {
399
- this.manager.undoStack.shift();
397
+ this.manager = manager;
398
+ manager.on('stack-item-added', event => {
399
+ if (event.type === 'undo') {
400
+ if (event.origin === manager) {
401
+ this.index++;
402
+ }
403
+ else {
404
+ this.historyItems.length = this.index;
405
+ this.historyItems.push(this.getRelativeCursorLocation());
406
+ this.index++;
407
+ }
408
+ }
409
+ else {
410
+ this.index--;
411
+ }
412
+ if (manager.undoStack.length > this.stackSize) {
413
+ this.historyItems.shift();
414
+ manager.undoStack.shift();
400
415
  }
401
416
  if (event.origin === this.yDoc) {
402
417
  this.pushEvent.next();
403
418
  }
404
419
  this.changeEvent.next();
405
420
  });
406
- this.manager.on('stack-item-popped', event => {
407
- const position = event.stackItem.meta.get(cursorKey);
421
+ manager.on('stack-item-popped', () => {
422
+ const position = this.historyItems[this.index - 1];
408
423
  if (position) {
409
- this.restoreCursorLocation(position);
424
+ const selection = this.getAbstractSelection(position);
425
+ if (selection) {
426
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
427
+ return;
428
+ }
410
429
  }
430
+ this.selection.unSelect();
411
431
  });
412
432
  this.subscriptions.push(this.selection.onChange.subscribe(() => {
413
433
  const paths = this.selection.getPaths();
@@ -471,11 +491,15 @@ let Collaborate = class Collaborate {
471
491
  }
472
492
  clear() {
473
493
  var _a;
494
+ this.index = 0;
495
+ this.historyItems = [];
474
496
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
475
497
  this.changeEvent.next();
476
498
  }
477
499
  destroy() {
478
500
  var _a;
501
+ this.index = 0;
502
+ this.historyItems = [];
479
503
  this.subscriptions.forEach(i => i.unsubscribe());
480
504
  this.collaborateCursor.destroy();
481
505
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
@@ -519,18 +543,22 @@ let Collaborate = class Collaborate {
519
543
  this.syncComponent(root, rootComponent);
520
544
  this.syncSlots(slots, rootComponent);
521
545
  }
522
- restoreCursorLocation(position) {
546
+ getAbstractSelection(position) {
523
547
  const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
524
548
  const focusPosition = createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
525
549
  if (anchorPosition && focusPosition) {
526
550
  const focusSlot = this.contentMap.get(focusPosition.type);
527
551
  const anchorSlot = this.contentMap.get(anchorPosition.type);
528
552
  if (focusSlot && anchorSlot) {
529
- this.selection.setBaseAndExtent(anchorSlot, anchorPosition.index, focusSlot, focusPosition.index);
530
- return;
553
+ return {
554
+ anchorSlot,
555
+ anchorOffset: anchorPosition.index,
556
+ focusSlot,
557
+ focusOffset: focusPosition.index
558
+ };
531
559
  }
532
560
  }
533
- this.selection.unSelect();
561
+ return null;
534
562
  }
535
563
  getRelativeCursorLocation() {
536
564
  const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
@@ -991,7 +1019,7 @@ const collaborateModule = {
991
1019
  CollaborateCursor,
992
1020
  {
993
1021
  provide: History,
994
- useClass: Collaborate
1022
+ useExisting: Collaborate
995
1023
  }
996
1024
  ]
997
1025
  };
package/bundles/index.js CHANGED
@@ -373,6 +373,8 @@ exports.Collaborate = class Collaborate {
373
373
  this.contentMap = new ContentMap();
374
374
  this.updateRemoteActions = [];
375
375
  this.noRecord = {};
376
+ this.historyItems = [];
377
+ this.index = 0;
376
378
  this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(stream.delay());
377
379
  this.onBack = this.backEvent.asObservable();
378
380
  this.onForward = this.forwardEvent.asObservable();
@@ -391,25 +393,43 @@ exports.Collaborate = class Collaborate {
391
393
  listen() {
392
394
  const root = this.yDoc.getMap('RootComponent');
393
395
  const rootComponent = this.rootComponentRef.component;
394
- this.manager = new yjs.UndoManager(root, {
396
+ const manager = new yjs.UndoManager(root, {
395
397
  trackedOrigins: new Set([this.yDoc])
396
398
  });
397
- const cursorKey = 'cursor-position';
398
- this.manager.on('stack-item-added', event => {
399
- event.stackItem.meta.set(cursorKey, this.getRelativeCursorLocation());
400
- if (this.manager.undoStack.length > this.stackSize) {
401
- this.manager.undoStack.shift();
399
+ this.manager = manager;
400
+ manager.on('stack-item-added', event => {
401
+ if (event.type === 'undo') {
402
+ if (event.origin === manager) {
403
+ this.index++;
404
+ }
405
+ else {
406
+ this.historyItems.length = this.index;
407
+ this.historyItems.push(this.getRelativeCursorLocation());
408
+ this.index++;
409
+ }
410
+ }
411
+ else {
412
+ this.index--;
413
+ }
414
+ if (manager.undoStack.length > this.stackSize) {
415
+ this.historyItems.shift();
416
+ manager.undoStack.shift();
402
417
  }
403
418
  if (event.origin === this.yDoc) {
404
419
  this.pushEvent.next();
405
420
  }
406
421
  this.changeEvent.next();
407
422
  });
408
- this.manager.on('stack-item-popped', event => {
409
- const position = event.stackItem.meta.get(cursorKey);
423
+ manager.on('stack-item-popped', () => {
424
+ const position = this.historyItems[this.index - 1];
410
425
  if (position) {
411
- this.restoreCursorLocation(position);
426
+ const selection = this.getAbstractSelection(position);
427
+ if (selection) {
428
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
429
+ return;
430
+ }
412
431
  }
432
+ this.selection.unSelect();
413
433
  });
414
434
  this.subscriptions.push(this.selection.onChange.subscribe(() => {
415
435
  const paths = this.selection.getPaths();
@@ -473,11 +493,15 @@ exports.Collaborate = class Collaborate {
473
493
  }
474
494
  clear() {
475
495
  var _a;
496
+ this.index = 0;
497
+ this.historyItems = [];
476
498
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
477
499
  this.changeEvent.next();
478
500
  }
479
501
  destroy() {
480
502
  var _a;
503
+ this.index = 0;
504
+ this.historyItems = [];
481
505
  this.subscriptions.forEach(i => i.unsubscribe());
482
506
  this.collaborateCursor.destroy();
483
507
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
@@ -521,18 +545,22 @@ exports.Collaborate = class Collaborate {
521
545
  this.syncComponent(root, rootComponent);
522
546
  this.syncSlots(slots, rootComponent);
523
547
  }
524
- restoreCursorLocation(position) {
548
+ getAbstractSelection(position) {
525
549
  const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
526
550
  const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
527
551
  if (anchorPosition && focusPosition) {
528
552
  const focusSlot = this.contentMap.get(focusPosition.type);
529
553
  const anchorSlot = this.contentMap.get(anchorPosition.type);
530
554
  if (focusSlot && anchorSlot) {
531
- this.selection.setBaseAndExtent(anchorSlot, anchorPosition.index, focusSlot, focusPosition.index);
532
- return;
555
+ return {
556
+ anchorSlot,
557
+ anchorOffset: anchorPosition.index,
558
+ focusSlot,
559
+ focusOffset: focusPosition.index
560
+ };
533
561
  }
534
562
  }
535
- this.selection.unSelect();
563
+ return null;
536
564
  }
537
565
  getRelativeCursorLocation() {
538
566
  const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
@@ -993,7 +1021,7 @@ const collaborateModule = {
993
1021
  exports.CollaborateCursor,
994
1022
  {
995
1023
  provide: core.History,
996
- useClass: exports.Collaborate
1024
+ useExisting: exports.Collaborate
997
1025
  }
998
1026
  ]
999
1027
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "2.5.9",
3
+ "version": "2.5.10",
4
4
  "description": "Textbus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.",
5
5
  "main": "./bundles/index.js",
6
6
  "module": "./bundles/index.esm.js",
@@ -27,8 +27,8 @@
27
27
  "dependencies": {
28
28
  "@tanbo/di": "^1.1.4",
29
29
  "@tanbo/stream": "^1.1.8",
30
- "@textbus/browser": "^2.5.9",
31
- "@textbus/core": "^2.5.9",
30
+ "@textbus/browser": "^2.5.10",
31
+ "@textbus/core": "^2.5.10",
32
32
  "reflect-metadata": "^0.1.13",
33
33
  "y-protocols": "^1.0.5",
34
34
  "yjs": "^13.5.39"
@@ -51,5 +51,5 @@
51
51
  "bugs": {
52
52
  "url": "https://github.com/textbus/textbus.git/issues"
53
53
  },
54
- "gitHead": "02dc4cd87f33a9bbfc52a1fc44b2d598de413663"
54
+ "gitHead": "c9108c9af2c1cc880877c9404e5d3de667d84c9b"
55
55
  }