@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,923 @@
|
|
|
1
|
+
package com.apollohg.editor
|
|
2
|
+
|
|
3
|
+
import android.os.Handler
|
|
4
|
+
import android.os.Looper
|
|
5
|
+
import android.os.SystemClock
|
|
6
|
+
import android.text.Selection
|
|
7
|
+
import android.text.Spanned
|
|
8
|
+
import android.view.KeyEvent
|
|
9
|
+
import android.view.inputmethod.BaseInputConnection
|
|
10
|
+
import android.view.inputmethod.CompletionInfo
|
|
11
|
+
import android.view.inputmethod.CorrectionInfo
|
|
12
|
+
import android.view.inputmethod.ExtractedText
|
|
13
|
+
import android.view.inputmethod.ExtractedTextRequest
|
|
14
|
+
import android.view.inputmethod.InputConnection
|
|
15
|
+
import android.view.inputmethod.InputConnectionWrapper
|
|
16
|
+
import android.view.inputmethod.SurroundingText
|
|
17
|
+
import android.view.inputmethod.TextAttribute
|
|
18
|
+
import android.view.inputmethod.TextSnapshot
|
|
19
|
+
import androidx.annotation.RequiresApi
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Custom [InputConnectionWrapper] that intercepts all text input from the soft keyboard
|
|
23
|
+
* and routes it through the Rust editor-core engine via the hosting [EditorEditText].
|
|
24
|
+
*
|
|
25
|
+
* Instead of letting Android's EditText text storage handle insertions and deletions
|
|
26
|
+
* directly, this class captures the user's intent (typing, deleting, IME composition)
|
|
27
|
+
* and delegates to the Rust editor. The Rust editor returns render elements, which are
|
|
28
|
+
* converted to [android.text.SpannableStringBuilder] via [RenderBridge] and applied
|
|
29
|
+
* back to the EditText.
|
|
30
|
+
*
|
|
31
|
+
* ## Composition (IME) Handling
|
|
32
|
+
*
|
|
33
|
+
* For CJK input methods, swipe keyboards, and some autocorrect flows, [setComposingText],
|
|
34
|
+
* [commitText], and [finishComposingText] are used together. During composition, we let
|
|
35
|
+
* the base [InputConnection] render transient composing text, but keep the original
|
|
36
|
+
* Rust-authorized replacement range so the final committed text lands at the correct
|
|
37
|
+
* document position.
|
|
38
|
+
*
|
|
39
|
+
* ## Key Events
|
|
40
|
+
*
|
|
41
|
+
* Hardware keyboard events (backspace, enter) arrive via [sendKeyEvent]. We intercept
|
|
42
|
+
* DEL and ENTER to route through the Rust editor.
|
|
43
|
+
*/
|
|
44
|
+
class EditorInputConnection(
|
|
45
|
+
internal val editorView: EditorEditText,
|
|
46
|
+
baseConnection: InputConnection,
|
|
47
|
+
internal val boundEditorId: Long,
|
|
48
|
+
internal val boundGeneration: Long,
|
|
49
|
+
internal val boundMapperGeneration: Long
|
|
50
|
+
) : InputConnectionWrapper(baseConnection, true) {
|
|
51
|
+
companion object {
|
|
52
|
+
private fun textTraceSummary(text: CharSequence?): String {
|
|
53
|
+
if (text == null) return "text=null"
|
|
54
|
+
val value = text.toString()
|
|
55
|
+
val codePoints = mutableListOf<String>()
|
|
56
|
+
var index = 0
|
|
57
|
+
while (index < value.length && codePoints.size < 4) {
|
|
58
|
+
val codePoint = Character.codePointAt(value, index)
|
|
59
|
+
codePoints.add(codePoint.toString(16))
|
|
60
|
+
index += Character.charCount(codePoint)
|
|
61
|
+
}
|
|
62
|
+
return "textLength=${value.length} codePoints=${codePoints.joinToString(",")}"
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
internal const val DUPLICATE_CORRECTION_COMMIT_WINDOW_MS = 1_000L
|
|
66
|
+
|
|
67
|
+
internal fun codePointsToUtf16Length(
|
|
68
|
+
text: String,
|
|
69
|
+
fromUtf16Offset: Int,
|
|
70
|
+
codePointCount: Int,
|
|
71
|
+
forward: Boolean
|
|
72
|
+
): Int {
|
|
73
|
+
if (codePointCount <= 0 || text.isEmpty()) return 0
|
|
74
|
+
|
|
75
|
+
var remaining = codePointCount
|
|
76
|
+
var utf16Length = 0
|
|
77
|
+
|
|
78
|
+
if (forward) {
|
|
79
|
+
var index = fromUtf16Offset.coerceIn(0, text.length)
|
|
80
|
+
while (index < text.length && remaining > 0) {
|
|
81
|
+
val codePoint = Character.codePointAt(text, index)
|
|
82
|
+
val charCount = Character.charCount(codePoint)
|
|
83
|
+
utf16Length += charCount
|
|
84
|
+
index += charCount
|
|
85
|
+
remaining--
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
var index = fromUtf16Offset.coerceIn(0, text.length)
|
|
89
|
+
while (index > 0 && remaining > 0) {
|
|
90
|
+
val codePoint = Character.codePointBefore(text, index)
|
|
91
|
+
val charCount = Character.charCount(codePoint)
|
|
92
|
+
utf16Length += charCount
|
|
93
|
+
index -= charCount
|
|
94
|
+
remaining--
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return utf16Length
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
internal var closedForInput = false
|
|
103
|
+
internal var extractedTextRequest: ExtractedTextRequest? = null
|
|
104
|
+
internal var lastPublishedExtractedText: ExtractedText? = null
|
|
105
|
+
internal var lastPublishedSelection: List<Int>? = null
|
|
106
|
+
|
|
107
|
+
override fun commitText(
|
|
108
|
+
text: CharSequence,
|
|
109
|
+
newCursorPosition: Int,
|
|
110
|
+
textAttribute: TextAttribute?
|
|
111
|
+
): Boolean = commitText(text, newCursorPosition)
|
|
112
|
+
|
|
113
|
+
override fun setComposingText(
|
|
114
|
+
text: CharSequence,
|
|
115
|
+
newCursorPosition: Int,
|
|
116
|
+
textAttribute: TextAttribute?
|
|
117
|
+
): Boolean = setComposingText(text, newCursorPosition)
|
|
118
|
+
|
|
119
|
+
override fun setComposingRegion(start: Int, end: Int, textAttribute: TextAttribute?): Boolean =
|
|
120
|
+
setComposingRegion(start, end)
|
|
121
|
+
|
|
122
|
+
override fun replaceText(
|
|
123
|
+
start: Int,
|
|
124
|
+
end: Int,
|
|
125
|
+
text: CharSequence,
|
|
126
|
+
newCursorPosition: Int,
|
|
127
|
+
textAttribute: TextAttribute?
|
|
128
|
+
): Boolean {
|
|
129
|
+
if (!isCurrentInputSessionFor("replaceText") || !editorView.isEditable) return true
|
|
130
|
+
if (start < 0 || end < 0) return false
|
|
131
|
+
val requestedText = currentMapper()?.visibleText?.toString() ?: return false
|
|
132
|
+
if (!editorView.prepareForExternalEditorUpdate()) return true
|
|
133
|
+
if (!isCurrentInputSession() ||
|
|
134
|
+
currentMapper()?.visibleText?.toString() != requestedText
|
|
135
|
+
) {
|
|
136
|
+
return true
|
|
137
|
+
}
|
|
138
|
+
val range =
|
|
139
|
+
rawRangeForIme(
|
|
140
|
+
start.coerceAtMost(requestedText.length),
|
|
141
|
+
end.coerceAtMost(requestedText.length)
|
|
142
|
+
)
|
|
143
|
+
?: return false
|
|
144
|
+
val raw = editorView.editableText.toString()
|
|
145
|
+
val normalized = if (range.first == range.second) {
|
|
146
|
+
PositionBridge.snapToScalarBoundary(range.first, raw, biasForward = true).let {
|
|
147
|
+
it to it
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
PositionBridge.snapRangeToScalarBoundaries(range.first, range.second, raw)
|
|
151
|
+
}
|
|
152
|
+
pendingDuplicateCorrectionCommit = null
|
|
153
|
+
pendingCompositionCorrectionCommit = null
|
|
154
|
+
editorView.runWithTransientInputMutationGuard {
|
|
155
|
+
super.setSelection(normalized.first, normalized.second)
|
|
156
|
+
}
|
|
157
|
+
commitTextToEditor(text.toString(), newCursorPosition)
|
|
158
|
+
return true
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
override fun getExtractedText(request: ExtractedTextRequest?, flags: Int): ExtractedText? =
|
|
162
|
+
extractedTextForIme(request, flags)
|
|
163
|
+
|
|
164
|
+
@RequiresApi(31)
|
|
165
|
+
override fun getSurroundingText(
|
|
166
|
+
beforeLength: Int,
|
|
167
|
+
afterLength: Int,
|
|
168
|
+
flags: Int
|
|
169
|
+
): SurroundingText? = surroundingTextForIme(beforeLength, afterLength, flags)
|
|
170
|
+
|
|
171
|
+
@RequiresApi(33)
|
|
172
|
+
override fun takeSnapshot(): TextSnapshot? = snapshotForIme()
|
|
173
|
+
|
|
174
|
+
override fun beginBatchEdit(): Boolean = isCurrentInputSession() && super.beginBatchEdit()
|
|
175
|
+
|
|
176
|
+
override fun performContextMenuAction(id: Int): Boolean =
|
|
177
|
+
isCurrentInputSession() && super.performContextMenuAction(id)
|
|
178
|
+
|
|
179
|
+
override fun performEditorAction(actionCode: Int): Boolean =
|
|
180
|
+
isCurrentInputSession() && editorView.isEditable && super.performEditorAction(actionCode)
|
|
181
|
+
|
|
182
|
+
override fun requestCursorUpdates(cursorUpdateMode: Int): Boolean =
|
|
183
|
+
isCurrentInputSession() && super.requestCursorUpdates(cursorUpdateMode)
|
|
184
|
+
|
|
185
|
+
override fun requestCursorUpdates(cursorUpdateMode: Int, cursorUpdateFilter: Int): Boolean =
|
|
186
|
+
isCurrentInputSession() && super.requestCursorUpdates(cursorUpdateMode, cursorUpdateFilter)
|
|
187
|
+
|
|
188
|
+
override fun closeConnection() {
|
|
189
|
+
if (closedForInput) return
|
|
190
|
+
if (isCurrentInputSession()) finishComposingText()
|
|
191
|
+
closedForInput = true
|
|
192
|
+
extractedTextRequest = null
|
|
193
|
+
lastPublishedExtractedText = null
|
|
194
|
+
super.closeConnection()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
internal var pendingDuplicateCorrectionCommit: PendingDuplicateCorrectionCommit? = null
|
|
198
|
+
internal var pendingCompositionCorrectionCommit: PendingCompositionCorrectionCommit? = null
|
|
199
|
+
internal var pendingCompositionCorrectionGeneration: Long = 0L
|
|
200
|
+
private var generatedCompositionAdjustment: GeneratedCompositionAdjustment? = null
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Called when the IME commits finalized text (single character, word,
|
|
204
|
+
* autocomplete selection, etc.).
|
|
205
|
+
*
|
|
206
|
+
* Routes the text through Rust instead of directly inserting into the EditText.
|
|
207
|
+
*/
|
|
208
|
+
override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean {
|
|
209
|
+
if (!isCurrentInputSessionFor("commitText")) return true
|
|
210
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
211
|
+
if (!editorView.isEditable) return true
|
|
212
|
+
if (editorView.isApplyingRustState) {
|
|
213
|
+
editorView.recordImeTraceForTesting(
|
|
214
|
+
"commitTextPassthrough",
|
|
215
|
+
"reason=applyingRust ${textTraceSummary(text)} cursor=$newCursorPosition"
|
|
216
|
+
)
|
|
217
|
+
return super.commitText(text, newCursorPosition)
|
|
218
|
+
}
|
|
219
|
+
if (editorView.editorId == 0L) {
|
|
220
|
+
editorView.recordImeTraceForTesting(
|
|
221
|
+
"commitTextPassthrough",
|
|
222
|
+
"reason=noEditor ${textTraceSummary(text)} cursor=$newCursorPosition"
|
|
223
|
+
)
|
|
224
|
+
return super.commitText(text, newCursorPosition)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
editorView.recordImeTraceForTesting(
|
|
228
|
+
"commitText",
|
|
229
|
+
"${textTraceSummary(text)} cursor=$newCursorPosition"
|
|
230
|
+
)
|
|
231
|
+
val committedText = text?.toString()
|
|
232
|
+
if (consumePendingCompositionCorrectionCommitIfNeeded(committedText, newCursorPosition)) {
|
|
233
|
+
return true
|
|
234
|
+
}
|
|
235
|
+
applyPendingCompositionCorrectionCommitIfNeeded("commitTextBeforePlain")
|
|
236
|
+
if (consumePendingDuplicateCorrectionCommitIfNeeded(committedText)) {
|
|
237
|
+
editorView.recordImeTraceForTesting(
|
|
238
|
+
"commitTextDuplicateCorrectionIgnored",
|
|
239
|
+
"textLength=${committedText?.length ?: 0}"
|
|
240
|
+
)
|
|
241
|
+
return true
|
|
242
|
+
}
|
|
243
|
+
commitTextToEditor(committedText, newCursorPosition)
|
|
244
|
+
return true
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
override fun commitCompletion(text: CompletionInfo?): Boolean {
|
|
248
|
+
if (!isCurrentInputSessionFor("commitCompletion")) return true
|
|
249
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
250
|
+
if (!editorView.isEditable) return true
|
|
251
|
+
if (editorView.isApplyingRustState) {
|
|
252
|
+
return super.commitCompletion(text)
|
|
253
|
+
}
|
|
254
|
+
if (editorView.editorId == 0L) {
|
|
255
|
+
return super.commitCompletion(text)
|
|
256
|
+
}
|
|
257
|
+
editorView.recordImeTraceForTesting(
|
|
258
|
+
"commitCompletion",
|
|
259
|
+
textTraceSummary(text?.text)
|
|
260
|
+
)
|
|
261
|
+
commitTextToEditor(text?.text?.toString(), 1)
|
|
262
|
+
return true
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
override fun getCursorCapsMode(reqModes: Int): Int {
|
|
266
|
+
val baseCapsMode = super.getCursorCapsMode(reqModes)
|
|
267
|
+
if (!isCurrentInputSession()) return baseCapsMode
|
|
268
|
+
val capsMode = editorView.cursorCapsModeForEditor(reqModes, baseCapsMode)
|
|
269
|
+
if (capsMode != baseCapsMode) {
|
|
270
|
+
editorView.recordImeTraceForTesting(
|
|
271
|
+
"getCursorCapsModeAdjusted",
|
|
272
|
+
"req=$reqModes base=$baseCapsMode caps=$capsMode"
|
|
273
|
+
)
|
|
274
|
+
}
|
|
275
|
+
return capsMode
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
override fun getTextBeforeCursor(n: Int, flags: Int): CharSequence? {
|
|
279
|
+
val mapper = currentMapper() ?: return ""
|
|
280
|
+
val cursor = minOf(editorView.selectionStart, editorView.selectionEnd)
|
|
281
|
+
if (cursor < 0) return ""
|
|
282
|
+
val end = mapper.rawToIme(cursor)
|
|
283
|
+
return imeTextSlice(mapper, maxOf(0, end - n.coerceAtLeast(0)), end, flags)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
override fun getTextAfterCursor(n: Int, flags: Int): CharSequence? {
|
|
287
|
+
val mapper = currentMapper() ?: return ""
|
|
288
|
+
val cursor = maxOf(editorView.selectionStart, editorView.selectionEnd)
|
|
289
|
+
if (cursor < 0) return ""
|
|
290
|
+
val start = mapper.rawToIme(cursor)
|
|
291
|
+
return imeTextSlice(
|
|
292
|
+
mapper,
|
|
293
|
+
start,
|
|
294
|
+
minOf(mapper.visibleText.length, start + n.coerceAtLeast(0)),
|
|
295
|
+
flags
|
|
296
|
+
)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
override fun getSelectedText(flags: Int): CharSequence? {
|
|
300
|
+
val mapper = currentMapper() ?: return ""
|
|
301
|
+
val rawStart = editorView.selectionStart
|
|
302
|
+
val rawEnd = editorView.selectionEnd
|
|
303
|
+
if (rawStart < 0 || rawEnd < 0) return ""
|
|
304
|
+
if (rawStart == rawEnd) return null
|
|
305
|
+
val imeStart = mapper.rawToIme(minOf(rawStart, rawEnd))
|
|
306
|
+
val imeEnd = mapper.rawToIme(maxOf(rawStart, rawEnd))
|
|
307
|
+
if (imeStart == imeEnd) return null
|
|
308
|
+
return imeTextSlice(
|
|
309
|
+
mapper,
|
|
310
|
+
imeStart,
|
|
311
|
+
imeEnd,
|
|
312
|
+
flags
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
override fun commitCorrection(correctionInfo: CorrectionInfo?): Boolean {
|
|
317
|
+
if (!isCurrentInputSessionFor("commitCorrection")) return true
|
|
318
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
319
|
+
if (!editorView.isEditable) return true
|
|
320
|
+
if (editorView.isApplyingRustState) {
|
|
321
|
+
return super.commitCorrection(correctionInfo)
|
|
322
|
+
}
|
|
323
|
+
if (editorView.editorId == 0L) {
|
|
324
|
+
return super.commitCorrection(correctionInfo)
|
|
325
|
+
}
|
|
326
|
+
val newText = correctionInfo?.newText?.toString()
|
|
327
|
+
if (newText == null) return true
|
|
328
|
+
editorView.recordImeTraceForTesting(
|
|
329
|
+
"commitCorrection",
|
|
330
|
+
"offset=${correctionInfo.offset} oldMissing=${correctionInfo.oldText == null} newLength=${newText.length}"
|
|
331
|
+
)
|
|
332
|
+
if (trackedCompositionReplacementRange() != null) {
|
|
333
|
+
editorView.recordImeTraceForTesting(
|
|
334
|
+
"commitCorrectionComposition",
|
|
335
|
+
"newLength=${newText.length}"
|
|
336
|
+
)
|
|
337
|
+
rememberPendingCompositionCorrectionCommit(newText)
|
|
338
|
+
return true
|
|
339
|
+
}
|
|
340
|
+
if (consumeInvalidatedCompositionReplacementRangeAndRestore()) {
|
|
341
|
+
editorView.recordImeTraceForTesting("commitCorrectionRestoredInvalidComposition")
|
|
342
|
+
return true
|
|
343
|
+
}
|
|
344
|
+
val oldText = correctionInfo.oldText?.toString()
|
|
345
|
+
if (oldText?.isEmpty() == true) {
|
|
346
|
+
editorView.recordImeTraceForTesting("correctionExplicitNoop", "reason=emptyOldText")
|
|
347
|
+
return true
|
|
348
|
+
}
|
|
349
|
+
val imeOffset = correctionInfo.offset
|
|
350
|
+
val mapper = currentMapper()
|
|
351
|
+
val applied = if (oldText != null && mapper != null) {
|
|
352
|
+
val validOffset = imeOffset in 0..mapper.visibleText.length
|
|
353
|
+
val imeEnd = if (
|
|
354
|
+
validOffset &&
|
|
355
|
+
oldText.length <= mapper.visibleText.length - imeOffset
|
|
356
|
+
) {
|
|
357
|
+
imeOffset + oldText.length
|
|
358
|
+
} else {
|
|
359
|
+
-1
|
|
360
|
+
}
|
|
361
|
+
if (
|
|
362
|
+
imeEnd >= 0 &&
|
|
363
|
+
mapper.visibleText.subSequence(imeOffset, imeEnd).toString() == oldText
|
|
364
|
+
) {
|
|
365
|
+
val rawStart = mapper.imeToRaw(
|
|
366
|
+
imeOffset,
|
|
367
|
+
ImeTextCoordinateMapper.Affinity.AFTER
|
|
368
|
+
)
|
|
369
|
+
val rawEnd = mapper.imeToRaw(
|
|
370
|
+
imeEnd,
|
|
371
|
+
ImeTextCoordinateMapper.Affinity.BEFORE
|
|
372
|
+
)
|
|
373
|
+
val renderedOldText = editorView.text
|
|
374
|
+
?.subSequence(rawStart, rawEnd)
|
|
375
|
+
?.toString()
|
|
376
|
+
?: ""
|
|
377
|
+
editorView.handleCorrectionCommit(
|
|
378
|
+
rawStart,
|
|
379
|
+
rawEnd,
|
|
380
|
+
renderedOldText,
|
|
381
|
+
newText
|
|
382
|
+
)
|
|
383
|
+
} else {
|
|
384
|
+
editorView.recordImeTraceForTesting(
|
|
385
|
+
"correctionExplicitNoop",
|
|
386
|
+
"reason=staleVisibleText offset=$imeOffset oldLength=${oldText.length}"
|
|
387
|
+
)
|
|
388
|
+
false
|
|
389
|
+
}
|
|
390
|
+
} else if (oldText == null) {
|
|
391
|
+
val visibleText = mapper?.visibleText?.toString()
|
|
392
|
+
val tokenRange = visibleText?.let {
|
|
393
|
+
editorView.missingOldTextCorrectionTokenRangeForEditor(it, imeOffset)
|
|
394
|
+
}
|
|
395
|
+
if (mapper != null && tokenRange != null) {
|
|
396
|
+
val rawStart = mapper.imeToRaw(
|
|
397
|
+
tokenRange.first,
|
|
398
|
+
ImeTextCoordinateMapper.Affinity.AFTER
|
|
399
|
+
)
|
|
400
|
+
val rawEnd = mapper.imeToRaw(
|
|
401
|
+
tokenRange.second,
|
|
402
|
+
ImeTextCoordinateMapper.Affinity.BEFORE
|
|
403
|
+
)
|
|
404
|
+
val renderedOldText = editorView.text
|
|
405
|
+
?.subSequence(rawStart, rawEnd)
|
|
406
|
+
?.toString()
|
|
407
|
+
?: ""
|
|
408
|
+
editorView.handleMissingOldTextCorrectionCommit(
|
|
409
|
+
rawStart,
|
|
410
|
+
rawEnd,
|
|
411
|
+
renderedOldText,
|
|
412
|
+
newText
|
|
413
|
+
)
|
|
414
|
+
} else {
|
|
415
|
+
editorView.recordImeTraceForTesting(
|
|
416
|
+
"correctionInferredNoop",
|
|
417
|
+
"reason=noVisibleToken offset=$imeOffset newLength=${newText.length}"
|
|
418
|
+
)
|
|
419
|
+
false
|
|
420
|
+
}
|
|
421
|
+
} else {
|
|
422
|
+
false
|
|
423
|
+
}
|
|
424
|
+
editorView.recordImeTraceForTesting(
|
|
425
|
+
"commitCorrectionResult",
|
|
426
|
+
"applied=$applied"
|
|
427
|
+
)
|
|
428
|
+
if (applied) {
|
|
429
|
+
rememberPendingDuplicateCorrectionCommit(newText)
|
|
430
|
+
}
|
|
431
|
+
return true
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
internal fun commitTextToEditor(committedText: String?, newCursorPosition: Int) {
|
|
435
|
+
val startedAt = System.nanoTime()
|
|
436
|
+
val trackedReplacementRange = trackedCompositionReplacementRange()
|
|
437
|
+
val rawComposingSpanRange = currentComposingSpanRawRange()
|
|
438
|
+
val currentAuthorizedComposingSpanRange = currentComposingSpanRange()
|
|
439
|
+
val visibleReplacementRange = rawComposingSpanRange ?: trackedReplacementRange
|
|
440
|
+
val replacementRange = trackedReplacementRange?.let { range ->
|
|
441
|
+
if (range.first == range.second) {
|
|
442
|
+
currentAuthorizedComposingSpanRange ?: range
|
|
443
|
+
} else {
|
|
444
|
+
range
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
if (replacementRange != null) {
|
|
448
|
+
editorView.recordImeTraceForTesting(
|
|
449
|
+
"commitTextRoute",
|
|
450
|
+
"route=composition replacement=${replacementRange.first}..${replacementRange.second} visible=${visibleReplacementRange?.first}..${visibleReplacementRange?.second} textLength=${committedText?.length ?: 0}"
|
|
451
|
+
)
|
|
452
|
+
clearCompositionTracking()
|
|
453
|
+
editorView.runWithTransientInputMutationGuard {
|
|
454
|
+
super.finishComposingText()
|
|
455
|
+
}
|
|
456
|
+
if (committedText != null) {
|
|
457
|
+
var didCommitAlreadyVisibleMutation = false
|
|
458
|
+
if (
|
|
459
|
+
trackedReplacementRange?.first == trackedReplacementRange?.second &&
|
|
460
|
+
rawComposingSpanRange == null
|
|
461
|
+
) {
|
|
462
|
+
editorView.runWithDeferredRustUpdateApplication {
|
|
463
|
+
didCommitAlreadyVisibleMutation =
|
|
464
|
+
editorView
|
|
465
|
+
.commitVisibleCompositionMutationForPendingImeOperation(
|
|
466
|
+
committedText,
|
|
467
|
+
newCursorPosition
|
|
468
|
+
)
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
if (!didCommitAlreadyVisibleMutation) {
|
|
472
|
+
visibleReplacementRange?.let { visibleRange ->
|
|
473
|
+
editorView.applyVisibleCompositionCommitForPendingImeOperationForEditor(
|
|
474
|
+
committedText,
|
|
475
|
+
visibleRange.first,
|
|
476
|
+
visibleRange.second,
|
|
477
|
+
newCursorPosition
|
|
478
|
+
)
|
|
479
|
+
}
|
|
480
|
+
editorView.runWithDeferredRustUpdateApplication {
|
|
481
|
+
editorView.handleCompositionCommit(
|
|
482
|
+
committedText,
|
|
483
|
+
replacementRange.first,
|
|
484
|
+
replacementRange.second,
|
|
485
|
+
newCursorPosition
|
|
486
|
+
)
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
editorView.restoreAuthorizedTextIfNeeded()
|
|
491
|
+
}
|
|
492
|
+
} else {
|
|
493
|
+
if (consumeInvalidatedCompositionReplacementRangeAndRestore()) {
|
|
494
|
+
editorView.recordImeTraceForTesting(
|
|
495
|
+
"commitTextRoute",
|
|
496
|
+
"route=restoreInvalidComposition textLength=${committedText?.length ?: 0}"
|
|
497
|
+
)
|
|
498
|
+
return
|
|
499
|
+
}
|
|
500
|
+
clearCompositionTracking()
|
|
501
|
+
editorView.recordImeTraceForTesting(
|
|
502
|
+
"commitTextRoute",
|
|
503
|
+
"route=plain textLength=${committedText?.length ?: 0}"
|
|
504
|
+
)
|
|
505
|
+
committedText?.let { editorView.handleTextCommit(it, newCursorPosition) }
|
|
506
|
+
}
|
|
507
|
+
editorView.recordImeTraceForTesting(
|
|
508
|
+
"commitTextRouteDone",
|
|
509
|
+
"textLength=${committedText?.length ?: 0} totalUs=${nanosToMicros(
|
|
510
|
+
System.nanoTime() - startedAt
|
|
511
|
+
)}"
|
|
512
|
+
)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Called when the IME requests deletion of text surrounding the cursor.
|
|
517
|
+
*
|
|
518
|
+
* Routes the deletion through Rust instead of directly modifying the EditText.
|
|
519
|
+
*
|
|
520
|
+
* @param beforeLength Number of UTF-16 code units to delete before the cursor.
|
|
521
|
+
* @param afterLength Number of UTF-16 code units to delete after the cursor.
|
|
522
|
+
*/
|
|
523
|
+
override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean {
|
|
524
|
+
if (!isCurrentInputSessionFor("deleteSurroundingText")) return true
|
|
525
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
526
|
+
if (!editorView.isEditable) return true
|
|
527
|
+
if (editorView.isApplyingRustState) {
|
|
528
|
+
return super.deleteSurroundingText(beforeLength, afterLength)
|
|
529
|
+
}
|
|
530
|
+
editorView.recordImeTraceForTesting(
|
|
531
|
+
"deleteSurroundingText",
|
|
532
|
+
"before=$beforeLength after=$afterLength"
|
|
533
|
+
)
|
|
534
|
+
if (
|
|
535
|
+
editorView.hasInvalidatedCompositionReplacementRangeForEditor() &&
|
|
536
|
+
isNoOpSurroundingDelete(beforeLength, afterLength)
|
|
537
|
+
) {
|
|
538
|
+
return finishStaleComposingUpdateAfterInvalidation()
|
|
539
|
+
}
|
|
540
|
+
if (consumeInvalidatedCompositionReplacementRangeAndRestore()) {
|
|
541
|
+
return true
|
|
542
|
+
}
|
|
543
|
+
if (trackedCompositionReplacementRange() != null) {
|
|
544
|
+
return performMappedCompositionSurroundingDelete(
|
|
545
|
+
beforeLength,
|
|
546
|
+
afterLength,
|
|
547
|
+
deleteInCodePoints = false
|
|
548
|
+
)
|
|
549
|
+
}
|
|
550
|
+
if (shouldDeferPlainSurroundingDelete(beforeLength, afterLength)) {
|
|
551
|
+
return performDeferredPlainSurroundingDelete(
|
|
552
|
+
beforeLength = beforeLength,
|
|
553
|
+
afterLength = afterLength,
|
|
554
|
+
deleteInCodePoints = false
|
|
555
|
+
)
|
|
556
|
+
}
|
|
557
|
+
editorView.handleDelete(beforeLength, afterLength)
|
|
558
|
+
return true
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
override fun deleteSurroundingTextInCodePoints(beforeLength: Int, afterLength: Int): Boolean {
|
|
562
|
+
if (!isCurrentInputSessionFor("deleteSurroundingTextInCodePoints")) return true
|
|
563
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
564
|
+
if (!editorView.isEditable) return true
|
|
565
|
+
if (editorView.isApplyingRustState) {
|
|
566
|
+
return super.deleteSurroundingTextInCodePoints(beforeLength, afterLength)
|
|
567
|
+
}
|
|
568
|
+
editorView.recordImeTraceForTesting(
|
|
569
|
+
"deleteSurroundingTextInCodePoints",
|
|
570
|
+
"before=$beforeLength after=$afterLength"
|
|
571
|
+
)
|
|
572
|
+
if (
|
|
573
|
+
editorView.hasInvalidatedCompositionReplacementRangeForEditor() &&
|
|
574
|
+
isNoOpSurroundingDelete(beforeLength, afterLength)
|
|
575
|
+
) {
|
|
576
|
+
return finishStaleComposingUpdateAfterInvalidation()
|
|
577
|
+
}
|
|
578
|
+
if (consumeInvalidatedCompositionReplacementRangeAndRestore()) {
|
|
579
|
+
return true
|
|
580
|
+
}
|
|
581
|
+
if (trackedCompositionReplacementRange() != null) {
|
|
582
|
+
return performMappedCompositionSurroundingDelete(
|
|
583
|
+
beforeLength,
|
|
584
|
+
afterLength,
|
|
585
|
+
deleteInCodePoints = true
|
|
586
|
+
)
|
|
587
|
+
}
|
|
588
|
+
if (shouldDeferPlainSurroundingDelete(beforeLength, afterLength)) {
|
|
589
|
+
return performDeferredPlainSurroundingDelete(
|
|
590
|
+
beforeLength = beforeLength,
|
|
591
|
+
afterLength = afterLength,
|
|
592
|
+
deleteInCodePoints = true
|
|
593
|
+
)
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
val currentText = editorView.text?.toString().orEmpty()
|
|
597
|
+
val cursor = editorView.selectionStart.coerceAtLeast(0)
|
|
598
|
+
val beforeUtf16Length = codePointsToUtf16Length(
|
|
599
|
+
text = currentText,
|
|
600
|
+
fromUtf16Offset = cursor,
|
|
601
|
+
codePointCount = beforeLength,
|
|
602
|
+
forward = false
|
|
603
|
+
)
|
|
604
|
+
val afterUtf16Length = codePointsToUtf16Length(
|
|
605
|
+
text = currentText,
|
|
606
|
+
fromUtf16Offset = editorView.selectionEnd.coerceAtLeast(cursor),
|
|
607
|
+
codePointCount = afterLength,
|
|
608
|
+
forward = true
|
|
609
|
+
)
|
|
610
|
+
editorView.handleDelete(beforeUtf16Length, afterUtf16Length)
|
|
611
|
+
return true
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Called when the IME sets composing (in-progress) text for CJK/swipe input.
|
|
616
|
+
*
|
|
617
|
+
* We let the base InputConnection handle this normally so the user sees
|
|
618
|
+
* the composing text with its underline decoration. The text is NOT sent
|
|
619
|
+
* to Rust during composition — only when the IME commits or finishes it.
|
|
620
|
+
*/
|
|
621
|
+
override fun setComposingText(text: CharSequence?, newCursorPosition: Int): Boolean {
|
|
622
|
+
if (!isCurrentInputSessionFor("setComposingText")) return true
|
|
623
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
624
|
+
if (!editorView.isEditable) return true
|
|
625
|
+
if (editorView.editorId == 0L) return super.setComposingText(text, newCursorPosition)
|
|
626
|
+
if (editorView.hasInvalidatedCompositionReplacementRangeForEditor()) {
|
|
627
|
+
return finishStaleComposingUpdateAfterInvalidation()
|
|
628
|
+
}
|
|
629
|
+
captureCompositionReplacementRangeIfNeeded()
|
|
630
|
+
val composingText = text?.toString()?.let { value ->
|
|
631
|
+
generatedCompositionAdjustment?.sanitize(value) ?: value
|
|
632
|
+
}
|
|
633
|
+
val adjustedComposingText =
|
|
634
|
+
editorView.samsungSentenceCapsComposingTextForEditor(composingText)
|
|
635
|
+
val textForBaseConnection = adjustedComposingText ?: text
|
|
636
|
+
editorView.recordImeTraceForTesting(
|
|
637
|
+
"setComposingText",
|
|
638
|
+
"${textTraceSummary(
|
|
639
|
+
text
|
|
640
|
+
)} cursor=$newCursorPosition adjusted=${textForBaseConnection.toString() != text?.toString()}"
|
|
641
|
+
)
|
|
642
|
+
editorView.setComposingTextForEditor(adjustedComposingText)
|
|
643
|
+
val trackedRange = trackedCompositionReplacementRange()
|
|
644
|
+
val currentText = editorView.text?.toString()
|
|
645
|
+
if (
|
|
646
|
+
trackedRange != null &&
|
|
647
|
+
currentText != null &&
|
|
648
|
+
editorView.isCurrentTextAuthorizedForEditor() &&
|
|
649
|
+
currentText.substring(trackedRange.first, trackedRange.second) == adjustedComposingText
|
|
650
|
+
) {
|
|
651
|
+
return editorView.runWithTransientInputMutationGuard {
|
|
652
|
+
val regionSet = super.setComposingRegion(trackedRange.first, trackedRange.second)
|
|
653
|
+
val requestedCursor = if (newCursorPosition > 0) {
|
|
654
|
+
trackedRange.second + newCursorPosition - 1
|
|
655
|
+
} else {
|
|
656
|
+
trackedRange.first + newCursorPosition
|
|
657
|
+
}.coerceIn(0, currentText.length)
|
|
658
|
+
val selectionSet = super.setSelection(requestedCursor, requestedCursor)
|
|
659
|
+
if (regionSet) {
|
|
660
|
+
editorView.applyTransientComposingTextStyleForEditor()
|
|
661
|
+
}
|
|
662
|
+
regionSet && selectionSet
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return editorView.runWithTransientInputMutationGuard {
|
|
666
|
+
val result = super.setComposingText(textForBaseConnection, newCursorPosition)
|
|
667
|
+
if (result) {
|
|
668
|
+
editorView.applyTransientComposingTextStyleForEditor()
|
|
669
|
+
}
|
|
670
|
+
result
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
override fun setComposingRegion(start: Int, end: Int): Boolean {
|
|
675
|
+
if (!isCurrentInputSessionFor("setComposingRegion")) return true
|
|
676
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
677
|
+
if (!editorView.isEditable) return true
|
|
678
|
+
val rawRange = rawRangeForIme(start, end) ?: return true
|
|
679
|
+
if (editorView.editorId == 0L) {
|
|
680
|
+
return super.setComposingRegion(rawRange.first, rawRange.second)
|
|
681
|
+
}
|
|
682
|
+
if (editorView.hasInvalidatedCompositionReplacementRangeForEditor()) {
|
|
683
|
+
return finishStaleComposingUpdateAfterInvalidation()
|
|
684
|
+
}
|
|
685
|
+
val currentText = editorView.text?.toString().orEmpty()
|
|
686
|
+
val requestedStart = minOf(rawRange.first, rawRange.second).coerceIn(0, currentText.length)
|
|
687
|
+
val requestedEnd = maxOf(rawRange.first, rawRange.second).coerceIn(0, currentText.length)
|
|
688
|
+
val contentRange = editorView.compositionContentRangeForEditor(requestedStart, requestedEnd)
|
|
689
|
+
if (contentRange == null) {
|
|
690
|
+
generatedCompositionAdjustment = null
|
|
691
|
+
editorView.recordImeTraceForTesting(
|
|
692
|
+
"setComposingRegionRejected",
|
|
693
|
+
"range=$start..$end reason=generatedInterior"
|
|
694
|
+
)
|
|
695
|
+
return true
|
|
696
|
+
}
|
|
697
|
+
if (editorView.isCurrentTextAuthorizedForEditor()) {
|
|
698
|
+
editorView.setCompositionReplacementRange(contentRange.first, contentRange.second)
|
|
699
|
+
}
|
|
700
|
+
generatedCompositionAdjustment = if (
|
|
701
|
+
contentRange.first != requestedStart || contentRange.second != requestedEnd
|
|
702
|
+
) {
|
|
703
|
+
GeneratedCompositionAdjustment(
|
|
704
|
+
leadingText = currentText.substring(requestedStart, contentRange.first),
|
|
705
|
+
trailingText = currentText.substring(contentRange.second, requestedEnd)
|
|
706
|
+
)
|
|
707
|
+
} else {
|
|
708
|
+
null
|
|
709
|
+
}
|
|
710
|
+
editorView.recordImeTraceForTesting(
|
|
711
|
+
"setComposingRegion",
|
|
712
|
+
"range=$start..$end content=${contentRange.first}..${contentRange.second}"
|
|
713
|
+
)
|
|
714
|
+
return editorView.runWithTransientInputMutationGuard {
|
|
715
|
+
val result = super.setComposingRegion(contentRange.first, contentRange.second)
|
|
716
|
+
if (result) {
|
|
717
|
+
editorView.applyTransientComposingTextStyleForEditor()
|
|
718
|
+
}
|
|
719
|
+
result
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
override fun setSelection(start: Int, end: Int): Boolean {
|
|
724
|
+
if (!isCurrentInputSessionFor("setSelection")) return true
|
|
725
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
726
|
+
val rawRange = rawRangeForIme(start, end) ?: return true
|
|
727
|
+
if (!editorView.isEditable) {
|
|
728
|
+
consumeInvalidatedCompositionReplacementRangeAndRestore()
|
|
729
|
+
return true
|
|
730
|
+
}
|
|
731
|
+
if (editorView.isApplyingRustState) {
|
|
732
|
+
return super.setSelection(rawRange.first, rawRange.second)
|
|
733
|
+
}
|
|
734
|
+
if (editorView.editorId == 0L) {
|
|
735
|
+
return super.setSelection(rawRange.first, rawRange.second)
|
|
736
|
+
}
|
|
737
|
+
if (editorView.hasInvalidatedCompositionReplacementRangeForEditor()) {
|
|
738
|
+
return finishStaleComposingUpdateAfterInvalidation()
|
|
739
|
+
}
|
|
740
|
+
return super.setSelection(rawRange.first, rawRange.second)
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Called when IME composition is finalized (user selects a candidate or
|
|
745
|
+
* presses space/enter to commit the composing text).
|
|
746
|
+
*
|
|
747
|
+
* At this point, the composed text is final. We notify the [EditorEditText]
|
|
748
|
+
* so it can capture the result and send it to Rust.
|
|
749
|
+
*/
|
|
750
|
+
override fun finishComposingText(): Boolean {
|
|
751
|
+
if (!isCurrentInputSessionFor("finishComposingText")) return true
|
|
752
|
+
if (editorView.hasActiveExternalTextCompositionForEditor()) return true
|
|
753
|
+
if (applyPendingCompositionCorrectionCommitIfNeeded("finishComposingText")) return true
|
|
754
|
+
return finishComposingTextInternal(blockWhenCompositionWasCancelled = false)
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
internal fun flushPendingCompositionForExternalMutation(): Boolean {
|
|
758
|
+
if (!isCurrentInputSessionFor("flushPendingComposition")) return true
|
|
759
|
+
if (!hasPendingComposition()) return true
|
|
760
|
+
return finishComposingTextInternal(blockWhenCompositionWasCancelled = true)
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
internal fun hasPendingComposition(): Boolean {
|
|
764
|
+
if (!isCurrentInputSessionFor("hasPendingComposition")) return false
|
|
765
|
+
if (trackedCompositionReplacementRange() != null) return true
|
|
766
|
+
val editable = editorView.text ?: return false
|
|
767
|
+
val start = BaseInputConnection.getComposingSpanStart(editable)
|
|
768
|
+
val end = BaseInputConnection.getComposingSpanEnd(editable)
|
|
769
|
+
return start >= 0 && end >= 0 && start != end
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
internal fun refreshComposingTextFromEditableForEditor() {
|
|
773
|
+
if (!isCurrentInputSessionFor("refreshComposingText")) return
|
|
774
|
+
refreshComposingTextFromEditable()
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
internal fun clearCompositionTrackingForEditor() {
|
|
778
|
+
if (!isCurrentInputSessionFor("clearCompositionTracking")) return
|
|
779
|
+
clearCompositionTracking()
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
internal fun deleteTransientTextForHardwareKeyEvent(event: KeyEvent): Boolean =
|
|
783
|
+
if (!isCurrentInputSession()) {
|
|
784
|
+
false
|
|
785
|
+
} else {
|
|
786
|
+
when (event.keyCode) {
|
|
787
|
+
KeyEvent.KEYCODE_DEL -> deleteTransientTextAroundSelectionInCodePoints(1, 0)
|
|
788
|
+
KeyEvent.KEYCODE_FORWARD_DEL -> deleteTransientTextAroundSelectionInCodePoints(0, 1)
|
|
789
|
+
else -> false
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
private fun finishComposingTextInternal(blockWhenCompositionWasCancelled: Boolean): Boolean {
|
|
794
|
+
if (!isCurrentInputSessionFor("finishComposingText")) return true
|
|
795
|
+
if (!editorView.isEditable) {
|
|
796
|
+
clearCompositionTracking()
|
|
797
|
+
editorView.restoreAuthorizedTextIfNeeded()
|
|
798
|
+
return true
|
|
799
|
+
}
|
|
800
|
+
if (editorView.editorId == 0L) return super.finishComposingText()
|
|
801
|
+
refreshComposingTextFromEditable()
|
|
802
|
+
val composed = editorView.composingTextForEditor() ?: currentComposingSpanText()
|
|
803
|
+
val trackedReplacementRange = trackedCompositionReplacementRange()
|
|
804
|
+
val didInvalidateReplacementRange = consumeInvalidatedCompositionReplacementRange()
|
|
805
|
+
val replacementRange = if (didInvalidateReplacementRange) {
|
|
806
|
+
null
|
|
807
|
+
} else {
|
|
808
|
+
trackedReplacementRange ?: currentComposingSpanRange()
|
|
809
|
+
}
|
|
810
|
+
editorView.recordImeTraceForTesting(
|
|
811
|
+
"finishComposingText",
|
|
812
|
+
"replacement=${replacementRange?.first}..${replacementRange?.second} composedLength=${composed?.length ?: 0} invalidated=$didInvalidateReplacementRange"
|
|
813
|
+
)
|
|
814
|
+
clearCompositionTracking()
|
|
815
|
+
|
|
816
|
+
// Prevent selection sync while the base connection commits the composed
|
|
817
|
+
// text, since the Rust document doesn't have it yet.
|
|
818
|
+
val result = editorView.runWithTransientInputMutationGuard {
|
|
819
|
+
super.finishComposingText()
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
if (
|
|
823
|
+
replacementRange != null &&
|
|
824
|
+
(!composed.isNullOrEmpty() || replacementRange.first != replacementRange.second)
|
|
825
|
+
) {
|
|
826
|
+
editorView.runWithDeferredRustUpdateApplication {
|
|
827
|
+
editorView.handleCompositionCommit(
|
|
828
|
+
composed.orEmpty(),
|
|
829
|
+
replacementRange.first,
|
|
830
|
+
replacementRange.second
|
|
831
|
+
)
|
|
832
|
+
}
|
|
833
|
+
return true
|
|
834
|
+
} else if (replacementRange != null) {
|
|
835
|
+
editorView.restoreAuthorizedTextIfNeeded()
|
|
836
|
+
return !blockWhenCompositionWasCancelled
|
|
837
|
+
} else if (didInvalidateReplacementRange) {
|
|
838
|
+
editorView.restoreAuthorizedTextIfNeeded()
|
|
839
|
+
return !blockWhenCompositionWasCancelled
|
|
840
|
+
}
|
|
841
|
+
return result
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
private fun captureCompositionReplacementRangeIfNeeded() {
|
|
845
|
+
editorView.captureCompositionReplacementRangeIfNeeded()
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
private fun trackedCompositionReplacementRange(): Pair<Int, Int>? =
|
|
849
|
+
editorView.compositionReplacementRange()
|
|
850
|
+
|
|
851
|
+
private fun clearCompositionTracking() {
|
|
852
|
+
generatedCompositionAdjustment = null
|
|
853
|
+
editorView.clearCompositionTrackingForEditor()
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
private fun consumeInvalidatedCompositionReplacementRange(): Boolean =
|
|
857
|
+
editorView.consumeInvalidatedCompositionReplacementRangeForEditor()
|
|
858
|
+
|
|
859
|
+
private fun consumeInvalidatedCompositionReplacementRangeAndRestore(): Boolean {
|
|
860
|
+
if (!consumeInvalidatedCompositionReplacementRange()) return false
|
|
861
|
+
clearCompositionTracking()
|
|
862
|
+
editorView.runWithTransientInputMutationGuard {
|
|
863
|
+
super.finishComposingText()
|
|
864
|
+
}
|
|
865
|
+
editorView.restoreAuthorizedTextIfNeeded()
|
|
866
|
+
return true
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
private fun finishStaleComposingUpdateAfterInvalidation(): Boolean {
|
|
870
|
+
clearCompositionTracking()
|
|
871
|
+
val result = editorView.runWithTransientInputMutationGuard {
|
|
872
|
+
super.finishComposingText()
|
|
873
|
+
}
|
|
874
|
+
editorView.restoreAuthorizedTextIfNeeded()
|
|
875
|
+
return result
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
override fun sendKeyEvent(event: KeyEvent?): Boolean {
|
|
879
|
+
if (!isCurrentInputSession()) return true
|
|
880
|
+
if (!editorView.commitExternalTextCompositionBeforeInteractionIfNeeded()) return true
|
|
881
|
+
if (
|
|
882
|
+
event?.action == KeyEvent.ACTION_UP &&
|
|
883
|
+
editorView.hasInvalidatedCompositionReplacementRangeForEditor()
|
|
884
|
+
) {
|
|
885
|
+
return finishStaleComposingUpdateAfterInvalidation()
|
|
886
|
+
}
|
|
887
|
+
if (
|
|
888
|
+
shouldConsumeInvalidatedCompositionForKeyEvent(event) &&
|
|
889
|
+
consumeInvalidatedCompositionReplacementRangeAndRestore()
|
|
890
|
+
) {
|
|
891
|
+
return true
|
|
892
|
+
}
|
|
893
|
+
if (!editorView.isEditable &&
|
|
894
|
+
event?.let { editorView.isReadOnlyTextMutationKeyEvent(it) } == true
|
|
895
|
+
) {
|
|
896
|
+
return true
|
|
897
|
+
}
|
|
898
|
+
if (event != null && editorView.handleCompositionKeyEvent(event) {
|
|
899
|
+
super.sendKeyEvent(event)
|
|
900
|
+
}
|
|
901
|
+
) {
|
|
902
|
+
return true
|
|
903
|
+
}
|
|
904
|
+
if (event != null && editorView.handleHardwareKeyEvent(event)) {
|
|
905
|
+
return true
|
|
906
|
+
}
|
|
907
|
+
if (event != null && editorView.handlePrintableHardwareKeyEvent(event) {
|
|
908
|
+
super.sendKeyEvent(event)
|
|
909
|
+
}
|
|
910
|
+
) {
|
|
911
|
+
return true
|
|
912
|
+
}
|
|
913
|
+
return super.sendKeyEvent(event)
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
private fun shouldConsumeInvalidatedCompositionForKeyEvent(event: KeyEvent?): Boolean {
|
|
917
|
+
if (event == null || event.action == KeyEvent.ACTION_UP) return false
|
|
918
|
+
return editorView.isReadOnlyTextMutationKeyEvent(event)
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
private fun isNoOpSurroundingDelete(beforeLength: Int, afterLength: Int): Boolean =
|
|
922
|
+
beforeLength <= 0 && afterLength <= 0
|
|
923
|
+
}
|