@textbus/collaborate 4.1.0-alpha.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -33,6 +33,4 @@ export declare class CollabHistory implements History {
33
33
  forward(): void;
34
34
  clear(): void;
35
35
  destroy(): void;
36
- private getAbstractSelection;
37
- private getRelativeCursorLocation;
38
36
  }
@@ -1,7 +1,19 @@
1
1
  import { Observable } from '@tanbo/stream';
2
- import { Component, Registry, Scheduler, Selection, Slot } from '@textbus/core';
3
- import { AbstractType, Doc as YDoc, Map as YMap, Text as YText } from 'yjs';
2
+ import { Component, Registry, Scheduler, Selection, Slot, AbstractSelection } from '@textbus/core';
3
+ import { AbstractType, Doc as YDoc, Map as YMap, RelativePosition, Text as YText } from 'yjs';
4
4
  import { SubModelLoader } from './sub-model-loader';
5
+ export interface RelativePositionRecord {
6
+ doc: YDoc;
7
+ position: RelativePosition;
8
+ }
9
+ export interface CursorPosition {
10
+ anchor: RelativePositionRecord;
11
+ focus: RelativePositionRecord;
12
+ }
13
+ export interface CollaborateHistorySelectionPosition {
14
+ before: CursorPosition | null;
15
+ after: CursorPosition | null;
16
+ }
5
17
  declare class SlotMap {
6
18
  private slotAndYTextMap;
7
19
  private yTextAndSlotMap;
@@ -31,6 +43,9 @@ export declare class Collaborate {
31
43
  constructor(scheduler: Scheduler, registry: Registry, selection: Selection, subModelLoader: SubModelLoader);
32
44
  syncRootComponent(yDoc: YDoc, sharedComponent: YMap<any>, localComponent: Component<any>): void;
33
45
  syncRootSlot(yDoc: YDoc, sharedSlot: YText, localSlot: Slot): void;
46
+ getAbstractSelection(position: CursorPosition): AbstractSelection | null;
47
+ getRelativeCursorLocation(): CursorPosition | null;
48
+ restoreCursorPosition(position: CursorPosition | null): void;
34
49
  private initSyncEvent;
35
50
  private syncComponent;
36
51
  private syncSlot;
@@ -1,7 +1,8 @@
1
+ import { HocuspocusProvider } from '@hocuspocus/provider';
1
2
  import { HocuspocusProviderConfiguration } from '@hocuspocus/provider';
2
3
  import { SyncConnector } from '../sync-connector';
3
4
  export declare class HocuspocusConnector extends SyncConnector {
4
- private provide;
5
+ provide: HocuspocusProvider;
5
6
  constructor(config: HocuspocusProviderConfiguration);
6
7
  setLocalStateField(key: string, data: Record<string, any>): void;
7
8
  onDestroy(): void;
@@ -1,7 +1,8 @@
1
1
  import { Doc as YDoc } from 'yjs';
2
+ import { WebsocketProvider } from 'y-websocket';
2
3
  import { SyncConnector } from '../sync-connector';
3
4
  export declare class YWebsocketConnector extends SyncConnector {
4
- private provide;
5
+ provide: WebsocketProvider;
5
6
  constructor(url: string, roomName: string, yDoc: YDoc);
6
7
  setLocalStateField(key: string, data: Record<string, any>): void;
7
8
  onDestroy(): void;
@@ -3,7 +3,7 @@ import { Subject, map, filter, Subscription } from '@tanbo/stream';
3
3
  import { WebsocketProvider } from 'y-websocket';
4
4
  import { Injectable, Inject, Optional } from '@viewfly/core';
5
5
  import { makeError, ChangeOrigin, Slot, createObjectProxy, createArrayProxy, AsyncSlot, AsyncComponent, Component, Scheduler, Registry, Selection, HISTORY_STACK_SIZE, RootComponentRef, History } from '@textbus/core';
6
- import { Doc, Map, Array as Array$1, Text, UndoManager, createAbsolutePositionFromRelativePosition, createRelativePositionFromTypeIndex } from 'yjs';
6
+ import { Doc, createAbsolutePositionFromRelativePosition, createRelativePositionFromTypeIndex, Map, Array as Array$1, Text, UndoManager } from 'yjs';
7
7
 
8
8
  /**
9
9
  * 协作通信通用接口
@@ -209,11 +209,66 @@ let Collaborate = class Collaborate {
209
209
  this.initLocalSlotBySharedSlot(sharedSlot, localSlot);
210
210
  }
211
211
  else {
212
- this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
212
+ yDoc.transact(() => {
213
+ this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
214
+ });
213
215
  }
214
216
  this.initSyncEvent(yDoc);
215
217
  this.syncSlot(sharedSlot, localSlot);
216
218
  }
219
+ getAbstractSelection(position) {
220
+ const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor.position, position.anchor.doc);
221
+ const focusPosition = createAbsolutePositionFromRelativePosition(position.focus.position, position.focus.doc);
222
+ if (anchorPosition && focusPosition) {
223
+ const focusSlot = this.slotMap.get(focusPosition.type);
224
+ const anchorSlot = this.slotMap.get(anchorPosition.type);
225
+ if (focusSlot && anchorSlot) {
226
+ return {
227
+ anchorSlot,
228
+ anchorOffset: anchorPosition.index,
229
+ focusSlot,
230
+ focusOffset: focusPosition.index
231
+ };
232
+ }
233
+ }
234
+ return null;
235
+ }
236
+ getRelativeCursorLocation() {
237
+ const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
238
+ if (anchorSlot) {
239
+ const anchorYText = this.slotMap.get(anchorSlot);
240
+ if (anchorYText) {
241
+ const anchorPosition = createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
242
+ if (focusSlot) {
243
+ const focusYText = this.slotMap.get(focusSlot);
244
+ if (focusYText) {
245
+ const focusPosition = createRelativePositionFromTypeIndex(focusYText, focusOffset);
246
+ return {
247
+ focus: {
248
+ doc: focusYText.doc,
249
+ position: focusPosition
250
+ },
251
+ anchor: {
252
+ doc: anchorYText.doc,
253
+ position: anchorPosition
254
+ }
255
+ };
256
+ }
257
+ }
258
+ }
259
+ }
260
+ return null;
261
+ }
262
+ restoreCursorPosition(position) {
263
+ if (!position) {
264
+ this.selection.unSelect();
265
+ return;
266
+ }
267
+ const selection = this.getAbstractSelection(position);
268
+ if (selection) {
269
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
270
+ }
271
+ }
217
272
  initSyncEvent(yDoc) {
218
273
  this.subscriptions.push(this.scheduler.onDocChanged.pipe(map(item => {
219
274
  return item.filter(i => {
@@ -469,6 +524,7 @@ let Collaborate = class Collaborate {
469
524
  yDoc: subDocument,
470
525
  yType: content
471
526
  });
527
+ this.initSyncEvent(subDocument);
472
528
  localSlot.loader.markAsLoaded();
473
529
  });
474
530
  localSlot.__changeMarker__.destroyCallbacks.push(() => {
@@ -626,6 +682,7 @@ let Collaborate = class Collaborate {
626
682
  yType: state,
627
683
  yDoc: subDocument
628
684
  });
685
+ this.initSyncEvent(subDocument);
629
686
  component.loader.markAsLoaded();
630
687
  });
631
688
  return sharedComponent;
@@ -899,7 +956,7 @@ let CollabHistory = class CollabHistory {
899
956
  this.manager = manager;
900
957
  let beforePosition = null;
901
958
  this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
902
- beforePosition = this.getRelativeCursorLocation();
959
+ beforePosition = this.collaborate.getRelativeCursorLocation();
903
960
  }), this.collaborate.onAddSubModel.subscribe(() => {
904
961
  throw collabHistoryErrorFn('single document does not support submodels.');
905
962
  }));
@@ -912,7 +969,7 @@ let CollabHistory = class CollabHistory {
912
969
  this.historyItems.length = this.index;
913
970
  this.historyItems.push({
914
971
  before: beforePosition,
915
- after: this.getRelativeCursorLocation()
972
+ after: this.collaborate.getRelativeCursorLocation()
916
973
  });
917
974
  this.index++;
918
975
  }
@@ -933,14 +990,7 @@ let CollabHistory = class CollabHistory {
933
990
  const index = ev.type === 'undo' ? this.index : this.index - 1;
934
991
  const position = this.historyItems[index] || null;
935
992
  const p = ev.type === 'undo' ? position === null || position === void 0 ? void 0 : position.before : position === null || position === void 0 ? void 0 : position.after;
936
- if (p) {
937
- const selection = this.getAbstractSelection(p);
938
- if (selection) {
939
- this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
940
- return;
941
- }
942
- }
943
- this.selection.unSelect();
993
+ this.collaborate.restoreCursorPosition(p);
944
994
  });
945
995
  }
946
996
  back() {
@@ -972,43 +1022,6 @@ let CollabHistory = class CollabHistory {
972
1022
  this.subscriptions.forEach(i => i.unsubscribe());
973
1023
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
974
1024
  }
975
- getAbstractSelection(position) {
976
- const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor, this.collaborate.yDoc);
977
- const focusPosition = createAbsolutePositionFromRelativePosition(position.focus, this.collaborate.yDoc);
978
- if (anchorPosition && focusPosition) {
979
- const focusSlot = this.collaborate.slotMap.get(focusPosition.type);
980
- const anchorSlot = this.collaborate.slotMap.get(anchorPosition.type);
981
- if (focusSlot && anchorSlot) {
982
- return {
983
- anchorSlot,
984
- anchorOffset: anchorPosition.index,
985
- focusSlot,
986
- focusOffset: focusPosition.index
987
- };
988
- }
989
- }
990
- return null;
991
- }
992
- getRelativeCursorLocation() {
993
- const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
994
- if (anchorSlot) {
995
- const anchorYText = this.collaborate.slotMap.get(anchorSlot);
996
- if (anchorYText) {
997
- const anchorPosition = createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
998
- if (focusSlot) {
999
- const focusYText = this.collaborate.slotMap.get(focusSlot);
1000
- if (focusYText) {
1001
- const focusPosition = createRelativePositionFromTypeIndex(focusYText, focusOffset);
1002
- return {
1003
- focus: focusPosition,
1004
- anchor: anchorPosition
1005
- };
1006
- }
1007
- }
1008
- }
1009
- }
1010
- return null;
1011
- }
1012
1025
  };
1013
1026
  CollabHistory = __decorate([
1014
1027
  Injectable(),
@@ -1105,8 +1118,9 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1105
1118
  get canForward() {
1106
1119
  return this.actionStack.length > 0 && this.index < this.actionStack.length;
1107
1120
  }
1108
- constructor(collaborate, rootComponentRef, stackSize, undoManagerConfig) {
1121
+ constructor(collaborate, scheduler, rootComponentRef, stackSize, undoManagerConfig) {
1109
1122
  this.collaborate = collaborate;
1123
+ this.scheduler = scheduler;
1110
1124
  this.rootComponentRef = rootComponentRef;
1111
1125
  this.stackSize = stackSize;
1112
1126
  this.undoManagerConfig = undoManagerConfig;
@@ -1119,6 +1133,7 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1119
1133
  this.index = 0;
1120
1134
  this.stackItem = null;
1121
1135
  this.timer = null;
1136
+ this.beforePosition = null;
1122
1137
  this.subscription = new Subscription();
1123
1138
  this.subDocs = new Set();
1124
1139
  this.listenerCaches = new Set();
@@ -1141,6 +1156,8 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1141
1156
  if (this.isListen) {
1142
1157
  this.listenItem(yType, yDoc);
1143
1158
  }
1159
+ }), this.scheduler.onLocalChangeBefore.subscribe(() => {
1160
+ this.beforePosition = this.collaborate.getRelativeCursorLocation();
1144
1161
  }));
1145
1162
  }
1146
1163
  forward() {
@@ -1150,9 +1167,10 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1150
1167
  clearTimeout(this.timer);
1151
1168
  const item = this.actionStack[this.index];
1152
1169
  if (item) {
1153
- for (const i of item) {
1170
+ for (const i of item.undoManagers) {
1154
1171
  i.redo();
1155
1172
  }
1173
+ this.collaborate.restoreCursorPosition(item.after);
1156
1174
  }
1157
1175
  this.index++;
1158
1176
  this.forwardEvent.next();
@@ -1163,29 +1181,32 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1163
1181
  return;
1164
1182
  }
1165
1183
  clearTimeout(this.timer);
1166
- let actions;
1184
+ let historyStackItem;
1167
1185
  if (this.stackItem) {
1168
- actions = this.stackItem;
1186
+ historyStackItem = this.stackItem;
1169
1187
  this.stackItem = null;
1170
1188
  }
1171
1189
  else {
1172
1190
  this.index--;
1173
- actions = this.actionStack[this.index];
1191
+ historyStackItem = this.actionStack[this.index];
1174
1192
  }
1175
- let len = actions.length;
1193
+ let len = historyStackItem.undoManagers.length;
1176
1194
  while (len > 0) {
1177
1195
  len--;
1178
- actions[len].undo();
1196
+ historyStackItem.undoManagers[len].undo();
1179
1197
  }
1180
- if (actions) {
1198
+ if (historyStackItem) {
1199
+ const beforePosition = historyStackItem.before;
1200
+ this.collaborate.restoreCursorPosition(beforePosition);
1181
1201
  this.backEvent.next();
1182
1202
  this.changeEvent.next();
1183
1203
  }
1184
1204
  }
1185
1205
  clear() {
1186
1206
  this.actionStack = [];
1187
- this.stackItem = [];
1207
+ this.stackItem = null;
1188
1208
  this.index = 0;
1209
+ this.beforePosition = null;
1189
1210
  clearTimeout(this.timer);
1190
1211
  this.listenerCaches.forEach((undoManager) => {
1191
1212
  undoManager.clear();
@@ -1194,6 +1215,7 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1194
1215
  }
1195
1216
  destroy() {
1196
1217
  this.clear();
1218
+ this.beforePosition = this.stackItem = null;
1197
1219
  this.subscription.unsubscribe();
1198
1220
  this.listenerCaches.forEach((undoManager) => {
1199
1221
  undoManager.destroy();
@@ -1224,7 +1246,7 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1224
1246
  if (this.index != this.actionStack.length) {
1225
1247
  const redoStack = this.actionStack.slice(this.index);
1226
1248
  redoStack.forEach(item => {
1227
- item.forEach(i => {
1249
+ item.undoManagers.forEach(i => {
1228
1250
  i.clear(false, true);
1229
1251
  });
1230
1252
  });
@@ -1232,7 +1254,11 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1232
1254
  this.changeEvent.next();
1233
1255
  }
1234
1256
  if (this.stackItem === null) {
1235
- this.stackItem = [];
1257
+ this.stackItem = {
1258
+ before: this.beforePosition,
1259
+ after: null,
1260
+ undoManagers: []
1261
+ };
1236
1262
  this.timer = setTimeout(() => {
1237
1263
  if (this.actionStack.length >= this.stackSize) {
1238
1264
  this.actionStack.shift();
@@ -1240,13 +1266,15 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1240
1266
  else {
1241
1267
  this.index++;
1242
1268
  }
1269
+ // this.beforePosition = this.collaborate.getRelativeCursorLocation()
1270
+ this.stackItem.after = this.beforePosition;
1243
1271
  this.actionStack.push(this.stackItem);
1244
1272
  this.stackItem = null;
1245
1273
  this.pushEvent.next();
1246
1274
  this.changeEvent.next();
1247
1275
  }, 500);
1248
1276
  }
1249
- this.stackItem.push(undoManager);
1277
+ this.stackItem.undoManagers.push(undoManager);
1250
1278
  }
1251
1279
  });
1252
1280
  this.listenerCaches.add(undoManager);
@@ -1254,9 +1282,10 @@ let MultipleDocCollabHistory = class MultipleDocCollabHistory {
1254
1282
  };
1255
1283
  MultipleDocCollabHistory = __decorate([
1256
1284
  Injectable(),
1257
- __param(2, Inject(HISTORY_STACK_SIZE)),
1258
- __param(3, Optional()),
1285
+ __param(3, Inject(HISTORY_STACK_SIZE)),
1286
+ __param(4, Optional()),
1259
1287
  __metadata("design:paramtypes", [Collaborate,
1288
+ Scheduler,
1260
1289
  RootComponentRef, Number, CustomUndoManagerConfig])
1261
1290
  ], MultipleDocCollabHistory);
1262
1291
 
package/bundles/index.js CHANGED
@@ -211,11 +211,66 @@ exports.Collaborate = class Collaborate {
211
211
  this.initLocalSlotBySharedSlot(sharedSlot, localSlot);
212
212
  }
213
213
  else {
214
- this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
214
+ yDoc.transact(() => {
215
+ this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
216
+ });
215
217
  }
216
218
  this.initSyncEvent(yDoc);
217
219
  this.syncSlot(sharedSlot, localSlot);
218
220
  }
221
+ getAbstractSelection(position) {
222
+ const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor.position, position.anchor.doc);
223
+ const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus.position, position.focus.doc);
224
+ if (anchorPosition && focusPosition) {
225
+ const focusSlot = this.slotMap.get(focusPosition.type);
226
+ const anchorSlot = this.slotMap.get(anchorPosition.type);
227
+ if (focusSlot && anchorSlot) {
228
+ return {
229
+ anchorSlot,
230
+ anchorOffset: anchorPosition.index,
231
+ focusSlot,
232
+ focusOffset: focusPosition.index
233
+ };
234
+ }
235
+ }
236
+ return null;
237
+ }
238
+ getRelativeCursorLocation() {
239
+ const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
240
+ if (anchorSlot) {
241
+ const anchorYText = this.slotMap.get(anchorSlot);
242
+ if (anchorYText) {
243
+ const anchorPosition = yjs.createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
244
+ if (focusSlot) {
245
+ const focusYText = this.slotMap.get(focusSlot);
246
+ if (focusYText) {
247
+ const focusPosition = yjs.createRelativePositionFromTypeIndex(focusYText, focusOffset);
248
+ return {
249
+ focus: {
250
+ doc: focusYText.doc,
251
+ position: focusPosition
252
+ },
253
+ anchor: {
254
+ doc: anchorYText.doc,
255
+ position: anchorPosition
256
+ }
257
+ };
258
+ }
259
+ }
260
+ }
261
+ }
262
+ return null;
263
+ }
264
+ restoreCursorPosition(position) {
265
+ if (!position) {
266
+ this.selection.unSelect();
267
+ return;
268
+ }
269
+ const selection = this.getAbstractSelection(position);
270
+ if (selection) {
271
+ this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
272
+ }
273
+ }
219
274
  initSyncEvent(yDoc) {
220
275
  this.subscriptions.push(this.scheduler.onDocChanged.pipe(stream.map(item => {
221
276
  return item.filter(i => {
@@ -471,6 +526,7 @@ exports.Collaborate = class Collaborate {
471
526
  yDoc: subDocument,
472
527
  yType: content
473
528
  });
529
+ this.initSyncEvent(subDocument);
474
530
  localSlot.loader.markAsLoaded();
475
531
  });
476
532
  localSlot.__changeMarker__.destroyCallbacks.push(() => {
@@ -628,6 +684,7 @@ exports.Collaborate = class Collaborate {
628
684
  yType: state,
629
685
  yDoc: subDocument
630
686
  });
687
+ this.initSyncEvent(subDocument);
631
688
  component.loader.markAsLoaded();
632
689
  });
633
690
  return sharedComponent;
@@ -901,7 +958,7 @@ exports.CollabHistory = class CollabHistory {
901
958
  this.manager = manager;
902
959
  let beforePosition = null;
903
960
  this.subscriptions.push(this.scheduler.onLocalChangeBefore.subscribe(() => {
904
- beforePosition = this.getRelativeCursorLocation();
961
+ beforePosition = this.collaborate.getRelativeCursorLocation();
905
962
  }), this.collaborate.onAddSubModel.subscribe(() => {
906
963
  throw collabHistoryErrorFn('single document does not support submodels.');
907
964
  }));
@@ -914,7 +971,7 @@ exports.CollabHistory = class CollabHistory {
914
971
  this.historyItems.length = this.index;
915
972
  this.historyItems.push({
916
973
  before: beforePosition,
917
- after: this.getRelativeCursorLocation()
974
+ after: this.collaborate.getRelativeCursorLocation()
918
975
  });
919
976
  this.index++;
920
977
  }
@@ -935,14 +992,7 @@ exports.CollabHistory = class CollabHistory {
935
992
  const index = ev.type === 'undo' ? this.index : this.index - 1;
936
993
  const position = this.historyItems[index] || null;
937
994
  const p = ev.type === 'undo' ? position === null || position === void 0 ? void 0 : position.before : position === null || position === void 0 ? void 0 : position.after;
938
- if (p) {
939
- const selection = this.getAbstractSelection(p);
940
- if (selection) {
941
- this.selection.setBaseAndExtent(selection.anchorSlot, selection.anchorOffset, selection.focusSlot, selection.focusOffset);
942
- return;
943
- }
944
- }
945
- this.selection.unSelect();
995
+ this.collaborate.restoreCursorPosition(p);
946
996
  });
947
997
  }
948
998
  back() {
@@ -974,43 +1024,6 @@ exports.CollabHistory = class CollabHistory {
974
1024
  this.subscriptions.forEach(i => i.unsubscribe());
975
1025
  (_a = this.manager) === null || _a === void 0 ? void 0 : _a.destroy();
976
1026
  }
977
- getAbstractSelection(position) {
978
- const anchorPosition = yjs.createAbsolutePositionFromRelativePosition(position.anchor, this.collaborate.yDoc);
979
- const focusPosition = yjs.createAbsolutePositionFromRelativePosition(position.focus, this.collaborate.yDoc);
980
- if (anchorPosition && focusPosition) {
981
- const focusSlot = this.collaborate.slotMap.get(focusPosition.type);
982
- const anchorSlot = this.collaborate.slotMap.get(anchorPosition.type);
983
- if (focusSlot && anchorSlot) {
984
- return {
985
- anchorSlot,
986
- anchorOffset: anchorPosition.index,
987
- focusSlot,
988
- focusOffset: focusPosition.index
989
- };
990
- }
991
- }
992
- return null;
993
- }
994
- getRelativeCursorLocation() {
995
- const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
996
- if (anchorSlot) {
997
- const anchorYText = this.collaborate.slotMap.get(anchorSlot);
998
- if (anchorYText) {
999
- const anchorPosition = yjs.createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
1000
- if (focusSlot) {
1001
- const focusYText = this.collaborate.slotMap.get(focusSlot);
1002
- if (focusYText) {
1003
- const focusPosition = yjs.createRelativePositionFromTypeIndex(focusYText, focusOffset);
1004
- return {
1005
- focus: focusPosition,
1006
- anchor: anchorPosition
1007
- };
1008
- }
1009
- }
1010
- }
1011
- }
1012
- return null;
1013
- }
1014
1027
  };
1015
1028
  exports.CollabHistory = __decorate([
1016
1029
  core$1.Injectable(),
@@ -1107,8 +1120,9 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1107
1120
  get canForward() {
1108
1121
  return this.actionStack.length > 0 && this.index < this.actionStack.length;
1109
1122
  }
1110
- constructor(collaborate, rootComponentRef, stackSize, undoManagerConfig) {
1123
+ constructor(collaborate, scheduler, rootComponentRef, stackSize, undoManagerConfig) {
1111
1124
  this.collaborate = collaborate;
1125
+ this.scheduler = scheduler;
1112
1126
  this.rootComponentRef = rootComponentRef;
1113
1127
  this.stackSize = stackSize;
1114
1128
  this.undoManagerConfig = undoManagerConfig;
@@ -1121,6 +1135,7 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1121
1135
  this.index = 0;
1122
1136
  this.stackItem = null;
1123
1137
  this.timer = null;
1138
+ this.beforePosition = null;
1124
1139
  this.subscription = new stream.Subscription();
1125
1140
  this.subDocs = new Set();
1126
1141
  this.listenerCaches = new Set();
@@ -1143,6 +1158,8 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1143
1158
  if (this.isListen) {
1144
1159
  this.listenItem(yType, yDoc);
1145
1160
  }
1161
+ }), this.scheduler.onLocalChangeBefore.subscribe(() => {
1162
+ this.beforePosition = this.collaborate.getRelativeCursorLocation();
1146
1163
  }));
1147
1164
  }
1148
1165
  forward() {
@@ -1152,9 +1169,10 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1152
1169
  clearTimeout(this.timer);
1153
1170
  const item = this.actionStack[this.index];
1154
1171
  if (item) {
1155
- for (const i of item) {
1172
+ for (const i of item.undoManagers) {
1156
1173
  i.redo();
1157
1174
  }
1175
+ this.collaborate.restoreCursorPosition(item.after);
1158
1176
  }
1159
1177
  this.index++;
1160
1178
  this.forwardEvent.next();
@@ -1165,29 +1183,32 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1165
1183
  return;
1166
1184
  }
1167
1185
  clearTimeout(this.timer);
1168
- let actions;
1186
+ let historyStackItem;
1169
1187
  if (this.stackItem) {
1170
- actions = this.stackItem;
1188
+ historyStackItem = this.stackItem;
1171
1189
  this.stackItem = null;
1172
1190
  }
1173
1191
  else {
1174
1192
  this.index--;
1175
- actions = this.actionStack[this.index];
1193
+ historyStackItem = this.actionStack[this.index];
1176
1194
  }
1177
- let len = actions.length;
1195
+ let len = historyStackItem.undoManagers.length;
1178
1196
  while (len > 0) {
1179
1197
  len--;
1180
- actions[len].undo();
1198
+ historyStackItem.undoManagers[len].undo();
1181
1199
  }
1182
- if (actions) {
1200
+ if (historyStackItem) {
1201
+ const beforePosition = historyStackItem.before;
1202
+ this.collaborate.restoreCursorPosition(beforePosition);
1183
1203
  this.backEvent.next();
1184
1204
  this.changeEvent.next();
1185
1205
  }
1186
1206
  }
1187
1207
  clear() {
1188
1208
  this.actionStack = [];
1189
- this.stackItem = [];
1209
+ this.stackItem = null;
1190
1210
  this.index = 0;
1211
+ this.beforePosition = null;
1191
1212
  clearTimeout(this.timer);
1192
1213
  this.listenerCaches.forEach((undoManager) => {
1193
1214
  undoManager.clear();
@@ -1196,6 +1217,7 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1196
1217
  }
1197
1218
  destroy() {
1198
1219
  this.clear();
1220
+ this.beforePosition = this.stackItem = null;
1199
1221
  this.subscription.unsubscribe();
1200
1222
  this.listenerCaches.forEach((undoManager) => {
1201
1223
  undoManager.destroy();
@@ -1226,7 +1248,7 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1226
1248
  if (this.index != this.actionStack.length) {
1227
1249
  const redoStack = this.actionStack.slice(this.index);
1228
1250
  redoStack.forEach(item => {
1229
- item.forEach(i => {
1251
+ item.undoManagers.forEach(i => {
1230
1252
  i.clear(false, true);
1231
1253
  });
1232
1254
  });
@@ -1234,7 +1256,11 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1234
1256
  this.changeEvent.next();
1235
1257
  }
1236
1258
  if (this.stackItem === null) {
1237
- this.stackItem = [];
1259
+ this.stackItem = {
1260
+ before: this.beforePosition,
1261
+ after: null,
1262
+ undoManagers: []
1263
+ };
1238
1264
  this.timer = setTimeout(() => {
1239
1265
  if (this.actionStack.length >= this.stackSize) {
1240
1266
  this.actionStack.shift();
@@ -1242,13 +1268,15 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1242
1268
  else {
1243
1269
  this.index++;
1244
1270
  }
1271
+ // this.beforePosition = this.collaborate.getRelativeCursorLocation()
1272
+ this.stackItem.after = this.beforePosition;
1245
1273
  this.actionStack.push(this.stackItem);
1246
1274
  this.stackItem = null;
1247
1275
  this.pushEvent.next();
1248
1276
  this.changeEvent.next();
1249
1277
  }, 500);
1250
1278
  }
1251
- this.stackItem.push(undoManager);
1279
+ this.stackItem.undoManagers.push(undoManager);
1252
1280
  }
1253
1281
  });
1254
1282
  this.listenerCaches.add(undoManager);
@@ -1256,9 +1284,10 @@ exports.MultipleDocCollabHistory = class MultipleDocCollabHistory {
1256
1284
  };
1257
1285
  exports.MultipleDocCollabHistory = __decorate([
1258
1286
  core$1.Injectable(),
1259
- __param(2, core$1.Inject(core.HISTORY_STACK_SIZE)),
1260
- __param(3, core$1.Optional()),
1287
+ __param(3, core$1.Inject(core.HISTORY_STACK_SIZE)),
1288
+ __param(4, core$1.Optional()),
1261
1289
  __metadata("design:paramtypes", [exports.Collaborate,
1290
+ core.Scheduler,
1262
1291
  core.RootComponentRef, Number, CustomUndoManagerConfig])
1263
1292
  ], exports.MultipleDocCollabHistory);
1264
1293
 
@@ -1,9 +1,10 @@
1
1
  import { Observable } from '@tanbo/stream';
2
- import { History, RootComponentRef } from '@textbus/core';
2
+ import { History, RootComponentRef, Scheduler } from '@textbus/core';
3
3
  import { Collaborate } from './collaborate';
4
4
  import { CustomUndoManagerConfig } from './collab-history';
5
5
  export declare class MultipleDocCollabHistory implements History {
6
6
  private collaborate;
7
+ private scheduler;
7
8
  private rootComponentRef;
8
9
  private stackSize;
9
10
  private undoManagerConfig;
@@ -22,10 +23,11 @@ export declare class MultipleDocCollabHistory implements History {
22
23
  private index;
23
24
  private stackItem;
24
25
  private timer;
26
+ private beforePosition;
25
27
  private subscription;
26
28
  private subDocs;
27
29
  private listenerCaches;
28
- constructor(collaborate: Collaborate, rootComponentRef: RootComponentRef, stackSize: number, undoManagerConfig: CustomUndoManagerConfig);
30
+ constructor(collaborate: Collaborate, scheduler: Scheduler, rootComponentRef: RootComponentRef, stackSize: number, undoManagerConfig: CustomUndoManagerConfig);
29
31
  listen(): void;
30
32
  forward(): void;
31
33
  back(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@textbus/collaborate",
3
- "version": "4.1.0-alpha.0",
3
+ "version": "4.1.0",
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
  "@hocuspocus/provider": "^2.13.6",
29
29
  "@tanbo/stream": "^1.2.5",
30
- "@textbus/core": "^4.1.0-alpha.0",
31
- "@viewfly/core": "^1.0.4",
30
+ "@textbus/core": "^4.1.0",
31
+ "@viewfly/core": "^1.0.5",
32
32
  "y-websocket": "^1.4.3",
33
33
  "yjs": "^13.6.14"
34
34
  },