@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,900 @@
|
|
|
1
|
+
package com.apollohg.editor.viewer
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Rect
|
|
5
|
+
import com.apollohg.editor.ImageLoadingPolicy
|
|
6
|
+
import com.apollohg.editor.ProseViewerConfiguration
|
|
7
|
+
import com.apollohg.editor.ProseViewerError
|
|
8
|
+
import com.apollohg.editor.ProseViewerSource
|
|
9
|
+
import com.facebook.react.bridge.Arguments
|
|
10
|
+
import com.facebook.react.bridge.ReadableMap
|
|
11
|
+
import com.facebook.react.bridge.WritableMap
|
|
12
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
13
|
+
import com.facebook.react.uimanager.ReactStylesDiffMap
|
|
14
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
15
|
+
import com.facebook.react.uimanager.StateWrapper
|
|
16
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
17
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
18
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
19
|
+
import com.facebook.react.uimanager.events.Event
|
|
20
|
+
import com.facebook.react.viewmanagers.PreparedProseViewerManagerDelegate
|
|
21
|
+
import com.facebook.react.viewmanagers.PreparedProseViewerManagerInterface
|
|
22
|
+
import com.facebook.yoga.YogaMeasureMode
|
|
23
|
+
import com.facebook.yoga.YogaMeasureOutput
|
|
24
|
+
import java.util.WeakHashMap
|
|
25
|
+
import kotlin.math.roundToInt
|
|
26
|
+
|
|
27
|
+
internal fun fabricConstraintPixels(value: Float): Int? {
|
|
28
|
+
if (!value.isFinite() || value <= 0f || value > Int.MAX_VALUE.toFloat()) return null
|
|
29
|
+
return value.roundToInt().takeIf { it > 0 }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
internal fun fabricPixelsToDp(value: Float, density: Float): Float? {
|
|
33
|
+
if (!value.isFinite() || value < 0f || !density.isFinite() || density <= 0f) return null
|
|
34
|
+
return value / density
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Fabric ViewManager; Yoga measurement creates the artifact and mounting only acquires it. */
|
|
38
|
+
@ReactModule(name = PreparedProseViewerManager.REACT_CLASS)
|
|
39
|
+
internal class PreparedProseViewerManager :
|
|
40
|
+
SimpleViewManager<PreparedProseDrawingView>(),
|
|
41
|
+
PreparedProseViewerManagerInterface<PreparedProseDrawingView> {
|
|
42
|
+
private val delegate: ViewManagerDelegate<PreparedProseDrawingView> =
|
|
43
|
+
PreparedProseViewerManagerDelegate(this)
|
|
44
|
+
private val states = WeakHashMap<PreparedProseDrawingView, ViewState>()
|
|
45
|
+
|
|
46
|
+
override fun getName(): String = REACT_CLASS
|
|
47
|
+
|
|
48
|
+
override fun getDelegate(): ViewManagerDelegate<PreparedProseDrawingView> = delegate
|
|
49
|
+
|
|
50
|
+
override fun createViewInstance(context: ThemedReactContext): PreparedProseDrawingView =
|
|
51
|
+
PreparedProseDrawingView(context).also { view ->
|
|
52
|
+
val state = ViewState()
|
|
53
|
+
states[view] = state
|
|
54
|
+
view.onCodeHighlightsReady = { state.publishFontRevision(1) }
|
|
55
|
+
view.onUsableMetricsChanged = { installCachedLayout(view) }
|
|
56
|
+
view.onVisibleRectChanged = { visible -> state.requestVisibleImages(view, visible) }
|
|
57
|
+
view.onFontConfigurationChanged =
|
|
58
|
+
{ configuration -> state.fontEnvironment.onConfigurationChanged(configuration) }
|
|
59
|
+
view.onInteractionActivated = { interaction -> dispatchInteraction(view, interaction) }
|
|
60
|
+
state.fontEnvironment.onInvalidated =
|
|
61
|
+
{ revision -> state.publishFontRevision(revision) }
|
|
62
|
+
state.fontEnvironment.activate(deliverPending = true)
|
|
63
|
+
state.imagePipeline.onPixels = { attachment, lease ->
|
|
64
|
+
val request = state.requestOrNull()
|
|
65
|
+
if (request != null &&
|
|
66
|
+
state.imagePipeline.acceptsCompletion(request.semanticGenerationIdentity)
|
|
67
|
+
) {
|
|
68
|
+
view.putImageLease(attachment.id, lease)
|
|
69
|
+
} else {
|
|
70
|
+
lease.close()
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
state.imagePipeline.onPixelsReleased = view::removeImageLeases
|
|
74
|
+
state.imagePipeline.onIntrinsicMetadata = { attachment, width, height ->
|
|
75
|
+
if (state.recordIntrinsicSize(attachment, width, height)) {
|
|
76
|
+
state.publishAttachmentRevision()
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
state.imagePipeline.onResourceFailure =
|
|
80
|
+
{ attachment -> dispatchResourceError(view, attachment) }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
override fun onDropViewInstance(view: PreparedProseDrawingView) {
|
|
84
|
+
states.remove(view)?.let { state ->
|
|
85
|
+
state.finishWithoutMountedReplacement(view)
|
|
86
|
+
state.release()
|
|
87
|
+
}
|
|
88
|
+
view.onCodeHighlightsReady = null
|
|
89
|
+
view.onUsableMetricsChanged = null
|
|
90
|
+
view.onVisibleRectChanged = null
|
|
91
|
+
view.onFontConfigurationChanged = null
|
|
92
|
+
view.onInteractionActivated = null
|
|
93
|
+
view.clearImageLeases()
|
|
94
|
+
view.install(null)
|
|
95
|
+
super.onDropViewInstance(view)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
override fun onSurfaceStopped(surfaceId: Int) {
|
|
99
|
+
// Yoga can measure a component that never receives a mounted View, so
|
|
100
|
+
// the weak view map is only supplemental lifecycle bookkeeping. The
|
|
101
|
+
// registry cleanup is intentionally unconditional and surface-wide.
|
|
102
|
+
PreparedProseLayoutRegistry.shared.deactivateFabricSurfaceId(surfaceId)
|
|
103
|
+
states.entries.forEach { (view, state) ->
|
|
104
|
+
if (state.ownsFabricSurface(surfaceId)) {
|
|
105
|
+
state.release()
|
|
106
|
+
view.clearImageLeases()
|
|
107
|
+
view.install(null)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
super.onSurfaceStopped(surfaceId)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** Test-only Fabric-side per-surface accounting; cache bytes stay separate. */
|
|
114
|
+
internal fun retainedSurfaceBytesForTesting(view: PreparedProseDrawingView): Long =
|
|
115
|
+
states[view]?.retainedSurfaceBytesForTesting(view)
|
|
116
|
+
?: PreparedProseDrawingView.retainedImagePixelsBytes(emptyMap<String, Any>())
|
|
117
|
+
|
|
118
|
+
override fun updateState(
|
|
119
|
+
view: PreparedProseDrawingView,
|
|
120
|
+
props: ReactStylesDiffMap,
|
|
121
|
+
stateWrapper: StateWrapper
|
|
122
|
+
): Any? {
|
|
123
|
+
val state = states.getOrPut(view, ::ViewState)
|
|
124
|
+
state.fontEnvironment.activate(deliverPending = true)
|
|
125
|
+
state.replaceStateWrapper(stateWrapper, stateWrapper.stateData?.fabricRevisionsOrNull())
|
|
126
|
+
state.beginSemanticImageGeneration(view)
|
|
127
|
+
reconcile(view, state)
|
|
128
|
+
return null
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
override fun setSourceKind(view: PreparedProseDrawingView, value: String?) =
|
|
132
|
+
update(view) { sourceKind = value ?: "json" }
|
|
133
|
+
|
|
134
|
+
override fun setSource(view: PreparedProseDrawingView, value: String?) =
|
|
135
|
+
update(view) { source = value.orEmpty() }
|
|
136
|
+
|
|
137
|
+
override fun setConfigJson(view: PreparedProseDrawingView, value: String?) =
|
|
138
|
+
update(view) { configJson = value ?: "{}" }
|
|
139
|
+
|
|
140
|
+
override fun setThemeJson(view: PreparedProseDrawingView, value: String?) =
|
|
141
|
+
update(view) { themeJson = value }
|
|
142
|
+
|
|
143
|
+
override fun setImagePolicyJson(view: PreparedProseDrawingView, value: String?) =
|
|
144
|
+
update(view) { imagePolicyJson = value }
|
|
145
|
+
|
|
146
|
+
override fun setImagesEnabled(view: PreparedProseDrawingView, value: Boolean) =
|
|
147
|
+
update(view) { imagesEnabled = value }
|
|
148
|
+
|
|
149
|
+
override fun setCollapsesWhenEmpty(view: PreparedProseDrawingView, value: Boolean) =
|
|
150
|
+
update(view) { collapsesWhenEmpty = value }
|
|
151
|
+
|
|
152
|
+
override fun setEnableLinkTaps(view: PreparedProseDrawingView, value: Boolean) {
|
|
153
|
+
// Capability only filters the installed interaction/accessibility
|
|
154
|
+
// nodes. It must not reconcile, acquire, or replace the generation.
|
|
155
|
+
view.linkInteractionsEnabled = value
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
override fun setMentionInteractionsEnabled(view: PreparedProseDrawingView, value: Boolean) {
|
|
159
|
+
view.mentionInteractionsEnabled = value
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
override fun setFontEnvironmentRevision(view: PreparedProseDrawingView, value: Int) =
|
|
163
|
+
update(view) { fontEnvironmentRevision = value.coerceAtLeast(0).toLong() }
|
|
164
|
+
|
|
165
|
+
override fun onAfterUpdateTransaction(view: PreparedProseDrawingView) {
|
|
166
|
+
super.onAfterUpdateTransaction(view)
|
|
167
|
+
val state = states[view] ?: return
|
|
168
|
+
state.beginSemanticImageGeneration(view)
|
|
169
|
+
reconcile(view, state)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
override fun measure(
|
|
173
|
+
context: Context,
|
|
174
|
+
localData: ReadableMap?,
|
|
175
|
+
props: ReadableMap?,
|
|
176
|
+
state: ReadableMap?,
|
|
177
|
+
width: Float,
|
|
178
|
+
widthMode: YogaMeasureMode,
|
|
179
|
+
height: Float,
|
|
180
|
+
heightMode: YogaMeasureMode,
|
|
181
|
+
attachmentsPositions: FloatArray?
|
|
182
|
+
): Long {
|
|
183
|
+
val density = context.resources.displayMetrics.density
|
|
184
|
+
val fontScale = context.resources.configuration.fontScale
|
|
185
|
+
val surface = localData?.let(::surfaceToken)
|
|
186
|
+
val finalLayout = FabricLeaseHandleBridge.currentFinalLayout()
|
|
187
|
+
val leaseHandle = FabricLeaseHandleBridge.currentHandle()
|
|
188
|
+
// A state snapshot can outlive its C++ family. Only the synchronous
|
|
189
|
+
// native thread-local handle proves this Yoga callback still belongs
|
|
190
|
+
// to an active exact state incarnation.
|
|
191
|
+
if (surface != null && leaseHandle <= 0L) {
|
|
192
|
+
PreparedProseInstrumentation.trace("measure") {
|
|
193
|
+
"declined: $surface has no live native lease handle"
|
|
194
|
+
}
|
|
195
|
+
return YogaMeasureOutput.make(0f, 0f)
|
|
196
|
+
}
|
|
197
|
+
val request = requestFrom(props, state, leaseHandle)
|
|
198
|
+
if (request == null) {
|
|
199
|
+
// An incomplete/stale Yoga callback has not named an exact
|
|
200
|
+
// generation. It must never tear down a newer incarnation on the
|
|
201
|
+
// same surface; recycle and surface-stop own terminal cleanup.
|
|
202
|
+
PreparedProseInstrumentation.trace("measure") {
|
|
203
|
+
"declined: state named no exact generation (surface=$surface, handle=$leaseHandle)"
|
|
204
|
+
}
|
|
205
|
+
return YogaMeasureOutput.make(0f, 0f)
|
|
206
|
+
}
|
|
207
|
+
val widthPx = fabricConstraintPixels(width)
|
|
208
|
+
// The registry begins and scopes this exact surface/component sidecar
|
|
209
|
+
// around preparation, so an LRU miss cannot borrow another surface.
|
|
210
|
+
val artifact = if (finalLayout != null && surface != null && widthPx != null) {
|
|
211
|
+
PreparedProseLayoutRegistry.shared.prepareFinalLayout(
|
|
212
|
+
request,
|
|
213
|
+
widthPx,
|
|
214
|
+
density,
|
|
215
|
+
finalLayout.contentOriginXPx,
|
|
216
|
+
finalLayout.contentOriginYPx,
|
|
217
|
+
surface,
|
|
218
|
+
leaseHandle,
|
|
219
|
+
fontScale
|
|
220
|
+
)
|
|
221
|
+
} else if (
|
|
222
|
+
(widthMode != YogaMeasureMode.EXACTLY && widthMode != YogaMeasureMode.AT_MOST) ||
|
|
223
|
+
widthPx == null
|
|
224
|
+
) {
|
|
225
|
+
PreparedProseLayoutRegistry.shared.measure(
|
|
226
|
+
request,
|
|
227
|
+
0,
|
|
228
|
+
density,
|
|
229
|
+
fabricSurface = surface,
|
|
230
|
+
fabricLeaseHandle = leaseHandle,
|
|
231
|
+
fontScale = fontScale
|
|
232
|
+
)
|
|
233
|
+
} else {
|
|
234
|
+
PreparedProseLayoutRegistry.shared.measure(
|
|
235
|
+
request,
|
|
236
|
+
widthPx,
|
|
237
|
+
density,
|
|
238
|
+
fabricSurface = surface,
|
|
239
|
+
fabricLeaseHandle = leaseHandle,
|
|
240
|
+
fontScale = fontScale
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
val measuredWidth = fabricPixelsToDp(artifact.widthPx.toFloat(), density) ?: 0f
|
|
244
|
+
val intrinsicHeight = fabricPixelsToDp(artifact.heightPx.toFloat(), density) ?: 0f
|
|
245
|
+
val constrainedHeight = fabricPixelsToDp(height, density)
|
|
246
|
+
val measuredHeight = when (heightMode) {
|
|
247
|
+
YogaMeasureMode.EXACTLY -> constrainedHeight ?: 0f
|
|
248
|
+
|
|
249
|
+
YogaMeasureMode.AT_MOST -> constrainedHeight?.let { minOf(intrinsicHeight, it) }
|
|
250
|
+
?: intrinsicHeight
|
|
251
|
+
|
|
252
|
+
else -> intrinsicHeight
|
|
253
|
+
}
|
|
254
|
+
PreparedProseInstrumentation.trace("measure") {
|
|
255
|
+
"surface=$surface handle=$leaseHandle $widthMode widthPx=$widthPx " +
|
|
256
|
+
"$heightMode heightPx=$height " +
|
|
257
|
+
"-> artifact ${artifact.widthPx}x${artifact.heightPx}px, yoga ${measuredWidth}x${measuredHeight}dp"
|
|
258
|
+
}
|
|
259
|
+
return YogaMeasureOutput.make(measuredWidth, measuredHeight)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
private fun update(view: PreparedProseDrawingView, mutation: ViewState.() -> Unit) {
|
|
263
|
+
val state = states.getOrPut(view, ::ViewState)
|
|
264
|
+
state.mutation()
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
private fun installCachedLayout(view: PreparedProseDrawingView) {
|
|
268
|
+
val state = states[view] ?: run {
|
|
269
|
+
PreparedProseInstrumentation.trace("mount") {
|
|
270
|
+
"declined: no view state (tag=${view.id})"
|
|
271
|
+
}
|
|
272
|
+
return
|
|
273
|
+
}
|
|
274
|
+
val request = state.requestOrNull() ?: run {
|
|
275
|
+
PreparedProseInstrumentation.trace("mount") {
|
|
276
|
+
"declined: props/state have not yet named a request (tag=${view.id})"
|
|
277
|
+
}
|
|
278
|
+
return
|
|
279
|
+
}
|
|
280
|
+
val surfaceId = UIManagerHelper.getSurfaceId(view)
|
|
281
|
+
if (surfaceId < 0 || view.id <= 0) {
|
|
282
|
+
PreparedProseInstrumentation.trace("mount") {
|
|
283
|
+
"declined: surfaceId=$surfaceId tag=${view.id}"
|
|
284
|
+
}
|
|
285
|
+
state.finishWithoutMountedReplacement(view)
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
val surface = FabricSurfaceToken(surfaceId, view.id)
|
|
289
|
+
val generation = state.adopt(surface, request)
|
|
290
|
+
state.bindFabricAttachmentState(generation)
|
|
291
|
+
val ticket = PreparedProseLayoutRegistry.shared.acquirePreparedMountTicket(
|
|
292
|
+
generation,
|
|
293
|
+
request.nativeFontRevision
|
|
294
|
+
)
|
|
295
|
+
if (ticket == null) {
|
|
296
|
+
PreparedProseInstrumentation.trace("mount") {
|
|
297
|
+
"miss: no final layout ticket for $generation"
|
|
298
|
+
}
|
|
299
|
+
PreparedProseLayoutRegistry.shared.prepareForFabricMount(generation) {
|
|
300
|
+
view.post {
|
|
301
|
+
val current = states[view] ?: return@post
|
|
302
|
+
if (current.generation != generation) return@post
|
|
303
|
+
val currentRequest = current.requestOrNull() ?: return@post
|
|
304
|
+
val prepared = PreparedProseLayoutRegistry.shared.acquirePreparedMountTicket(
|
|
305
|
+
generation,
|
|
306
|
+
currentRequest.nativeFontRevision
|
|
307
|
+
)
|
|
308
|
+
?: return@post
|
|
309
|
+
installPreparedTicket(view, current, prepared)
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
installPreparedTicket(view, state, ticket)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
private fun installPreparedTicket(
|
|
318
|
+
view: PreparedProseDrawingView,
|
|
319
|
+
state: ViewState,
|
|
320
|
+
ticket: PreparedMountTicket
|
|
321
|
+
) {
|
|
322
|
+
val currentRequest = state.requestOrNull() ?: return
|
|
323
|
+
if (ticket.nativeFontRevision != currentRequest.nativeFontRevision) {
|
|
324
|
+
prepareCurrentTicket(view, state)
|
|
325
|
+
return
|
|
326
|
+
}
|
|
327
|
+
PreparedProseInstrumentation.trace("mount") {
|
|
328
|
+
"installed: ${ticket.generation} widthPx=${ticket.contentWidthPx} heightPx=${ticket.artifact.heightPx}"
|
|
329
|
+
}
|
|
330
|
+
state.installMountedReplacement(view, ticket)
|
|
331
|
+
state.beginImages(view, ticket.artifact, currentRequest)
|
|
332
|
+
ViewerAtomConfiguration.parse(currentRequest.configuration.themeJson)?.let { atoms ->
|
|
333
|
+
val density = view.resources.displayMetrics.density
|
|
334
|
+
dispatchViewerEvent(
|
|
335
|
+
view,
|
|
336
|
+
"topAtomLayout",
|
|
337
|
+
Arguments.createMap().apply {
|
|
338
|
+
putString("generation", atoms.generation)
|
|
339
|
+
putString("revision", atoms.revision)
|
|
340
|
+
putDouble("layoutWidth", ticket.artifact.widthPx.toDouble() / density)
|
|
341
|
+
putString(
|
|
342
|
+
"atomsJson",
|
|
343
|
+
ticket.artifact.atomsJson(
|
|
344
|
+
density,
|
|
345
|
+
ticket.contentOriginXPx,
|
|
346
|
+
ticket.contentOriginYPx
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
}
|
|
350
|
+
)
|
|
351
|
+
}
|
|
352
|
+
ticket.artifact.error?.let { dispatchError(view, currentRequest, it) }
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
private fun prepareCurrentTicket(view: PreparedProseDrawingView, state: ViewState) {
|
|
356
|
+
val generation = state.generation ?: return
|
|
357
|
+
PreparedProseLayoutRegistry.shared.prepareForFabricMount(generation) { prepared ->
|
|
358
|
+
if (!prepared) return@prepareForFabricMount
|
|
359
|
+
view.post {
|
|
360
|
+
val current = states[view] ?: return@post
|
|
361
|
+
if (current.generation != generation) return@post
|
|
362
|
+
val request = current.requestOrNull() ?: return@post
|
|
363
|
+
val ticket = PreparedProseLayoutRegistry.shared.acquirePreparedMountTicket(
|
|
364
|
+
generation,
|
|
365
|
+
request.nativeFontRevision
|
|
366
|
+
)
|
|
367
|
+
?: return@post
|
|
368
|
+
installPreparedTicket(view, current, ticket)
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private fun dispatchError(
|
|
374
|
+
view: PreparedProseDrawingView,
|
|
375
|
+
request: ProseViewerRequest,
|
|
376
|
+
error: ProseViewerError
|
|
377
|
+
) {
|
|
378
|
+
val state = states[view] ?: return
|
|
379
|
+
if (!state.errorReporter.shouldReport(request.semanticGenerationIdentity)) return
|
|
380
|
+
dispatchViewerEvent(
|
|
381
|
+
view,
|
|
382
|
+
EVENT_ERROR,
|
|
383
|
+
Arguments.createMap().apply {
|
|
384
|
+
putString("domain", error.domain)
|
|
385
|
+
putString("code", error.code.value)
|
|
386
|
+
putString("message", error.message)
|
|
387
|
+
putBoolean("fatal", true)
|
|
388
|
+
}
|
|
389
|
+
)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private fun dispatchResourceError(
|
|
393
|
+
view: PreparedProseDrawingView,
|
|
394
|
+
attachment: ViewerImageAttachment
|
|
395
|
+
) {
|
|
396
|
+
val state = states[view] ?: return
|
|
397
|
+
state.requestOrNull() ?: return
|
|
398
|
+
if (!state.recordResourceFailure(attachment.ordinal)) return
|
|
399
|
+
dispatchViewerEvent(
|
|
400
|
+
view,
|
|
401
|
+
EVENT_ERROR,
|
|
402
|
+
Arguments.createMap().apply {
|
|
403
|
+
putString("domain", "viewer.resource")
|
|
404
|
+
putString("code", "RESOURCE_LOAD_FAILED")
|
|
405
|
+
putString("message", "An image resource could not be loaded.")
|
|
406
|
+
putBoolean("fatal", false)
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
private fun dispatchInteraction(
|
|
412
|
+
view: PreparedProseDrawingView,
|
|
413
|
+
interaction: PreparedProseInteraction
|
|
414
|
+
): Boolean {
|
|
415
|
+
val isLink = interaction.kind == PreparedProseInteraction.Kind.LINK
|
|
416
|
+
val payload = Arguments.createMap().apply {
|
|
417
|
+
if (isLink) {
|
|
418
|
+
putString("href", interaction.href)
|
|
419
|
+
putString("text", interaction.visibleText)
|
|
420
|
+
} else {
|
|
421
|
+
putDouble("docPos", (interaction.docPos ?: return false).toDouble())
|
|
422
|
+
putString("label", interaction.label)
|
|
423
|
+
putString("attrsJson", interaction.attrsJson ?: return false)
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
dispatchViewerEvent(view, if (isLink) EVENT_PRESS_LINK else EVENT_PRESS_MENTION, payload)
|
|
427
|
+
return true
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private fun dispatchViewerEvent(
|
|
431
|
+
view: PreparedProseDrawingView,
|
|
432
|
+
eventName: String,
|
|
433
|
+
payload: WritableMap
|
|
434
|
+
) {
|
|
435
|
+
val context = UIManagerHelper.getReactContext(view)
|
|
436
|
+
UIManagerHelper.getEventDispatcherForReactTag(context, view.id)?.dispatchEvent(
|
|
437
|
+
PreparedProseViewerEvent(
|
|
438
|
+
UIManagerHelper.getSurfaceId(view),
|
|
439
|
+
view.id,
|
|
440
|
+
eventName,
|
|
441
|
+
payload
|
|
442
|
+
)
|
|
443
|
+
)
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private fun requestFrom(
|
|
447
|
+
props: ReadableMap?,
|
|
448
|
+
state: ReadableMap?,
|
|
449
|
+
nativeLeaseHandle: Long = 0
|
|
450
|
+
): ProseViewerRequest? {
|
|
451
|
+
val revisions = state?.fabricRevisionsOrNull(nativeLeaseHandle) ?: return null
|
|
452
|
+
return requestFrom(props, revisions)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private fun requestFrom(
|
|
456
|
+
props: ReadableMap?,
|
|
457
|
+
revisions: FabricStateRevisions
|
|
458
|
+
): ProseViewerRequest {
|
|
459
|
+
val sourceKind = props?.stringOrNull("sourceKind") ?: "json"
|
|
460
|
+
val source = if (sourceKind == "html") {
|
|
461
|
+
ProseViewerSource.Html(props?.stringOrNull("source").orEmpty())
|
|
462
|
+
} else {
|
|
463
|
+
ProseViewerSource.Json(props?.stringOrNull("source").orEmpty())
|
|
464
|
+
}
|
|
465
|
+
return ProseViewerRequest(
|
|
466
|
+
source = source,
|
|
467
|
+
configuration = ProseViewerConfiguration(
|
|
468
|
+
configJson = props?.stringOrNull("configJson") ?: "{}",
|
|
469
|
+
themeJson = props?.stringOrNull("themeJson"),
|
|
470
|
+
imagePolicyJson = props?.stringOrNull("imagePolicyJson"),
|
|
471
|
+
imagesEnabled = props?.booleanOrDefault("imagesEnabled", true) ?: true,
|
|
472
|
+
collapsesWhenEmpty = props?.booleanOrDefault("collapsesWhenEmpty", true) ?: true
|
|
473
|
+
),
|
|
474
|
+
attachmentRevision = revisions.attachmentRevision,
|
|
475
|
+
nativeFontRevision = revisions.nativeFontRevision,
|
|
476
|
+
fontEnvironmentRevision = props?.longOrZero("fontEnvironmentRevision") ?: 0
|
|
477
|
+
)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private fun reconcile(view: PreparedProseDrawingView, state: ViewState) {
|
|
481
|
+
val request = state.requestOrNull() ?: run {
|
|
482
|
+
state.releaseGeneration(view)
|
|
483
|
+
return
|
|
484
|
+
}
|
|
485
|
+
// `adopt` is the authoritative commit boundary. Releasing G1 here
|
|
486
|
+
// would race a G2 Yoga handoff and blank a valid mounted fallback.
|
|
487
|
+
installCachedLayout(view)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private fun surfaceToken(data: ReadableMap): FabricSurfaceToken? {
|
|
491
|
+
val surfaceId = data.longOrZero("surfaceId").toInt()
|
|
492
|
+
val componentTag = data.longOrZero("componentTag").toInt()
|
|
493
|
+
return if (surfaceId > 0 &&
|
|
494
|
+
componentTag > 0
|
|
495
|
+
) {
|
|
496
|
+
FabricSurfaceToken(surfaceId, componentTag)
|
|
497
|
+
} else {
|
|
498
|
+
null
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private fun ReadableMap.stringOrNull(key: String): String? =
|
|
503
|
+
if (hasKey(key) && !isNull(key)) getString(key) else null
|
|
504
|
+
|
|
505
|
+
private fun ReadableMap.booleanOrDefault(key: String, default: Boolean): Boolean =
|
|
506
|
+
if (hasKey(key) && !isNull(key)) getBoolean(key) else default
|
|
507
|
+
|
|
508
|
+
private fun ReadableMap.longOrZero(key: String): Long =
|
|
509
|
+
if (!hasKey(key) || isNull(key)) 0 else getDouble(key).toLong().coerceAtLeast(0)
|
|
510
|
+
|
|
511
|
+
private fun ReadableMap.fabricRevisionsOrNull(
|
|
512
|
+
nativeLeaseHandle: Long = 0
|
|
513
|
+
): FabricStateRevisions? {
|
|
514
|
+
val attachmentRevision = longOrNull("attachmentRevision") ?: return null
|
|
515
|
+
val nativeFontRevision = longOrNull("nativeFontRevision") ?: return null
|
|
516
|
+
// State's optional decimal representation is exact. The hot native
|
|
517
|
+
// measurement path receives this same handle as a JNI jlong above.
|
|
518
|
+
val stateHandle = stringOrNull("leaseHandle")?.toLongOrNull()?.takeIf { it > 0 } ?: 0L
|
|
519
|
+
val handle = stateHandle.takeIf { it > 0 } ?: nativeLeaseHandle
|
|
520
|
+
if (nativeLeaseHandle > 0 && stateHandle > 0 &&
|
|
521
|
+
stateHandle != nativeLeaseHandle
|
|
522
|
+
) {
|
|
523
|
+
return null
|
|
524
|
+
}
|
|
525
|
+
return FabricStateRevisions(attachmentRevision, nativeFontRevision, handle)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
private fun ReadableMap.longOrNull(key: String): Long? =
|
|
529
|
+
if (!hasKey(key) || isNull(key)) null else getDouble(key).toLong().coerceAtLeast(0)
|
|
530
|
+
|
|
531
|
+
internal data class FabricStateRevisions(
|
|
532
|
+
val attachmentRevision: Long,
|
|
533
|
+
val nativeFontRevision: Long,
|
|
534
|
+
val leaseHandle: Long
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
internal class ViewState(
|
|
538
|
+
var sourceKind: String = "json",
|
|
539
|
+
var source: String = "",
|
|
540
|
+
var configJson: String = "{}",
|
|
541
|
+
var themeJson: String? = null,
|
|
542
|
+
var imagePolicyJson: String? = null,
|
|
543
|
+
var imagesEnabled: Boolean = true,
|
|
544
|
+
var collapsesWhenEmpty: Boolean = true,
|
|
545
|
+
var fontEnvironmentRevision: Long = 0,
|
|
546
|
+
var revisions: FabricStateRevisions? = null,
|
|
547
|
+
var stateWrapper: StateWrapper? = null,
|
|
548
|
+
var generation: FabricGenerationToken? = null,
|
|
549
|
+
// This is independent from the generation lease: an accepted props
|
|
550
|
+
// replacement can release the lease before the next Yoga pass, while
|
|
551
|
+
// the mounted sidecar is still owned by this exact Fabric token.
|
|
552
|
+
private var sidecarGeneration: FabricGenerationToken? = null,
|
|
553
|
+
val errorReporter: FabricErrorReporter = FabricErrorReporter(),
|
|
554
|
+
private val replacementAccessibilityTransaction: FabricReplacementAccessibilityTransaction =
|
|
555
|
+
FabricReplacementAccessibilityTransaction(),
|
|
556
|
+
private val createStateMap: () -> WritableMap = { Arguments.createMap() }
|
|
557
|
+
) {
|
|
558
|
+
private var pendingFontRevision = 0L
|
|
559
|
+
fun requestOrNull(): ProseViewerRequest? = revisions?.let { revisions ->
|
|
560
|
+
ProseViewerRequest(
|
|
561
|
+
source = if (sourceKind ==
|
|
562
|
+
"html"
|
|
563
|
+
) {
|
|
564
|
+
ProseViewerSource.Html(source)
|
|
565
|
+
} else {
|
|
566
|
+
ProseViewerSource.Json(source)
|
|
567
|
+
},
|
|
568
|
+
configuration = ProseViewerConfiguration(
|
|
569
|
+
configJson,
|
|
570
|
+
themeJson,
|
|
571
|
+
imagePolicyJson,
|
|
572
|
+
imagesEnabled,
|
|
573
|
+
collapsesWhenEmpty
|
|
574
|
+
),
|
|
575
|
+
attachmentRevision = revisions.attachmentRevision,
|
|
576
|
+
nativeFontRevision = revisions.nativeFontRevision,
|
|
577
|
+
fontEnvironmentRevision = fontEnvironmentRevision
|
|
578
|
+
)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
fun replaceStateWrapper(next: StateWrapper, nextRevisions: FabricStateRevisions?) {
|
|
582
|
+
if (stateWrapper !== next) stateWrapper?.destroyState()
|
|
583
|
+
stateWrapper = next
|
|
584
|
+
val prior = revisions
|
|
585
|
+
revisions = nextRevisions?.let { incoming ->
|
|
586
|
+
val leaseHandle = incoming.leaseHandle.takeIf { it > 0 }
|
|
587
|
+
?: prior?.leaseHandle
|
|
588
|
+
?: 0
|
|
589
|
+
if (leaseHandle > 0 && prior?.leaseHandle == leaseHandle) {
|
|
590
|
+
incoming.copy(
|
|
591
|
+
attachmentRevision = maxOf(
|
|
592
|
+
incoming.attachmentRevision,
|
|
593
|
+
prior.attachmentRevision
|
|
594
|
+
),
|
|
595
|
+
nativeFontRevision = maxOf(
|
|
596
|
+
incoming.nativeFontRevision,
|
|
597
|
+
prior.nativeFontRevision
|
|
598
|
+
),
|
|
599
|
+
leaseHandle = leaseHandle
|
|
600
|
+
)
|
|
601
|
+
} else {
|
|
602
|
+
incoming.copy(leaseHandle = leaseHandle)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
if (pendingFontRevision > 0 && revisions != null) {
|
|
606
|
+
pendingFontRevision = 0
|
|
607
|
+
val current = requireNotNull(revisions)
|
|
608
|
+
publishRevisions(
|
|
609
|
+
FabricStateRevisions(
|
|
610
|
+
current.attachmentRevision,
|
|
611
|
+
current.nativeFontRevision + 1,
|
|
612
|
+
current.leaseHandle
|
|
613
|
+
)
|
|
614
|
+
)
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
private var attachmentRevisions = ViewerAttachmentRevisionState()
|
|
619
|
+
val fontEnvironment = ViewerFontEnvironment()
|
|
620
|
+
val imagePipeline = ViewerImagePipeline()
|
|
621
|
+
private var visibleRect: android.graphics.Rect = android.graphics.Rect()
|
|
622
|
+
|
|
623
|
+
fun beginImages(
|
|
624
|
+
view: PreparedProseDrawingView,
|
|
625
|
+
artifact: PreparedProseLayout,
|
|
626
|
+
request: ProseViewerRequest
|
|
627
|
+
) {
|
|
628
|
+
// The semantic reset happens when props/state are accepted, before
|
|
629
|
+
// Yoga can prepare a replacement. Mount binds only this artifact's
|
|
630
|
+
// ordinal descriptors and must preserve a permitted revision.
|
|
631
|
+
attachmentRevisions.admit(artifact.imageAttachments.size)
|
|
632
|
+
fontEnvironment.activate()
|
|
633
|
+
imagePipeline.begin(
|
|
634
|
+
request.semanticGenerationIdentity,
|
|
635
|
+
request.configuration.imagesEnabled,
|
|
636
|
+
ImageLoadingPolicy.fromJson(request.configuration.imagePolicyJson)
|
|
637
|
+
)
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/** Phase one of Fabric image setup: no artifact is required yet. */
|
|
641
|
+
fun beginSemanticImageGeneration(view: PreparedProseDrawingView) {
|
|
642
|
+
val request = requestOrNull() ?: return
|
|
643
|
+
if (!attachmentRevisions.beginSemanticGeneration(
|
|
644
|
+
request.semanticGenerationIdentity
|
|
645
|
+
)
|
|
646
|
+
) {
|
|
647
|
+
return
|
|
648
|
+
}
|
|
649
|
+
imagePipeline.cancel()
|
|
650
|
+
view.clearImageLeases()
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
fun bindFabricAttachmentState(generation: FabricGenerationToken) {
|
|
654
|
+
attachmentRevisions = FabricAttachmentSidecars.state(generation) ?: attachmentRevisions
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
fun recordIntrinsicSize(
|
|
658
|
+
attachment: ViewerImageAttachment,
|
|
659
|
+
width: Int,
|
|
660
|
+
height: Int
|
|
661
|
+
): Boolean = attachmentRevisions.recordIntrinsicSize(
|
|
662
|
+
attachment.id,
|
|
663
|
+
attachment.ordinal,
|
|
664
|
+
width,
|
|
665
|
+
height,
|
|
666
|
+
attachment.declaredSize
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
fun recordResourceFailure(ordinal: Int): Boolean =
|
|
670
|
+
attachmentRevisions.recordResourceFailure(ordinal)
|
|
671
|
+
|
|
672
|
+
internal fun retainedSurfaceBytesForTesting(view: PreparedProseDrawingView): Long {
|
|
673
|
+
val layout = view.preparedLayout?.retainedBytes ?: 0L
|
|
674
|
+
val sidecar = attachmentRevisions.retainedPublicationBytesForTesting.toLong()
|
|
675
|
+
val pixels = view.retainedImagePixelsBytesForTesting
|
|
676
|
+
return listOf(layout, sidecar, pixels).fold(0L) { total, value ->
|
|
677
|
+
if (value > 0 && total > Long.MAX_VALUE - value) Long.MAX_VALUE else total + value
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
fun requestVisibleImages(view: PreparedProseDrawingView, visible: android.graphics.Rect) {
|
|
682
|
+
visibleRect = android.graphics.Rect(visible)
|
|
683
|
+
val artifact = view.preparedLayout ?: return
|
|
684
|
+
imagePipeline.updateVisibleRect(visibleRect, artifact.imageAttachments)
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
fun publishAttachmentRevision() {
|
|
688
|
+
val current = revisions ?: return
|
|
689
|
+
publishRevisions(
|
|
690
|
+
FabricStateRevisions(
|
|
691
|
+
current.attachmentRevision + 1,
|
|
692
|
+
current.nativeFontRevision,
|
|
693
|
+
current.leaseHandle
|
|
694
|
+
)
|
|
695
|
+
)
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
fun publishFontRevision(revision: Long) {
|
|
699
|
+
if (revision <= 0) return
|
|
700
|
+
val current = revisions
|
|
701
|
+
if (current == null) {
|
|
702
|
+
pendingFontRevision = maxOf(pendingFontRevision, revision)
|
|
703
|
+
return
|
|
704
|
+
}
|
|
705
|
+
publishRevisions(
|
|
706
|
+
FabricStateRevisions(
|
|
707
|
+
current.attachmentRevision,
|
|
708
|
+
current.nativeFontRevision + 1,
|
|
709
|
+
current.leaseHandle
|
|
710
|
+
)
|
|
711
|
+
)
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
private fun publishRevisions(next: FabricStateRevisions) {
|
|
715
|
+
val current = revisions
|
|
716
|
+
if (current == next) return
|
|
717
|
+
revisions = next
|
|
718
|
+
stateWrapper?.updateState(
|
|
719
|
+
createStateMap().apply {
|
|
720
|
+
putDouble("attachmentRevision", next.attachmentRevision.toDouble())
|
|
721
|
+
putDouble("nativeFontRevision", next.nativeFontRevision.toDouble())
|
|
722
|
+
}
|
|
723
|
+
)
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
fun releaseGeneration(view: PreparedProseDrawingView) {
|
|
727
|
+
generation?.let(PreparedProseLayoutRegistry.shared::releaseFabricGeneration)
|
|
728
|
+
generation = null
|
|
729
|
+
releaseSidecarOwnership()
|
|
730
|
+
imagePipeline.cancel()
|
|
731
|
+
replacementAccessibilityTransaction.finishWithoutMountedReplacement(view)
|
|
732
|
+
view.clearImageLeases()
|
|
733
|
+
view.install(null)
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
fun installMountedReplacement(view: PreparedProseDrawingView, ticket: PreparedMountTicket) {
|
|
737
|
+
replacementAccessibilityTransaction.installMountedReplacement(view, ticket)
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
fun finishWithoutMountedReplacement(view: PreparedProseDrawingView) {
|
|
741
|
+
replacementAccessibilityTransaction.finishWithoutMountedReplacement(view)
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
fun adopt(surface: FabricSurfaceToken, request: ProseViewerRequest): FabricGenerationToken {
|
|
745
|
+
val handle = revisions?.leaseHandle ?: 0L
|
|
746
|
+
require(handle > 0) { "Fabric mount attempted without an exact native lease handle." }
|
|
747
|
+
val next = FabricGenerationToken(surface, request.generationIdentity, handle)
|
|
748
|
+
// This is the state/props commit boundary. Permit the canonical
|
|
749
|
+
// incoming generation before releasing any prior owner or trying
|
|
750
|
+
// to acquire: delayed G1 Yoga callbacks are now inert, while a
|
|
751
|
+
// G2 measurement already in flight remains eligible to finish.
|
|
752
|
+
PreparedProseLayoutRegistry.shared.activateFabricGeneration(next)
|
|
753
|
+
val previousSidecar = sidecarGeneration
|
|
754
|
+
if (previousSidecar != null && previousSidecar != next) {
|
|
755
|
+
// The view may already carry another Fabric tag by the time
|
|
756
|
+
// this callback runs. Remove only the sidecar token recorded
|
|
757
|
+
// for its former owner, never one reconstructed from the view.
|
|
758
|
+
PreparedProseLayoutRegistry.shared.releaseFabricGeneration(previousSidecar)
|
|
759
|
+
}
|
|
760
|
+
sidecarGeneration = next
|
|
761
|
+
if (generation != null && generation != next) {
|
|
762
|
+
PreparedProseLayoutRegistry.shared.releaseFabricGeneration(generation!!)
|
|
763
|
+
}
|
|
764
|
+
generation = next
|
|
765
|
+
return next
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
fun release() {
|
|
769
|
+
// A replacement keeps mounted G1 alive while G2 is pending or
|
|
770
|
+
// failed. Recycling is terminal for the exact state-family
|
|
771
|
+
// handle, so sweep every owner lease after marking it inactive
|
|
772
|
+
// rather than releasing only G2 through active-generation checks.
|
|
773
|
+
val terminalOwner = generation?.let { FabricLeaseOwner(it.surface, it.leaseHandle) }
|
|
774
|
+
?: sidecarGeneration?.let { FabricLeaseOwner(it.surface, it.leaseHandle) }
|
|
775
|
+
terminalOwner?.let { owner ->
|
|
776
|
+
PreparedProseLayoutRegistry.shared.deactivateFabricLease(
|
|
777
|
+
owner.surface,
|
|
778
|
+
owner.leaseHandle
|
|
779
|
+
)
|
|
780
|
+
}
|
|
781
|
+
generation = null
|
|
782
|
+
sidecarGeneration = null
|
|
783
|
+
imagePipeline.cancel()
|
|
784
|
+
fontEnvironment.deactivate()
|
|
785
|
+
attachmentRevisions.reset()
|
|
786
|
+
stateWrapper?.destroyState()
|
|
787
|
+
stateWrapper = null
|
|
788
|
+
revisions = null
|
|
789
|
+
errorReporter.reset()
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
fun ownsFabricSurface(surfaceId: Int): Boolean =
|
|
793
|
+
generation?.surface?.surfaceId == surfaceId ||
|
|
794
|
+
sidecarGeneration?.surface?.surfaceId == surfaceId
|
|
795
|
+
|
|
796
|
+
private fun releaseSidecarOwnership() {
|
|
797
|
+
val sidecar = sidecarGeneration ?: return
|
|
798
|
+
// Clear only the state incarnation recorded for this view. A
|
|
799
|
+
// stale recycled H1 must not remove H2 merely because Fabric has
|
|
800
|
+
// reused the same surface/component tag.
|
|
801
|
+
sidecarGeneration = null
|
|
802
|
+
PreparedProseLayoutRegistry.shared.releaseFabricGeneration(sidecar)
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
companion object {
|
|
807
|
+
const val REACT_CLASS = "PreparedProseViewer"
|
|
808
|
+
private const val EVENT_ERROR = "topError"
|
|
809
|
+
private const val EVENT_PRESS_LINK = "topPressLink"
|
|
810
|
+
private const val EVENT_PRESS_MENTION = "topPressMention"
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Fabric direct event carrying an already-built payload. Every viewer event
|
|
816
|
+
* reports a discrete outcome, so coalescing stays off: two link presses or two
|
|
817
|
+
* distinct resource failures on one view must both reach JS.
|
|
818
|
+
*/
|
|
819
|
+
private class PreparedProseViewerEvent(
|
|
820
|
+
surfaceId: Int,
|
|
821
|
+
viewTag: Int,
|
|
822
|
+
private val name: String,
|
|
823
|
+
private val payload: WritableMap
|
|
824
|
+
) : Event<PreparedProseViewerEvent>(surfaceId, viewTag) {
|
|
825
|
+
override fun getEventName(): String = name
|
|
826
|
+
|
|
827
|
+
override fun getEventData(): WritableMap = payload
|
|
828
|
+
|
|
829
|
+
override fun canCoalesce(): Boolean = false
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Makes replacement accessibility notification ownership explicit. A removed
|
|
834
|
+
* old subtree is announced by either the final mounted artifact or, if Fabric
|
|
835
|
+
* cannot mount it, by the removal itself—never by both.
|
|
836
|
+
*/
|
|
837
|
+
internal class FabricReplacementAccessibilityTransaction {
|
|
838
|
+
private enum class NotificationOwner {
|
|
839
|
+
NONE,
|
|
840
|
+
FINAL_INSTALL,
|
|
841
|
+
REMOVED_SUBTREE
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
private var notificationOwner = NotificationOwner.NONE
|
|
845
|
+
|
|
846
|
+
fun clearReplacing(view: PreparedProseDrawingView) {
|
|
847
|
+
if (view.preparedLayout == null) return
|
|
848
|
+
view.install(null, announceAccessibilitySubtree = false)
|
|
849
|
+
notificationOwner = NotificationOwner.FINAL_INSTALL
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
fun installMountedReplacement(view: PreparedProseDrawingView, ticket: PreparedMountTicket) {
|
|
853
|
+
installMountedReplacement(
|
|
854
|
+
view,
|
|
855
|
+
ticket.artifact,
|
|
856
|
+
ticket.contentOriginXPx,
|
|
857
|
+
ticket.contentOriginYPx
|
|
858
|
+
)
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
fun installMountedReplacement(view: PreparedProseDrawingView, artifact: PreparedProseLayout) {
|
|
862
|
+
installMountedReplacement(view, artifact, 0, 0)
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
private fun installMountedReplacement(
|
|
866
|
+
view: PreparedProseDrawingView,
|
|
867
|
+
artifact: PreparedProseLayout,
|
|
868
|
+
contentOriginXPx: Int,
|
|
869
|
+
contentOriginYPx: Int
|
|
870
|
+
) {
|
|
871
|
+
view.install(
|
|
872
|
+
artifact,
|
|
873
|
+
announceAccessibilitySubtree = notificationOwner != NotificationOwner.REMOVED_SUBTREE,
|
|
874
|
+
contentOriginXPx = contentOriginXPx,
|
|
875
|
+
contentOriginYPx = contentOriginYPx
|
|
876
|
+
)
|
|
877
|
+
notificationOwner = NotificationOwner.NONE
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
fun finishWithoutMountedReplacement(view: PreparedProseDrawingView) {
|
|
881
|
+
if (notificationOwner != NotificationOwner.FINAL_INSTALL) return
|
|
882
|
+
view.announceAccessibilitySubtreeChanged()
|
|
883
|
+
notificationOwner = NotificationOwner.REMOVED_SUBTREE
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/** Small lifecycle seam that guarantees Fabric emits one error per request generation. */
|
|
888
|
+
internal class FabricErrorReporter {
|
|
889
|
+
private var reportedGenerationIdentity: String? = null
|
|
890
|
+
|
|
891
|
+
fun shouldReport(generationIdentity: String): Boolean {
|
|
892
|
+
if (reportedGenerationIdentity == generationIdentity) return false
|
|
893
|
+
reportedGenerationIdentity = generationIdentity
|
|
894
|
+
return true
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
fun reset() {
|
|
898
|
+
reportedGenerationIdentity = null
|
|
899
|
+
}
|
|
900
|
+
}
|