@apollohg/react-native-rich-text-editor 2.0.0
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/LICENSE +160 -0
- package/README.md +259 -0
- package/RUST-STANDARD-LIBRARY-NOTICES.html +8266 -0
- package/ReactNativeProseEditor.podspec +59 -0
- package/THIRD_PARTY_NOTICES.md +31155 -0
- package/android/build.gradle +188 -0
- package/android/consumer-rules.pro +18 -0
- package/android/expo/build.gradle +17 -0
- package/android/src/debug/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +7 -0
- package/android/src/main/assets/editor-icons/MaterialIcons.json +2236 -0
- package/android/src/main/assets/editor-icons/MaterialIcons.ttf +0 -0
- package/android/src/main/java/com/apollohg/editor/AndroidApiCompat.kt +19 -0
- package/android/src/main/java/com/apollohg/editor/AndroidCollaborationTransport.kt +860 -0
- package/android/src/main/java/com/apollohg/editor/CaretGeometry.kt +91 -0
- package/android/src/main/java/com/apollohg/editor/CodeHighlighting.kt +141 -0
- package/android/src/main/java/com/apollohg/editor/DecodedBitmapBudget.kt +250 -0
- package/android/src/main/java/com/apollohg/editor/EditorAddons.kt +133 -0
- package/android/src/main/java/com/apollohg/editor/EditorBlockSpacing.kt +51 -0
- package/android/src/main/java/com/apollohg/editor/EditorBoxDrawable.kt +16 -0
- package/android/src/main/java/com/apollohg/editor/EditorBoxDrawing.kt +234 -0
- package/android/src/main/java/com/apollohg/editor/EditorCheckboxSpan.kt +87 -0
- package/android/src/main/java/com/apollohg/editor/EditorCodeHighlighting.kt +120 -0
- package/android/src/main/java/com/apollohg/editor/EditorDecorationLayer.java +18 -0
- package/android/src/main/java/com/apollohg/editor/EditorDocumentLayout.kt +626 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +1042 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextAnnotations.kt +191 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextCaret.kt +100 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextClipboard.kt +101 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextComposition.kt +220 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextConfiguration.kt +316 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextCorrection.kt +303 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDeferredUpdates.kt +327 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDeletion.kt +258 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDiagnostics.kt +83 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextDragDrop.kt +67 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextExternalComposition.kt +357 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextHardwareInput.kt +277 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +280 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextInputLifecycle.kt +183 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextInputPreparation.kt +79 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextInputTraits.kt +384 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextLayout.kt +100 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextNativeMutation.kt +243 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextPlaceholder.kt +154 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextRenderPatch.kt +347 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextRendering.kt +313 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextRustCommands.kt +281 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextSelection.kt +352 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextState.kt +113 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextTaskMarkers.kt +92 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextTextCommit.kt +327 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextToolbar.kt +84 -0
- package/android/src/main/java/com/apollohg/editor/EditorEditTextUpdates.kt +245 -0
- package/android/src/main/java/com/apollohg/editor/EditorGlyphHeightCursorDrawable.kt +42 -0
- package/android/src/main/java/com/apollohg/editor/EditorHeightBehavior.kt +13 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputConnection.kt +923 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputCoordinates.kt +191 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputCorrection.kt +107 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputCursorGeometry.kt +128 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputSnapshots.kt +134 -0
- package/android/src/main/java/com/apollohg/editor/EditorInputSurroundingDeletion.kt +321 -0
- package/android/src/main/java/com/apollohg/editor/EditorKeyboardToolbarView.kt +851 -0
- package/android/src/main/java/com/apollohg/editor/EditorMentionStyle.kt +192 -0
- package/android/src/main/java/com/apollohg/editor/EditorReconciliationWatcher.kt +46 -0
- package/android/src/main/java/com/apollohg/editor/EditorStyleSheet.kt +303 -0
- package/android/src/main/java/com/apollohg/editor/EditorStyleSheetSpans.kt +253 -0
- package/android/src/main/java/com/apollohg/editor/EditorSurfaceInputConnection.kt +67 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextDecorationDrawing.kt +143 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextSurface.kt +712 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceDragDrop.kt +94 -0
- package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceInteraction.kt +708 -0
- package/android/src/main/java/com/apollohg/editor/EditorTheme.kt +650 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Adapter.kt +912 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2AdapterMutations.kt +402 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2AdapterRendering.kt +123 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2AdapterSelection.kt +203 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Backend.kt +120 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Driver.kt +87 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2Registry.kt +97 -0
- package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +409 -0
- package/android/src/main/java/com/apollohg/editor/ExpoAutoGrowStyleSizePublisher.kt +34 -0
- package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +266 -0
- package/android/src/main/java/com/apollohg/editor/ImeTextCoordinateMapper.kt +102 -0
- package/android/src/main/java/com/apollohg/editor/KeyboardToolbarImeAnimationController.kt +101 -0
- package/android/src/main/java/com/apollohg/editor/MentionSuggestionChipView.kt +234 -0
- package/android/src/main/java/com/apollohg/editor/NativeCollaborationTransportRegistry.kt +493 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +813 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewAtoms.kt +68 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewBinding.kt +126 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewDiagnostics.kt +208 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewErrors.kt +146 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewEvents.kt +150 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewExternalComposition.kt +39 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewFocus.kt +176 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewLifecycle.kt +302 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewMentions.kt +259 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewNativeActions.kt +179 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewOutsideTap.kt +214 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPendingUpdates.kt +376 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewProperties.kt +234 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPropertyRetries.kt +197 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewToolbar.kt +285 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewTypes.kt +28 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewUpdates.kt +271 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +687 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorOutsideTapDispatcher.kt +380 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorV2Numbers.kt +45 -0
- package/android/src/main/java/com/apollohg/editor/NativeEditorViewRegistry.kt +372 -0
- package/android/src/main/java/com/apollohg/editor/NativeImagePipeline.kt +22 -0
- package/android/src/main/java/com/apollohg/editor/NativeToolbar.kt +193 -0
- package/android/src/main/java/com/apollohg/editor/NativeToolbarIcons.kt +177 -0
- package/android/src/main/java/com/apollohg/editor/NativeToolbarItem.kt +274 -0
- package/android/src/main/java/com/apollohg/editor/OkHttpCollaborationSocket.kt +102 -0
- package/android/src/main/java/com/apollohg/editor/OrderedListMarkerFormatter.kt +130 -0
- package/android/src/main/java/com/apollohg/editor/PointerTransparentView.java +18 -0
- package/android/src/main/java/com/apollohg/editor/PositionBridge.kt +128 -0
- package/android/src/main/java/com/apollohg/editor/ProseViewerView.kt +854 -0
- package/android/src/main/java/com/apollohg/editor/RemoteSelectionOverlayView.kt +314 -0
- package/android/src/main/java/com/apollohg/editor/RenderBlockSpans.kt +314 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridge.kt +224 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeBlockStyles.kt +407 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeElements.kt +544 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeInlineAndAtoms.kt +631 -0
- package/android/src/main/java/com/apollohg/editor/RenderBridgeParagraphs.kt +215 -0
- package/android/src/main/java/com/apollohg/editor/RenderImageDecoder.kt +748 -0
- package/android/src/main/java/com/apollohg/editor/RenderImageLoader.kt +900 -0
- package/android/src/main/java/com/apollohg/editor/RenderLayoutConstants.kt +117 -0
- package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +337 -0
- package/android/src/main/java/com/apollohg/editor/RenderParagraphSpans.kt +182 -0
- package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +951 -0
- package/android/src/main/java/com/apollohg/editor/SharedNativeImagePipeline.kt +78 -0
- package/android/src/main/java/com/apollohg/editor/UniffiEditorV2Backend.kt +261 -0
- package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1656 -0
- package/android/src/main/java/com/apollohg/editor/viewer/FabricAttachmentSidecars.kt +80 -0
- package/android/src/main/java/com/apollohg/editor/viewer/FabricLeaseHandleBridge.kt +59 -0
- package/android/src/main/java/com/apollohg/editor/viewer/FallbackSelectionGeometry.kt +450 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseDrawingView.kt +678 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseInstrumentation.kt +608 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayout.kt +186 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutCache.kt +393 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutRegistry.kt +828 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseTheme.kt +316 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerManager.kt +900 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerPackage.kt +16 -0
- package/android/src/main/java/com/apollohg/editor/viewer/PreparedViewerAtoms.kt +89 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerCodeHighlighting.kt +91 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerDocument.kt +453 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerFontEnvironment.kt +282 -0
- package/android/src/main/java/com/apollohg/editor/viewer/ViewerImagePipeline.kt +460 -0
- package/android/src/main/jni/CMakeLists.txt +85 -0
- package/android/src/main/jni/PreparedProseViewerMeasurementsManager.cpp +334 -0
- package/android/src/main/jni/ReactNativeProseEditorSpec.h +17 -0
- package/android/src/main/jni/reactnativeproseeditor.h +6 -0
- package/android/src/main/res/values/attrs.xml +6 -0
- package/android/src/release/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +9 -0
- package/app.plugin.js +62 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseMeasurementsManager.h +62 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerComponentDescriptor.h +30 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.cpp +192 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.h +46 -0
- package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerState.h +145 -0
- package/dist/AtomHost.d.ts +17 -0
- package/dist/AtomHost.js +135 -0
- package/dist/DefaultAtomChip.d.ts +2 -0
- package/dist/DefaultAtomChip.js +22 -0
- package/dist/EditorAddon.d.ts +32 -0
- package/dist/EditorAddon.js +29 -0
- package/dist/EditorAddonNormalization.d.ts +6 -0
- package/dist/EditorAddonNormalization.js +48 -0
- package/dist/EditorMentionThemeNormalization.d.ts +8 -0
- package/dist/EditorMentionThemeNormalization.js +22 -0
- package/dist/EditorMentionThemeValidation.d.ts +12 -0
- package/dist/EditorMentionThemeValidation.js +95 -0
- package/dist/EditorStyleSheet.d.ts +4 -0
- package/dist/EditorStyleSheet.js +10 -0
- package/dist/EditorStyleSheetNormalization.d.ts +3 -0
- package/dist/EditorStyleSheetNormalization.js +226 -0
- package/dist/EditorStyleSheetTypes.d.ts +151 -0
- package/dist/EditorStyleSheetTypes.js +2 -0
- package/dist/EditorTheme.d.ts +117 -0
- package/dist/EditorTheme.js +41 -0
- package/dist/EditorToolbar.d.ts +4 -0
- package/dist/EditorToolbar.js +17 -0
- package/dist/EditorToolbarComponent.d.ts +13 -0
- package/dist/EditorToolbarComponent.js +24 -0
- package/dist/EditorToolbarItems.d.ts +9 -0
- package/dist/EditorToolbarItems.js +58 -0
- package/dist/EditorToolbarRegistry.d.ts +59 -0
- package/dist/EditorToolbarRegistry.js +175 -0
- package/dist/EditorToolbarTypes.d.ts +273 -0
- package/dist/EditorToolbarTypes.js +2 -0
- package/dist/EditorToolbarVisuals.d.ts +154 -0
- package/dist/EditorToolbarVisuals.js +228 -0
- package/dist/EditorUpdateRevision.d.ts +8 -0
- package/dist/EditorUpdateRevision.js +22 -0
- package/dist/ExternalTextComposition.d.ts +45 -0
- package/dist/ExternalTextComposition.js +537 -0
- package/dist/ImageLoadingPolicy.d.ts +54 -0
- package/dist/ImageLoadingPolicy.js +60 -0
- package/dist/NativeEditorBoundaryError.d.ts +111 -0
- package/dist/NativeEditorBoundaryError.js +268 -0
- package/dist/NativeEditorBridge.d.ts +9 -0
- package/dist/NativeEditorBridge.js +37 -0
- package/dist/NativeEditorCollaborationTransport.d.ts +154 -0
- package/dist/NativeEditorCollaborationTransport.js +275 -0
- package/dist/NativeEditorCreateConfig.d.ts +16 -0
- package/dist/NativeEditorCreateConfig.js +249 -0
- package/dist/NativeEditorCreateJson.d.ts +76 -0
- package/dist/NativeEditorCreateJson.js +474 -0
- package/dist/NativeEditorCreateValidation.d.ts +32 -0
- package/dist/NativeEditorCreateValidation.js +150 -0
- package/dist/NativeEditorDocumentBridge.d.ts +72 -0
- package/dist/NativeEditorDocumentBridge.js +305 -0
- package/dist/NativeEditorDocumentHandle.d.ts +70 -0
- package/dist/NativeEditorDocumentHandle.js +89 -0
- package/dist/NativeEditorLocalAwareness.d.ts +34 -0
- package/dist/NativeEditorLocalAwareness.js +153 -0
- package/dist/NativeEditorNativeModule.d.ts +48 -0
- package/dist/NativeEditorNativeModule.js +34 -0
- package/dist/NativeEditorRenderNormalization.d.ts +22 -0
- package/dist/NativeEditorRenderNormalization.js +274 -0
- package/dist/NativeEditorResultNormalization.d.ts +108 -0
- package/dist/NativeEditorResultNormalization.js +400 -0
- package/dist/NativeEditorTypes.d.ts +318 -0
- package/dist/NativeEditorTypes.js +15 -0
- package/dist/NativeEditorV2Decimal.d.ts +5 -0
- package/dist/NativeEditorV2Decimal.js +18 -0
- package/dist/NativeProseViewer.d.ts +122 -0
- package/dist/NativeProseViewer.js +130 -0
- package/dist/NativeRichTextEditor.d.ts +3 -0
- package/dist/NativeRichTextEditor.js +6 -0
- package/dist/ResourceLimits.d.ts +100 -0
- package/dist/ResourceLimits.js +80 -0
- package/dist/RichTextEditor.d.ts +4 -0
- package/dist/RichTextEditor.js +25 -0
- package/dist/RichTextEditorNativeTypes.d.ts +122 -0
- package/dist/RichTextEditorNativeTypes.js +2 -0
- package/dist/RichTextEditorNativeView.d.ts +12 -0
- package/dist/RichTextEditorNativeView.js +15 -0
- package/dist/RichTextEditorSerialization.d.ts +53 -0
- package/dist/RichTextEditorSerialization.js +283 -0
- package/dist/RichTextEditorTypes.d.ts +281 -0
- package/dist/RichTextEditorTypes.js +2 -0
- package/dist/ViewerConfiguration.d.ts +22 -0
- package/dist/ViewerConfiguration.js +6 -0
- package/dist/YjsCollaboration.d.ts +146 -0
- package/dist/YjsCollaboration.js +496 -0
- package/dist/addons.d.ts +193 -0
- package/dist/addons.js +122 -0
- package/dist/atomConstants.d.ts +3 -0
- package/dist/atomConstants.js +6 -0
- package/dist/atomInstances.d.ts +35 -0
- package/dist/atomInstances.js +79 -0
- package/dist/atomPolicy.d.ts +4 -0
- package/dist/atomPolicy.js +47 -0
- package/dist/atomUpdates.d.ts +2 -0
- package/dist/atomUpdates.js +38 -0
- package/dist/atoms.d.ts +92 -0
- package/dist/atoms.js +222 -0
- package/dist/attributeValidation.d.ts +4 -0
- package/dist/attributeValidation.js +97 -0
- package/dist/contentExpression.d.ts +6 -0
- package/dist/contentExpression.js +335 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +78 -0
- package/dist/listMarkers.d.ts +15 -0
- package/dist/listMarkers.js +21 -0
- package/dist/schemaDefinition.d.ts +143 -0
- package/dist/schemaDefinition.js +206 -0
- package/dist/schemaDocument.d.ts +17 -0
- package/dist/schemaDocument.js +69 -0
- package/dist/schemaDocumentConstruction.d.ts +5 -0
- package/dist/schemaDocumentConstruction.js +125 -0
- package/dist/schemaNormalization.d.ts +29 -0
- package/dist/schemaNormalization.js +313 -0
- package/dist/schemaPresets.d.ts +68 -0
- package/dist/schemaPresets.js +198 -0
- package/dist/schemaResolution.d.ts +9 -0
- package/dist/schemaResolution.js +211 -0
- package/dist/schemas.d.ts +5 -0
- package/dist/schemas.js +28 -0
- package/dist/specs/PreparedProseViewerNativeComponent.d.ts +37 -0
- package/dist/specs/PreparedProseViewerNativeComponent.js +6 -0
- package/dist/useEditorToolbarInteractions.d.ts +12 -0
- package/dist/useEditorToolbarInteractions.js +218 -0
- package/dist/useEditorToolbarItems.d.ts +8 -0
- package/dist/useEditorToolbarItems.js +280 -0
- package/dist/useEditorToolbarPresentation.d.ts +4 -0
- package/dist/useEditorToolbarPresentation.js +203 -0
- package/dist/useEditorToolbarState.d.ts +63 -0
- package/dist/useEditorToolbarState.js +108 -0
- package/dist/useFocusPreservingFrames.d.ts +17 -0
- package/dist/useFocusPreservingFrames.js +108 -0
- package/dist/useNativeEditor.d.ts +66 -0
- package/dist/useNativeEditor.js +370 -0
- package/dist/useRichTextEditorCommands.d.ts +21 -0
- package/dist/useRichTextEditorCommands.js +299 -0
- package/dist/useRichTextEditorEvents.d.ts +18 -0
- package/dist/useRichTextEditorEvents.js +216 -0
- package/dist/useRichTextEditorMentions.d.ts +11 -0
- package/dist/useRichTextEditorMentions.js +316 -0
- package/dist/useRichTextEditorPresentation.d.ts +5 -0
- package/dist/useRichTextEditorPresentation.js +178 -0
- package/dist/useRichTextEditorState.d.ts +180 -0
- package/dist/useRichTextEditorState.js +405 -0
- package/dist/useRichTextEditorUpdates.d.ts +10 -0
- package/dist/useRichTextEditorUpdates.js +308 -0
- package/dist/useViewerAtoms.d.ts +38 -0
- package/dist/useViewerAtoms.js +288 -0
- package/expo-module.config.json +13 -0
- package/ios/EditorAddons.swift +354 -0
- package/ios/EditorCodeHighlighting.swift +184 -0
- package/ios/EditorCore.xcframework/Info.plist +44 -0
- 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/ios/EditorInteractionOverlays.swift +697 -0
- package/ios/EditorLayoutManager.swift +971 -0
- package/ios/EditorNodeTypes.swift +37 -0
- package/ios/EditorStyleSheet.swift +461 -0
- package/ios/EditorTextView+AttributedPatch.swift +305 -0
- package/ios/EditorTextView+Binding.swift +61 -0
- package/ios/EditorTextView+Caret.swift +333 -0
- package/ios/EditorTextView+Commands.swift +203 -0
- package/ios/EditorTextView+Delegate.swift +65 -0
- package/ios/EditorTextView+Diagnostics.swift +225 -0
- package/ios/EditorTextView+DragDrop.swift +290 -0
- package/ios/EditorTextView+ExternalComposition.swift +364 -0
- package/ios/EditorTextView+Images.swift +354 -0
- package/ios/EditorTextView+InputTraits.swift +200 -0
- package/ios/EditorTextView+KeyboardInput.swift +318 -0
- package/ios/EditorTextView+Layout.swift +245 -0
- package/ios/EditorTextView+MarkedText.swift +267 -0
- package/ios/EditorTextView+NativeInputLifecycle.swift +372 -0
- package/ios/EditorTextView+NativeMutation.swift +471 -0
- package/ios/EditorTextView+Reconciliation.swift +97 -0
- package/ios/EditorTextView+RenderPatch.swift +573 -0
- package/ios/EditorTextView+Rendering.swift +539 -0
- package/ios/EditorTextView+Selection.swift +542 -0
- package/ios/EditorTextView.swift +953 -0
- package/ios/EditorTheme.swift +626 -0
- package/ios/EditorV2Adapter+Commands.swift +204 -0
- package/ios/EditorV2Adapter+Envelope.swift +238 -0
- package/ios/EditorV2Adapter+Mutation.swift +392 -0
- package/ios/EditorV2Adapter+Registry.swift +185 -0
- package/ios/EditorV2Adapter+RenderState.swift +360 -0
- package/ios/EditorV2Adapter+RenderValidation.swift +420 -0
- package/ios/EditorV2Adapter+Selection.swift +329 -0
- package/ios/EditorV2Adapter+TextCommands.swift +430 -0
- package/ios/EditorV2Adapter.swift +376 -0
- package/ios/EditorV2Shadow.swift +353 -0
- package/ios/Generated_editor_core.swift +2378 -0
- package/ios/NativeCodeHighlighting.swift +159 -0
- package/ios/NativeCollaborationSocket.swift +144 -0
- package/ios/NativeCollaborationTransport+Protocol.swift +258 -0
- package/ios/NativeCollaborationTransport+Socket.swift +379 -0
- package/ios/NativeCollaborationTransport+Validation.swift +103 -0
- package/ios/NativeCollaborationTransport.swift +322 -0
- package/ios/NativeCollaborationTransportRegistry.swift +521 -0
- package/ios/NativeEditorExpoView+AccessoryRetry.swift +219 -0
- package/ios/NativeEditorExpoView+Binding.swift +268 -0
- package/ios/NativeEditorExpoView+Diagnostics.swift +66 -0
- package/ios/NativeEditorExpoView+Events.swift +131 -0
- package/ios/NativeEditorExpoView+Focus.swift +169 -0
- package/ios/NativeEditorExpoView+MentionRetry.swift +288 -0
- package/ios/NativeEditorExpoView+Mentions.swift +288 -0
- package/ios/NativeEditorExpoView+Properties.swift +300 -0
- package/ios/NativeEditorExpoView+Toolbar.swift +86 -0
- package/ios/NativeEditorExpoView+Updates.swift +312 -0
- package/ios/NativeEditorExpoView.swift +349 -0
- package/ios/NativeEditorModule.swift +856 -0
- package/ios/NativeEditorViewRegistry.swift +226 -0
- package/ios/NativeToolbar+ButtonStyle.swift +214 -0
- package/ios/NativeToolbar+Buttons.swift +228 -0
- package/ios/NativeToolbar+Diagnostics.swift +114 -0
- package/ios/NativeToolbar+Menu.swift +101 -0
- package/ios/NativeToolbar+Models.swift +519 -0
- package/ios/NativeToolbar+Placeholder.swift +39 -0
- package/ios/NativeToolbar.swift +612 -0
- package/ios/OrderedListMarkerFormatter.swift +103 -0
- package/ios/PositionBridge.swift +596 -0
- package/ios/ProseViewerView.swift +462 -0
- package/ios/RenderBridge+Atoms.swift +288 -0
- package/ios/RenderBridge+Attachments.swift +246 -0
- package/ios/RenderBridge+BlockBoundaries.swift +313 -0
- package/ios/RenderBridge+Style.swift +343 -0
- package/ios/RenderBridge.swift +704 -0
- package/ios/RichTextEditorView.swift +930 -0
- package/ios/SharedNativeImagePipeline+Cache.swift +189 -0
- package/ios/SharedNativeImagePipeline+Transport.swift +328 -0
- package/ios/SharedNativeImagePipeline.swift +533 -0
- package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +436 -0
- package/ios/Viewer/CoreTextProseLayoutEngine+Models.swift +322 -0
- package/ios/Viewer/CoreTextProseLayoutEngine.swift +635 -0
- package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.h +4 -0
- package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.mm +767 -0
- package/ios/Viewer/Fabric/PreparedProseMeasurementsManager.mm +118 -0
- package/ios/Viewer/NativeSVGImageDecoder.h +9 -0
- package/ios/Viewer/NativeSVGImageDecoder.mm +106 -0
- package/ios/Viewer/NativeSVGPreflight.h +11 -0
- package/ios/Viewer/NativeSVGPreflight.mm +219 -0
- package/ios/Viewer/PreparedProseDrawingView.swift +639 -0
- package/ios/Viewer/PreparedProseInstrumentation.swift +387 -0
- package/ios/Viewer/PreparedProseLayout.swift +326 -0
- package/ios/Viewer/PreparedProseLayoutCache.swift +766 -0
- package/ios/Viewer/PreparedProseLayoutRegistry+Artifacts.swift +377 -0
- package/ios/Viewer/PreparedProseLayoutRegistry+Fabric.swift +582 -0
- package/ios/Viewer/PreparedProseLayoutRegistry+FabricOwnership.swift +128 -0
- package/ios/Viewer/PreparedProseLayoutRegistry.swift +381 -0
- package/ios/Viewer/ViewerDocument.swift +575 -0
- package/ios/Viewer/ViewerFontEnvironment.swift +283 -0
- package/ios/Viewer/ViewerImagePipeline.swift +478 -0
- package/ios/editor_coreFFI/editor_coreFFI.h +1023 -0
- package/ios/editor_coreFFI/module.modulemap +7 -0
- package/package.json +151 -0
- package/react-native.config.js +17 -0
- 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/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +3146 -0
- package/src/AtomHost.tsx +180 -0
- package/src/DefaultAtomChip.tsx +27 -0
- package/src/EditorAddon.ts +65 -0
- package/src/EditorAddonNormalization.ts +49 -0
- package/src/EditorMentionThemeNormalization.ts +25 -0
- package/src/EditorMentionThemeValidation.ts +133 -0
- package/src/EditorStyleSheet.ts +9 -0
- package/src/EditorStyleSheetNormalization.ts +219 -0
- package/src/EditorStyleSheetTypes.ts +189 -0
- package/src/EditorTheme.ts +196 -0
- package/src/EditorToolbar.tsx +31 -0
- package/src/EditorToolbarComponent.tsx +23 -0
- package/src/EditorToolbarItems.tsx +64 -0
- package/src/EditorToolbarRegistry.tsx +254 -0
- package/src/EditorToolbarTypes.tsx +322 -0
- package/src/EditorToolbarVisuals.tsx +270 -0
- package/src/EditorUpdateRevision.ts +26 -0
- package/src/ExternalTextComposition.ts +658 -0
- package/src/ImageLoadingPolicy.ts +125 -0
- package/src/NativeEditorBoundaryError.ts +345 -0
- package/src/NativeEditorBridge.ts +93 -0
- package/src/NativeEditorCollaborationTransport.ts +493 -0
- package/src/NativeEditorCreateConfig.ts +326 -0
- package/src/NativeEditorCreateJson.ts +579 -0
- package/src/NativeEditorCreateValidation.ts +178 -0
- package/src/NativeEditorDocumentBridge.ts +485 -0
- package/src/NativeEditorDocumentHandle.ts +168 -0
- package/src/NativeEditorLocalAwareness.ts +168 -0
- package/src/NativeEditorNativeModule.ts +97 -0
- package/src/NativeEditorRenderNormalization.ts +320 -0
- package/src/NativeEditorResultNormalization.ts +469 -0
- package/src/NativeEditorTypes.ts +366 -0
- package/src/NativeEditorV2Decimal.ts +13 -0
- package/src/NativeProseViewer.tsx +356 -0
- package/src/NativeRichTextEditor.tsx +33 -0
- package/src/ResourceLimits.ts +187 -0
- package/src/RichTextEditor.tsx +27 -0
- package/src/RichTextEditorNativeTypes.tsx +144 -0
- package/src/RichTextEditorNativeView.tsx +21 -0
- package/src/RichTextEditorSerialization.tsx +381 -0
- package/src/RichTextEditorTypes.tsx +327 -0
- package/src/ViewerConfiguration.ts +23 -0
- package/src/YjsCollaboration.ts +692 -0
- package/src/addons.ts +311 -0
- package/src/atomConstants.ts +3 -0
- package/src/atomInstances.ts +123 -0
- package/src/atomPolicy.ts +47 -0
- package/src/atomUpdates.ts +52 -0
- package/src/atoms.ts +379 -0
- package/src/attributeValidation.ts +116 -0
- package/src/contentExpression.ts +338 -0
- package/src/index.ts +295 -0
- package/src/listMarkers.ts +18 -0
- package/src/schemaDefinition.ts +395 -0
- package/src/schemaDocument.ts +92 -0
- package/src/schemaDocumentConstruction.ts +148 -0
- package/src/schemaNormalization.ts +367 -0
- package/src/schemaPresets.ts +250 -0
- package/src/schemaResolution.ts +242 -0
- package/src/schemas.ts +43 -0
- package/src/specs/PreparedProseViewerNativeComponent.ts +40 -0
- package/src/useEditorToolbarInteractions.tsx +329 -0
- package/src/useEditorToolbarItems.tsx +390 -0
- package/src/useEditorToolbarPresentation.tsx +483 -0
- package/src/useEditorToolbarState.tsx +172 -0
- package/src/useFocusPreservingFrames.ts +171 -0
- package/src/useNativeEditor.ts +534 -0
- package/src/useRichTextEditorCommands.tsx +478 -0
- package/src/useRichTextEditorEvents.tsx +342 -0
- package/src/useRichTextEditorMentions.tsx +441 -0
- package/src/useRichTextEditorPresentation.tsx +563 -0
- package/src/useRichTextEditorState.tsx +620 -0
- package/src/useRichTextEditorUpdates.tsx +403 -0
- package/src/useViewerAtoms.tsx +427 -0
|
@@ -0,0 +1,912 @@
|
|
|
1
|
+
package com.apollohg.editor
|
|
2
|
+
|
|
3
|
+
import org.json.JSONArray
|
|
4
|
+
import org.json.JSONObject
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The v2 adapter.
|
|
8
|
+
*
|
|
9
|
+
* Owns one v2 editor session (decimal-string handle) and translates the
|
|
10
|
+
* existing native view operations into typed v2 transactions/results. Every
|
|
11
|
+
* mutation is one typed transaction against the tracked base document
|
|
12
|
+
* revision. Transient IME/composing state never reaches the adapter — only
|
|
13
|
+
* final commits do.
|
|
14
|
+
*
|
|
15
|
+
* Render derivation: the v2 render accessor
|
|
16
|
+
* ([EditorV2Backend.renderUpdate] / [EditorV2Backend.resolveScalarSelection]
|
|
17
|
+
* / [EditorV2Backend.docToScalar] / [EditorV2Backend.scalarToDoc]) returns
|
|
18
|
+
* everything the view needs — full render blocks, toolbar active state, the
|
|
19
|
+
* mirrored scalar selection resolved to doc positions, and the lenient
|
|
20
|
+
* doc↔scalar mapping (including the document's scalar extent) — derived
|
|
21
|
+
* directly from the live v2 session.
|
|
22
|
+
*/
|
|
23
|
+
internal class EditorV2Adapter private constructor(
|
|
24
|
+
internal val backend: EditorV2Backend,
|
|
25
|
+
val editorId: String,
|
|
26
|
+
internal val roomBound: Boolean,
|
|
27
|
+
internal val collaborationWake: (String, CollaborationWakeReason) -> Unit
|
|
28
|
+
) : EditorV2Driver {
|
|
29
|
+
|
|
30
|
+
var onAutonomousError: ((EditorV2Error) -> Unit)? = null
|
|
31
|
+
|
|
32
|
+
private data class AutonomousErrorOwner(
|
|
33
|
+
val token: Long,
|
|
34
|
+
val callback: (EditorV2Error) -> Unit,
|
|
35
|
+
val onReleased: () -> Unit
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
/** One live native-view binding exclusively owns autonomous errors. */
|
|
39
|
+
private var autonomousErrorOwner: AutonomousErrorOwner? = null
|
|
40
|
+
|
|
41
|
+
var baseDocumentRevision: ULong = 0uL
|
|
42
|
+
internal set
|
|
43
|
+
|
|
44
|
+
/** Paired with [baseDocumentRevision] by the same locked render read. */
|
|
45
|
+
var stateRevision: ULong = 0uL
|
|
46
|
+
internal set
|
|
47
|
+
private var nextRequestId: ULong = 0uL
|
|
48
|
+
internal var nativeOwnerId: String? = null
|
|
49
|
+
private var nativeOwnerToken: Long? = null
|
|
50
|
+
internal var positionEpoch: String? = null
|
|
51
|
+
internal var lastRequestIdForTesting: ULong? = null
|
|
52
|
+
private set
|
|
53
|
+
internal var backendEnvelopeCallCountForTesting = 0
|
|
54
|
+
private set
|
|
55
|
+
internal var lastSyncedScalarSelection: IntArray? = null
|
|
56
|
+
internal var cachedAuthoritativeScalarSelection: IntArray? = null
|
|
57
|
+
internal var cachedScalarLength: Int? = null
|
|
58
|
+
internal var cachedActiveState: JSONObject? = null
|
|
59
|
+
internal var cachedHistoryState: JSONObject? = null
|
|
60
|
+
internal var cachedViewUpdateJson: String? = null
|
|
61
|
+
internal var cachedAtomicRenderJson: String? = null
|
|
62
|
+
internal var cachedAtomicRenderDocumentRevision: ULong? = null
|
|
63
|
+
internal var renderUpdateCallCountForTesting = 0
|
|
64
|
+
internal set
|
|
65
|
+
internal var destroyed = false
|
|
66
|
+
|
|
67
|
+
/** Diagnostics for handled paths that never surface as error events. */
|
|
68
|
+
val debugNotes = mutableListOf<String>()
|
|
69
|
+
|
|
70
|
+
companion object {
|
|
71
|
+
/**
|
|
72
|
+
* Attach to an existing v2 session created through the module's
|
|
73
|
+
* JS-facing `editorV2Create` entry. The session is NOT re-created;
|
|
74
|
+
* the adapter routes the bound view's interactions through the
|
|
75
|
+
* shared session (the TS document handle and collaboration
|
|
76
|
+
* controller drive the same session over the module surface).
|
|
77
|
+
*/
|
|
78
|
+
fun attach(
|
|
79
|
+
backend: EditorV2Backend,
|
|
80
|
+
editorId: String,
|
|
81
|
+
roomBound: Boolean,
|
|
82
|
+
collaborationWake: (String, CollaborationWakeReason) -> Unit = { id, reason ->
|
|
83
|
+
NativeCollaborationTransportRegistry.notifyOutboundAvailable(id, reason)
|
|
84
|
+
}
|
|
85
|
+
): EditorV2Adapter? {
|
|
86
|
+
if (!isCanonicalDecimalEditorId(editorId)) return null
|
|
87
|
+
// Attachment establishes only that the handle is live. The first
|
|
88
|
+
// render adopts the revision, scalar extent, selection, active,
|
|
89
|
+
// and history caches as one locked snapshot before input resumes.
|
|
90
|
+
if (backend.getState(editorId) !is EditorV2CallResult.Ok) return null
|
|
91
|
+
return EditorV2Adapter(backend, editorId, roomBound, collaborationWake)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private fun isCanonicalDecimalEditorId(editorId: String): Boolean = editorId.isNotEmpty() &&
|
|
95
|
+
editorId.all { it in '0'..'9' } &&
|
|
96
|
+
(editorId == "0" || editorId.first() != '0') &&
|
|
97
|
+
editorId.toULongOrNull() != null
|
|
98
|
+
|
|
99
|
+
fun contractError(message: String): EditorV2Error =
|
|
100
|
+
EditorV2Error(domain = "boundary", code = "FFI_RESULT_INVALID", message = message)
|
|
101
|
+
|
|
102
|
+
internal fun destroyedError(): EditorV2Error = EditorV2Error(
|
|
103
|
+
domain = "lifecycle",
|
|
104
|
+
code = "ENGINE_DESTROYED",
|
|
105
|
+
message = "editor session is destroyed"
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fun destroy(): EditorV2Error? {
|
|
110
|
+
if (destroyed) return null
|
|
111
|
+
nativeOwnerId?.let { backend.releaseNativeBinding(editorId, it) }
|
|
112
|
+
nativeOwnerId = null
|
|
113
|
+
nativeOwnerToken = null
|
|
114
|
+
positionEpoch = null
|
|
115
|
+
destroyed = true
|
|
116
|
+
val error = backend.destroy(editorId) ?: return null
|
|
117
|
+
if (error.code == "ENGINE_DESTROYED" || error.code == "ENGINE_DESTROYING") return null
|
|
118
|
+
return error
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun requestIdExhaustedError(): EditorV2Error = EditorV2Error(
|
|
122
|
+
domain = "boundary",
|
|
123
|
+
code = "CONFIG_INVALID",
|
|
124
|
+
message = "v2 request id counter exhausted",
|
|
125
|
+
requestId = nextRequestId.toString(),
|
|
126
|
+
limit = ULong.MAX_VALUE.toString()
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
private fun buildEnvelope(
|
|
130
|
+
payload: JSONObject,
|
|
131
|
+
includeBaseRevision: Boolean = true
|
|
132
|
+
): EditorV2CallResult<String> {
|
|
133
|
+
if (nextRequestId == ULong.MAX_VALUE) {
|
|
134
|
+
return EditorV2CallResult.Err(requestIdExhaustedError())
|
|
135
|
+
}
|
|
136
|
+
nextRequestId += 1u
|
|
137
|
+
lastRequestIdForTesting = nextRequestId
|
|
138
|
+
val parts = mutableListOf(
|
|
139
|
+
"\"version\":1",
|
|
140
|
+
"\"requestId\":${JSONObject.quote(nextRequestId.toString())}"
|
|
141
|
+
)
|
|
142
|
+
if (includeBaseRevision) {
|
|
143
|
+
parts.add(
|
|
144
|
+
"\"baseDocumentRevision\":${JSONObject.quote(baseDocumentRevision.toString())}"
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
val payloadJson = payload.toString()
|
|
148
|
+
if (payloadJson.length > 2) {
|
|
149
|
+
parts.add(payloadJson.substring(1, payloadJson.length - 1))
|
|
150
|
+
}
|
|
151
|
+
return EditorV2CallResult.Ok(
|
|
152
|
+
parts.joinToString(separator = ",", prefix = "{", postfix = "}")
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
internal fun callWithEnvelope(
|
|
157
|
+
payload: JSONObject,
|
|
158
|
+
includeBaseRevision: Boolean = true,
|
|
159
|
+
call: (String) -> EditorV2CallResult<String>
|
|
160
|
+
): EditorV2CallResult<String> =
|
|
161
|
+
when (val envelope = buildEnvelope(payload, includeBaseRevision)) {
|
|
162
|
+
is EditorV2CallResult.Err -> envelope
|
|
163
|
+
|
|
164
|
+
is EditorV2CallResult.Ok -> {
|
|
165
|
+
backendEnvelopeCallCountForTesting += 1
|
|
166
|
+
call(envelope.value)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
internal fun setNextRequestIdForTesting(requestId: ULong) {
|
|
171
|
+
nextRequestId = requestId
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private fun positionEnvelope(scalar: Int, affinity: String? = null): JSONObject {
|
|
175
|
+
val envelope = JSONObject().put("offset", scalar).put("kind", "scalar")
|
|
176
|
+
if (affinity != null) envelope.put("affinity", affinity)
|
|
177
|
+
return envelope
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
internal fun selectionEnvelope(anchor: Int, head: Int, affinity: String): JSONObject =
|
|
181
|
+
JSONObject().put(
|
|
182
|
+
"selection",
|
|
183
|
+
JSONObject()
|
|
184
|
+
.put("type", "text")
|
|
185
|
+
.put("anchor", positionEnvelope(anchor, affinity))
|
|
186
|
+
.put("head", positionEnvelope(head, affinity))
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
internal fun bindAutonomousErrorOwner(
|
|
190
|
+
token: Long,
|
|
191
|
+
callback: (EditorV2Error) -> Unit,
|
|
192
|
+
onReleased: () -> Unit
|
|
193
|
+
) {
|
|
194
|
+
val displaced = synchronized(this) {
|
|
195
|
+
autonomousErrorOwner.also {
|
|
196
|
+
autonomousErrorOwner = AutonomousErrorOwner(token, callback, onReleased)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
claimNativeBinding(token, replaceExisting = true)
|
|
200
|
+
displaced?.onReleased?.invoke()
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
internal fun claimNativeBindingIfUnowned(token: Long) {
|
|
204
|
+
claimNativeBinding(token, replaceExisting = false)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
internal fun isNativeBindingOwner(token: Long): Boolean = synchronized(this) {
|
|
208
|
+
nativeOwnerToken == token
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private fun claimNativeBinding(token: Long, replaceExisting: Boolean) {
|
|
212
|
+
val releasedOwner = synchronized(this) {
|
|
213
|
+
if (!replaceExisting && nativeOwnerToken != null) return
|
|
214
|
+
if (nativeOwnerToken == token) return
|
|
215
|
+
nativeOwnerId.also {
|
|
216
|
+
nativeOwnerToken = token
|
|
217
|
+
nativeOwnerId = token.toString()
|
|
218
|
+
positionEpoch = null
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
releasedOwner?.let { backend.releaseNativeBinding(editorId, it) }
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
internal fun releaseNativeBindingOwner(token: Long) {
|
|
225
|
+
val releasedOwner = synchronized(this) {
|
|
226
|
+
if (nativeOwnerToken != token) return
|
|
227
|
+
nativeOwnerToken = null
|
|
228
|
+
positionEpoch = null
|
|
229
|
+
nativeOwnerId.also { nativeOwnerId = null }
|
|
230
|
+
}
|
|
231
|
+
releasedOwner?.let { backend.releaseNativeBinding(editorId, it) }
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** A stale view may clear only its own binding generation. */
|
|
235
|
+
internal fun clearAutonomousErrorOwner(token: Long) {
|
|
236
|
+
val released = synchronized(this) {
|
|
237
|
+
if (autonomousErrorOwner?.token == token) {
|
|
238
|
+
autonomousErrorOwner = null
|
|
239
|
+
true
|
|
240
|
+
} else {
|
|
241
|
+
false
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (released) releaseNativeBindingOwner(token)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** Pair release invalidates the final owner even when no view remains registered. */
|
|
248
|
+
internal fun releaseAutonomousErrorOwner() {
|
|
249
|
+
val released = synchronized(this) {
|
|
250
|
+
autonomousErrorOwner.also {
|
|
251
|
+
autonomousErrorOwner = null
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
released?.let { releaseNativeBindingOwner(it.token) }
|
|
255
|
+
released?.onReleased?.invoke()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
internal fun ownsAutonomousErrorOwner(token: Long): Boolean = synchronized(this) {
|
|
259
|
+
autonomousErrorOwner?.token == token
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
internal fun emit(error: EditorV2Error) {
|
|
263
|
+
debugNotes.add("emit ${error.domain}/${error.code}: ${error.message}")
|
|
264
|
+
val callback = synchronized(this) {
|
|
265
|
+
autonomousErrorOwner?.callback ?: onAutonomousError
|
|
266
|
+
}
|
|
267
|
+
callback?.invoke(error)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
internal fun atomicRenderJson(matchingDocumentRevision: String): String? {
|
|
271
|
+
val revision = matchingDocumentRevision.toULongOrNull() ?: return null
|
|
272
|
+
if (cachedAtomicRenderDocumentRevision != revision) return null
|
|
273
|
+
return cachedAtomicRenderJson
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
@Volatile
|
|
277
|
+
internal var latestJSDrivenDocumentRevision: ULong = 0uL
|
|
278
|
+
|
|
279
|
+
private fun parseExternalReset(resetJson: String): JSONObject? {
|
|
280
|
+
val reset = try {
|
|
281
|
+
JSONObject(resetJson)
|
|
282
|
+
} catch (_: Exception) {
|
|
283
|
+
null
|
|
284
|
+
}
|
|
285
|
+
if (reset == null || reset.optString("history") != "resetAndClear" ||
|
|
286
|
+
reset.keys().asSequence().toSet() !=
|
|
287
|
+
setOf(
|
|
288
|
+
"history",
|
|
289
|
+
"documentRevision",
|
|
290
|
+
if (reset.has("setJson")) "setJson" else "setHtml"
|
|
291
|
+
) ||
|
|
292
|
+
(reset.opt("setJson") !is JSONObject && reset.opt("setHtml") !is String) ||
|
|
293
|
+
canonicalV2U64(reset.opt("documentRevision") as? String) == null
|
|
294
|
+
) {
|
|
295
|
+
emit(contractError("external reset intent is malformed"))
|
|
296
|
+
return null
|
|
297
|
+
}
|
|
298
|
+
return reset
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
internal fun validateExternalReset(resetJson: String): Boolean =
|
|
302
|
+
parseExternalReset(resetJson) != null
|
|
303
|
+
|
|
304
|
+
@Synchronized
|
|
305
|
+
internal fun adoptExternalReset(renderJson: String, resetJson: String): String? {
|
|
306
|
+
val reset = parseExternalReset(resetJson) ?: return null
|
|
307
|
+
val current = refreshFromRustState(null) ?: return null
|
|
308
|
+
if (parseAtomicRenderSnapshot(current)?.documentRevision ==
|
|
309
|
+
reset.getString("documentRevision").toULong()
|
|
310
|
+
) {
|
|
311
|
+
return adoptExternalRender(renderJson)
|
|
312
|
+
}
|
|
313
|
+
if (latestJSDrivenDocumentRevision >
|
|
314
|
+
reset.getString("documentRevision").toULong()
|
|
315
|
+
) {
|
|
316
|
+
return current
|
|
317
|
+
}
|
|
318
|
+
when (val result = backend.getState(editorId)) {
|
|
319
|
+
is EditorV2CallResult.Err -> {
|
|
320
|
+
emit(result.error)
|
|
321
|
+
return null
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
is EditorV2CallResult.Ok -> {
|
|
325
|
+
val origin = try {
|
|
326
|
+
JSONObject(result.value).getString("documentOrigin")
|
|
327
|
+
} catch (
|
|
328
|
+
_: Exception
|
|
329
|
+
) {
|
|
330
|
+
null
|
|
331
|
+
}
|
|
332
|
+
if (origin == null) {
|
|
333
|
+
emit(contractError("v2 reset state violates the frozen shape"))
|
|
334
|
+
return null
|
|
335
|
+
}
|
|
336
|
+
if (origin != "nativeView") return refreshFromRustState(null)
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
reset.remove("documentRevision")
|
|
340
|
+
return when (
|
|
341
|
+
val result = callWithEnvelope(reset, includeBaseRevision = false) { requestJson ->
|
|
342
|
+
backend.replaceDocument(editorId, requestJson)
|
|
343
|
+
}
|
|
344
|
+
) {
|
|
345
|
+
is EditorV2CallResult.Err -> {
|
|
346
|
+
emit(result.error)
|
|
347
|
+
null
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
is EditorV2CallResult.Ok -> {
|
|
351
|
+
val commit = try {
|
|
352
|
+
JSONObject(result.value)
|
|
353
|
+
} catch (_: Exception) {
|
|
354
|
+
null
|
|
355
|
+
}
|
|
356
|
+
if (commit?.opt("changed") !is Boolean ||
|
|
357
|
+
(commit.opt("documentRevision") as? String)?.toULongOrNull() == null
|
|
358
|
+
) {
|
|
359
|
+
emit(contractError("v2 reset result violates the frozen shape"))
|
|
360
|
+
return null
|
|
361
|
+
}
|
|
362
|
+
val update = refreshFromRustState(null) ?: return null
|
|
363
|
+
if (commit.getBoolean("changed")) {
|
|
364
|
+
publishCachedCollaborationSelection()
|
|
365
|
+
notifyCollaborationMutation()
|
|
366
|
+
}
|
|
367
|
+
update
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
internal fun adoptExternalRender(renderJson: String): String? {
|
|
373
|
+
if (destroyed) {
|
|
374
|
+
emit(destroyedError())
|
|
375
|
+
return null
|
|
376
|
+
}
|
|
377
|
+
val snapshot = parseAtomicRenderSnapshot(renderJson)
|
|
378
|
+
if (snapshot == null) {
|
|
379
|
+
emit(contractError("v2 atomic render snapshot violates the frozen shape"))
|
|
380
|
+
return null
|
|
381
|
+
}
|
|
382
|
+
val resolvedPositionEpoch = when {
|
|
383
|
+
snapshot.positionEpoch != null -> snapshot.positionEpoch
|
|
384
|
+
nativeOwnerId == null -> positionEpoch
|
|
385
|
+
else -> pinPositionEpochCandidate(snapshot.documentRevision) ?: return null
|
|
386
|
+
}
|
|
387
|
+
val pinned = PinnedAtomicRenderSnapshot(snapshot, resolvedPositionEpoch)
|
|
388
|
+
return adopt(
|
|
389
|
+
pinned.snapshot,
|
|
390
|
+
stripViewSelection = false,
|
|
391
|
+
engineOwnedSelection = true,
|
|
392
|
+
resolvedPositionEpoch = pinned.positionEpoch
|
|
393
|
+
)
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
internal fun validateExternalRender(renderJson: String): Boolean {
|
|
397
|
+
if (destroyed) {
|
|
398
|
+
emit(destroyedError())
|
|
399
|
+
return false
|
|
400
|
+
}
|
|
401
|
+
if (parseAtomicRenderSnapshot(renderJson) != null) return true
|
|
402
|
+
emit(contractError("v2 atomic render snapshot violates the frozen shape"))
|
|
403
|
+
return false
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
override fun refreshFromRustState(mirrorSelection: IntArray?): String? =
|
|
407
|
+
// This result crosses the controlled-prop boundary, which admits only
|
|
408
|
+
// complete frozen atomic render snapshots. Its parse/adopt side effect
|
|
409
|
+
// updates adapter caches, but its public result must retain every
|
|
410
|
+
// validated wire field, including selection and scalarLength.
|
|
411
|
+
refreshInternal(
|
|
412
|
+
mirrorSelection,
|
|
413
|
+
stripViewSelection = false,
|
|
414
|
+
controlledPropSnapshot = true
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
internal fun recoverNativeRender(): String? {
|
|
418
|
+
val ownerId = synchronized(this) {
|
|
419
|
+
positionEpoch = null
|
|
420
|
+
nativeOwnerId
|
|
421
|
+
}
|
|
422
|
+
ownerId?.let { backend.releaseNativeBinding(editorId, it) }
|
|
423
|
+
return refreshInternal(null, stripViewSelection = false)
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
override fun currentStateJson(): String? =
|
|
427
|
+
refreshInternal(cachedAuthoritativeScalarSelection?.copyOf(), stripViewSelection = false)
|
|
428
|
+
|
|
429
|
+
override fun documentHtml(): String? {
|
|
430
|
+
if (destroyed) return null
|
|
431
|
+
return when (val result = backend.getDocumentHtml(editorId)) {
|
|
432
|
+
is EditorV2CallResult.Err -> {
|
|
433
|
+
emit(result.error)
|
|
434
|
+
null
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
is EditorV2CallResult.Ok -> try {
|
|
438
|
+
JSONObject(result.value).getString("html")
|
|
439
|
+
} catch (error: Exception) {
|
|
440
|
+
emit(contractError("v2 getDocumentHtml value violates the frozen shape"))
|
|
441
|
+
null
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
override fun documentJson(): String? {
|
|
447
|
+
if (destroyed) return null
|
|
448
|
+
return fetchDocumentJson()
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
override fun contentSnapshotJson(): String? {
|
|
452
|
+
if (destroyed) return null
|
|
453
|
+
return when (val result = backend.getContentSnapshot(editorId)) {
|
|
454
|
+
is EditorV2CallResult.Err -> {
|
|
455
|
+
emit(result.error)
|
|
456
|
+
null
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
is EditorV2CallResult.Ok -> result.value
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
override fun historyCanUndo(): Boolean? =
|
|
464
|
+
cachedHistoryState?.let { exactBool(it.opt("canUndo")) }
|
|
465
|
+
|
|
466
|
+
override fun historyCanRedo(): Boolean? =
|
|
467
|
+
cachedHistoryState?.let { exactBool(it.opt("canRedo")) }
|
|
468
|
+
|
|
469
|
+
override fun selectionJson(): String? {
|
|
470
|
+
val update =
|
|
471
|
+
refreshInternal(
|
|
472
|
+
cachedAuthoritativeScalarSelection?.copyOf(),
|
|
473
|
+
stripViewSelection = false
|
|
474
|
+
)
|
|
475
|
+
?: return null
|
|
476
|
+
return try {
|
|
477
|
+
JSONObject(update).getJSONObject("selection").toString()
|
|
478
|
+
} catch (error: Exception) {
|
|
479
|
+
null
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
override fun syncSelection(anchor: Int, head: Int): EditorV2SelectionSync? {
|
|
484
|
+
if (destroyed) {
|
|
485
|
+
emit(destroyedError())
|
|
486
|
+
return null
|
|
487
|
+
}
|
|
488
|
+
if (nativeOwnerId != null) {
|
|
489
|
+
val previousDocumentRevision = baseDocumentRevision
|
|
490
|
+
val update =
|
|
491
|
+
performNativeIntent(nativeIntent("setSelection", anchor, head)).updateJsonOrNull()
|
|
492
|
+
?: return null
|
|
493
|
+
val mapping = textDocumentSelection(update) ?: return null
|
|
494
|
+
publishCollaborationSelection(mapping[0], mapping[1])
|
|
495
|
+
return EditorV2SelectionSync(
|
|
496
|
+
mapping[0],
|
|
497
|
+
mapping[1],
|
|
498
|
+
update.takeIf { baseDocumentRevision != previousDocumentRevision }
|
|
499
|
+
)
|
|
500
|
+
}
|
|
501
|
+
var refreshedUpdateJson: String? = null
|
|
502
|
+
val mapping = when (val outcome = ensureSelection(anchor, head)) {
|
|
503
|
+
is SelectionSyncOutcome.Ok -> resolveSelectionMapping(anchor, head)
|
|
504
|
+
|
|
505
|
+
is SelectionSyncOutcome.Refreshed -> {
|
|
506
|
+
refreshedUpdateJson = outcome.updateJson
|
|
507
|
+
textDocumentSelection(outcome.updateJson)
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
is SelectionSyncOutcome.Failed -> return null
|
|
511
|
+
}
|
|
512
|
+
if (mapping == null) return null
|
|
513
|
+
publishCollaborationSelection(mapping[0], mapping[1])
|
|
514
|
+
return EditorV2SelectionSync(mapping[0], mapping[1], refreshedUpdateJson)
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
override fun syncSelectionQuiet(anchor: Int, head: Int): String? {
|
|
518
|
+
if (destroyed) return null
|
|
519
|
+
if (nativeOwnerId != null) {
|
|
520
|
+
val previousDocumentRevision = baseDocumentRevision
|
|
521
|
+
val update =
|
|
522
|
+
performNativeIntent(nativeIntent("setSelection", anchor, head)).updateJsonOrNull()
|
|
523
|
+
?: return null
|
|
524
|
+
val mapping = textDocumentSelection(update) ?: return update
|
|
525
|
+
publishCollaborationSelection(mapping[0], mapping[1])
|
|
526
|
+
return update.takeIf { baseDocumentRevision != previousDocumentRevision }
|
|
527
|
+
}
|
|
528
|
+
var refreshedUpdateJson: String? = null
|
|
529
|
+
val mapping = when (val outcome = ensureSelection(anchor, head)) {
|
|
530
|
+
is SelectionSyncOutcome.Ok -> {
|
|
531
|
+
if (!roomBound) return null
|
|
532
|
+
val selection = lastSyncedScalarSelection ?: return null
|
|
533
|
+
resolveSelectionMapping(selection[0], selection[1])
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
is SelectionSyncOutcome.Refreshed -> {
|
|
537
|
+
refreshedUpdateJson = outcome.updateJson
|
|
538
|
+
textDocumentSelection(outcome.updateJson)
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
is SelectionSyncOutcome.Failed -> return null
|
|
542
|
+
} ?: return refreshedUpdateJson
|
|
543
|
+
publishCollaborationSelection(mapping[0], mapping[1])
|
|
544
|
+
return refreshedUpdateJson
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
override fun scalarPositionForDoc(docPos: Int): Int? =
|
|
548
|
+
mapPosition(backend.docToScalar(editorId, docPos), "scalar")
|
|
549
|
+
|
|
550
|
+
override fun docPositionForScalar(scalar: Int): Int? =
|
|
551
|
+
mapPosition(backend.scalarToDoc(editorId, scalar), "doc")
|
|
552
|
+
|
|
553
|
+
override fun insertText(text: String, atScalarPos: Int): String? {
|
|
554
|
+
if (text.isEmpty()) return currentStateJson()
|
|
555
|
+
if (nativeOwnerId != null) {
|
|
556
|
+
return performNativeIntent(
|
|
557
|
+
nativeIntent("insertText", atScalarPos, atScalarPos).put("text", text)
|
|
558
|
+
).updateJsonOrNull()
|
|
559
|
+
}
|
|
560
|
+
val postCaret = atScalarPos + text.codePointCount(0, text.length)
|
|
561
|
+
return performMutation(
|
|
562
|
+
preSelection = intArrayOf(atScalarPos, atScalarPos),
|
|
563
|
+
postSelectionMirror = intArrayOf(postCaret, postCaret),
|
|
564
|
+
includeSelectionInUpdate = true
|
|
565
|
+
) {
|
|
566
|
+
callWithEnvelope(JSONObject().put("text", text)) { requestJson ->
|
|
567
|
+
backend.applyInput(editorId, requestJson)
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
override fun replaceTextRange(scalarFrom: Int, scalarTo: Int, text: String): String? {
|
|
573
|
+
if (text.isEmpty()) {
|
|
574
|
+
return deleteScalarRange(scalarFrom, scalarTo)
|
|
575
|
+
}
|
|
576
|
+
if (nativeOwnerId != null) {
|
|
577
|
+
return performNativeIntent(
|
|
578
|
+
nativeIntent("replaceSelectionText", scalarFrom, scalarTo).put("text", text)
|
|
579
|
+
).updateJsonOrNull()
|
|
580
|
+
}
|
|
581
|
+
val postCaret = scalarFrom + text.codePointCount(0, text.length)
|
|
582
|
+
// A range-replacing commit (autocorrect, paste-over-selection, IME
|
|
583
|
+
// commit over a composing range) is ONE typed ReplaceSelectionText
|
|
584
|
+
// transaction: the planner's InsertText is collapsed-only.
|
|
585
|
+
return performMutation(
|
|
586
|
+
preSelection = intArrayOf(scalarFrom, scalarTo),
|
|
587
|
+
postSelectionMirror = intArrayOf(postCaret, postCaret),
|
|
588
|
+
includeSelectionInUpdate = true
|
|
589
|
+
) {
|
|
590
|
+
callWithEnvelope(
|
|
591
|
+
JSONObject().put(
|
|
592
|
+
"command",
|
|
593
|
+
JSONObject().put("type", "replaceSelectionText").put("text", text)
|
|
594
|
+
)
|
|
595
|
+
) { requestJson ->
|
|
596
|
+
backend.applyCommand(editorId, requestJson)
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
override fun replaceTextRangeNative(
|
|
602
|
+
scalarFrom: Int,
|
|
603
|
+
scalarTo: Int,
|
|
604
|
+
text: String
|
|
605
|
+
): EditorV2NativeIntentResult {
|
|
606
|
+
if (nativeOwnerId == null) return EditorV2NativeIntentResult.Rejected
|
|
607
|
+
if (text.isEmpty()) {
|
|
608
|
+
val clampedFrom = clampScalar(scalarFrom)
|
|
609
|
+
val clampedTo = clampScalar(scalarTo)
|
|
610
|
+
if (clampedFrom >= clampedTo) {
|
|
611
|
+
return refreshUnchangedNativeOutcome(
|
|
612
|
+
performNativeIntent(
|
|
613
|
+
nativeIntent("setSelection", clampedFrom, clampedFrom),
|
|
614
|
+
reportPositionEpochInvalid = true
|
|
615
|
+
)
|
|
616
|
+
)
|
|
617
|
+
}
|
|
618
|
+
return refreshUnchangedNativeOutcome(
|
|
619
|
+
performNativeIntent(
|
|
620
|
+
nativeIntent("deleteRange", clampedFrom, clampedTo),
|
|
621
|
+
reportPositionEpochInvalid = true
|
|
622
|
+
)
|
|
623
|
+
)
|
|
624
|
+
}
|
|
625
|
+
return refreshUnchangedNativeOutcome(
|
|
626
|
+
performNativeIntent(
|
|
627
|
+
nativeIntent("replaceSelectionText", scalarFrom, scalarTo).put("text", text),
|
|
628
|
+
reportPositionEpochInvalid = true
|
|
629
|
+
)
|
|
630
|
+
)
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
override fun deleteScalarRangeNative(
|
|
634
|
+
scalarFrom: Int,
|
|
635
|
+
scalarTo: Int
|
|
636
|
+
): EditorV2NativeIntentResult {
|
|
637
|
+
if (nativeOwnerId == null) return EditorV2NativeIntentResult.Rejected
|
|
638
|
+
val clampedFrom = clampScalar(scalarFrom)
|
|
639
|
+
val clampedTo = clampScalar(scalarTo)
|
|
640
|
+
val intent = if (clampedFrom >= clampedTo) {
|
|
641
|
+
nativeIntent("setSelection", clampedFrom, clampedFrom)
|
|
642
|
+
} else {
|
|
643
|
+
nativeIntent("deleteRange", clampedFrom, clampedTo)
|
|
644
|
+
}
|
|
645
|
+
return refreshUnchangedNativeOutcome(
|
|
646
|
+
performNativeIntent(intent, reportPositionEpochInvalid = true)
|
|
647
|
+
)
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
override fun deleteScalarRange(scalarFrom: Int, scalarTo: Int): String? {
|
|
651
|
+
val clampedFrom = clampScalar(scalarFrom)
|
|
652
|
+
val clampedTo = clampScalar(scalarTo)
|
|
653
|
+
if (clampedFrom >= clampedTo) return currentStateJson()
|
|
654
|
+
if (nativeOwnerId != null) {
|
|
655
|
+
return deleteScalarRangeNative(clampedFrom, clampedTo).updateJsonOrNull()
|
|
656
|
+
}
|
|
657
|
+
return performMutation(
|
|
658
|
+
postSelectionMirror = intArrayOf(clampedFrom, clampedFrom),
|
|
659
|
+
includeSelectionInUpdate = true
|
|
660
|
+
) {
|
|
661
|
+
callWithEnvelope(
|
|
662
|
+
JSONObject().put(
|
|
663
|
+
"command",
|
|
664
|
+
JSONObject()
|
|
665
|
+
.put("type", "deleteRange")
|
|
666
|
+
.put(
|
|
667
|
+
"range",
|
|
668
|
+
JSONObject()
|
|
669
|
+
.put("from", positionEnvelope(clampedFrom))
|
|
670
|
+
.put("to", positionEnvelope(clampedTo))
|
|
671
|
+
)
|
|
672
|
+
)
|
|
673
|
+
) { requestJson ->
|
|
674
|
+
backend.applyCommand(editorId, requestJson)
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
override fun deleteBackwardAtSelection(anchor: Int, head: Int): String? {
|
|
680
|
+
if (nativeOwnerId != null) {
|
|
681
|
+
return performNativeIntent(
|
|
682
|
+
nativeIntent("deleteBackward", anchor, head)
|
|
683
|
+
).updateJsonOrNull()
|
|
684
|
+
}
|
|
685
|
+
val postCaret = if (anchor == head) (anchor - 1).coerceAtLeast(0) else minOf(anchor, head)
|
|
686
|
+
return performMutation(
|
|
687
|
+
preSelection = intArrayOf(anchor, head),
|
|
688
|
+
postSelectionMirror = intArrayOf(postCaret, postCaret),
|
|
689
|
+
includeSelectionInUpdate = true
|
|
690
|
+
) {
|
|
691
|
+
callWithEnvelope(
|
|
692
|
+
JSONObject().put("command", JSONObject().put("type", "deleteBackward"))
|
|
693
|
+
) { requestJson ->
|
|
694
|
+
backend.applyCommand(editorId, requestJson)
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
override fun splitBlockAt(scalarPos: Int): EditorV2SplitRender? = if (nativeOwnerId != null) {
|
|
700
|
+
when (
|
|
701
|
+
val outcome = performNativeIntent(
|
|
702
|
+
nativeIntent("splitBlock", scalarPos, scalarPos)
|
|
703
|
+
)
|
|
704
|
+
) {
|
|
705
|
+
is EditorV2NativeIntentResult.Applied ->
|
|
706
|
+
EditorV2SplitRender(outcome.render.updateJson, outcome.render.changed)
|
|
707
|
+
|
|
708
|
+
is EditorV2NativeIntentResult.Recovered ->
|
|
709
|
+
EditorV2SplitRender(outcome.updateJson, false)
|
|
710
|
+
|
|
711
|
+
EditorV2NativeIntentResult.Rejected -> null
|
|
712
|
+
}
|
|
713
|
+
} else {
|
|
714
|
+
performSplitMutation(
|
|
715
|
+
preSelection = intArrayOf(scalarPos, scalarPos),
|
|
716
|
+
postSelectionMirror = intArrayOf(scalarPos + 1, scalarPos + 1)
|
|
717
|
+
) {
|
|
718
|
+
callWithEnvelope(
|
|
719
|
+
JSONObject().put("command", JSONObject().put("type", "splitBlock"))
|
|
720
|
+
) { requestJson ->
|
|
721
|
+
backend.applyCommand(editorId, requestJson)
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
override fun deleteAndSplit(scalarFrom: Int, scalarTo: Int): EditorV2SplitRender? =
|
|
727
|
+
if (nativeOwnerId != null) {
|
|
728
|
+
when (
|
|
729
|
+
val outcome = performNativeIntent(
|
|
730
|
+
nativeIntent("deleteAndSplit", scalarFrom, scalarTo)
|
|
731
|
+
)
|
|
732
|
+
) {
|
|
733
|
+
is EditorV2NativeIntentResult.Applied ->
|
|
734
|
+
EditorV2SplitRender(outcome.render.updateJson, outcome.render.changed)
|
|
735
|
+
|
|
736
|
+
is EditorV2NativeIntentResult.Recovered ->
|
|
737
|
+
EditorV2SplitRender(outcome.updateJson, false)
|
|
738
|
+
|
|
739
|
+
EditorV2NativeIntentResult.Rejected -> null
|
|
740
|
+
}
|
|
741
|
+
} else {
|
|
742
|
+
performSplitMutation(
|
|
743
|
+
preSelection = intArrayOf(scalarFrom, scalarTo),
|
|
744
|
+
postSelectionMirror = intArrayOf(scalarFrom + 1, scalarFrom + 1)
|
|
745
|
+
) {
|
|
746
|
+
callWithEnvelope(
|
|
747
|
+
JSONObject().put("command", JSONObject().put("type", "deleteAndSplit"))
|
|
748
|
+
) { requestJson ->
|
|
749
|
+
backend.applyCommand(editorId, requestJson)
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
override fun moveSelection(anchor: Int, head: Int, destination: Int): String? {
|
|
755
|
+
val from = minOf(anchor, head)
|
|
756
|
+
val to = maxOf(anchor, head)
|
|
757
|
+
return commandAtSelection(
|
|
758
|
+
JSONObject()
|
|
759
|
+
.put("type", "moveSelection")
|
|
760
|
+
.put(
|
|
761
|
+
"range",
|
|
762
|
+
JSONObject()
|
|
763
|
+
.put("from", positionEnvelope(from))
|
|
764
|
+
.put("to", positionEnvelope(to))
|
|
765
|
+
)
|
|
766
|
+
.put("at", positionEnvelope(destination)),
|
|
767
|
+
anchor,
|
|
768
|
+
head
|
|
769
|
+
)
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
override fun insertNode(nodeType: String, anchor: Int, head: Int): String? = commandAtSelection(
|
|
773
|
+
JSONObject().put("type", "insertNode").put("nodeType", nodeType),
|
|
774
|
+
anchor,
|
|
775
|
+
head
|
|
776
|
+
)
|
|
777
|
+
|
|
778
|
+
override fun insertContentHtmlAtSelection(html: String, anchor: Int, head: Int): String? =
|
|
779
|
+
commandAtSelection(
|
|
780
|
+
JSONObject().put("type", "insertContentHtml").put("html", html),
|
|
781
|
+
anchor,
|
|
782
|
+
head
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
override fun insertContentJsonAtSelection(json: String, anchor: Int, head: Int): String? {
|
|
786
|
+
val fragment = try {
|
|
787
|
+
JSONObject(json)
|
|
788
|
+
} catch (error: Exception) {
|
|
789
|
+
emit(contractError("insertContentJson fragment is not valid JSON"))
|
|
790
|
+
return null
|
|
791
|
+
}
|
|
792
|
+
return commandAtSelection(
|
|
793
|
+
JSONObject().put("type", "insertContentJson").put("json", fragment),
|
|
794
|
+
anchor,
|
|
795
|
+
head
|
|
796
|
+
)
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
override fun toggleMark(markName: String, anchor: Int, head: Int): String? = commandAtSelection(
|
|
800
|
+
JSONObject().put("type", "toggleMark").put("markType", markName),
|
|
801
|
+
anchor,
|
|
802
|
+
head
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
override fun setMark(markName: String, attrsJson: String, anchor: Int, head: Int): String? {
|
|
806
|
+
val attrs = try {
|
|
807
|
+
JSONObject(attrsJson)
|
|
808
|
+
} catch (error: Exception) {
|
|
809
|
+
emit(contractError("setMark attrs are not valid JSON"))
|
|
810
|
+
return null
|
|
811
|
+
}
|
|
812
|
+
return commandAtSelection(
|
|
813
|
+
JSONObject().put("type", "setMark").put("markType", markName).put("attrs", attrs),
|
|
814
|
+
anchor,
|
|
815
|
+
head
|
|
816
|
+
)
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
override fun unsetMark(markName: String, anchor: Int, head: Int): String? = commandAtSelection(
|
|
820
|
+
JSONObject().put("type", "unsetMark").put("markType", markName),
|
|
821
|
+
anchor,
|
|
822
|
+
head
|
|
823
|
+
)
|
|
824
|
+
|
|
825
|
+
override fun toggleHeading(level: Int, anchor: Int, head: Int): String? = commandAtSelection(
|
|
826
|
+
JSONObject().put("type", "toggleHeading").put("level", level),
|
|
827
|
+
anchor,
|
|
828
|
+
head
|
|
829
|
+
)
|
|
830
|
+
|
|
831
|
+
override fun toggleCodeBlock(anchor: Int, head: Int): String? =
|
|
832
|
+
commandAtSelection(JSONObject().put("type", "toggleCodeBlock"), anchor, head)
|
|
833
|
+
|
|
834
|
+
override fun toggleBlockquote(anchor: Int, head: Int): String? =
|
|
835
|
+
commandAtSelection(JSONObject().put("type", "toggleBlockquote"), anchor, head)
|
|
836
|
+
|
|
837
|
+
override fun wrapInList(listType: String, anchor: Int, head: Int): String? {
|
|
838
|
+
val itemType = EditorNodeTypes.listItemType(listType)
|
|
839
|
+
return commandAtSelection(
|
|
840
|
+
JSONObject().put(
|
|
841
|
+
"type",
|
|
842
|
+
"wrapInList"
|
|
843
|
+
).put("listType", listType).put("itemType", itemType),
|
|
844
|
+
anchor,
|
|
845
|
+
head
|
|
846
|
+
)
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
override fun unwrapFromList(anchor: Int, head: Int): String? =
|
|
850
|
+
commandAtSelection(JSONObject().put("type", "unwrapFromList"), anchor, head)
|
|
851
|
+
|
|
852
|
+
override fun indentListItem(anchor: Int, head: Int): String? =
|
|
853
|
+
commandAtSelection(JSONObject().put("type", "indentListItem"), anchor, head)
|
|
854
|
+
|
|
855
|
+
override fun outdentListItem(anchor: Int, head: Int): String? =
|
|
856
|
+
commandAtSelection(JSONObject().put("type", "outdentListItem"), anchor, head)
|
|
857
|
+
|
|
858
|
+
override fun toggleTaskItemCheckedAtSelection(anchor: Int, head: Int): String? =
|
|
859
|
+
commandAtSelection(JSONObject().put("type", "toggleTaskItemChecked"), anchor, head)
|
|
860
|
+
|
|
861
|
+
override fun resizeImageAtDocPos(docPos: Int, width: Int, height: Int): String? {
|
|
862
|
+
val scalar = scalarPositionForDoc(docPos) ?: return null
|
|
863
|
+
return performMutation(adoptEngineSelection = true) {
|
|
864
|
+
callWithEnvelope(
|
|
865
|
+
JSONObject().put(
|
|
866
|
+
"command",
|
|
867
|
+
JSONObject()
|
|
868
|
+
.put("type", "resizeImage")
|
|
869
|
+
.put("at", positionEnvelope(scalar))
|
|
870
|
+
.put("width", width)
|
|
871
|
+
.put("height", height)
|
|
872
|
+
)
|
|
873
|
+
) { requestJson ->
|
|
874
|
+
backend.applyCommand(editorId, requestJson)
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
override fun undo(): String? =
|
|
880
|
+
performHistoryMutation { requestJson -> backend.undo(editorId, requestJson) }
|
|
881
|
+
|
|
882
|
+
override fun redo(): String? =
|
|
883
|
+
performHistoryMutation { requestJson -> backend.redo(editorId, requestJson) }
|
|
884
|
+
|
|
885
|
+
override fun setContentHtml(html: String): String? =
|
|
886
|
+
performMutation(postSelectionMirror = intArrayOf(0, 0), includeSelectionInUpdate = true) {
|
|
887
|
+
callWithEnvelope(
|
|
888
|
+
JSONObject().put("setHtml", html).put("history", "resetAndClear")
|
|
889
|
+
) { requestJson ->
|
|
890
|
+
backend.applyLocalApi(editorId, requestJson)
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
override fun setContentJson(json: String): String? {
|
|
895
|
+
val document = try {
|
|
896
|
+
JSONObject(json)
|
|
897
|
+
} catch (error: Exception) {
|
|
898
|
+
emit(contractError("setContentJson document is not valid JSON"))
|
|
899
|
+
return null
|
|
900
|
+
}
|
|
901
|
+
return performMutation(
|
|
902
|
+
postSelectionMirror = intArrayOf(0, 0),
|
|
903
|
+
includeSelectionInUpdate = true
|
|
904
|
+
) {
|
|
905
|
+
callWithEnvelope(
|
|
906
|
+
JSONObject().put("setJson", document).put("history", "resetAndClear")
|
|
907
|
+
) { requestJson ->
|
|
908
|
+
backend.applyLocalApi(editorId, requestJson)
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|