@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,80 @@
|
|
|
1
|
+
package com.apollohg.editor.viewer
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Yoga prepares Fabric artifacts before a View exists. Keep its publication
|
|
5
|
+
* sidecar by exact state incarnation so a new semantic identity is cleared before intrinsic
|
|
6
|
+
* fallback lookup, then mount binds the same state without a second reset.
|
|
7
|
+
*/
|
|
8
|
+
internal object FabricAttachmentSidecars {
|
|
9
|
+
private val lock = Any()
|
|
10
|
+
private val states = mutableMapOf<FabricGenerationToken, ViewerAttachmentRevisionState>()
|
|
11
|
+
private val measurementState = ThreadLocal<ViewerAttachmentRevisionState>()
|
|
12
|
+
|
|
13
|
+
/** Only preparation's explicitly bound owner may satisfy an LRU miss. */
|
|
14
|
+
val currentMeasurementState: ViewerAttachmentRevisionState?
|
|
15
|
+
get() = measurementState.get()
|
|
16
|
+
|
|
17
|
+
fun beginIfActive(
|
|
18
|
+
generation: FabricGenerationToken,
|
|
19
|
+
semanticIdentity: String,
|
|
20
|
+
isActive: () -> Boolean
|
|
21
|
+
): ViewerAttachmentRevisionState? = synchronized(lock) {
|
|
22
|
+
if (!isActive()) return@synchronized null
|
|
23
|
+
states.getOrPut(generation, ::ViewerAttachmentRevisionState).also {
|
|
24
|
+
it.beginSemanticGeneration(semanticIdentity)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fun begin(
|
|
29
|
+
generation: FabricGenerationToken,
|
|
30
|
+
semanticIdentity: String
|
|
31
|
+
): ViewerAttachmentRevisionState = beginIfActive(generation, semanticIdentity) { true }
|
|
32
|
+
?: error("Unconditionally active sidecar unexpectedly rejected.")
|
|
33
|
+
|
|
34
|
+
fun state(generation: FabricGenerationToken): ViewerAttachmentRevisionState? =
|
|
35
|
+
synchronized(lock) {
|
|
36
|
+
states[generation]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Nestable and exception-safe: Yoga workers may reuse the same thread. */
|
|
40
|
+
fun <T> withMeasurementState(state: ViewerAttachmentRevisionState, body: () -> T): T {
|
|
41
|
+
val previous = measurementState.get()
|
|
42
|
+
measurementState.set(state)
|
|
43
|
+
return try {
|
|
44
|
+
body()
|
|
45
|
+
} finally {
|
|
46
|
+
if (previous == null) measurementState.remove() else measurementState.set(previous)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fun remove(generation: FabricGenerationToken) = synchronized(lock) {
|
|
51
|
+
states.remove(generation)?.reset()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fun remove(surface: FabricSurfaceToken) = synchronized(lock) {
|
|
55
|
+
states.keys.filter { it.surface == surface }.forEach { states.remove(it)?.reset() }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
fun removeSurface(surfaceId: Int) = synchronized(lock) {
|
|
59
|
+
states.keys.filter {
|
|
60
|
+
it.surface.surfaceId == surfaceId
|
|
61
|
+
}.forEach { token -> states.remove(token)?.reset() }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fun remove(owner: FabricLeaseOwner) = synchronized(lock) {
|
|
65
|
+
states.keys
|
|
66
|
+
.filter { it.surface == owner.surface && it.leaseHandle == owner.leaseHandle }
|
|
67
|
+
.forEach { states.remove(it)?.reset() }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Commit keeps the incoming generation's in-flight sidecar but drops every stale revision for this family. */
|
|
71
|
+
fun removeOtherGenerations(owner: FabricLeaseOwner, keeping: FabricGenerationToken) =
|
|
72
|
+
synchronized(lock) {
|
|
73
|
+
states.keys
|
|
74
|
+
.filter {
|
|
75
|
+
it.surface == owner.surface && it.leaseHandle == owner.leaseHandle &&
|
|
76
|
+
it != keeping
|
|
77
|
+
}
|
|
78
|
+
.forEach { states.remove(it)?.reset() }
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
package com.apollohg.editor.viewer
|
|
2
|
+
|
|
3
|
+
/** JNI-only handoff; handles never pass through `ReadableMap.getDouble()`. */
|
|
4
|
+
internal object FabricLeaseHandleBridge {
|
|
5
|
+
private val current = ThreadLocal<Long>()
|
|
6
|
+
internal data class FinalLayout(
|
|
7
|
+
val leaseHandle: Long,
|
|
8
|
+
val contentOriginXPx: Int,
|
|
9
|
+
val contentOriginYPx: Int
|
|
10
|
+
)
|
|
11
|
+
private val finalLayout = ThreadLocal<FinalLayout>()
|
|
12
|
+
|
|
13
|
+
@JvmStatic fun beginNativeMeasure(leaseHandle: Long) {
|
|
14
|
+
finalLayout.remove()
|
|
15
|
+
if (leaseHandle > 0) current.set(leaseHandle) else current.remove()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@JvmStatic
|
|
19
|
+
fun beginNativeFinalLayout(leaseHandle: Long, contentOriginXPx: Int, contentOriginYPx: Int) {
|
|
20
|
+
if (leaseHandle <= 0) {
|
|
21
|
+
current.remove()
|
|
22
|
+
finalLayout.remove()
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
current.set(leaseHandle)
|
|
26
|
+
finalLayout.set(FinalLayout(leaseHandle, contentOriginXPx, contentOriginYPx))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@JvmStatic fun endNativeMeasure() {
|
|
30
|
+
current.remove()
|
|
31
|
+
finalLayout.remove()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fun currentHandle(): Long = current.get() ?: 0L
|
|
35
|
+
|
|
36
|
+
fun currentFinalLayout(): FinalLayout? = finalLayout.get()
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The C++ state lifecycle registers before its first Yoga pass and invokes
|
|
40
|
+
* the matching release from its final shared-state destructor. These are
|
|
41
|
+
* static calls only: no View, Context, or manager is retained across JNI.
|
|
42
|
+
*/
|
|
43
|
+
@JvmStatic fun registerNativeLease(surfaceId: Int, componentTag: Int, leaseHandle: Long) {
|
|
44
|
+
if (surfaceId <= 0 || componentTag <= 0 || leaseHandle <= 0) return
|
|
45
|
+
PreparedProseLayoutRegistry.shared.registerFabricLease(
|
|
46
|
+
FabricSurfaceToken(surfaceId, componentTag),
|
|
47
|
+
leaseHandle
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Invoked only from the C++ state-family's final destructor callback. */
|
|
52
|
+
@JvmStatic fun finalizeNativeLease(surfaceId: Int, componentTag: Int, leaseHandle: Long) {
|
|
53
|
+
if (surfaceId <= 0 || componentTag <= 0 || leaseHandle <= 0) return
|
|
54
|
+
PreparedProseLayoutRegistry.shared.finalizeFabricLease(
|
|
55
|
+
FabricSurfaceToken(surfaceId, componentTag),
|
|
56
|
+
leaseHandle
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
package com.apollohg.editor.viewer
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.graphics.Paint
|
|
5
|
+
import android.graphics.Path
|
|
6
|
+
import android.graphics.PathMeasure
|
|
7
|
+
import android.graphics.Rect
|
|
8
|
+
import android.graphics.RectF
|
|
9
|
+
import android.graphics.Typeface
|
|
10
|
+
import android.text.Layout
|
|
11
|
+
import android.text.SpannableString
|
|
12
|
+
import android.text.Spanned
|
|
13
|
+
import android.text.StaticLayout
|
|
14
|
+
import android.text.TextPaint
|
|
15
|
+
import android.text.style.BackgroundColorSpan
|
|
16
|
+
import android.text.style.ForegroundColorSpan
|
|
17
|
+
import android.text.style.LineHeightSpan
|
|
18
|
+
import android.text.style.MetricAffectingSpan
|
|
19
|
+
import android.text.style.ReplacementSpan
|
|
20
|
+
import android.text.style.StrikethroughSpan
|
|
21
|
+
import android.text.style.UnderlineSpan
|
|
22
|
+
import com.apollohg.editor.EditorLinkTheme
|
|
23
|
+
import com.apollohg.editor.EditorMentionTheme
|
|
24
|
+
import com.apollohg.editor.EditorOrderedListMarkerTheme
|
|
25
|
+
import com.apollohg.editor.EditorTextStyle
|
|
26
|
+
import com.apollohg.editor.EditorTheme
|
|
27
|
+
import com.apollohg.editor.OrderedListMarkerFormatter
|
|
28
|
+
import com.apollohg.editor.ProseViewerError
|
|
29
|
+
import java.text.Bidi
|
|
30
|
+
import kotlin.math.abs
|
|
31
|
+
import kotlin.math.ceil
|
|
32
|
+
import kotlin.math.max
|
|
33
|
+
import kotlin.math.min
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* StaticLayout can split one visual selection run into edge-touching contours.
|
|
37
|
+
* Android [Rect.right] is exclusive, so only overlapping or edge-touching
|
|
38
|
+
* contours with compatible vertical bounds belong to one hit region.
|
|
39
|
+
*/
|
|
40
|
+
internal fun mergeAdjacentSameLineSelectionFragments(fragments: List<Rect>): List<Rect> {
|
|
41
|
+
val ordered = fragments.sortedWith(compareBy<Rect> { it.top }.thenBy { it.left })
|
|
42
|
+
val merged = mutableListOf<Rect>()
|
|
43
|
+
ordered.forEach { fragment ->
|
|
44
|
+
val previous = merged.lastOrNull()
|
|
45
|
+
if (
|
|
46
|
+
previous != null &&
|
|
47
|
+
abs(previous.top - fragment.top) <= SELECTION_FRAGMENT_PIXEL_TOLERANCE_PX &&
|
|
48
|
+
abs(previous.bottom - fragment.bottom) <= SELECTION_FRAGMENT_PIXEL_TOLERANCE_PX &&
|
|
49
|
+
fragment.left <= previous.right
|
|
50
|
+
) {
|
|
51
|
+
merged[merged.lastIndex] = Rect(
|
|
52
|
+
min(previous.left, fragment.left),
|
|
53
|
+
min(previous.top, fragment.top),
|
|
54
|
+
max(previous.right, fragment.right),
|
|
55
|
+
max(previous.bottom, fragment.bottom)
|
|
56
|
+
)
|
|
57
|
+
} else {
|
|
58
|
+
merged += Rect(fragment)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return merged
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private const val SELECTION_FRAGMENT_PIXEL_TOLERANCE_PX = 1
|
|
65
|
+
|
|
66
|
+
internal enum class FallbackVisualEdge { LEFT, RIGHT }
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Java [Bidi]'s run accessors are indexed in logical order. Keep that source
|
|
70
|
+
* identity immutable, then explicitly project it into visual order before any
|
|
71
|
+
* geometry asks about neighbours or line-edge ownership.
|
|
72
|
+
*/
|
|
73
|
+
internal data class FallbackLogicalBidiRun(
|
|
74
|
+
val logicalIndex: Int,
|
|
75
|
+
val documentStart: Int,
|
|
76
|
+
val documentEnd: Int,
|
|
77
|
+
val level: Byte
|
|
78
|
+
) {
|
|
79
|
+
val isRtl: Boolean get() = (level.toInt() and 1) == 1
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
internal data class FallbackVisualBidiRun(
|
|
83
|
+
val visualIndex: Int,
|
|
84
|
+
val logicalRun: FallbackLogicalBidiRun
|
|
85
|
+
) {
|
|
86
|
+
val documentStart: Int get() = logicalRun.documentStart
|
|
87
|
+
val documentEnd: Int get() = logicalRun.documentEnd
|
|
88
|
+
val isRtl: Boolean get() = logicalRun.isRtl
|
|
89
|
+
|
|
90
|
+
fun offsetAt(edge: FallbackVisualEdge): Int = when (edge) {
|
|
91
|
+
FallbackVisualEdge.LEFT -> if (isRtl) documentEnd else documentStart
|
|
92
|
+
FallbackVisualEdge.RIGHT -> if (isRtl) documentStart else documentEnd
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fun edgeForLogicalEnd(): FallbackVisualEdge =
|
|
96
|
+
if (isRtl) FallbackVisualEdge.LEFT else FallbackVisualEdge.RIGHT
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* [Bidi.getRunStart], [Bidi.getRunLimit], and [Bidi.getRunLevel] take a
|
|
101
|
+
* logical run index. [Bidi.reorderVisually] is the public Unicode Bidi API
|
|
102
|
+
* that turns those immutable logical records into left-to-right visual order.
|
|
103
|
+
*/
|
|
104
|
+
internal fun visualBidiRuns(
|
|
105
|
+
logicalRuns: List<FallbackLogicalBidiRun>
|
|
106
|
+
): List<FallbackVisualBidiRun> {
|
|
107
|
+
if (logicalRuns.isEmpty()) return emptyList()
|
|
108
|
+
|
|
109
|
+
val levels = ByteArray(logicalRuns.size) { logicalRuns[it].level }
|
|
110
|
+
val reordered: Array<Any> = Array(logicalRuns.size) { logicalRuns[it] }
|
|
111
|
+
Bidi.reorderVisually(levels, 0, reordered, 0, reordered.size)
|
|
112
|
+
return reordered.mapIndexed { visualIndex, value ->
|
|
113
|
+
FallbackVisualBidiRun(visualIndex, value as FallbackLogicalBidiRun)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private fun fallbackHorizontalAtVisualEdge(
|
|
118
|
+
layout: StaticLayout,
|
|
119
|
+
offset: Int,
|
|
120
|
+
edge: FallbackVisualEdge
|
|
121
|
+
): Float {
|
|
122
|
+
val primary = layout.getPrimaryHorizontal(offset)
|
|
123
|
+
val secondary = layout.getSecondaryHorizontal(offset)
|
|
124
|
+
return if (edge ==
|
|
125
|
+
FallbackVisualEdge.RIGHT
|
|
126
|
+
) {
|
|
127
|
+
max(primary, secondary)
|
|
128
|
+
} else {
|
|
129
|
+
min(primary, secondary)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The logical side of a cursor position. This mirrors Layout's internal
|
|
135
|
+
* `getHorizontal(offset, trailing, ...)` calls: a selection starts at the
|
|
136
|
+
* leading edge of its next logical character and ends at the trailing edge of
|
|
137
|
+
* its previous logical character. It is deliberately not a visual left/right
|
|
138
|
+
* concept.
|
|
139
|
+
*/
|
|
140
|
+
internal enum class FallbackLogicalCaretAffinity { LEADING_NEXT, TRAILING_PREVIOUS }
|
|
141
|
+
|
|
142
|
+
internal fun FallbackVisualBidiRun.affinityAt(
|
|
143
|
+
edge: FallbackVisualEdge
|
|
144
|
+
): FallbackLogicalCaretAffinity = if (offsetAt(edge) == documentStart) {
|
|
145
|
+
FallbackLogicalCaretAffinity.LEADING_NEXT
|
|
146
|
+
} else {
|
|
147
|
+
FallbackLogicalCaretAffinity.TRAILING_PREVIOUS
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Mirrors Layout's primary-caret decision from the adjacent logical embedding
|
|
152
|
+
* levels. At a directional boundary the same offset has two valid positions;
|
|
153
|
+
* which one is primary is determined by the transition, not by the current
|
|
154
|
+
* run's direction or by the paragraph's base direction alone.
|
|
155
|
+
*/
|
|
156
|
+
internal fun primaryIsTrailingPrevious(offset: Int, geometry: FallbackLineGeometry): Boolean {
|
|
157
|
+
val paragraphLevel = if (geometry.paragraphDirection == Layout.DIR_RIGHT_TO_LEFT) 1 else 0
|
|
158
|
+
val current = geometry.logicalRuns.firstOrNull {
|
|
159
|
+
offset in it.documentStart until it.documentEnd
|
|
160
|
+
}
|
|
161
|
+
// Inside a logical run the public primary cursor is the leading-next
|
|
162
|
+
// position. Only a run boundary needs the preceding-level comparison.
|
|
163
|
+
if (current != null && offset > current.documentStart) return false
|
|
164
|
+
|
|
165
|
+
val levelAt = current?.level?.toInt() ?: paragraphLevel
|
|
166
|
+
val levelBefore = when {
|
|
167
|
+
offset == geometry.lineStart -> paragraphLevel
|
|
168
|
+
|
|
169
|
+
else -> geometry.logicalRuns.firstOrNull {
|
|
170
|
+
offset - 1 in it.documentStart until it.documentEnd
|
|
171
|
+
}?.level?.toInt() ?: paragraphLevel
|
|
172
|
+
}
|
|
173
|
+
return levelBefore < levelAt
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Resolves one public horizontal API result using Layout-equivalent affinity. */
|
|
177
|
+
internal fun fallbackHorizontalForLogicalCaret(
|
|
178
|
+
geometry: FallbackLineGeometry,
|
|
179
|
+
offset: Int,
|
|
180
|
+
affinity: FallbackLogicalCaretAffinity
|
|
181
|
+
): Float {
|
|
182
|
+
val desiredTrailing = affinity == FallbackLogicalCaretAffinity.TRAILING_PREVIOUS
|
|
183
|
+
return if (desiredTrailing == primaryIsTrailingPrevious(offset, geometry)) {
|
|
184
|
+
geometry.primaryHorizontal(offset)
|
|
185
|
+
} else {
|
|
186
|
+
geometry.secondaryHorizontal(offset)
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Emulates Layout's private current-line trailing lookup at a soft-wrap end.
|
|
192
|
+
* The public horizontal APIs resolve that shared offset as the next line's
|
|
193
|
+
* start, so an internal terminal run instead borrows the same visual boundary
|
|
194
|
+
* from its adjacent run. Only a run which owns the outer visual edge may use
|
|
195
|
+
* the current line's left/right extent.
|
|
196
|
+
*/
|
|
197
|
+
private fun softWrapTerminalBoundary(
|
|
198
|
+
terminalRun: FallbackVisualBidiRun,
|
|
199
|
+
visualRuns: List<FallbackVisualBidiRun>,
|
|
200
|
+
softWrapLineEnd: Int,
|
|
201
|
+
outerLineBoundary: (FallbackVisualEdge) -> Float,
|
|
202
|
+
logicalCaretHorizontal: (offset: Int, affinity: FallbackLogicalCaretAffinity) -> Float
|
|
203
|
+
): Float? {
|
|
204
|
+
val terminalEdge = terminalRun.edgeForLogicalEnd()
|
|
205
|
+
val isOuter = when (terminalEdge) {
|
|
206
|
+
FallbackVisualEdge.LEFT -> terminalRun.visualIndex == 0
|
|
207
|
+
FallbackVisualEdge.RIGHT -> terminalRun.visualIndex == visualRuns.lastIndex
|
|
208
|
+
}
|
|
209
|
+
if (isOuter) {
|
|
210
|
+
return outerLineBoundary(terminalEdge)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
val neighbor = when (terminalEdge) {
|
|
214
|
+
FallbackVisualEdge.LEFT -> visualRuns.getOrNull(terminalRun.visualIndex - 1)
|
|
215
|
+
FallbackVisualEdge.RIGHT -> visualRuns.getOrNull(terminalRun.visualIndex + 1)
|
|
216
|
+
} ?: return null
|
|
217
|
+
val neighborEdge = if (terminalEdge == FallbackVisualEdge.LEFT) {
|
|
218
|
+
FallbackVisualEdge.RIGHT
|
|
219
|
+
} else {
|
|
220
|
+
FallbackVisualEdge.LEFT
|
|
221
|
+
}
|
|
222
|
+
val neighborOffset = neighbor.offsetAt(neighborEdge)
|
|
223
|
+
// A distinct visual run cannot own the terminal line-end offset. Refuse a
|
|
224
|
+
// malformed/unexpected Bidi result rather than resolving that offset on
|
|
225
|
+
// the next line and expanding this hit rectangle across adjacent content.
|
|
226
|
+
if (neighborOffset == softWrapLineEnd) return null
|
|
227
|
+
return logicalCaretHorizontal(neighborOffset, neighbor.affinityAt(neighborEdge))
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Test support for direct visual-edge fixtures. Production selection uses
|
|
232
|
+
* [fallbackSelectionRectsForLine], which resolves both endpoints by logical
|
|
233
|
+
* caret affinity instead of collapsing them to physical left/right extremes.
|
|
234
|
+
*/
|
|
235
|
+
internal fun fallbackSelectionRectForVisualRun(
|
|
236
|
+
layout: StaticLayout,
|
|
237
|
+
runStart: Int,
|
|
238
|
+
runEnd: Int,
|
|
239
|
+
runIsRtl: Boolean,
|
|
240
|
+
line: Int,
|
|
241
|
+
width: Int,
|
|
242
|
+
softWrapLineEnd: Int? = null,
|
|
243
|
+
softWrapTerminalBoundary: Float? = null
|
|
244
|
+
): Rect? {
|
|
245
|
+
if (runStart >= runEnd) return null
|
|
246
|
+
|
|
247
|
+
fun visualBoundary(offset: Int, logicalRunStart: Boolean): Float {
|
|
248
|
+
val visualRightEdge = if (runIsRtl) logicalRunStart else !logicalRunStart
|
|
249
|
+
// A soft-wrap terminal offset is also the following line's start.
|
|
250
|
+
// Layout's horizontal lookup therefore resolves it on that following
|
|
251
|
+
// line. The current line's matching visual extreme is the exact
|
|
252
|
+
// trailing boundary for this Bidi run. Keep ordinary primary/secondary
|
|
253
|
+
// affinity lookup for a current-line start and for the final document
|
|
254
|
+
// boundary, neither of which has this ambiguous line ownership.
|
|
255
|
+
if (!logicalRunStart && offset == softWrapLineEnd) {
|
|
256
|
+
softWrapTerminalBoundary?.let { return it }
|
|
257
|
+
return if (visualRightEdge) layout.getLineRight(line) else layout.getLineLeft(line)
|
|
258
|
+
}
|
|
259
|
+
return fallbackHorizontalAtVisualEdge(
|
|
260
|
+
layout,
|
|
261
|
+
offset,
|
|
262
|
+
if (visualRightEdge) FallbackVisualEdge.RIGHT else FallbackVisualEdge.LEFT
|
|
263
|
+
)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
val start = visualBoundary(runStart, logicalRunStart = true)
|
|
267
|
+
val end = visualBoundary(runEnd, logicalRunStart = false)
|
|
268
|
+
val left = kotlin.math.floor(min(start, end)).toInt().coerceIn(0, width)
|
|
269
|
+
val right = ceil(max(start, end)).toInt().coerceIn(0, width)
|
|
270
|
+
return Rect(left, layout.getLineTop(line), right, layout.getLineBottom(line)).takeIf {
|
|
271
|
+
!it.isEmpty
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* The line-level input required by the Bidi fallback. Keeping it separate
|
|
277
|
+
* from [StaticLayout] makes the cursor-affinity algorithm deterministic while
|
|
278
|
+
* leaving layout extraction at the production adapter boundary.
|
|
279
|
+
*/
|
|
280
|
+
internal data class FallbackLineGeometry(
|
|
281
|
+
val text: CharSequence,
|
|
282
|
+
val lineStart: Int,
|
|
283
|
+
val rawLineEnd: Int,
|
|
284
|
+
val nextLineStart: Int?,
|
|
285
|
+
val paragraphDirection: Int,
|
|
286
|
+
val top: Int,
|
|
287
|
+
val bottom: Int,
|
|
288
|
+
val width: Int,
|
|
289
|
+
/** Full drawable-line runs in logical order, including embedding levels. */
|
|
290
|
+
val logicalRuns: List<FallbackLogicalBidiRun>,
|
|
291
|
+
val outerLineBoundary: (FallbackVisualEdge) -> Float,
|
|
292
|
+
val primaryHorizontal: (Int) -> Float,
|
|
293
|
+
val secondaryHorizontal: (Int) -> Float
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Derives fallback selection geometry from one already-resolved visual line.
|
|
298
|
+
*
|
|
299
|
+
* The [StaticLayout] adapter below supplies this geometry in production. The
|
|
300
|
+
* algorithm intentionally owns the soft-wrap, selection-intersection, Bidi
|
|
301
|
+
* ordering, and terminal-neighbour checks so those invariants do not depend
|
|
302
|
+
* on host text shaping.
|
|
303
|
+
*/
|
|
304
|
+
internal fun fallbackSelectionRectsForGeometry(
|
|
305
|
+
geometry: FallbackLineGeometry,
|
|
306
|
+
start: Int,
|
|
307
|
+
end: Int
|
|
308
|
+
): List<Rect> {
|
|
309
|
+
val lineStart = geometry.lineStart
|
|
310
|
+
val rawLineEnd = geometry.rawLineEnd
|
|
311
|
+
// A hard-break line includes its terminator in StaticLayout's end offset.
|
|
312
|
+
// It has no drawable/cursor run, so exclude it before constructing Bidi.
|
|
313
|
+
val lineEnd = if (
|
|
314
|
+
rawLineEnd > lineStart &&
|
|
315
|
+
rawLineEnd <= geometry.text.length &&
|
|
316
|
+
geometry.text[rawLineEnd - 1] == '\n'
|
|
317
|
+
) {
|
|
318
|
+
rawLineEnd - 1
|
|
319
|
+
} else {
|
|
320
|
+
rawLineEnd
|
|
321
|
+
}
|
|
322
|
+
val softWrapLineEnd = rawLineEnd.takeIf {
|
|
323
|
+
lineEnd == rawLineEnd &&
|
|
324
|
+
rawLineEnd < geometry.text.length &&
|
|
325
|
+
geometry.nextLineStart == rawLineEnd
|
|
326
|
+
}
|
|
327
|
+
val selectedStart = maxOf(start, lineStart).coerceAtMost(lineEnd)
|
|
328
|
+
val selectedEnd = minOf(end, lineEnd).coerceAtLeast(lineStart)
|
|
329
|
+
if (selectedStart >= selectedEnd || lineStart >= lineEnd) return emptyList()
|
|
330
|
+
|
|
331
|
+
val visualRuns = visualBidiRuns(geometry.logicalRuns)
|
|
332
|
+
val fragments = mutableListOf<Rect>()
|
|
333
|
+
for (visualRun in visualRuns) {
|
|
334
|
+
val intersectedStart = maxOf(selectedStart, visualRun.documentStart)
|
|
335
|
+
val intersectedEnd = minOf(selectedEnd, visualRun.documentEnd)
|
|
336
|
+
val resolvesSoftWrapTerminal = softWrapLineEnd != null &&
|
|
337
|
+
visualRun.documentEnd == softWrapLineEnd &&
|
|
338
|
+
intersectedEnd == softWrapLineEnd
|
|
339
|
+
val terminalBoundary = if (resolvesSoftWrapTerminal) {
|
|
340
|
+
softWrapTerminalBoundary(
|
|
341
|
+
terminalRun = visualRun,
|
|
342
|
+
visualRuns = visualRuns,
|
|
343
|
+
softWrapLineEnd = softWrapLineEnd!!,
|
|
344
|
+
outerLineBoundary = geometry.outerLineBoundary,
|
|
345
|
+
logicalCaretHorizontal = { offset, affinity ->
|
|
346
|
+
fallbackHorizontalForLogicalCaret(geometry, offset, affinity)
|
|
347
|
+
}
|
|
348
|
+
)
|
|
349
|
+
} else {
|
|
350
|
+
null
|
|
351
|
+
}
|
|
352
|
+
// Do not allow an internal terminal boundary to fall through to the
|
|
353
|
+
// generic whole-line shortcut: that would over-expand the rectangle.
|
|
354
|
+
if (resolvesSoftWrapTerminal && terminalBoundary == null) continue
|
|
355
|
+
if (intersectedStart >= intersectedEnd) continue
|
|
356
|
+
fun visualBoundary(offset: Int, logicalRunStart: Boolean): Float {
|
|
357
|
+
val visualRightEdge = if (visualRun.isRtl) logicalRunStart else !logicalRunStart
|
|
358
|
+
val edge = if (visualRightEdge) FallbackVisualEdge.RIGHT else FallbackVisualEdge.LEFT
|
|
359
|
+
if (!logicalRunStart && offset == softWrapLineEnd) {
|
|
360
|
+
return terminalBoundary ?: geometry.outerLineBoundary(edge)
|
|
361
|
+
}
|
|
362
|
+
return fallbackHorizontalForLogicalCaret(
|
|
363
|
+
geometry,
|
|
364
|
+
offset,
|
|
365
|
+
if (logicalRunStart) {
|
|
366
|
+
FallbackLogicalCaretAffinity.LEADING_NEXT
|
|
367
|
+
} else {
|
|
368
|
+
FallbackLogicalCaretAffinity.TRAILING_PREVIOUS
|
|
369
|
+
}
|
|
370
|
+
)
|
|
371
|
+
}
|
|
372
|
+
val startBoundary = visualBoundary(intersectedStart, logicalRunStart = true)
|
|
373
|
+
val endBoundary = visualBoundary(intersectedEnd, logicalRunStart = false)
|
|
374
|
+
Rect(
|
|
375
|
+
kotlin.math.floor(min(startBoundary, endBoundary)).toInt().coerceIn(0, geometry.width),
|
|
376
|
+
geometry.top,
|
|
377
|
+
ceil(max(startBoundary, endBoundary)).toInt().coerceIn(0, geometry.width),
|
|
378
|
+
geometry.bottom
|
|
379
|
+
).takeIf { !it.isEmpty }?.let(fragments::add)
|
|
380
|
+
}
|
|
381
|
+
return fragments
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Derives fallback selection geometry from the complete [StaticLayout] line.
|
|
386
|
+
*
|
|
387
|
+
* The line's Bidi resolution must use the same paragraph direction as the
|
|
388
|
+
* layout that supplied its cursor positions. Resolving only the selected
|
|
389
|
+
* substring can give neutral characters and embedded runs a different level.
|
|
390
|
+
*/
|
|
391
|
+
internal fun fallbackSelectionRectsForLine(
|
|
392
|
+
layout: StaticLayout,
|
|
393
|
+
start: Int,
|
|
394
|
+
end: Int,
|
|
395
|
+
line: Int,
|
|
396
|
+
width: Int
|
|
397
|
+
): List<Rect> = fallbackSelectionRectsForGeometry(
|
|
398
|
+
FallbackLineGeometry(
|
|
399
|
+
text = layout.text,
|
|
400
|
+
lineStart = layout.getLineStart(line),
|
|
401
|
+
rawLineEnd = layout.getLineEnd(line),
|
|
402
|
+
nextLineStart = if (line + 1 < layout.lineCount) layout.getLineStart(line + 1) else null,
|
|
403
|
+
paragraphDirection = layout.getParagraphDirection(line),
|
|
404
|
+
top = layout.getLineTop(line),
|
|
405
|
+
bottom = layout.getLineBottom(line),
|
|
406
|
+
width = width,
|
|
407
|
+
logicalRuns = fallbackLogicalBidiRunsForLine(layout, line),
|
|
408
|
+
outerLineBoundary = { edge ->
|
|
409
|
+
if (edge ==
|
|
410
|
+
FallbackVisualEdge.LEFT
|
|
411
|
+
) {
|
|
412
|
+
layout.getLineLeft(line)
|
|
413
|
+
} else {
|
|
414
|
+
layout.getLineRight(line)
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
primaryHorizontal = layout::getPrimaryHorizontal,
|
|
418
|
+
secondaryHorizontal = layout::getSecondaryHorizontal
|
|
419
|
+
),
|
|
420
|
+
start,
|
|
421
|
+
end
|
|
422
|
+
)
|
|
423
|
+
|
|
424
|
+
private fun fallbackLogicalBidiRunsForLine(
|
|
425
|
+
layout: StaticLayout,
|
|
426
|
+
line: Int
|
|
427
|
+
): List<FallbackLogicalBidiRun> {
|
|
428
|
+
val lineStart = layout.getLineStart(line)
|
|
429
|
+
val rawLineEnd = layout.getLineEnd(line)
|
|
430
|
+
val lineEnd = if (rawLineEnd > lineStart && layout.text[rawLineEnd - 1] == '\n') {
|
|
431
|
+
rawLineEnd - 1
|
|
432
|
+
} else {
|
|
433
|
+
rawLineEnd
|
|
434
|
+
}
|
|
435
|
+
if (lineStart >= lineEnd) return emptyList()
|
|
436
|
+
val direction = if (layout.getParagraphDirection(line) == Layout.DIR_RIGHT_TO_LEFT) {
|
|
437
|
+
Bidi.DIRECTION_RIGHT_TO_LEFT
|
|
438
|
+
} else {
|
|
439
|
+
Bidi.DIRECTION_LEFT_TO_RIGHT
|
|
440
|
+
}
|
|
441
|
+
val bidi = Bidi(layout.text.subSequence(lineStart, lineEnd).toString(), direction)
|
|
442
|
+
return List(bidi.runCount) { logicalIndex ->
|
|
443
|
+
FallbackLogicalBidiRun(
|
|
444
|
+
logicalIndex = logicalIndex,
|
|
445
|
+
documentStart = lineStart + bidi.getRunStart(logicalIndex),
|
|
446
|
+
documentEnd = lineStart + bidi.getRunLimit(logicalIndex),
|
|
447
|
+
level = bidi.getRunLevel(logicalIndex).toByte()
|
|
448
|
+
)
|
|
449
|
+
}
|
|
450
|
+
}
|