@textbus/collaborate 3.0.0-alpha.30 → 3.0.0-alpha.31

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, Factory, History, RootComponentRef, Scheduler, Selection, SelectionPaths, Slot, Starter } from '@textbus/core';
2
+ import { AbstractSelection, ComponentInstance, Controller, Factory, History, RootComponentRef, Scheduler, Selection, SelectionPaths, Slot, Starter } 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
  interface CursorPosition {
5
5
  anchor: RelativePosition;
@@ -50,6 +50,8 @@ export declare class Collaborate implements History {
50
50
  protected contentMap: ContentMap;
51
51
  protected updateRemoteActions: Array<UpdateItem>;
52
52
  protected noRecord: {};
53
+ protected historyItems: Array<CursorPosition | null>;
54
+ protected index: number;
53
55
  constructor(stackSize: number, rootComponentRef: RootComponentRef, controller: Controller, scheduler: Scheduler, factory: Factory, selection: Selection, starter: Starter);
54
56
  listen(): void;
55
57
  back(): void;
@@ -57,7 +59,7 @@ export declare class Collaborate implements History {
57
59
  clear(): void;
58
60
  destroy(): void;
59
61
  protected syncRootComponent(root: YMap<any>, rootComponent: ComponentInstance): void;
60
- protected restoreCursorLocation(position: CursorPosition): void;
62
+ protected getAbstractSelection(position: CursorPosition): AbstractSelection | null;
61
63
  protected getRelativeCursorLocation(): CursorPosition | null;
62
64
  protected syncSlotContent(content: YText, slot: Slot): void;
63
65
  protected syncSlotState(remoteSlot: YMap<any>, slot: Slot): void;
@@ -98,6 +98,8 @@ let Collaborate = class Collaborate {
98
98
  this.contentMap = new ContentMap();
99
99
  this.updateRemoteActions = [];
100
100
  this.noRecord = {};
101
+ this.historyItems = [];
102
+ this.index = 0;
101
103
  this.onBack = this.backEvent.asObservable();
102
104
  this.onForward = this.forwardEvent.asObservable();
103
105
  this.onChange = this.changeEvent.asObservable();
@@ -115,25 +117,43 @@ let Collaborate = class Collaborate {
115
117
  listen() {
116
118
  const root = this.yDoc.getMap('RootComponent');
117
119
  const rootComponent = this.rootComponentRef.component;
118
- this.manager = new UndoManager(root, {
120
+ const manager = new UndoManager(root, {
119
121
  trackedOrigins: new Set([this.yDoc])
120
122
  });
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();
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();
126
141
  }
127
142
  if (event.origin === this.yDoc) {
128
143
  this.pushEvent.next();
129
144
  }
130
145
  this.changeEvent.next();
131
146
  });
132
- this.manager.on('stack-item-popped', event => {
133
- const position = event.stackItem.meta.get(cursorKey);
147
+ manager.on('stack-item-popped', () => {
148
+ const position = this.historyItems[this.index - 1];
134
149
  if (position) {
135
- this.restoreCursorLocation(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
+ }
136
155
  }
156
+ this.selection.unSelect();
137
157
  });
138
158
  this.subscriptions.push(this.selection.onChange.subscribe(() => {
139
159
  const paths = this.selection.getPaths();
@@ -194,11 +214,15 @@ let Collaborate = class Collaborate {
194
214
  }
195
215
  clear() {
196
216
  var _a;
217
+ this.index = 0;
218
+ this.historyItems = [];
197
219
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
198
220
  this.changeEvent.next();
199
221
  }
200
222
  destroy() {
201
223
  var _a;
224
+ this.index = 0;
225
+ this.historyItems = [];
202
226
  this.subscriptions.forEach(i => i.unsubscribe());
203
227
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
204
228
  }
@@ -241,18 +265,22 @@ let Collaborate = class Collaborate {
241
265
  this.syncComponentState(root, rootComponent);
242
266
  this.syncComponentSlots(slots, rootComponent);
243
267
  }
244
- restoreCursorLocation(position) {
268
+ getAbstractSelection(position) {
245
269
  const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
246
270
  const focusPosition = createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
247
271
  if (anchorPosition && focusPosition) {
248
272
  const focusSlot = this.contentMap.get(focusPosition.type);
249
273
  const anchorSlot = this.contentMap.get(anchorPosition.type);
250
274
  if (focusSlot && anchorSlot) {
251
- this.selection.setBaseAndExtent(anchorSlot, anchorPosition.index, focusSlot, focusPosition.index);
252
- return;
275
+ return {
276
+ anchorSlot,
277
+ anchorOffset: anchorPosition.index,
278
+ focusSlot,
279
+ focusOffset: focusPosition.index
280
+ };
253
281
  }
254
282
  }
255
- this.selection.unSelect();
283
+ return null;
256
284
  }
257
285
  getRelativeCursorLocation() {
258
286
  const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
package/bundles/index.js CHANGED
@@ -100,6 +100,8 @@ exports.Collaborate = class Collaborate {
100
100
  this.contentMap = new ContentMap();
101
101
  this.updateRemoteActions = [];
102
102
  this.noRecord = {};
103
+ this.historyItems = [];
104
+ this.index = 0;
103
105
  this.onBack = this.backEvent.asObservable();
104
106
  this.onForward = this.forwardEvent.asObservable();
105
107
  this.onChange = this.changeEvent.asObservable();
@@ -117,25 +119,43 @@ exports.Collaborate = class Collaborate {
117
119
  listen() {
118
120
  const root = this.yDoc.getMap('RootComponent');
119
121
  const rootComponent = this.rootComponentRef.component;
120
- this.manager = new yjs.UndoManager(root, {
122
+ const manager = new yjs.UndoManager(root, {
121
123
  trackedOrigins: new Set([this.yDoc])
122
124
  });
123
- const cursorKey = 'cursor-position';
124
- this.manager.on('stack-item-added', event => {
125
- event.stackItem.meta.set(cursorKey, this.getRelativeCursorLocation());
126
- if (this.manager.undoStack.length > this.stackSize) {
127
- this.manager.undoStack.shift();
125
+ this.manager = manager;
126
+ manager.on('stack-item-added', event => {
127
+ if (event.type === 'undo') {
128
+ if (event.origin === manager) {
129
+ this.index++;
130
+ }
131
+ else {
132
+ this.historyItems.length = this.index;
133
+ this.historyItems.push(this.getRelativeCursorLocation());
134
+ this.index++;
135
+ }
136
+ }
137
+ else {
138
+ this.index--;
139
+ }
140
+ if (manager.undoStack.length > this.stackSize) {
141
+ this.historyItems.shift();
142
+ manager.undoStack.shift();
128
143
  }
129
144
  if (event.origin === this.yDoc) {
130
145
  this.pushEvent.next();
131
146
  }
132
147
  this.changeEvent.next();
133
148
  });
134
- this.manager.on('stack-item-popped', event => {
135
- const position = event.stackItem.meta.get(cursorKey);
149
+ manager.on('stack-item-popped', () => {
150
+ const position = this.historyItems[this.index - 1];
136
151
  if (position) {
137
- this.restoreCursorLocation(position);
152
+ const selection = this.getAbstractSelection(position);
153
+ if (selection) {
154
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
155
+ return;
156
+ }
138
157
  }
158
+ this.selection.unSelect();
139
159
  });
140
160
  this.subscriptions.push(this.selection.onChange.subscribe(() => {
141
161
  const paths = this.selection.getPaths();
@@ -196,11 +216,15 @@ exports.Collaborate = class Collaborate {
196
216
  }
197
217
  clear() {
198
218
  var _a;
219
+ this.index = 0;
220
+ this.historyItems = [];
199
221
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.clear();
200
222
  this.changeEvent.next();
201
223
  }
202
224
  destroy() {
203
225
  var _a;
226
+ this.index = 0;
227
+ this.historyItems = [];
204
228
  this.subscriptions.forEach(i => i.unsubscribe());
205
229
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
206
230
  }
@@ -243,18 +267,22 @@ exports.Collaborate = class Collaborate {
243
267
  this.syncComponentState(root, rootComponent);
244
268
  this.syncComponentSlots(slots, rootComponent);
245
269
  }
246
- restoreCursorLocation(position) {
270
+ getAbstractSelection(position) {
247
271
  const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor, this.yDoc);
248
272
  const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus, this.yDoc);
249
273
  if (anchorPosition && focusPosition) {
250
274
  const focusSlot = this.contentMap.get(focusPosition.type);
251
275
  const anchorSlot = this.contentMap.get(anchorPosition.type);
252
276
  if (focusSlot && anchorSlot) {
253
- this.selection.setBaseAndExtent(anchorSlot, anchorPosition.index, focusSlot, focusPosition.index);
254
- return;
277
+ return {
278
+ anchorSlot,
279
+ anchorOffset: anchorPosition.index,
280
+ focusSlot,
281
+ focusOffset: focusPosition.index
282
+ };
255
283
  }
256
284
  }
257
- this.selection.unSelect();
285
+ return null;
258
286
  }
259
287
  getRelativeCursorLocation() {
260
288
  const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "3.0.0-alpha.30",
3
+ "version": "3.0.0-alpha.31",
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,7 +27,7 @@
27
27
  "dependencies": {
28
28
  "@tanbo/di": "^1.1.4",
29
29
  "@tanbo/stream": "^1.1.8",
30
- "@textbus/core": "^3.0.0-alpha.30",
30
+ "@textbus/core": "^3.0.0-alpha.31",
31
31
  "reflect-metadata": "^0.1.13",
32
32
  "y-protocols": "^1.0.5",
33
33
  "yjs": "^13.5.39"
@@ -50,5 +50,5 @@
50
50
  "bugs": {
51
51
  "url": "https://github.com/textbus/textbus.git/issues"
52
52
  },
53
- "gitHead": "5e6ca16bf169e611d816d58b9a98118073a41e47"
53
+ "gitHead": "341e11b65b5c82b1f4815f33831b2dfa5d49e1bc"
54
54
  }