@apollohg/react-native-rich-text-editor 2.0.0 → 2.0.1
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/README.md +1 -1
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/android/build.gradle +3 -0
- package/app.plugin.js +42 -39
- package/dist/AtomHost.js +18 -11
- package/dist/EditorAddon.js +4 -2
- package/dist/EditorAddonNormalization.js +17 -9
- package/dist/EditorMentionThemeNormalization.js +6 -3
- package/dist/EditorMentionThemeValidation.js +28 -11
- package/dist/EditorStyleSheetNormalization.js +84 -37
- package/dist/EditorTheme.d.ts +4 -0
- package/dist/EditorTheme.js +5 -3
- package/dist/EditorToolbarComponent.d.ts +1 -1
- package/dist/EditorToolbarComponent.js +1 -1
- package/dist/EditorToolbarRegistry.js +5 -5
- package/dist/EditorToolbarTypes.d.ts +12 -12
- package/dist/EditorToolbarVisuals.js +1 -1
- package/dist/ExternalTextComposition.js +89 -43
- package/dist/ImageLoadingPolicy.d.ts +1 -1
- package/dist/NativeEditorBoundaryError.d.ts +7 -7
- package/dist/NativeEditorBoundaryError.js +9 -5
- package/dist/NativeEditorCollaborationTransport.d.ts +7 -7
- package/dist/NativeEditorCollaborationTransport.js +28 -15
- package/dist/NativeEditorCreateConfig.js +11 -6
- package/dist/NativeEditorCreateJson.js +51 -25
- package/dist/NativeEditorCreateValidation.js +11 -6
- package/dist/NativeEditorDocumentBridge.d.ts +1 -1
- package/dist/NativeEditorDocumentBridge.js +32 -18
- package/dist/NativeEditorDocumentHandle.d.ts +4 -4
- package/dist/NativeEditorDocumentHandle.js +1 -1
- package/dist/NativeEditorLocalAwareness.js +25 -13
- package/dist/NativeEditorNativeModule.d.ts +8 -1
- package/dist/NativeEditorNativeModule.js +7 -5
- package/dist/NativeEditorRenderNormalization.js +66 -25
- package/dist/NativeEditorResultNormalization.js +53 -29
- package/dist/NativeEditorTypes.d.ts +10 -10
- package/dist/NativeEditorV2Decimal.js +6 -3
- package/dist/NativeProseViewer.js +11 -3
- package/dist/ResourceLimits.d.ts +2 -2
- package/dist/ResourceLimits.js +7 -2
- package/dist/RichTextEditor.js +1 -1
- package/dist/RichTextEditorNativeTypes.d.ts +1 -1
- package/dist/RichTextEditorNativeView.d.ts +1 -3
- package/dist/RichTextEditorSerialization.js +24 -14
- package/dist/RichTextEditorTypes.d.ts +1 -1
- package/dist/YjsCollaboration.d.ts +7 -7
- package/dist/YjsCollaboration.js +42 -26
- package/dist/addons.d.ts +4 -4
- package/dist/addons.js +3 -3
- package/dist/atomInstances.js +6 -3
- package/dist/atomUpdates.js +7 -4
- package/dist/atoms.js +20 -12
- package/dist/attributeValidation.js +55 -24
- package/dist/contentExpression.js +80 -42
- package/dist/listMarkers.d.ts +1 -1
- package/dist/listMarkers.js +1 -1
- package/dist/schemaDefinition.d.ts +1 -1
- package/dist/schemaDefinition.js +23 -14
- package/dist/schemaDocument.js +1 -1
- package/dist/schemaDocumentConstruction.js +25 -14
- package/dist/schemaNormalization.js +51 -29
- package/dist/schemaPresets.d.ts +1 -1
- package/dist/schemaPresets.js +9 -4
- package/dist/schemaResolution.js +46 -25
- package/dist/specs/PreparedProseViewerNativeComponent.d.ts +4 -0
- package/dist/useEditorToolbarInteractions.d.ts +2 -2
- package/dist/useEditorToolbarInteractions.js +45 -23
- package/dist/useEditorToolbarItems.d.ts +1 -1
- package/dist/useEditorToolbarItems.js +4 -3
- package/dist/useEditorToolbarPresentation.d.ts +3 -3
- package/dist/useEditorToolbarPresentation.js +4 -4
- package/dist/useEditorToolbarState.d.ts +1 -1
- package/dist/useEditorToolbarState.js +1 -1
- package/dist/useFocusPreservingFrames.js +11 -8
- package/dist/useNativeEditor.d.ts +1 -1
- package/dist/useNativeEditor.js +21 -11
- package/dist/useRichTextEditorCommands.d.ts +2 -2
- package/dist/useRichTextEditorCommands.js +59 -29
- package/dist/useRichTextEditorEvents.d.ts +3 -3
- package/dist/useRichTextEditorEvents.js +75 -32
- package/dist/useRichTextEditorMentions.d.ts +4 -4
- package/dist/useRichTextEditorMentions.js +48 -29
- package/dist/useRichTextEditorPresentation.d.ts +4 -4
- package/dist/useRichTextEditorPresentation.js +25 -23
- package/dist/useRichTextEditorState.d.ts +3 -3
- package/dist/useRichTextEditorState.js +20 -15
- package/dist/useRichTextEditorUpdates.d.ts +1 -1
- package/dist/useRichTextEditorUpdates.js +99 -41
- package/dist/useViewerAtoms.js +63 -36
- package/ios/EditorCore.xcframework/Info.plist +5 -5
- package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
- package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
- package/package.json +11 -3
- package/react-native.config.js +1 -1
- package/rust/android/arm64-v8a/libeditor_core.so +0 -0
- package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
- package/rust/android/x86/libeditor_core.so +0 -0
- package/rust/android/x86_64/libeditor_core.so +0 -0
- package/src/AtomHost.tsx +58 -28
- package/src/EditorAddon.ts +18 -8
- package/src/EditorAddonNormalization.ts +40 -11
- package/src/EditorMentionThemeNormalization.ts +15 -4
- package/src/EditorMentionThemeValidation.ts +51 -14
- package/src/EditorStyleSheet.ts +1 -0
- package/src/EditorStyleSheetNormalization.ts +195 -64
- package/src/EditorTheme.ts +13 -5
- package/src/EditorToolbarComponent.tsx +2 -1
- package/src/EditorToolbarRegistry.tsx +23 -13
- package/src/EditorToolbarTypes.tsx +12 -12
- package/src/EditorToolbarVisuals.tsx +6 -3
- package/src/EditorUpdateRevision.ts +1 -0
- package/src/ExternalTextComposition.ts +259 -49
- package/src/ImageLoadingPolicy.ts +3 -1
- package/src/NativeEditorBoundaryError.ts +38 -11
- package/src/NativeEditorCollaborationTransport.ts +108 -27
- package/src/NativeEditorCreateConfig.ts +92 -19
- package/src/NativeEditorCreateJson.ts +163 -26
- package/src/NativeEditorCreateValidation.ts +33 -12
- package/src/NativeEditorDocumentBridge.ts +111 -19
- package/src/NativeEditorDocumentHandle.ts +9 -4
- package/src/NativeEditorLocalAwareness.ts +70 -15
- package/src/NativeEditorNativeModule.ts +13 -9
- package/src/NativeEditorRenderNormalization.ts +128 -29
- package/src/NativeEditorResultNormalization.ts +143 -32
- package/src/NativeEditorTypes.ts +12 -11
- package/src/NativeEditorV2Decimal.ts +12 -3
- package/src/NativeProseViewer.tsx +46 -16
- package/src/ResourceLimits.ts +15 -8
- package/src/RichTextEditor.tsx +3 -1
- package/src/RichTextEditorNativeTypes.tsx +1 -1
- package/src/RichTextEditorNativeView.tsx +2 -8
- package/src/RichTextEditorSerialization.tsx +70 -24
- package/src/RichTextEditorTypes.tsx +1 -1
- package/src/YjsCollaboration.ts +143 -47
- package/src/addons.ts +12 -8
- package/src/atomInstances.ts +25 -5
- package/src/atomUpdates.ts +23 -6
- package/src/atoms.ts +85 -18
- package/src/attributeValidation.ts +97 -33
- package/src/contentExpression.ts +218 -63
- package/src/listMarkers.ts +1 -1
- package/src/schemaDefinition.ts +82 -20
- package/src/schemaDocument.ts +15 -1
- package/src/schemaDocumentConstruction.ts +80 -16
- package/src/schemaNormalization.ts +155 -41
- package/src/schemaPresets.ts +37 -31
- package/src/schemaResolution.ts +126 -27
- package/src/specs/PreparedProseViewerNativeComponent.ts +4 -2
- package/src/useEditorToolbarInteractions.tsx +85 -36
- package/src/useEditorToolbarItems.tsx +50 -22
- package/src/useEditorToolbarPresentation.tsx +81 -58
- package/src/useEditorToolbarState.tsx +8 -6
- package/src/useFocusPreservingFrames.ts +43 -15
- package/src/useNativeEditor.ts +111 -51
- package/src/useRichTextEditorCommands.tsx +127 -54
- package/src/useRichTextEditorEvents.tsx +144 -42
- package/src/useRichTextEditorMentions.tsx +118 -37
- package/src/useRichTextEditorPresentation.tsx +128 -114
- package/src/useRichTextEditorState.tsx +76 -40
- package/src/useRichTextEditorUpdates.tsx +207 -56
- package/src/useViewerAtoms.tsx +162 -66
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import { applyRenderPatch, collectAtomInstanceBlocks } from './atomInstances';
|
|
8
8
|
import { allocateEditorUpdateRevision } from './EditorUpdateRevision';
|
|
9
9
|
import { setActiveEditorToolbarFrameOwnerForEditor } from './EditorToolbar';
|
|
10
|
-
import { useRichTextEditorState } from './useRichTextEditorState';
|
|
10
|
+
import { type useRichTextEditorState } from './useRichTextEditorState';
|
|
11
11
|
import {
|
|
12
12
|
selectedAtomKeys,
|
|
13
13
|
equalStringSets,
|
|
@@ -84,52 +84,59 @@ export function useRichTextEditorUpdates(
|
|
|
84
84
|
const updateAtomSelection = useCallback(
|
|
85
85
|
(selection: Selection, instances = atomStateRef.current.instances) => {
|
|
86
86
|
const next = selectedAtomKeys(selection, instances);
|
|
87
|
-
setSelectedKeys(
|
|
87
|
+
setSelectedKeys(current => (equalStringSets(current, next) ? current : next));
|
|
88
88
|
},
|
|
89
|
-
[]
|
|
89
|
+
[ atomStateRef, setSelectedKeys ]
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
const refreshAtomsFromUpdate = useCallback(
|
|
93
93
|
(update: NativeEditorAtomicRenderSnapshot) => {
|
|
94
94
|
const previous = atomStateRef.current;
|
|
95
|
+
|
|
95
96
|
const source =
|
|
96
97
|
update.renderPatch != null &&
|
|
97
98
|
update.renderPatch.baseDocumentVersion !== previous.documentVersion
|
|
98
99
|
? bridge.renderUpdate()
|
|
99
100
|
: update;
|
|
101
|
+
|
|
100
102
|
if (
|
|
101
103
|
source.renderPatch != null &&
|
|
102
104
|
source.renderPatch.baseDocumentVersion !== previous.documentVersion
|
|
103
105
|
) {
|
|
104
106
|
return;
|
|
105
107
|
}
|
|
108
|
+
|
|
106
109
|
const blocks =
|
|
107
110
|
source.renderBlocks != null
|
|
108
111
|
? source.renderBlocks
|
|
109
112
|
: applyRenderPatch(previous.blocks, {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
startIndex: source.renderPatch.startIndex,
|
|
114
|
+
deleteCount: source.renderPatch.deleteCount,
|
|
115
|
+
renderBlocks: source.renderPatch.renderBlocks,
|
|
116
|
+
});
|
|
117
|
+
|
|
114
118
|
const patchedCollection =
|
|
115
119
|
source.renderPatch != null && previous.hasOnlyStableAtomKeys
|
|
116
120
|
? collectAtomInstanceBlocks(
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
121
|
+
source.renderPatch.renderBlocks,
|
|
122
|
+
registeredAtomTypes
|
|
123
|
+
)
|
|
120
124
|
: null;
|
|
125
|
+
|
|
121
126
|
const collection =
|
|
122
127
|
source.renderPatch != null && patchedCollection?.hasOnlyStableKeys
|
|
123
128
|
? {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
instanceBlocks: applyRenderPatch(previous.instanceBlocks, {
|
|
130
|
+
startIndex: source.renderPatch.startIndex,
|
|
131
|
+
deleteCount: source.renderPatch.deleteCount,
|
|
132
|
+
renderBlocks: patchedCollection.instanceBlocks,
|
|
133
|
+
}),
|
|
134
|
+
hasOnlyStableKeys: true,
|
|
135
|
+
}
|
|
131
136
|
: collectAtomInstanceBlocks(blocks, registeredAtomTypes);
|
|
137
|
+
|
|
132
138
|
const instances = collection.instanceBlocks.flat();
|
|
139
|
+
|
|
133
140
|
const next = {
|
|
134
141
|
blocks,
|
|
135
142
|
instanceBlocks: collection.instanceBlocks,
|
|
@@ -137,19 +144,28 @@ export function useRichTextEditorUpdates(
|
|
|
137
144
|
documentVersion: source.documentVersion,
|
|
138
145
|
hasOnlyStableAtomKeys: collection.hasOnlyStableKeys,
|
|
139
146
|
};
|
|
147
|
+
|
|
140
148
|
atomStateRef.current = next;
|
|
149
|
+
|
|
141
150
|
if (!equalAtomInstances(previous.instances, next.instances)) {
|
|
142
151
|
setAtomState(next);
|
|
143
152
|
}
|
|
153
|
+
|
|
144
154
|
updateAtomSelection(selectionRef.current, next.instances);
|
|
145
155
|
},
|
|
146
|
-
[
|
|
156
|
+
[ atomStateRef,
|
|
157
|
+
bridge,
|
|
158
|
+
registeredAtomTypes,
|
|
159
|
+
selectionRef,
|
|
160
|
+
setAtomState,
|
|
161
|
+
updateAtomSelection ]
|
|
147
162
|
);
|
|
148
163
|
|
|
149
164
|
useEffect(() => {
|
|
150
165
|
const current = atomStateRef.current;
|
|
151
166
|
const collection = collectAtomInstanceBlocks(current.blocks, registeredAtomTypes);
|
|
152
167
|
const instances = collection.instances;
|
|
168
|
+
|
|
153
169
|
const next = {
|
|
154
170
|
blocks: current.blocks,
|
|
155
171
|
instanceBlocks: collection.instanceBlocks,
|
|
@@ -157,12 +173,19 @@ export function useRichTextEditorUpdates(
|
|
|
157
173
|
documentVersion: current.documentVersion,
|
|
158
174
|
hasOnlyStableAtomKeys: collection.hasOnlyStableKeys,
|
|
159
175
|
};
|
|
176
|
+
|
|
160
177
|
atomStateRef.current = next;
|
|
178
|
+
|
|
161
179
|
if (!equalAtomInstances(current.instances, instances)) {
|
|
162
180
|
setAtomState(next);
|
|
163
181
|
}
|
|
182
|
+
|
|
164
183
|
updateAtomSelection(selectionRef.current, instances);
|
|
165
|
-
}, [
|
|
184
|
+
}, [ atomStateRef,
|
|
185
|
+
registeredAtomTypes,
|
|
186
|
+
selectionRef,
|
|
187
|
+
setAtomState,
|
|
188
|
+
updateAtomSelection ]);
|
|
166
189
|
|
|
167
190
|
useLayoutEffect(() => {
|
|
168
191
|
if (
|
|
@@ -172,18 +195,28 @@ export function useRichTextEditorUpdates(
|
|
|
172
195
|
) {
|
|
173
196
|
return;
|
|
174
197
|
}
|
|
198
|
+
|
|
175
199
|
atomSeedEditorIdRef.current = editorId;
|
|
176
200
|
refreshAtomsFromUpdate(bridge.renderUpdate());
|
|
177
|
-
}, [
|
|
201
|
+
}, [ atomSeedEditorIdRef,
|
|
202
|
+
bridge,
|
|
203
|
+
document.isReady,
|
|
204
|
+
documentHandle,
|
|
205
|
+
editorId,
|
|
206
|
+
refreshAtomsFromUpdate ]);
|
|
178
207
|
|
|
179
208
|
const applyTypedUpdateState = useCallback(
|
|
180
209
|
(
|
|
181
210
|
update: Pick<NativeEditorAtomicRenderSnapshot, 'selection' | 'activeState'>,
|
|
182
211
|
isCurrent: () => boolean = () => true
|
|
183
212
|
) => {
|
|
184
|
-
if (!isCurrent())
|
|
213
|
+
if (!isCurrent()) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
|
|
185
217
|
selectionRef.current = update.selection;
|
|
186
218
|
updateAtomSelection(update.selection);
|
|
219
|
+
|
|
187
220
|
if (
|
|
188
221
|
update.selection.type === 'text' &&
|
|
189
222
|
update.selection.anchorScalar != null &&
|
|
@@ -194,37 +227,74 @@ export function useRichTextEditorUpdates(
|
|
|
194
227
|
head: update.selection.headScalar,
|
|
195
228
|
};
|
|
196
229
|
}
|
|
197
|
-
|
|
230
|
+
|
|
231
|
+
if (!isCurrent()) {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
198
235
|
const nextActiveState = update.activeState;
|
|
199
236
|
activeStateRef.current = nextActiveState;
|
|
200
|
-
|
|
237
|
+
|
|
238
|
+
if (!isCurrent()) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
|
|
201
242
|
setActiveState(nextActiveState);
|
|
202
|
-
|
|
243
|
+
|
|
244
|
+
if (!isCurrent()) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
|
|
203
248
|
const key = stringifyCachedJson(nextActiveState);
|
|
249
|
+
|
|
204
250
|
if (key !== activeStateKeyRef.current) {
|
|
205
|
-
if (!isCurrent())
|
|
251
|
+
if (!isCurrent()) {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
|
|
206
255
|
activeStateKeyRef.current = key;
|
|
207
|
-
|
|
256
|
+
|
|
257
|
+
if (!isCurrent()) {
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
208
261
|
onActiveStateChangeRef.current?.(nextActiveState);
|
|
209
262
|
}
|
|
263
|
+
|
|
210
264
|
return isCurrent();
|
|
211
265
|
},
|
|
212
|
-
[
|
|
266
|
+
[ activeStateKeyRef,
|
|
267
|
+
activeStateRef,
|
|
268
|
+
onActiveStateChangeRef,
|
|
269
|
+
scalarSelectionRef,
|
|
270
|
+
selectionRef,
|
|
271
|
+
setActiveState,
|
|
272
|
+
updateAtomSelection ]
|
|
213
273
|
);
|
|
214
274
|
|
|
215
275
|
const applyUpdateState = useCallback(
|
|
216
276
|
(updateJson: string | null | undefined) => {
|
|
217
|
-
if (typeof updateJson !== 'string' || updateJson.length === 0)
|
|
277
|
+
if (typeof updateJson !== 'string' || updateJson.length === 0) {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
|
|
218
281
|
let parsed: Record<string, unknown>;
|
|
282
|
+
|
|
219
283
|
try {
|
|
220
284
|
const candidate = JSON.parse(updateJson) as unknown;
|
|
221
|
-
|
|
285
|
+
|
|
286
|
+
if (!isRecord(candidate)) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
|
|
222
290
|
parsed = candidate;
|
|
223
291
|
} catch {
|
|
224
292
|
return null;
|
|
225
293
|
}
|
|
294
|
+
|
|
226
295
|
const nextSelection = parseSelectionFromUpdate(parsed.selection);
|
|
227
296
|
const nextActiveState = parseActiveStateFromUpdate(parsed.activeState);
|
|
297
|
+
|
|
228
298
|
if (nextSelection && nextActiveState) {
|
|
229
299
|
applyTypedUpdateState({
|
|
230
300
|
selection: nextSelection,
|
|
@@ -236,67 +306,124 @@ export function useRichTextEditorUpdates(
|
|
|
236
306
|
activeStateRef.current = nextActiveState;
|
|
237
307
|
setActiveState(nextActiveState);
|
|
238
308
|
const key = stringifyCachedJson(nextActiveState);
|
|
309
|
+
|
|
239
310
|
if (key !== activeStateKeyRef.current) {
|
|
240
311
|
activeStateKeyRef.current = key;
|
|
241
312
|
onActiveStateChangeRef.current?.(nextActiveState);
|
|
242
313
|
}
|
|
243
314
|
}
|
|
315
|
+
|
|
244
316
|
return parsed;
|
|
245
317
|
},
|
|
246
|
-
[
|
|
318
|
+
[ activeStateKeyRef,
|
|
319
|
+
activeStateRef,
|
|
320
|
+
applyTypedUpdateState,
|
|
321
|
+
onActiveStateChangeRef,
|
|
322
|
+
selectionRef,
|
|
323
|
+
setActiveState ]
|
|
247
324
|
);
|
|
248
325
|
|
|
249
326
|
const pushEngineUpdateToView = useCallback(() => {
|
|
250
|
-
if (documentHandle.isDestroyed)
|
|
327
|
+
if (documentHandle.isDestroyed) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
251
331
|
const sourceEditorId = documentHandle.editorId;
|
|
252
332
|
const sourceBindingGeneration = pushedUpdateBindingGenerationRef.current;
|
|
333
|
+
|
|
253
334
|
const isCurrentSource = () => {
|
|
254
335
|
const current =
|
|
255
336
|
sourceEditorId === currentPushedUpdateEditorIdRef.current &&
|
|
256
337
|
sourceBindingGeneration === pushedUpdateBindingGenerationRef.current;
|
|
338
|
+
|
|
257
339
|
return current;
|
|
258
340
|
};
|
|
341
|
+
|
|
259
342
|
const allocation = allocateEditorUpdateRevision(pushRevisionRef.current);
|
|
343
|
+
|
|
260
344
|
if ('error' in allocation) {
|
|
261
345
|
bridge._emitAutonomousError(allocation.error);
|
|
346
|
+
|
|
262
347
|
return;
|
|
263
348
|
}
|
|
349
|
+
|
|
264
350
|
const reset = bridge._pendingViewReset;
|
|
265
351
|
const snapshot = bridge.renderUpdate();
|
|
352
|
+
|
|
266
353
|
// renderUpdate can synchronously re-enter React and bind this
|
|
267
354
|
// component to another handle. Do not let any side effect from A
|
|
268
355
|
// reach B once that happens.
|
|
269
|
-
if (!isCurrentSource())
|
|
356
|
+
if (!isCurrentSource()) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
|
|
270
360
|
refreshAtomsFromUpdate(snapshot);
|
|
271
|
-
|
|
361
|
+
|
|
362
|
+
if (!isCurrentSource()) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
272
366
|
const updateJson = JSON.stringify(snapshot);
|
|
273
|
-
|
|
367
|
+
|
|
368
|
+
if (!isCurrentSource()) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
274
372
|
if (!applyTypedUpdateState(snapshot, isCurrentSource)) {
|
|
275
373
|
return;
|
|
276
374
|
}
|
|
277
|
-
|
|
375
|
+
|
|
376
|
+
if (!isCurrentSource()) {
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
278
380
|
lastPushedEngineRevisionRef.current = snapshot.documentVersion;
|
|
279
|
-
|
|
381
|
+
|
|
382
|
+
if (!isCurrentSource()) {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
|
|
280
386
|
pushRevisionRef.current = allocation.revision;
|
|
281
|
-
|
|
387
|
+
|
|
388
|
+
if (!isCurrentSource()) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
|
|
282
392
|
setPushedUpdate({
|
|
283
393
|
json: updateJson,
|
|
284
394
|
resetJson: reset?.json,
|
|
285
395
|
revision: allocation.revision,
|
|
286
396
|
editorId: sourceEditorId,
|
|
287
397
|
});
|
|
288
|
-
|
|
289
|
-
|
|
398
|
+
|
|
399
|
+
if (bridge._pendingViewReset === reset) {
|
|
400
|
+
bridge._pendingViewReset = null;
|
|
401
|
+
}
|
|
402
|
+
}, [ applyTypedUpdateState,
|
|
403
|
+
bridge,
|
|
404
|
+
currentPushedUpdateEditorIdRef,
|
|
405
|
+
documentHandle.editorId,
|
|
406
|
+
documentHandle.isDestroyed,
|
|
407
|
+
lastPushedEngineRevisionRef,
|
|
408
|
+
pushRevisionRef,
|
|
409
|
+
pushedUpdateBindingGenerationRef,
|
|
410
|
+
refreshAtomsFromUpdate,
|
|
411
|
+
setPushedUpdate ]);
|
|
290
412
|
|
|
291
413
|
useLayoutEffect(() => {
|
|
292
414
|
const pending = pendingFocusedRebindRef.current;
|
|
293
|
-
|
|
415
|
+
|
|
416
|
+
if (pending?.editorId !== editorId || !document.isReady) {
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
|
|
294
420
|
pendingFocusedRebindRef.current = null;
|
|
295
421
|
|
|
296
422
|
const snapshot = bridge.renderUpdate();
|
|
297
423
|
const anchor = Math.min(pending.anchor, snapshot.scalarLength);
|
|
298
424
|
const head = Math.min(pending.head, snapshot.scalarLength);
|
|
299
425
|
const collapsed = anchor === head;
|
|
426
|
+
|
|
300
427
|
const setSelection = (affinity: NativeEditorPositionAffinity) =>
|
|
301
428
|
bridge.setSelection({
|
|
302
429
|
baseDocumentRevision: snapshot.documentVersion,
|
|
@@ -311,35 +438,46 @@ export function useRichTextEditorUpdates(
|
|
|
311
438
|
try {
|
|
312
439
|
setSelection(collapsed ? 'after' : 'before');
|
|
313
440
|
} catch (error) {
|
|
314
|
-
if (!collapsed || !isPositionInvalidError(error))
|
|
441
|
+
if (!collapsed || !isPositionInvalidError(error)) {
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
444
|
+
|
|
315
445
|
setSelection('before');
|
|
316
446
|
}
|
|
447
|
+
|
|
317
448
|
pushEngineUpdateToView();
|
|
318
449
|
} catch (error) {
|
|
319
|
-
if (!isPositionInvalidError(error))
|
|
450
|
+
if (!isPositionInvalidError(error)) {
|
|
451
|
+
throw error;
|
|
452
|
+
}
|
|
320
453
|
}
|
|
321
454
|
|
|
322
455
|
setActiveEditorToolbarFrameOwnerForEditor(toolbarFrameOwnerId, true);
|
|
323
456
|
onFocusRef.current?.();
|
|
324
|
-
}, [bridge,
|
|
457
|
+
}, [ bridge,
|
|
458
|
+
document.isReady,
|
|
459
|
+
editorId,
|
|
460
|
+
onFocusRef,
|
|
461
|
+
pendingFocusedRebindRef,
|
|
462
|
+
pushEngineUpdateToView,
|
|
463
|
+
toolbarFrameOwnerId ]);
|
|
325
464
|
|
|
326
465
|
// A pending update is owned by the handle that produced its snapshot.
|
|
327
466
|
// Drop it when this component rebinds, so no old session state reaches
|
|
328
467
|
// the next native view binding.
|
|
329
468
|
useEffect(() => {
|
|
330
|
-
setPushedUpdate(
|
|
331
|
-
if (current == null || current.editorId === editorId)
|
|
469
|
+
setPushedUpdate(current => {
|
|
470
|
+
if (current == null || current.editorId === editorId) {
|
|
471
|
+
return current;
|
|
472
|
+
}
|
|
473
|
+
|
|
332
474
|
return null;
|
|
333
475
|
});
|
|
334
|
-
}, [editorId]);
|
|
476
|
+
}, [ editorId, setPushedUpdate ]);
|
|
335
477
|
|
|
336
478
|
const pendingViewReset = bridge._pendingViewReset;
|
|
337
479
|
|
|
338
|
-
//
|
|
339
|
-
// document-API mutation) the view learns the new state here. Native-
|
|
340
|
-
// driven commits (typing, native toolbar) already updated the view
|
|
341
|
-
// through the adapter and are never echoed back. The first observed
|
|
342
|
-
// revision is skipped: the view pulls the initial state natively on bind.
|
|
480
|
+
// Native commits already update the view; echo only subsequent JS-driven revisions.
|
|
343
481
|
useEffect(() => {
|
|
344
482
|
// The document hook refreshes its state after the rebind commit. Its
|
|
345
483
|
// first render can therefore still contain A's revision; do not let
|
|
@@ -347,13 +485,20 @@ export function useRichTextEditorUpdates(
|
|
|
347
485
|
if (didRebindRevisionScope) {
|
|
348
486
|
return;
|
|
349
487
|
}
|
|
350
|
-
|
|
488
|
+
|
|
489
|
+
if (!document.isReady || document.documentRevision == null) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
351
493
|
const revision = document.documentRevision;
|
|
494
|
+
|
|
352
495
|
if (!pendingViewReset && !didObserveInitialRevisionRef.current) {
|
|
353
496
|
didObserveInitialRevisionRef.current = true;
|
|
354
497
|
lastPushedEngineRevisionRef.current = revision;
|
|
498
|
+
|
|
355
499
|
return;
|
|
356
500
|
}
|
|
501
|
+
|
|
357
502
|
if (
|
|
358
503
|
!pendingViewReset &&
|
|
359
504
|
lastPushedEngineRevisionRef.current != null &&
|
|
@@ -361,6 +506,7 @@ export function useRichTextEditorUpdates(
|
|
|
361
506
|
) {
|
|
362
507
|
return;
|
|
363
508
|
}
|
|
509
|
+
|
|
364
510
|
if (
|
|
365
511
|
!pendingViewReset &&
|
|
366
512
|
(revision === lastNativeDrivenRevisionRef.current ||
|
|
@@ -370,13 +516,15 @@ export function useRichTextEditorUpdates(
|
|
|
370
516
|
if (document.documentOrigin === 'remoteCollaboration' && !documentHandle.isDestroyed) {
|
|
371
517
|
refreshAtomsFromUpdate(bridge.renderUpdate());
|
|
372
518
|
}
|
|
519
|
+
|
|
373
520
|
lastPushedEngineRevisionRef.current = revision;
|
|
521
|
+
|
|
374
522
|
return;
|
|
375
523
|
}
|
|
524
|
+
|
|
376
525
|
lastNativeDrivenRevisionRef.current = null;
|
|
377
526
|
pushEngineUpdateToView();
|
|
378
|
-
}, [
|
|
379
|
-
pendingViewReset,
|
|
527
|
+
}, [ pendingViewReset,
|
|
380
528
|
didRebindRevisionScope,
|
|
381
529
|
document.isReady,
|
|
382
530
|
document.documentRevision,
|
|
@@ -385,13 +533,16 @@ export function useRichTextEditorUpdates(
|
|
|
385
533
|
documentHandle,
|
|
386
534
|
pushEngineUpdateToView,
|
|
387
535
|
refreshAtomsFromUpdate,
|
|
388
|
-
|
|
536
|
+
didObserveInitialRevisionRef,
|
|
537
|
+
lastPushedEngineRevisionRef,
|
|
538
|
+
lastNativeDrivenRevisionRef ]);
|
|
389
539
|
|
|
390
540
|
const afterLocalEngineMutation = useCallback(() => {
|
|
391
541
|
onLocalCommitRef.current?.();
|
|
392
542
|
pushEngineUpdateToView();
|
|
393
543
|
document.refresh();
|
|
394
|
-
}, [document, pushEngineUpdateToView]);
|
|
544
|
+
}, [ document, onLocalCommitRef, pushEngineUpdateToView ]);
|
|
545
|
+
|
|
395
546
|
return {
|
|
396
547
|
refreshAtomsFromUpdate,
|
|
397
548
|
afterLocalEngineMutation,
|