@textbus/collaborate 5.2.1 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.esm.js +1099 -642
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1411 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.esm.js
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
|
-
import { Injectable
|
|
2
|
-
import { makeError
|
|
3
|
-
import { Subject
|
|
4
|
-
import { UndoManager
|
|
5
|
-
import { HocuspocusProvider
|
|
6
|
-
import { WebsocketProvider
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { Injectable, Inject, Optional } from "@viewfly/core";
|
|
2
|
+
import { makeError, HISTORY_STACK_SIZE, ChangeOrigin, Slot, observe, AsyncSlot, AsyncComponent, Component, History, Selection } from "@textbus/core";
|
|
3
|
+
import { Subject, map, filter, Subscription } from "@tanbo/stream";
|
|
4
|
+
import { UndoManager, Doc, createAbsolutePositionFromRelativePosition, createRelativePositionFromTypeIndex, Map, Array as Array$1, Text } from "yjs";
|
|
5
|
+
import { HocuspocusProvider } from "@hocuspocus/provider";
|
|
6
|
+
import { WebsocketProvider } from "y-websocket";
|
|
7
|
+
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
8
|
+
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
9
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
10
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
11
|
+
if (decorator = decorators[i])
|
|
12
|
+
result = decorator(result) || result;
|
|
13
|
+
return result;
|
|
14
|
+
};
|
|
15
|
+
var __decorateParam$1 = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
16
|
+
class CustomUndoManagerConfig {
|
|
13
17
|
}
|
|
14
|
-
const
|
|
15
|
-
let
|
|
16
|
-
constructor(
|
|
17
|
-
this.rootComponentRef =
|
|
18
|
+
const collabHistoryErrorFn = makeError("CollabHistory");
|
|
19
|
+
let CollabHistory = class {
|
|
20
|
+
constructor(rootComponentRef, collaborate, scheduler, stackSize, undoManagerConfig) {
|
|
21
|
+
this.rootComponentRef = rootComponentRef;
|
|
22
|
+
this.collaborate = collaborate;
|
|
23
|
+
this.scheduler = scheduler;
|
|
24
|
+
this.stackSize = stackSize;
|
|
25
|
+
this.undoManagerConfig = undoManagerConfig;
|
|
26
|
+
this.onBack = this.backEvent.asObservable();
|
|
27
|
+
this.onForward = this.forwardEvent.asObservable();
|
|
28
|
+
this.onChange = this.changeEvent.asObservable();
|
|
29
|
+
this.onPush = this.pushEvent.asObservable();
|
|
18
30
|
}
|
|
19
31
|
rootComponentRef;
|
|
20
32
|
collaborate;
|
|
@@ -26,150 +38,234 @@ let E = class {
|
|
|
26
38
|
onChange;
|
|
27
39
|
onPush;
|
|
28
40
|
get canBack() {
|
|
29
|
-
return this.manager?.canUndo() ||
|
|
41
|
+
return this.manager?.canUndo() || false;
|
|
30
42
|
}
|
|
31
43
|
get canForward() {
|
|
32
|
-
return this.manager?.canRedo() ||
|
|
44
|
+
return this.manager?.canRedo() || false;
|
|
33
45
|
}
|
|
34
46
|
manager = null;
|
|
35
47
|
historyItems = [];
|
|
36
48
|
index = 0;
|
|
37
49
|
subscriptions = [];
|
|
38
|
-
backEvent = new
|
|
39
|
-
forwardEvent = new
|
|
40
|
-
changeEvent = new
|
|
41
|
-
pushEvent = new
|
|
50
|
+
backEvent = new Subject();
|
|
51
|
+
forwardEvent = new Subject();
|
|
52
|
+
changeEvent = new Subject();
|
|
53
|
+
pushEvent = new Subject();
|
|
42
54
|
listen() {
|
|
43
|
-
const
|
|
44
|
-
this.
|
|
45
|
-
|
|
55
|
+
const root = this.collaborate.yDoc.getMap("RootComponent");
|
|
56
|
+
const rootComponent = this.rootComponentRef.component;
|
|
57
|
+
this.collaborate.syncRootComponent(this.collaborate.yDoc, root, rootComponent);
|
|
58
|
+
const undoManagerConfig = this.undoManagerConfig || {};
|
|
59
|
+
const manager = new UndoManager(root, {
|
|
46
60
|
trackedOrigins: /* @__PURE__ */ new Set([this.collaborate.yDoc]),
|
|
47
|
-
captureTransaction(
|
|
48
|
-
|
|
61
|
+
captureTransaction(arg) {
|
|
62
|
+
if (undoManagerConfig.captureTransaction) {
|
|
63
|
+
return undoManagerConfig.captureTransaction(arg);
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
49
66
|
},
|
|
50
|
-
deleteFilter(
|
|
51
|
-
|
|
67
|
+
deleteFilter(item) {
|
|
68
|
+
if (undoManagerConfig.deleteFilter) {
|
|
69
|
+
return undoManagerConfig.deleteFilter(item);
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
52
72
|
}
|
|
53
73
|
});
|
|
54
|
-
this.manager =
|
|
55
|
-
let
|
|
74
|
+
this.manager = manager;
|
|
75
|
+
let beforePosition = null;
|
|
56
76
|
this.subscriptions.push(
|
|
57
77
|
this.scheduler.onLocalChangeBefore.subscribe(() => {
|
|
58
|
-
|
|
78
|
+
beforePosition = this.collaborate.getRelativeCursorLocation();
|
|
59
79
|
}),
|
|
60
80
|
this.collaborate.onAddSubModel.subscribe(() => {
|
|
61
|
-
throw
|
|
81
|
+
throw collabHistoryErrorFn("single document does not support submodels.");
|
|
62
82
|
})
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
83
|
+
);
|
|
84
|
+
manager.on("stack-item-added", (event) => {
|
|
85
|
+
if (event.type === "undo") {
|
|
86
|
+
if (event.origin === manager) {
|
|
87
|
+
this.index++;
|
|
88
|
+
} else {
|
|
89
|
+
this.historyItems.length = this.index;
|
|
90
|
+
this.historyItems.push({
|
|
91
|
+
before: beforePosition,
|
|
92
|
+
after: this.collaborate.getRelativeCursorLocation()
|
|
93
|
+
});
|
|
94
|
+
this.index++;
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
this.index--;
|
|
98
|
+
}
|
|
99
|
+
if (manager.undoStack.length > this.stackSize) {
|
|
100
|
+
this.historyItems.shift();
|
|
101
|
+
manager.undoStack.shift();
|
|
102
|
+
}
|
|
103
|
+
if (event.origin === this.collaborate.yDoc) {
|
|
104
|
+
this.pushEvent.next();
|
|
105
|
+
}
|
|
106
|
+
this.changeEvent.next();
|
|
107
|
+
});
|
|
108
|
+
manager.on("stack-item-popped", (ev) => {
|
|
109
|
+
const index = ev.type === "undo" ? this.index : this.index - 1;
|
|
110
|
+
const position = this.historyItems[index] || null;
|
|
111
|
+
const p = ev.type === "undo" ? position?.before : position?.after;
|
|
112
|
+
this.collaborate.restoreCursorPosition(p);
|
|
71
113
|
});
|
|
72
114
|
}
|
|
73
115
|
back() {
|
|
74
|
-
|
|
116
|
+
if (this.canBack) {
|
|
117
|
+
this.manager?.undo();
|
|
118
|
+
this.backEvent.next();
|
|
119
|
+
}
|
|
75
120
|
}
|
|
76
121
|
forward() {
|
|
77
|
-
|
|
122
|
+
if (this.canForward) {
|
|
123
|
+
this.manager?.redo();
|
|
124
|
+
this.forwardEvent.next();
|
|
125
|
+
}
|
|
78
126
|
}
|
|
79
127
|
clear() {
|
|
80
|
-
const
|
|
81
|
-
this.historyItems =
|
|
128
|
+
const last = this.historyItems.pop();
|
|
129
|
+
this.historyItems = last ? [last] : [];
|
|
130
|
+
this.index = last ? 1 : 0;
|
|
131
|
+
this.manager?.clear();
|
|
132
|
+
this.changeEvent.next();
|
|
82
133
|
}
|
|
83
134
|
destroy() {
|
|
84
|
-
this.index = 0
|
|
135
|
+
this.index = 0;
|
|
136
|
+
this.historyItems = [];
|
|
137
|
+
this.subscriptions.forEach((i) => i.unsubscribe());
|
|
138
|
+
if (this.manager) {
|
|
139
|
+
this.manager.destroy();
|
|
140
|
+
this.manager.captureTransaction = () => true;
|
|
141
|
+
this.manager.deleteFilter = () => true;
|
|
142
|
+
this.manager.trackedOrigins = /* @__PURE__ */ new Set([null]);
|
|
143
|
+
}
|
|
144
|
+
this.manager = null;
|
|
85
145
|
}
|
|
86
146
|
};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
],
|
|
92
|
-
var
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
147
|
+
CollabHistory = __decorateClass$3([
|
|
148
|
+
Injectable(),
|
|
149
|
+
__decorateParam$1(3, Inject(HISTORY_STACK_SIZE)),
|
|
150
|
+
__decorateParam$1(4, Optional())
|
|
151
|
+
], CollabHistory);
|
|
152
|
+
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
153
|
+
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
154
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
155
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
156
|
+
if (decorator = decorators[i])
|
|
157
|
+
result = decorator(result) || result;
|
|
158
|
+
return result;
|
|
96
159
|
};
|
|
97
|
-
const
|
|
98
|
-
class
|
|
160
|
+
const collaborateErrorFn = makeError("Collaborate");
|
|
161
|
+
class SlotMap {
|
|
99
162
|
slotAndYTextMap = /* @__PURE__ */ new WeakMap();
|
|
100
163
|
yTextAndSlotMap = /* @__PURE__ */ new WeakMap();
|
|
101
|
-
set(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
164
|
+
set(key, value) {
|
|
165
|
+
if (key instanceof Slot) {
|
|
166
|
+
this.slotAndYTextMap.set(key, value);
|
|
167
|
+
this.yTextAndSlotMap.set(value, key);
|
|
168
|
+
} else {
|
|
169
|
+
this.slotAndYTextMap.set(value, key);
|
|
170
|
+
this.yTextAndSlotMap.set(key, value);
|
|
171
|
+
}
|
|
106
172
|
}
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
173
|
+
get(key) {
|
|
174
|
+
if (key instanceof Slot) {
|
|
175
|
+
return this.slotAndYTextMap.get(key) || null;
|
|
176
|
+
}
|
|
177
|
+
return this.yTextAndSlotMap.get(key) || null;
|
|
178
|
+
}
|
|
179
|
+
delete(key) {
|
|
180
|
+
if (key instanceof Slot) {
|
|
181
|
+
const v = this.slotAndYTextMap.get(key);
|
|
182
|
+
this.slotAndYTextMap.delete(key);
|
|
183
|
+
if (v) {
|
|
184
|
+
this.yTextAndSlotMap.delete(v);
|
|
185
|
+
}
|
|
111
186
|
} else {
|
|
112
|
-
const
|
|
113
|
-
this.yTextAndSlotMap.delete(
|
|
187
|
+
const v = this.yTextAndSlotMap.get(key);
|
|
188
|
+
this.yTextAndSlotMap.delete(key);
|
|
189
|
+
if (v) {
|
|
190
|
+
this.slotAndYTextMap.delete(v);
|
|
191
|
+
}
|
|
114
192
|
}
|
|
115
193
|
}
|
|
116
194
|
}
|
|
117
|
-
let
|
|
118
|
-
constructor(
|
|
119
|
-
this.scheduler =
|
|
195
|
+
let Collaborate = class {
|
|
196
|
+
constructor(scheduler, registry, selection, subModelLoader) {
|
|
197
|
+
this.scheduler = scheduler;
|
|
198
|
+
this.registry = registry;
|
|
199
|
+
this.selection = selection;
|
|
200
|
+
this.subModelLoader = subModelLoader;
|
|
201
|
+
this.onAddSubModel = this.addSubModelEvent.asObservable();
|
|
120
202
|
}
|
|
121
203
|
scheduler;
|
|
122
204
|
registry;
|
|
123
205
|
selection;
|
|
124
206
|
subModelLoader;
|
|
125
|
-
yDoc = new
|
|
126
|
-
slotMap = new
|
|
207
|
+
yDoc = new Doc();
|
|
208
|
+
slotMap = new SlotMap();
|
|
127
209
|
onAddSubModel;
|
|
128
210
|
subscriptions = [];
|
|
129
|
-
updateFromRemote =
|
|
130
|
-
addSubModelEvent = new
|
|
211
|
+
updateFromRemote = false;
|
|
212
|
+
addSubModelEvent = new Subject();
|
|
131
213
|
updateRemoteActions = /* @__PURE__ */ new WeakMap();
|
|
132
214
|
noRecord = {};
|
|
133
|
-
syncRootComponent(
|
|
134
|
-
this.initSyncEvent(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
215
|
+
syncRootComponent(yDoc, sharedComponent, localComponent) {
|
|
216
|
+
this.initSyncEvent(yDoc);
|
|
217
|
+
this.syncComponent(yDoc, sharedComponent, localComponent);
|
|
218
|
+
}
|
|
219
|
+
syncRootSlot(yDoc, sharedSlot, localSlot) {
|
|
220
|
+
if (sharedSlot.length) {
|
|
221
|
+
localSlot.retain(0);
|
|
222
|
+
localSlot.delete(localSlot.length);
|
|
223
|
+
localSlot.cleanAttributes();
|
|
224
|
+
localSlot.cleanFormats();
|
|
225
|
+
this.initLocalSlotBySharedSlot(sharedSlot, localSlot);
|
|
226
|
+
} else {
|
|
227
|
+
yDoc.transact(() => {
|
|
228
|
+
this.initSharedSlotByLocalSlot(sharedSlot, localSlot);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
this.initSyncEvent(yDoc);
|
|
232
|
+
this.syncSlot(sharedSlot, localSlot);
|
|
233
|
+
}
|
|
234
|
+
getAbstractSelection(position) {
|
|
235
|
+
const anchorPosition = createAbsolutePositionFromRelativePosition(position.anchor.position, position.anchor.doc);
|
|
236
|
+
const focusPosition = createAbsolutePositionFromRelativePosition(position.focus.position, position.focus.doc);
|
|
237
|
+
if (anchorPosition && focusPosition) {
|
|
238
|
+
const focusSlot = this.slotMap.get(focusPosition.type);
|
|
239
|
+
const anchorSlot = this.slotMap.get(anchorPosition.type);
|
|
240
|
+
if (focusSlot && anchorSlot) {
|
|
146
241
|
return {
|
|
147
|
-
anchorSlot
|
|
148
|
-
anchorOffset:
|
|
149
|
-
focusSlot
|
|
150
|
-
focusOffset:
|
|
242
|
+
anchorSlot,
|
|
243
|
+
anchorOffset: anchorPosition.index,
|
|
244
|
+
focusSlot,
|
|
245
|
+
focusOffset: focusPosition.index
|
|
151
246
|
};
|
|
247
|
+
}
|
|
152
248
|
}
|
|
153
249
|
return null;
|
|
154
250
|
}
|
|
155
251
|
getRelativeCursorLocation() {
|
|
156
|
-
const { anchorSlot
|
|
157
|
-
if (
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
164
|
-
const
|
|
252
|
+
const { anchorSlot, anchorOffset, focusSlot, focusOffset } = this.selection;
|
|
253
|
+
if (anchorSlot) {
|
|
254
|
+
const anchorYText = this.slotMap.get(anchorSlot);
|
|
255
|
+
if (anchorYText) {
|
|
256
|
+
const anchorPosition = createRelativePositionFromTypeIndex(anchorYText, anchorOffset);
|
|
257
|
+
if (focusSlot) {
|
|
258
|
+
const focusYText = this.slotMap.get(focusSlot);
|
|
259
|
+
if (focusYText) {
|
|
260
|
+
const focusPosition = createRelativePositionFromTypeIndex(focusYText, focusOffset);
|
|
165
261
|
return {
|
|
166
262
|
focus: {
|
|
167
|
-
doc:
|
|
168
|
-
position:
|
|
263
|
+
doc: focusYText.doc,
|
|
264
|
+
position: focusPosition
|
|
169
265
|
},
|
|
170
266
|
anchor: {
|
|
171
|
-
doc:
|
|
172
|
-
position:
|
|
267
|
+
doc: anchorYText.doc,
|
|
268
|
+
position: anchorPosition
|
|
173
269
|
}
|
|
174
270
|
};
|
|
175
271
|
}
|
|
@@ -178,315 +274,494 @@ let f = class {
|
|
|
178
274
|
}
|
|
179
275
|
return null;
|
|
180
276
|
}
|
|
181
|
-
restoreCursorPosition(
|
|
182
|
-
if (!
|
|
277
|
+
restoreCursorPosition(position) {
|
|
278
|
+
if (!position) {
|
|
183
279
|
this.selection.unSelect();
|
|
184
280
|
return;
|
|
185
281
|
}
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
282
|
+
const selection = this.getAbstractSelection(position);
|
|
283
|
+
if (selection) {
|
|
284
|
+
this.selection.setBaseAndExtent(
|
|
285
|
+
selection.anchorSlot,
|
|
286
|
+
selection.anchorOffset,
|
|
287
|
+
selection.focusSlot,
|
|
288
|
+
selection.focusOffset
|
|
289
|
+
);
|
|
290
|
+
}
|
|
193
291
|
}
|
|
194
|
-
initSyncEvent(
|
|
292
|
+
initSyncEvent(yDoc) {
|
|
195
293
|
this.subscriptions.push(
|
|
196
294
|
this.scheduler.onDocChanged.pipe(
|
|
197
|
-
|
|
198
|
-
|
|
295
|
+
map((item) => {
|
|
296
|
+
return item.filter((i) => {
|
|
297
|
+
return i.from !== ChangeOrigin.Remote;
|
|
298
|
+
});
|
|
299
|
+
}),
|
|
300
|
+
filter((item) => {
|
|
301
|
+
return item.length;
|
|
302
|
+
})
|
|
199
303
|
).subscribe(() => {
|
|
200
|
-
const
|
|
201
|
-
let
|
|
202
|
-
const
|
|
203
|
-
for (const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
304
|
+
const updates = [];
|
|
305
|
+
let update = null;
|
|
306
|
+
const updateRemoteActions = this.updateRemoteActions.get(yDoc) || [];
|
|
307
|
+
for (const item of updateRemoteActions) {
|
|
308
|
+
if (!update) {
|
|
309
|
+
update = {
|
|
310
|
+
record: item.record,
|
|
311
|
+
actions: []
|
|
312
|
+
};
|
|
313
|
+
updates.push(update);
|
|
314
|
+
}
|
|
315
|
+
if (update.record === item.record) {
|
|
316
|
+
update.actions.push(item.action);
|
|
317
|
+
} else {
|
|
318
|
+
update = {
|
|
319
|
+
record: item.record,
|
|
320
|
+
actions: [item.action]
|
|
321
|
+
};
|
|
322
|
+
updates.push(update);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
this.updateRemoteActions.delete(yDoc);
|
|
326
|
+
for (const item of updates) {
|
|
327
|
+
yDoc.transact(() => {
|
|
328
|
+
item.actions.forEach((fn) => {
|
|
329
|
+
fn();
|
|
216
330
|
});
|
|
217
|
-
},
|
|
331
|
+
}, item.record ? yDoc : this.noRecord);
|
|
332
|
+
}
|
|
218
333
|
})
|
|
219
334
|
);
|
|
220
335
|
}
|
|
221
|
-
syncComponent(
|
|
222
|
-
let
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
336
|
+
syncComponent(yDoc, sharedComponent, localComponent) {
|
|
337
|
+
let state = sharedComponent.get("state");
|
|
338
|
+
if (!state) {
|
|
339
|
+
state = new Map();
|
|
340
|
+
this.syncLocalMapToSharedMap(localComponent.state, state);
|
|
341
|
+
yDoc.transact(() => {
|
|
342
|
+
sharedComponent.set("state", state);
|
|
343
|
+
});
|
|
344
|
+
} else {
|
|
345
|
+
Object.keys(localComponent.state).forEach((key) => {
|
|
346
|
+
Reflect.deleteProperty(localComponent.state, key);
|
|
347
|
+
});
|
|
348
|
+
this.syncSharedMapToLocalMap(state, localComponent.state);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
syncSlot(sharedSlot, localSlot) {
|
|
352
|
+
const syncRemote = (ev, tr) => {
|
|
353
|
+
this.runRemoteUpdate(tr, () => {
|
|
354
|
+
localSlot.retain(0);
|
|
355
|
+
ev.keysChanged.forEach((key) => {
|
|
356
|
+
const change = ev.keys.get(key);
|
|
357
|
+
if (!change) {
|
|
235
358
|
return;
|
|
236
|
-
const c = i.action;
|
|
237
|
-
if (c === "update" || c === "add") {
|
|
238
|
-
const h = this.registry.getAttribute(a);
|
|
239
|
-
h && e.setAttribute(h, t.getAttribute(a));
|
|
240
|
-
} else if (c === "delete") {
|
|
241
|
-
const h = this.registry.getAttribute(a);
|
|
242
|
-
h && e.removeAttribute(h);
|
|
243
359
|
}
|
|
244
|
-
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
360
|
+
const updateType = change.action;
|
|
361
|
+
if (updateType === "update" || updateType === "add") {
|
|
362
|
+
const attribute = this.registry.getAttribute(key);
|
|
363
|
+
if (attribute) {
|
|
364
|
+
localSlot.setAttribute(attribute, sharedSlot.getAttribute(key));
|
|
249
365
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
366
|
+
} else if (updateType === "delete") {
|
|
367
|
+
const attribute = this.registry.getAttribute(key);
|
|
368
|
+
if (attribute) {
|
|
369
|
+
localSlot.removeAttribute(attribute);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
ev.delta.forEach((action) => {
|
|
374
|
+
if (Reflect.has(action, "retain")) {
|
|
375
|
+
if (action.attributes) {
|
|
376
|
+
const formats = remoteFormatsToLocal(this.registry, action.attributes);
|
|
377
|
+
if (formats.length) {
|
|
378
|
+
localSlot.retain(action.retain, formats);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
localSlot.retain(localSlot.index + action.retain);
|
|
382
|
+
} else if (action.insert) {
|
|
383
|
+
const index = localSlot.index;
|
|
384
|
+
let length = 1;
|
|
385
|
+
if (typeof action.insert === "string") {
|
|
386
|
+
length = action.insert.length;
|
|
387
|
+
localSlot.insert(action.insert, remoteFormatsToLocal(this.registry, action.attributes));
|
|
388
|
+
} else {
|
|
389
|
+
const sharedComponent = action.insert;
|
|
390
|
+
const component = this.createLocalComponentBySharedComponent(sharedComponent);
|
|
391
|
+
localSlot.insert(component);
|
|
392
|
+
}
|
|
393
|
+
if (this.selection.isSelected && !(tr.origin instanceof UndoManager)) {
|
|
394
|
+
if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset > index) {
|
|
395
|
+
this.selection.setAnchor(localSlot, this.selection.anchorOffset + length);
|
|
396
|
+
}
|
|
397
|
+
if (localSlot === this.selection.focusSlot && this.selection.focusOffset > index) {
|
|
398
|
+
this.selection.setFocus(localSlot, this.selection.focusOffset + length);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
} else if (action.delete) {
|
|
402
|
+
const index = localSlot.index;
|
|
403
|
+
localSlot.delete(action.delete);
|
|
404
|
+
if (this.selection.isSelected && !(tr.origin instanceof UndoManager)) {
|
|
405
|
+
if (localSlot === this.selection.anchorSlot && this.selection.anchorOffset >= index) {
|
|
406
|
+
this.selection.setAnchor(localSlot, this.selection.startOffset - action.delete);
|
|
407
|
+
}
|
|
408
|
+
if (localSlot === this.selection.focusSlot && this.selection.focusOffset >= index) {
|
|
409
|
+
this.selection.setFocus(localSlot, this.selection.focusOffset - action.delete);
|
|
410
|
+
}
|
|
259
411
|
}
|
|
260
|
-
this.selection.isSelected && !(r.origin instanceof b) && (e === this.selection.anchorSlot && this.selection.anchorOffset > i && this.selection.setAnchor(e, this.selection.anchorOffset + c), e === this.selection.focusSlot && this.selection.focusOffset > i && this.selection.setFocus(e, this.selection.focusOffset + c));
|
|
261
|
-
} else if (a.delete) {
|
|
262
|
-
const i = e.index;
|
|
263
|
-
e.delete(a.delete), this.selection.isSelected && !(r.origin instanceof b) && (e === this.selection.anchorSlot && this.selection.anchorOffset >= i && this.selection.setAnchor(e, this.selection.startOffset - a.delete), e === this.selection.focusSlot && this.selection.focusOffset >= i && this.selection.setFocus(e, this.selection.focusOffset - a.delete));
|
|
264
412
|
}
|
|
265
413
|
});
|
|
266
414
|
});
|
|
267
415
|
};
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
this.runLocalUpdate(
|
|
271
|
-
let
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
416
|
+
sharedSlot.observe(syncRemote);
|
|
417
|
+
const sub = localSlot.onContentChange.subscribe((actions) => {
|
|
418
|
+
this.runLocalUpdate(sharedSlot.doc, true, () => {
|
|
419
|
+
let offset = 0;
|
|
420
|
+
let length = 0;
|
|
421
|
+
for (const action of actions) {
|
|
422
|
+
if (action.type === "retain") {
|
|
423
|
+
const formats = action.formats;
|
|
424
|
+
if (formats) {
|
|
425
|
+
const keys = Object.keys(formats);
|
|
426
|
+
let length2 = keys.length;
|
|
427
|
+
keys.forEach((key) => {
|
|
428
|
+
const formatter = this.registry.getFormatter(key);
|
|
429
|
+
if (!formatter) {
|
|
430
|
+
length2--;
|
|
431
|
+
Reflect.deleteProperty(formats, key);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
if (length2) {
|
|
435
|
+
sharedSlot.format(offset, action.offset, formats);
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
offset = action.offset;
|
|
439
|
+
}
|
|
440
|
+
} else if (action.type === "contentInsert") {
|
|
441
|
+
const delta = sharedSlot.toDelta();
|
|
442
|
+
const isEmpty = delta.length === 1 && delta[0].insert === Slot.emptyPlaceholder;
|
|
443
|
+
if (typeof action.content === "string") {
|
|
444
|
+
length = action.content.length;
|
|
445
|
+
sharedSlot.insert(offset, action.content, action.formats || {});
|
|
446
|
+
} else {
|
|
447
|
+
length = 1;
|
|
448
|
+
const sharedComponent = this.createSharedComponentByLocalComponent(action.ref);
|
|
449
|
+
sharedSlot.insertEmbed(offset, sharedComponent, action.formats || {});
|
|
450
|
+
}
|
|
451
|
+
if (isEmpty && offset === 0) {
|
|
452
|
+
sharedSlot.delete(sharedSlot.length - 1, 1);
|
|
291
453
|
}
|
|
292
|
-
|
|
293
|
-
} else if (
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
454
|
+
offset += length;
|
|
455
|
+
} else if (action.type === "delete") {
|
|
456
|
+
const delta = sharedSlot.toDelta();
|
|
457
|
+
if (sharedSlot.length) {
|
|
458
|
+
sharedSlot.delete(offset, action.count);
|
|
459
|
+
}
|
|
460
|
+
if (sharedSlot.length === 0) {
|
|
461
|
+
sharedSlot.insert(0, "\n", delta[0]?.attributes);
|
|
462
|
+
}
|
|
463
|
+
} else if (action.type === "attrSet") {
|
|
464
|
+
sharedSlot.setAttribute(action.name, action.value);
|
|
465
|
+
} else if (action.type === "attrDelete") {
|
|
466
|
+
sharedSlot.removeAttribute(action.name);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
298
469
|
});
|
|
299
470
|
});
|
|
300
|
-
this.slotMap.set(
|
|
301
|
-
|
|
471
|
+
this.slotMap.set(localSlot, sharedSlot);
|
|
472
|
+
localSlot.__changeMarker__.addDetachCallback(() => {
|
|
473
|
+
this.slotMap.delete(localSlot);
|
|
474
|
+
sharedSlot.unobserve(syncRemote);
|
|
475
|
+
sub.unsubscribe();
|
|
302
476
|
});
|
|
303
477
|
}
|
|
304
478
|
destroy() {
|
|
305
|
-
this.subscriptions.forEach((
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
479
|
+
this.subscriptions.forEach((i) => i.unsubscribe());
|
|
480
|
+
this.subscriptions = [];
|
|
481
|
+
}
|
|
482
|
+
syncSharedMapToLocalMap(sharedMap, localMap) {
|
|
483
|
+
sharedMap.forEach((value, key) => {
|
|
484
|
+
localMap[key] = this.createLocalModelBySharedByModel(value);
|
|
485
|
+
});
|
|
486
|
+
this.syncObject(sharedMap, localMap);
|
|
487
|
+
}
|
|
488
|
+
createLocalMapBySharedMap(sharedMap) {
|
|
489
|
+
const localMap = observe({});
|
|
490
|
+
this.syncSharedMapToLocalMap(sharedMap, localMap);
|
|
491
|
+
return localMap;
|
|
492
|
+
}
|
|
493
|
+
createLocalArrayBySharedArray(sharedArray) {
|
|
494
|
+
const localArray = observe([]);
|
|
495
|
+
localArray.push(...sharedArray.map((item) => this.createLocalModelBySharedByModel(item)));
|
|
496
|
+
this.syncArray(sharedArray, localArray);
|
|
497
|
+
return localArray;
|
|
498
|
+
}
|
|
499
|
+
syncLocalMapToSharedMap(localMap, sharedMap) {
|
|
500
|
+
Object.entries(localMap).forEach(([key, value]) => {
|
|
501
|
+
sharedMap.set(key, this.createSharedModelByLocalModel(value));
|
|
502
|
+
});
|
|
503
|
+
this.syncObject(sharedMap, localMap);
|
|
504
|
+
}
|
|
505
|
+
createSharedMapByLocalMap(localMap) {
|
|
506
|
+
const sharedMap = new Map();
|
|
507
|
+
this.syncLocalMapToSharedMap(localMap, sharedMap);
|
|
508
|
+
return sharedMap;
|
|
509
|
+
}
|
|
510
|
+
createSharedArrayByLocalArray(localArray) {
|
|
511
|
+
const sharedArray = new Array$1();
|
|
512
|
+
localArray.forEach((value) => {
|
|
513
|
+
sharedArray.push([this.createSharedModelByLocalModel(value)]);
|
|
514
|
+
});
|
|
515
|
+
this.syncArray(sharedArray, localArray);
|
|
516
|
+
return sharedArray;
|
|
517
|
+
}
|
|
518
|
+
createSharedSlotByLocalSlot(localSlot) {
|
|
519
|
+
const sharedSlot = new Text();
|
|
520
|
+
const isAsyncSlot = localSlot instanceof AsyncSlot;
|
|
521
|
+
sharedSlot.setAttribute("schema", [...localSlot.schema]);
|
|
522
|
+
sharedSlot.setAttribute("type", isAsyncSlot ? "async" : "sync");
|
|
523
|
+
if (isAsyncSlot) {
|
|
524
|
+
let isDestroyed = false;
|
|
525
|
+
const sharedMetadata = this.createSharedMapByLocalMap(localSlot.metadata);
|
|
526
|
+
sharedSlot.setAttribute("metadata", sharedMetadata);
|
|
527
|
+
this.subModelLoader.createSubModelBySlot(localSlot).then((subDocument) => {
|
|
528
|
+
if (isDestroyed) {
|
|
342
529
|
return;
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
530
|
+
}
|
|
531
|
+
const content = subDocument.getText("content");
|
|
532
|
+
const state = subDocument.getMap("state");
|
|
533
|
+
this.syncLocalMapToSharedMap(localSlot.state, state);
|
|
534
|
+
this.initSharedSlotByLocalSlot(content, localSlot);
|
|
535
|
+
this.syncSlot(content, localSlot);
|
|
536
|
+
this.addSubModelEvent.next({
|
|
537
|
+
yDoc: subDocument,
|
|
538
|
+
yType: content
|
|
539
|
+
});
|
|
540
|
+
this.initSyncEvent(subDocument);
|
|
541
|
+
localSlot.loader.markAsLoaded();
|
|
542
|
+
});
|
|
543
|
+
localSlot.__changeMarker__.addDetachCallback(() => {
|
|
544
|
+
isDestroyed = true;
|
|
545
|
+
});
|
|
546
|
+
return sharedSlot;
|
|
547
|
+
}
|
|
548
|
+
const sharedSlotState = new Map();
|
|
549
|
+
this.syncLocalMapToSharedMap(localSlot.state, sharedSlotState);
|
|
550
|
+
sharedSlot.setAttribute("state", sharedSlotState);
|
|
551
|
+
const sharedContent = new Text();
|
|
552
|
+
this.initSharedSlotByLocalSlot(sharedContent, localSlot);
|
|
553
|
+
sharedSlot.insertEmbed(0, sharedContent);
|
|
554
|
+
this.syncSlot(sharedContent, localSlot);
|
|
555
|
+
return sharedSlot;
|
|
556
|
+
}
|
|
557
|
+
initSharedSlotByLocalSlot(sharedContent, localSlot) {
|
|
558
|
+
let offset = 0;
|
|
559
|
+
localSlot.toDelta().forEach((i) => {
|
|
560
|
+
let formats = {};
|
|
561
|
+
if (i.formats) {
|
|
562
|
+
i.formats.forEach((item) => {
|
|
563
|
+
formats[item[0].name] = item[1];
|
|
564
|
+
});
|
|
565
|
+
} else {
|
|
566
|
+
formats = null;
|
|
567
|
+
}
|
|
568
|
+
if (typeof i.insert === "string") {
|
|
569
|
+
sharedContent.insert(offset, i.insert, formats);
|
|
570
|
+
} else {
|
|
571
|
+
const sharedComponent = this.createSharedComponentByLocalComponent(i.insert);
|
|
572
|
+
sharedContent.insertEmbed(offset, sharedComponent, formats);
|
|
368
573
|
}
|
|
369
|
-
|
|
370
|
-
})
|
|
371
|
-
|
|
574
|
+
offset += i.insert.length;
|
|
575
|
+
});
|
|
576
|
+
localSlot.getAttributes().forEach((item) => {
|
|
577
|
+
sharedContent.setAttribute(item[0].name, item[1]);
|
|
372
578
|
});
|
|
373
579
|
}
|
|
374
|
-
createLocalSlotBySharedSlot(
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
const
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
580
|
+
createLocalSlotBySharedSlot(sharedSlot) {
|
|
581
|
+
const type = sharedSlot.getAttribute("type");
|
|
582
|
+
const schema = sharedSlot.getAttribute("schema");
|
|
583
|
+
if (type === "async") {
|
|
584
|
+
const metadata = sharedSlot.getAttribute("metadata");
|
|
585
|
+
const slot = new AsyncSlot(schema || [], {}, {});
|
|
586
|
+
this.syncSharedMapToLocalMap(metadata, slot.metadata);
|
|
587
|
+
const loadedSubDocument = this.subModelLoader.getLoadedModelBySlot(slot);
|
|
588
|
+
if (loadedSubDocument) {
|
|
589
|
+
const subContent = loadedSubDocument.getText("content");
|
|
590
|
+
const data = loadedSubDocument.getMap("state");
|
|
591
|
+
this.syncSharedMapToLocalMap(data, slot.state);
|
|
592
|
+
this.syncRootSlot(loadedSubDocument, subContent, slot);
|
|
593
|
+
this.addSubModelEvent.next({
|
|
594
|
+
yDoc: loadedSubDocument,
|
|
595
|
+
yType: subContent
|
|
596
|
+
});
|
|
597
|
+
slot.loader.markAsLoaded();
|
|
598
|
+
return slot;
|
|
386
599
|
}
|
|
387
|
-
let
|
|
388
|
-
|
|
389
|
-
|
|
600
|
+
let isDestroyed = false;
|
|
601
|
+
slot.loader.onRequestLoad.toPromise().then(() => {
|
|
602
|
+
return this.subModelLoader.loadSubModelBySlot(slot);
|
|
603
|
+
}).then((subDocument) => {
|
|
604
|
+
if (isDestroyed) {
|
|
390
605
|
return;
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
606
|
+
}
|
|
607
|
+
const subContent = subDocument.getText("content");
|
|
608
|
+
const state = subDocument.getMap("state");
|
|
609
|
+
this.syncSharedMapToLocalMap(state, slot.state);
|
|
610
|
+
this.syncRootSlot(subDocument, subContent, slot);
|
|
611
|
+
this.addSubModelEvent.next({
|
|
612
|
+
yDoc: subDocument,
|
|
613
|
+
yType: subContent
|
|
614
|
+
});
|
|
615
|
+
slot.loader.markAsLoaded();
|
|
616
|
+
});
|
|
617
|
+
slot.__changeMarker__.addDetachCallback(() => {
|
|
618
|
+
isDestroyed = true;
|
|
619
|
+
});
|
|
620
|
+
return slot;
|
|
621
|
+
}
|
|
622
|
+
const contentDelta = sharedSlot.toDelta();
|
|
623
|
+
const content = contentDelta[0]?.insert;
|
|
624
|
+
if (!(content instanceof Text)) {
|
|
625
|
+
throw collaborateErrorFn("shared slot content type is not `YText`.");
|
|
626
|
+
}
|
|
627
|
+
const localSlot = new Slot(schema || [], {});
|
|
628
|
+
const sharedSlotState = sharedSlot.getAttribute("state");
|
|
629
|
+
this.syncSharedMapToLocalMap(sharedSlotState, localSlot.state);
|
|
630
|
+
this.initLocalSlotBySharedSlot(content, localSlot);
|
|
631
|
+
this.syncSlot(content, localSlot);
|
|
632
|
+
return localSlot;
|
|
633
|
+
}
|
|
634
|
+
initLocalSlotBySharedSlot(content, localSlot) {
|
|
635
|
+
const delta = content.toDelta();
|
|
636
|
+
const attrs = content.getAttributes();
|
|
637
|
+
Object.keys(attrs).forEach((key) => {
|
|
638
|
+
const attribute = this.registry.getAttribute(key);
|
|
639
|
+
if (attribute) {
|
|
640
|
+
localSlot.setAttribute(attribute, attrs[key]);
|
|
641
|
+
}
|
|
411
642
|
});
|
|
412
|
-
for (const
|
|
413
|
-
if (
|
|
414
|
-
if (typeof
|
|
415
|
-
const
|
|
416
|
-
|
|
643
|
+
for (const action of delta) {
|
|
644
|
+
if (action.insert) {
|
|
645
|
+
if (typeof action.insert === "string") {
|
|
646
|
+
const formats = remoteFormatsToLocal(this.registry, action.attributes);
|
|
647
|
+
localSlot.insert(action.insert, formats);
|
|
417
648
|
} else {
|
|
418
|
-
const
|
|
419
|
-
|
|
649
|
+
const sharedComponent = action.insert;
|
|
650
|
+
const component = this.createLocalComponentBySharedComponent(sharedComponent);
|
|
651
|
+
localSlot.insert(component, remoteFormatsToLocal(this.registry, action.attributes));
|
|
420
652
|
}
|
|
421
|
-
else
|
|
422
|
-
throw
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
653
|
+
} else {
|
|
654
|
+
throw collaborateErrorFn("unexpected delta action.");
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
createSharedModelByLocalModel(localModel) {
|
|
659
|
+
if (localModel instanceof Slot) {
|
|
660
|
+
return this.createSharedSlotByLocalSlot(localModel);
|
|
661
|
+
}
|
|
662
|
+
if (Array.isArray(localModel)) {
|
|
663
|
+
return this.createSharedArrayByLocalArray(localModel);
|
|
664
|
+
}
|
|
665
|
+
if (typeof localModel === "object" && localModel !== null) {
|
|
666
|
+
return this.createSharedMapByLocalMap(localModel);
|
|
667
|
+
}
|
|
668
|
+
return localModel;
|
|
669
|
+
}
|
|
670
|
+
createLocalModelBySharedByModel(sharedModel) {
|
|
671
|
+
if (sharedModel instanceof Map) {
|
|
672
|
+
return this.createLocalMapBySharedMap(sharedModel);
|
|
673
|
+
}
|
|
674
|
+
if (sharedModel instanceof Array$1) {
|
|
675
|
+
return this.createLocalArrayBySharedArray(sharedModel);
|
|
676
|
+
}
|
|
677
|
+
if (sharedModel instanceof Text) {
|
|
678
|
+
return this.createLocalSlotBySharedSlot(sharedModel);
|
|
679
|
+
}
|
|
680
|
+
return sharedModel;
|
|
681
|
+
}
|
|
682
|
+
createSharedComponentByLocalComponent(component) {
|
|
683
|
+
const sharedComponent = new Map();
|
|
684
|
+
sharedComponent.set("name", component.name);
|
|
685
|
+
if (component instanceof AsyncComponent) {
|
|
686
|
+
sharedComponent.set("type", "async");
|
|
687
|
+
const sharedMetadata = this.createSharedMapByLocalMap(component.metadata);
|
|
688
|
+
sharedComponent.set("metadata", sharedMetadata);
|
|
689
|
+
const state = component.state;
|
|
690
|
+
let isDestroyed = false;
|
|
691
|
+
state.__changeMarker__.addDetachCallback(() => {
|
|
692
|
+
isDestroyed = true;
|
|
693
|
+
});
|
|
694
|
+
this.subModelLoader.createSubModelByComponent(component).then((subDocument) => {
|
|
695
|
+
if (isDestroyed) {
|
|
442
696
|
return;
|
|
443
|
-
const i = a.getMap("state");
|
|
444
|
-
this.syncComponent(a, i, t), this.addSubModelEvent.next({
|
|
445
|
-
yType: i,
|
|
446
|
-
yDoc: a
|
|
447
|
-
}), this.initSyncEvent(a), t.loader.markAsLoaded();
|
|
448
|
-
}), e;
|
|
449
|
-
}
|
|
450
|
-
const s = this.createSharedMapByLocalMap(t.state);
|
|
451
|
-
return e.set("state", s), e.set("type", "sync"), e;
|
|
452
|
-
}
|
|
453
|
-
createLocalComponentBySharedComponent(t) {
|
|
454
|
-
const e = t.get("name"), s = t.get("type");
|
|
455
|
-
let n;
|
|
456
|
-
if (s === "async") {
|
|
457
|
-
if (n = this.registry.createComponentByData(e, {}, {}), n instanceof D) {
|
|
458
|
-
const o = t.get("metadata");
|
|
459
|
-
this.syncSharedMapToLocalMap(o, n.metadata);
|
|
460
|
-
const r = this.subModelLoader.getLoadedModelByComponent(n);
|
|
461
|
-
if (r) {
|
|
462
|
-
const c = r.getMap("state");
|
|
463
|
-
return this.syncComponent(r, c, n), this.addSubModelEvent.next({
|
|
464
|
-
yType: c,
|
|
465
|
-
yDoc: r
|
|
466
|
-
}), n.loader.markAsLoaded(), n;
|
|
467
697
|
}
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
698
|
+
const state2 = subDocument.getMap("state");
|
|
699
|
+
this.syncComponent(subDocument, state2, component);
|
|
700
|
+
this.addSubModelEvent.next({
|
|
701
|
+
yType: state2,
|
|
702
|
+
yDoc: subDocument
|
|
703
|
+
});
|
|
704
|
+
this.initSyncEvent(subDocument);
|
|
705
|
+
component.loader.markAsLoaded();
|
|
706
|
+
});
|
|
707
|
+
return sharedComponent;
|
|
708
|
+
}
|
|
709
|
+
const sharedState = this.createSharedMapByLocalMap(component.state);
|
|
710
|
+
sharedComponent.set("state", sharedState);
|
|
711
|
+
sharedComponent.set("type", "sync");
|
|
712
|
+
return sharedComponent;
|
|
713
|
+
}
|
|
714
|
+
createLocalComponentBySharedComponent(yMap) {
|
|
715
|
+
const componentName = yMap.get("name");
|
|
716
|
+
const type = yMap.get("type");
|
|
717
|
+
let instance;
|
|
718
|
+
if (type === "async") {
|
|
719
|
+
instance = this.registry.createComponentByData(componentName, {}, {});
|
|
720
|
+
if (instance instanceof AsyncComponent) {
|
|
721
|
+
const sharedMetadata = yMap.get("metadata");
|
|
722
|
+
this.syncSharedMapToLocalMap(sharedMetadata, instance.metadata);
|
|
723
|
+
const loadedSubDocument = this.subModelLoader.getLoadedModelByComponent(instance);
|
|
724
|
+
if (loadedSubDocument) {
|
|
725
|
+
const state2 = loadedSubDocument.getMap("state");
|
|
726
|
+
this.syncComponent(loadedSubDocument, state2, instance);
|
|
727
|
+
this.addSubModelEvent.next({
|
|
728
|
+
yType: state2,
|
|
729
|
+
yDoc: loadedSubDocument
|
|
730
|
+
});
|
|
731
|
+
instance.loader.markAsLoaded();
|
|
732
|
+
return instance;
|
|
733
|
+
}
|
|
734
|
+
const state = instance.state;
|
|
735
|
+
let isDestroyed = false;
|
|
736
|
+
instance.loader.onRequestLoad.toPromise().then(() => {
|
|
737
|
+
return this.subModelLoader.loadSubModelByComponent(instance);
|
|
738
|
+
}).then((subDocument) => {
|
|
739
|
+
if (isDestroyed) {
|
|
472
740
|
return;
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
741
|
+
}
|
|
742
|
+
const state2 = subDocument.getMap("state");
|
|
743
|
+
this.syncComponent(subDocument, state2, instance);
|
|
744
|
+
this.addSubModelEvent.next({
|
|
745
|
+
yType: state2,
|
|
746
|
+
yDoc: subDocument
|
|
747
|
+
});
|
|
748
|
+
instance.loader.markAsLoaded();
|
|
749
|
+
});
|
|
750
|
+
state.__changeMarker__.addDetachCallback(() => {
|
|
751
|
+
isDestroyed = true;
|
|
480
752
|
});
|
|
481
|
-
} else if (
|
|
482
|
-
throw
|
|
753
|
+
} else if (instance instanceof Component) {
|
|
754
|
+
throw collaborateErrorFn(`component name \`${componentName}\` is not a async component.`);
|
|
755
|
+
}
|
|
483
756
|
} else {
|
|
484
|
-
const
|
|
485
|
-
|
|
757
|
+
const sharedState = yMap.get("state");
|
|
758
|
+
const state = this.createLocalMapBySharedMap(sharedState);
|
|
759
|
+
instance = this.registry.createComponentByData(componentName, state);
|
|
486
760
|
}
|
|
487
|
-
if (
|
|
488
|
-
return
|
|
489
|
-
|
|
761
|
+
if (instance) {
|
|
762
|
+
return instance;
|
|
763
|
+
}
|
|
764
|
+
throw collaborateErrorFn(`cannot find component factory \`${componentName}\`.`);
|
|
490
765
|
}
|
|
491
766
|
/**
|
|
492
767
|
* 双向同步数组
|
|
@@ -494,52 +769,80 @@ let f = class {
|
|
|
494
769
|
* @param localArray
|
|
495
770
|
* @private
|
|
496
771
|
*/
|
|
497
|
-
syncArray(
|
|
498
|
-
function
|
|
499
|
-
console.error(
|
|
500
|
-
}
|
|
501
|
-
const
|
|
502
|
-
this.runLocalUpdate(
|
|
503
|
-
let
|
|
504
|
-
for (const
|
|
505
|
-
switch (
|
|
772
|
+
syncArray(sharedArray, localArray) {
|
|
773
|
+
function logError(type) {
|
|
774
|
+
console.error(collaborateErrorFn(`${type} error, length exceeded, path in ${localArray.__changeMarker__.getPaths().join("/")}`));
|
|
775
|
+
}
|
|
776
|
+
const sub = localArray.__changeMarker__.onSelfChange.subscribe((actions) => {
|
|
777
|
+
this.runLocalUpdate(sharedArray.doc, !localArray.__changeMarker__.irrevocableUpdate, () => {
|
|
778
|
+
let index = 0;
|
|
779
|
+
for (const action of actions) {
|
|
780
|
+
switch (action.type) {
|
|
506
781
|
case "retain":
|
|
507
|
-
|
|
782
|
+
index = action.offset;
|
|
508
783
|
break;
|
|
509
784
|
case "insert":
|
|
510
785
|
{
|
|
511
|
-
const
|
|
512
|
-
if (!Array.isArray(
|
|
513
|
-
throw
|
|
514
|
-
|
|
515
|
-
|
|
786
|
+
const ref = action.ref;
|
|
787
|
+
if (!Array.isArray(ref)) {
|
|
788
|
+
throw collaborateErrorFn("The insertion action must have a reference value.");
|
|
789
|
+
}
|
|
790
|
+
const data = ref.map((item) => {
|
|
791
|
+
return this.createSharedModelByLocalModel(item);
|
|
792
|
+
});
|
|
793
|
+
if (index <= sharedArray.length) {
|
|
794
|
+
sharedArray.insert(index, data);
|
|
795
|
+
} else {
|
|
796
|
+
sharedArray.insert(sharedArray.length, data);
|
|
797
|
+
logError("insert");
|
|
798
|
+
}
|
|
516
799
|
}
|
|
517
800
|
break;
|
|
518
801
|
case "delete":
|
|
519
|
-
if (
|
|
802
|
+
if (action.count <= 0) {
|
|
520
803
|
break;
|
|
521
|
-
|
|
804
|
+
}
|
|
805
|
+
if (index < sharedArray.length) {
|
|
806
|
+
sharedArray.delete(index, action.count);
|
|
807
|
+
} else {
|
|
808
|
+
logError("delete");
|
|
809
|
+
}
|
|
522
810
|
break;
|
|
523
811
|
case "setIndex":
|
|
524
|
-
|
|
812
|
+
if (action.index < sharedArray.length) {
|
|
813
|
+
sharedArray.delete(action.index, 1);
|
|
814
|
+
sharedArray.insert(action.index, [this.createSharedModelByLocalModel(action.ref)]);
|
|
815
|
+
} else {
|
|
816
|
+
sharedArray.insert(sharedArray.length, [this.createSharedModelByLocalModel(action.ref)]);
|
|
817
|
+
logError("setIndex");
|
|
818
|
+
}
|
|
525
819
|
break;
|
|
526
820
|
}
|
|
821
|
+
}
|
|
527
822
|
});
|
|
528
|
-
})
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
823
|
+
});
|
|
824
|
+
const syncRemote = (ev, tr) => {
|
|
825
|
+
this.runRemoteUpdate(tr, () => {
|
|
826
|
+
let index = 0;
|
|
827
|
+
ev.delta.forEach((action) => {
|
|
828
|
+
if (Reflect.has(action, "retain")) {
|
|
829
|
+
index += action.retain;
|
|
830
|
+
} else if (action.insert) {
|
|
831
|
+
const data = action.insert.map((item) => {
|
|
832
|
+
return this.createLocalModelBySharedByModel(item);
|
|
833
|
+
});
|
|
834
|
+
localArray.splice(index, 0, ...data);
|
|
835
|
+
index += data.length;
|
|
836
|
+
} else if (action.delete) {
|
|
837
|
+
localArray.splice(index, action.delete);
|
|
838
|
+
}
|
|
538
839
|
});
|
|
539
840
|
});
|
|
540
841
|
};
|
|
541
|
-
|
|
542
|
-
|
|
842
|
+
sharedArray.observe(syncRemote);
|
|
843
|
+
localArray.__changeMarker__.addDetachCallback(() => {
|
|
844
|
+
sub.unsubscribe();
|
|
845
|
+
sharedArray.unobserve(syncRemote);
|
|
543
846
|
});
|
|
544
847
|
}
|
|
545
848
|
/**
|
|
@@ -548,65 +851,90 @@ let f = class {
|
|
|
548
851
|
* @param localObject
|
|
549
852
|
* @private
|
|
550
853
|
*/
|
|
551
|
-
syncObject(
|
|
552
|
-
const
|
|
553
|
-
this.runRemoteUpdate(
|
|
554
|
-
|
|
555
|
-
if (
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
} else
|
|
559
|
-
Reflect.deleteProperty(
|
|
854
|
+
syncObject(sharedObject, localObject) {
|
|
855
|
+
const syncRemote = (ev, tr) => {
|
|
856
|
+
this.runRemoteUpdate(tr, () => {
|
|
857
|
+
ev.changes.keys.forEach((item, key) => {
|
|
858
|
+
if (item.action === "add" || item.action === "update") {
|
|
859
|
+
const value = sharedObject.get(key);
|
|
860
|
+
localObject[key] = this.createLocalModelBySharedByModel(value);
|
|
861
|
+
} else {
|
|
862
|
+
Reflect.deleteProperty(localObject, key);
|
|
863
|
+
}
|
|
560
864
|
});
|
|
561
865
|
});
|
|
562
866
|
};
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
this.runLocalUpdate(
|
|
566
|
-
for (const
|
|
567
|
-
switch (
|
|
867
|
+
sharedObject.observe(syncRemote);
|
|
868
|
+
const sub = localObject.__changeMarker__.onSelfChange.subscribe((actions) => {
|
|
869
|
+
this.runLocalUpdate(sharedObject.doc, !localObject.__changeMarker__.irrevocableUpdate, () => {
|
|
870
|
+
for (const action of actions) {
|
|
871
|
+
switch (action.type) {
|
|
568
872
|
case "propSet":
|
|
569
873
|
{
|
|
570
|
-
const
|
|
571
|
-
|
|
874
|
+
const subModel = this.createSharedModelByLocalModel(action.ref);
|
|
875
|
+
sharedObject.set(action.key, subModel);
|
|
876
|
+
if (sharedObject.size === 0) {
|
|
877
|
+
console.error(collaborateErrorFn(`prop set error, key is ${action.key}`));
|
|
878
|
+
}
|
|
572
879
|
}
|
|
573
880
|
break;
|
|
574
881
|
case "propDelete":
|
|
575
|
-
|
|
882
|
+
sharedObject.delete(action.key);
|
|
576
883
|
break;
|
|
577
884
|
}
|
|
885
|
+
}
|
|
578
886
|
});
|
|
579
887
|
});
|
|
580
|
-
|
|
581
|
-
|
|
888
|
+
localObject.__changeMarker__.addDetachCallback(function() {
|
|
889
|
+
sharedObject.unobserve(syncRemote);
|
|
890
|
+
sub.unsubscribe();
|
|
582
891
|
});
|
|
583
892
|
}
|
|
584
|
-
runLocalUpdate(
|
|
585
|
-
if (this.updateFromRemote || !
|
|
893
|
+
runLocalUpdate(yDoc, record, fn) {
|
|
894
|
+
if (this.updateFromRemote || !yDoc) {
|
|
586
895
|
return;
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
896
|
+
}
|
|
897
|
+
let changeList = this.updateRemoteActions.get(yDoc);
|
|
898
|
+
if (!changeList) {
|
|
899
|
+
changeList = [];
|
|
900
|
+
this.updateRemoteActions.set(yDoc, changeList);
|
|
901
|
+
}
|
|
902
|
+
changeList.push({
|
|
903
|
+
record,
|
|
904
|
+
action: fn
|
|
591
905
|
});
|
|
592
906
|
}
|
|
593
|
-
runRemoteUpdate(
|
|
594
|
-
|
|
907
|
+
runRemoteUpdate(tr, fn) {
|
|
908
|
+
if (tr.origin === tr.doc) {
|
|
909
|
+
return;
|
|
910
|
+
}
|
|
911
|
+
this.updateFromRemote = true;
|
|
912
|
+
if (tr.origin instanceof UndoManager) {
|
|
913
|
+
this.scheduler.historyApplyTransact(fn);
|
|
914
|
+
} else {
|
|
915
|
+
this.scheduler.remoteUpdateTransact(fn);
|
|
916
|
+
}
|
|
917
|
+
this.updateFromRemote = false;
|
|
595
918
|
}
|
|
596
919
|
};
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
],
|
|
600
|
-
function
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
920
|
+
Collaborate = __decorateClass$2([
|
|
921
|
+
Injectable()
|
|
922
|
+
], Collaborate);
|
|
923
|
+
function remoteFormatsToLocal(registry, attrs) {
|
|
924
|
+
const formats = [];
|
|
925
|
+
if (attrs) {
|
|
926
|
+
Object.keys(attrs).forEach((key) => {
|
|
927
|
+
const formatter = registry.getFormatter(key);
|
|
928
|
+
if (formatter) {
|
|
929
|
+
formats.push([formatter, attrs[key]]);
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
return formats;
|
|
606
934
|
}
|
|
607
|
-
class
|
|
935
|
+
class MessageBus {
|
|
608
936
|
onSync;
|
|
609
|
-
syncEvent = new
|
|
937
|
+
syncEvent = new Subject();
|
|
610
938
|
constructor() {
|
|
611
939
|
this.onSync = this.syncEvent.asObservable();
|
|
612
940
|
}
|
|
@@ -617,14 +945,26 @@ class z {
|
|
|
617
945
|
this.syncEvent.next();
|
|
618
946
|
}
|
|
619
947
|
}
|
|
620
|
-
var
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
948
|
+
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
949
|
+
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
950
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
951
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
952
|
+
if (decorator = decorators[i])
|
|
953
|
+
result = decorator(result) || result;
|
|
954
|
+
return result;
|
|
955
|
+
};
|
|
956
|
+
var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
|
|
957
|
+
let MultipleDocCollabHistory = class {
|
|
958
|
+
constructor(collaborate, scheduler, rootComponentRef, stackSize, undoManagerConfig) {
|
|
959
|
+
this.collaborate = collaborate;
|
|
960
|
+
this.scheduler = scheduler;
|
|
961
|
+
this.rootComponentRef = rootComponentRef;
|
|
962
|
+
this.stackSize = stackSize;
|
|
963
|
+
this.undoManagerConfig = undoManagerConfig;
|
|
964
|
+
this.onChange = this.changeEvent.asObservable();
|
|
965
|
+
this.onBack = this.backEvent.asObservable();
|
|
966
|
+
this.onForward = this.forwardEvent.asObservable();
|
|
967
|
+
this.onPush = this.pushEvent.asObservable();
|
|
628
968
|
}
|
|
629
969
|
collaborate;
|
|
630
970
|
scheduler;
|
|
@@ -641,25 +981,34 @@ let k = class {
|
|
|
641
981
|
get canForward() {
|
|
642
982
|
return this.actionStack.length > 0 && this.index < this.actionStack.length;
|
|
643
983
|
}
|
|
644
|
-
isListen =
|
|
645
|
-
changeEvent = new
|
|
646
|
-
backEvent = new
|
|
647
|
-
forwardEvent = new
|
|
648
|
-
pushEvent = new
|
|
984
|
+
isListen = false;
|
|
985
|
+
changeEvent = new Subject();
|
|
986
|
+
backEvent = new Subject();
|
|
987
|
+
forwardEvent = new Subject();
|
|
988
|
+
pushEvent = new Subject();
|
|
649
989
|
actionStack = [];
|
|
650
990
|
index = 0;
|
|
651
991
|
stackItem = null;
|
|
652
992
|
timer = null;
|
|
653
993
|
beforePosition = null;
|
|
654
|
-
subscription = new
|
|
994
|
+
subscription = new Subscription();
|
|
655
995
|
subDocs = /* @__PURE__ */ new Set();
|
|
656
996
|
listenerCaches = /* @__PURE__ */ new Set();
|
|
657
997
|
listen() {
|
|
658
|
-
this.isListen =
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
998
|
+
this.isListen = true;
|
|
999
|
+
const root = this.collaborate.yDoc.getMap("RootComponent");
|
|
1000
|
+
const rootComponent = this.rootComponentRef.component;
|
|
1001
|
+
this.collaborate.syncRootComponent(this.collaborate.yDoc, root, rootComponent);
|
|
1002
|
+
this.listenItem(root, this.collaborate.yDoc);
|
|
1003
|
+
this.subscription.add(
|
|
1004
|
+
this.collaborate.onAddSubModel.subscribe(({ yType, yDoc }) => {
|
|
1005
|
+
if (this.subDocs.has(yType)) {
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
this.subDocs.add(yType);
|
|
1009
|
+
if (this.isListen) {
|
|
1010
|
+
this.listenItem(yType, yDoc);
|
|
1011
|
+
}
|
|
663
1012
|
}),
|
|
664
1013
|
this.scheduler.onLocalChangeBefore.subscribe(() => {
|
|
665
1014
|
this.beforePosition = this.collaborate.getRelativeCursorLocation();
|
|
@@ -667,104 +1016,162 @@ let k = class {
|
|
|
667
1016
|
);
|
|
668
1017
|
}
|
|
669
1018
|
forward() {
|
|
670
|
-
if (!this.canForward)
|
|
1019
|
+
if (!this.canForward) {
|
|
671
1020
|
return;
|
|
1021
|
+
}
|
|
672
1022
|
clearTimeout(this.timer);
|
|
673
|
-
const
|
|
674
|
-
if (
|
|
675
|
-
for (const
|
|
676
|
-
|
|
677
|
-
|
|
1023
|
+
const item = this.actionStack[this.index];
|
|
1024
|
+
if (item) {
|
|
1025
|
+
for (const i of item.undoManagers) {
|
|
1026
|
+
i.redo();
|
|
1027
|
+
}
|
|
1028
|
+
this.collaborate.restoreCursorPosition(item.after);
|
|
678
1029
|
}
|
|
679
|
-
this.index
|
|
1030
|
+
this.index++;
|
|
1031
|
+
this.forwardEvent.next();
|
|
1032
|
+
this.changeEvent.next();
|
|
680
1033
|
}
|
|
681
1034
|
back() {
|
|
682
|
-
if (!this.canBack)
|
|
1035
|
+
if (!this.canBack) {
|
|
683
1036
|
return;
|
|
1037
|
+
}
|
|
684
1038
|
clearTimeout(this.timer);
|
|
685
|
-
let
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
1039
|
+
let historyStackItem;
|
|
1040
|
+
if (this.stackItem) {
|
|
1041
|
+
historyStackItem = this.stackItem;
|
|
1042
|
+
this.stackItem = null;
|
|
1043
|
+
} else {
|
|
1044
|
+
this.index--;
|
|
1045
|
+
historyStackItem = this.actionStack[this.index];
|
|
1046
|
+
}
|
|
1047
|
+
let len = historyStackItem.undoManagers.length;
|
|
1048
|
+
while (len > 0) {
|
|
1049
|
+
len--;
|
|
1050
|
+
historyStackItem.undoManagers[len].undo();
|
|
1051
|
+
}
|
|
1052
|
+
if (historyStackItem) {
|
|
1053
|
+
const beforePosition = historyStackItem.before;
|
|
1054
|
+
this.collaborate.restoreCursorPosition(beforePosition);
|
|
1055
|
+
this.backEvent.next();
|
|
1056
|
+
this.changeEvent.next();
|
|
693
1057
|
}
|
|
694
1058
|
}
|
|
695
1059
|
clear() {
|
|
696
|
-
this.actionStack = []
|
|
697
|
-
|
|
698
|
-
|
|
1060
|
+
this.actionStack = [];
|
|
1061
|
+
this.stackItem = null;
|
|
1062
|
+
this.index = 0;
|
|
1063
|
+
this.beforePosition = null;
|
|
1064
|
+
clearTimeout(this.timer);
|
|
1065
|
+
this.listenerCaches.forEach((undoManager) => {
|
|
1066
|
+
undoManager.clear();
|
|
1067
|
+
});
|
|
1068
|
+
this.changeEvent.next();
|
|
699
1069
|
}
|
|
700
1070
|
destroy() {
|
|
701
|
-
this.clear()
|
|
702
|
-
|
|
703
|
-
|
|
1071
|
+
this.clear();
|
|
1072
|
+
this.beforePosition = this.stackItem = null;
|
|
1073
|
+
this.subscription.unsubscribe();
|
|
1074
|
+
this.listenerCaches.forEach((undoManager) => {
|
|
1075
|
+
undoManager.destroy();
|
|
1076
|
+
});
|
|
1077
|
+
this.subDocs.clear();
|
|
1078
|
+
this.listenerCaches.clear();
|
|
704
1079
|
}
|
|
705
|
-
listenItem(
|
|
706
|
-
const
|
|
707
|
-
|
|
1080
|
+
listenItem(yType, yDoc) {
|
|
1081
|
+
const undoManagerConfig = this.undoManagerConfig || {};
|
|
1082
|
+
const undoManager = new UndoManager(yType, {
|
|
1083
|
+
trackedOrigins: /* @__PURE__ */ new Set([yDoc]),
|
|
708
1084
|
captureTimeout: 0,
|
|
709
|
-
captureTransaction(
|
|
710
|
-
|
|
1085
|
+
captureTransaction(arg) {
|
|
1086
|
+
if (undoManagerConfig.captureTransaction) {
|
|
1087
|
+
return undoManagerConfig.captureTransaction(arg);
|
|
1088
|
+
}
|
|
1089
|
+
return true;
|
|
711
1090
|
},
|
|
712
|
-
deleteFilter(
|
|
713
|
-
|
|
1091
|
+
deleteFilter(item) {
|
|
1092
|
+
if (undoManagerConfig.deleteFilter) {
|
|
1093
|
+
return undoManagerConfig.deleteFilter(item);
|
|
1094
|
+
}
|
|
1095
|
+
return true;
|
|
714
1096
|
}
|
|
715
1097
|
});
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
1098
|
+
undoManager.on("stack-item-added", (event) => {
|
|
1099
|
+
if (event.type === "undo" && !(event.origin instanceof UndoManager)) {
|
|
1100
|
+
if (this.index != this.actionStack.length) {
|
|
1101
|
+
const redoStack = this.actionStack.slice(this.index);
|
|
1102
|
+
redoStack.forEach((item) => {
|
|
1103
|
+
item.undoManagers.forEach((i) => {
|
|
1104
|
+
i.clear(false, true);
|
|
1105
|
+
});
|
|
1106
|
+
});
|
|
1107
|
+
this.actionStack.length = this.index;
|
|
1108
|
+
this.changeEvent.next();
|
|
1109
|
+
}
|
|
1110
|
+
if (this.stackItem === null) {
|
|
1111
|
+
this.stackItem = {
|
|
1112
|
+
before: this.beforePosition,
|
|
1113
|
+
after: null,
|
|
1114
|
+
undoManagers: []
|
|
1115
|
+
};
|
|
1116
|
+
this.timer = setTimeout(() => {
|
|
1117
|
+
if (this.actionStack.length >= this.stackSize) {
|
|
1118
|
+
this.actionStack.shift();
|
|
1119
|
+
} else {
|
|
1120
|
+
this.index++;
|
|
1121
|
+
}
|
|
1122
|
+
this.stackItem.after = this.beforePosition;
|
|
1123
|
+
this.actionStack.push(this.stackItem);
|
|
1124
|
+
this.stackItem = null;
|
|
1125
|
+
this.pushEvent.next();
|
|
1126
|
+
this.changeEvent.next();
|
|
1127
|
+
}, 500);
|
|
1128
|
+
}
|
|
1129
|
+
this.stackItem.undoManagers.push(undoManager);
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
this.listenerCaches.add(undoManager);
|
|
729
1133
|
}
|
|
730
1134
|
};
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
],
|
|
736
|
-
var
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
1135
|
+
MultipleDocCollabHistory = __decorateClass$1([
|
|
1136
|
+
Injectable(),
|
|
1137
|
+
__decorateParam(3, Inject(HISTORY_STACK_SIZE)),
|
|
1138
|
+
__decorateParam(4, Optional())
|
|
1139
|
+
], MultipleDocCollabHistory);
|
|
1140
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
1141
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
1142
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
1143
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
1144
|
+
if (decorator = decorators[i])
|
|
1145
|
+
result = decorator(result) || result;
|
|
1146
|
+
return result;
|
|
740
1147
|
};
|
|
741
|
-
const
|
|
742
|
-
class
|
|
1148
|
+
const subModelLoaderErrorFn = makeError("subModelLoaderError");
|
|
1149
|
+
class SubModelLoader {
|
|
743
1150
|
}
|
|
744
|
-
let
|
|
1151
|
+
let NonSubModelLoader = class extends SubModelLoader {
|
|
745
1152
|
createSubModelBySlot() {
|
|
746
|
-
throw
|
|
1153
|
+
throw subModelLoaderErrorFn("single document does not support async slot.");
|
|
747
1154
|
}
|
|
748
1155
|
createSubModelByComponent() {
|
|
749
|
-
throw
|
|
1156
|
+
throw subModelLoaderErrorFn("single document does not support async component.");
|
|
750
1157
|
}
|
|
751
1158
|
loadSubModelByComponent() {
|
|
752
|
-
throw
|
|
1159
|
+
throw subModelLoaderErrorFn("single document does not support async component.");
|
|
753
1160
|
}
|
|
754
1161
|
loadSubModelBySlot() {
|
|
755
|
-
throw
|
|
1162
|
+
throw subModelLoaderErrorFn("single document does not support async slot.");
|
|
756
1163
|
}
|
|
757
1164
|
getLoadedModelBySlot() {
|
|
758
|
-
throw
|
|
1165
|
+
throw subModelLoaderErrorFn("single document does not support async slot.");
|
|
759
1166
|
}
|
|
760
1167
|
getLoadedModelByComponent() {
|
|
761
|
-
throw
|
|
1168
|
+
throw subModelLoaderErrorFn("single document does not support async component.");
|
|
762
1169
|
}
|
|
763
1170
|
};
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
],
|
|
767
|
-
class
|
|
1171
|
+
NonSubModelLoader = __decorateClass([
|
|
1172
|
+
Injectable()
|
|
1173
|
+
], NonSubModelLoader);
|
|
1174
|
+
class SyncConnector {
|
|
768
1175
|
/**
|
|
769
1176
|
* 当文档加载完成时触发的观察者
|
|
770
1177
|
*/
|
|
@@ -773,187 +1180,237 @@ class p {
|
|
|
773
1180
|
* 当文档 awareness 状态变更时触发的观察者
|
|
774
1181
|
*/
|
|
775
1182
|
onStateChange;
|
|
776
|
-
loadEvent = new
|
|
777
|
-
stateChangeEvent = new
|
|
1183
|
+
loadEvent = new Subject();
|
|
1184
|
+
stateChangeEvent = new Subject();
|
|
778
1185
|
constructor() {
|
|
779
|
-
this.onLoad = this.loadEvent.asObservable()
|
|
1186
|
+
this.onLoad = this.loadEvent.asObservable();
|
|
1187
|
+
this.onStateChange = this.stateChangeEvent.asObservable();
|
|
780
1188
|
}
|
|
781
1189
|
}
|
|
782
|
-
class
|
|
1190
|
+
class HocuspocusConnector extends SyncConnector {
|
|
783
1191
|
provide;
|
|
784
|
-
constructor(
|
|
785
|
-
super()
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1192
|
+
constructor(config) {
|
|
1193
|
+
super();
|
|
1194
|
+
this.provide = new HocuspocusProvider({
|
|
1195
|
+
...config,
|
|
1196
|
+
onSynced: (data) => {
|
|
1197
|
+
config.onSynced?.(data);
|
|
1198
|
+
this.loadEvent.next();
|
|
789
1199
|
},
|
|
790
|
-
onAwarenessUpdate: (
|
|
791
|
-
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
1200
|
+
onAwarenessUpdate: (data) => {
|
|
1201
|
+
config.onAwarenessUpdate?.(data);
|
|
1202
|
+
const states = data.states.map((state) => {
|
|
1203
|
+
return {
|
|
1204
|
+
clientId: state.clientId,
|
|
1205
|
+
message: state.message
|
|
1206
|
+
};
|
|
1207
|
+
});
|
|
1208
|
+
this.stateChangeEvent.next(states);
|
|
797
1209
|
}
|
|
798
1210
|
});
|
|
799
1211
|
}
|
|
800
|
-
setLocalStateField(
|
|
801
|
-
this.provide.setAwarenessField(
|
|
1212
|
+
setLocalStateField(key, data) {
|
|
1213
|
+
this.provide.setAwarenessField(key, data);
|
|
802
1214
|
}
|
|
803
1215
|
onDestroy() {
|
|
804
|
-
this.provide.disconnect()
|
|
1216
|
+
this.provide.disconnect();
|
|
1217
|
+
this.provide.destroy();
|
|
805
1218
|
}
|
|
806
1219
|
}
|
|
807
|
-
class
|
|
1220
|
+
class YWebsocketConnector extends SyncConnector {
|
|
808
1221
|
provide;
|
|
809
|
-
onSync = (
|
|
810
|
-
|
|
1222
|
+
onSync = (is) => {
|
|
1223
|
+
if (is) {
|
|
1224
|
+
this.loadEvent.next();
|
|
1225
|
+
}
|
|
811
1226
|
};
|
|
812
1227
|
onUpdate = () => {
|
|
813
|
-
const
|
|
814
|
-
this.provide.awareness.getStates().forEach((
|
|
815
|
-
|
|
816
|
-
clientId:
|
|
817
|
-
message:
|
|
1228
|
+
const syncStates = [];
|
|
1229
|
+
this.provide.awareness.getStates().forEach((state, id) => {
|
|
1230
|
+
syncStates.push({
|
|
1231
|
+
clientId: id,
|
|
1232
|
+
message: state.message
|
|
818
1233
|
});
|
|
819
|
-
})
|
|
1234
|
+
});
|
|
1235
|
+
this.stateChangeEvent.next(syncStates);
|
|
820
1236
|
};
|
|
821
|
-
constructor(
|
|
822
|
-
super()
|
|
1237
|
+
constructor(url, roomName, yDoc) {
|
|
1238
|
+
super();
|
|
1239
|
+
this.onLoad = this.loadEvent.asObservable();
|
|
1240
|
+
this.onStateChange = this.stateChangeEvent.asObservable();
|
|
1241
|
+
this.provide = new WebsocketProvider(url, roomName, yDoc);
|
|
1242
|
+
this.provide.once("sync", this.onSync);
|
|
1243
|
+
this.provide.awareness.on("update", this.onUpdate);
|
|
823
1244
|
}
|
|
824
|
-
setLocalStateField(
|
|
825
|
-
this.provide.awareness.setLocalStateField(
|
|
1245
|
+
setLocalStateField(key, data) {
|
|
1246
|
+
this.provide.awareness.setLocalStateField(key, data);
|
|
826
1247
|
}
|
|
827
1248
|
onDestroy() {
|
|
828
|
-
this.provide.awareness.off("update", this.onUpdate)
|
|
1249
|
+
this.provide.awareness.off("update", this.onUpdate);
|
|
1250
|
+
this.provide.disconnect();
|
|
1251
|
+
this.provide.destroy();
|
|
829
1252
|
}
|
|
830
1253
|
}
|
|
831
|
-
class
|
|
832
|
-
constructor(
|
|
833
|
-
this.config =
|
|
1254
|
+
class CollaborateModule {
|
|
1255
|
+
constructor(config) {
|
|
1256
|
+
this.config = config;
|
|
834
1257
|
}
|
|
835
1258
|
config;
|
|
836
|
-
subscription = new
|
|
1259
|
+
subscription = new Subscription();
|
|
837
1260
|
providers = [
|
|
838
|
-
|
|
839
|
-
|
|
1261
|
+
Collaborate,
|
|
1262
|
+
CollabHistory,
|
|
840
1263
|
{
|
|
841
|
-
provide:
|
|
842
|
-
useExisting:
|
|
1264
|
+
provide: History,
|
|
1265
|
+
useExisting: CollabHistory
|
|
843
1266
|
},
|
|
844
1267
|
{
|
|
845
|
-
provide:
|
|
846
|
-
useFactory: (
|
|
847
|
-
|
|
1268
|
+
provide: SyncConnector,
|
|
1269
|
+
useFactory: (collab) => {
|
|
1270
|
+
return this.config.createConnector(collab.yDoc);
|
|
1271
|
+
},
|
|
1272
|
+
deps: [Collaborate]
|
|
848
1273
|
},
|
|
849
1274
|
{
|
|
850
|
-
provide:
|
|
851
|
-
useClass:
|
|
1275
|
+
provide: SubModelLoader,
|
|
1276
|
+
useClass: NonSubModelLoader
|
|
852
1277
|
}
|
|
853
1278
|
];
|
|
854
1279
|
timer = null;
|
|
855
|
-
setup(
|
|
856
|
-
const
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
1280
|
+
setup(textbus) {
|
|
1281
|
+
const messageBus = textbus.get(MessageBus, null);
|
|
1282
|
+
const connector = textbus.get(SyncConnector);
|
|
1283
|
+
const collab = textbus.get(Collaborate);
|
|
1284
|
+
if (messageBus) {
|
|
1285
|
+
const selection = textbus.get(Selection);
|
|
1286
|
+
connector.setLocalStateField("message", messageBus.get(textbus));
|
|
1287
|
+
this.subscription.add(
|
|
1288
|
+
messageBus.onSync.subscribe(() => {
|
|
1289
|
+
connector.setLocalStateField("message", messageBus.get(textbus));
|
|
862
1290
|
}),
|
|
863
|
-
|
|
864
|
-
|
|
1291
|
+
selection.onChange.subscribe(() => {
|
|
1292
|
+
connector.setLocalStateField("message", messageBus.get(textbus));
|
|
865
1293
|
}),
|
|
866
|
-
|
|
867
|
-
|
|
1294
|
+
connector.onStateChange.subscribe((states) => {
|
|
1295
|
+
messageBus.consume(states, textbus);
|
|
868
1296
|
})
|
|
869
1297
|
);
|
|
870
1298
|
}
|
|
871
|
-
return
|
|
872
|
-
if (!this.config.onlyLoad)
|
|
1299
|
+
return connector.onLoad.toPromise().then(() => {
|
|
1300
|
+
if (!this.config.onlyLoad) {
|
|
873
1301
|
return;
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
1302
|
+
}
|
|
1303
|
+
const root = collab.yDoc.getMap("RootComponent");
|
|
1304
|
+
if (root.has("state")) {
|
|
1305
|
+
return;
|
|
1306
|
+
}
|
|
1307
|
+
return new Promise((resolve) => {
|
|
1308
|
+
const testing = () => {
|
|
1309
|
+
if (root.has("state")) {
|
|
1310
|
+
resolve();
|
|
1311
|
+
} else {
|
|
1312
|
+
this.timer = setTimeout(testing, 1e3);
|
|
1313
|
+
}
|
|
1314
|
+
};
|
|
1315
|
+
this.timer = setTimeout(testing, 1e3);
|
|
1316
|
+
});
|
|
882
1317
|
});
|
|
883
1318
|
}
|
|
884
|
-
onDestroy(
|
|
885
|
-
this.subscription.unsubscribe()
|
|
1319
|
+
onDestroy(textbus) {
|
|
1320
|
+
this.subscription.unsubscribe();
|
|
1321
|
+
textbus.get(Collaborate).destroy();
|
|
1322
|
+
textbus.get(History).destroy();
|
|
1323
|
+
textbus.get(SyncConnector).onDestroy();
|
|
1324
|
+
clearTimeout(this.timer);
|
|
886
1325
|
}
|
|
887
1326
|
}
|
|
888
|
-
class
|
|
889
|
-
constructor(
|
|
890
|
-
this.config =
|
|
1327
|
+
class MultipleDocumentCollaborateModule {
|
|
1328
|
+
constructor(config) {
|
|
1329
|
+
this.config = config;
|
|
891
1330
|
}
|
|
892
1331
|
config;
|
|
893
|
-
subscription = new
|
|
1332
|
+
subscription = new Subscription();
|
|
894
1333
|
providers = [
|
|
895
|
-
|
|
896
|
-
|
|
1334
|
+
Collaborate,
|
|
1335
|
+
MultipleDocCollabHistory,
|
|
897
1336
|
{
|
|
898
|
-
provide:
|
|
899
|
-
useExisting:
|
|
1337
|
+
provide: History,
|
|
1338
|
+
useExisting: MultipleDocCollabHistory
|
|
900
1339
|
},
|
|
901
1340
|
{
|
|
902
|
-
provide:
|
|
903
|
-
useFactory: (
|
|
904
|
-
|
|
1341
|
+
provide: SyncConnector,
|
|
1342
|
+
useFactory: (collab) => {
|
|
1343
|
+
return this.config.createConnector(collab.yDoc);
|
|
1344
|
+
},
|
|
1345
|
+
deps: [Collaborate]
|
|
905
1346
|
},
|
|
906
1347
|
{
|
|
907
|
-
provide:
|
|
908
|
-
useFactory: () =>
|
|
1348
|
+
provide: SubModelLoader,
|
|
1349
|
+
useFactory: () => {
|
|
1350
|
+
return this.config.subModelLoader;
|
|
1351
|
+
}
|
|
909
1352
|
}
|
|
910
1353
|
];
|
|
911
1354
|
timer = null;
|
|
912
|
-
setup(
|
|
913
|
-
const
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1355
|
+
setup(textbus) {
|
|
1356
|
+
const messageBus = textbus.get(MessageBus, null);
|
|
1357
|
+
const connector = textbus.get(SyncConnector);
|
|
1358
|
+
const collab = textbus.get(Collaborate);
|
|
1359
|
+
if (messageBus) {
|
|
1360
|
+
const selection = textbus.get(Selection);
|
|
1361
|
+
connector.setLocalStateField("message", messageBus.get(textbus));
|
|
1362
|
+
this.subscription.add(
|
|
1363
|
+
messageBus.onSync.subscribe(() => {
|
|
1364
|
+
connector.setLocalStateField("message", messageBus.get(textbus));
|
|
919
1365
|
}),
|
|
920
|
-
|
|
921
|
-
|
|
1366
|
+
selection.onChange.subscribe(() => {
|
|
1367
|
+
connector.setLocalStateField("message", messageBus.get(textbus));
|
|
922
1368
|
}),
|
|
923
|
-
|
|
924
|
-
|
|
1369
|
+
connector.onStateChange.subscribe((states) => {
|
|
1370
|
+
messageBus.consume(states, textbus);
|
|
925
1371
|
})
|
|
926
1372
|
);
|
|
927
1373
|
}
|
|
928
|
-
return
|
|
929
|
-
if (!this.config.onlyLoad)
|
|
1374
|
+
return connector.onLoad.toPromise().then(() => {
|
|
1375
|
+
if (!this.config.onlyLoad) {
|
|
930
1376
|
return;
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1377
|
+
}
|
|
1378
|
+
const root = collab.yDoc.getMap("RootComponent");
|
|
1379
|
+
if (root.has("state")) {
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
return new Promise((resolve) => {
|
|
1383
|
+
const testing = () => {
|
|
1384
|
+
if (root.has("state")) {
|
|
1385
|
+
resolve();
|
|
1386
|
+
} else {
|
|
1387
|
+
this.timer = setTimeout(testing, 1e3);
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1390
|
+
this.timer = setTimeout(testing, 1e3);
|
|
1391
|
+
});
|
|
939
1392
|
});
|
|
940
1393
|
}
|
|
941
|
-
onDestroy(
|
|
942
|
-
this.subscription.unsubscribe()
|
|
1394
|
+
onDestroy(textbus) {
|
|
1395
|
+
this.subscription.unsubscribe();
|
|
1396
|
+
textbus.get(Collaborate).destroy();
|
|
1397
|
+
textbus.get(History).destroy();
|
|
1398
|
+
textbus.get(SyncConnector).onDestroy();
|
|
1399
|
+
clearTimeout(this.timer);
|
|
943
1400
|
}
|
|
944
1401
|
}
|
|
945
1402
|
export {
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1403
|
+
CollabHistory,
|
|
1404
|
+
Collaborate,
|
|
1405
|
+
CollaborateModule,
|
|
1406
|
+
CustomUndoManagerConfig,
|
|
1407
|
+
HocuspocusConnector,
|
|
1408
|
+
MessageBus,
|
|
1409
|
+
MultipleDocCollabHistory,
|
|
1410
|
+
MultipleDocumentCollaborateModule,
|
|
1411
|
+
NonSubModelLoader,
|
|
1412
|
+
SubModelLoader,
|
|
1413
|
+
SyncConnector,
|
|
1414
|
+
YWebsocketConnector
|
|
958
1415
|
};
|
|
959
1416
|
//# sourceMappingURL=index.esm.js.map
|