@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,186 @@
|
|
|
1
|
+
package com.apollohg.editor.viewer
|
|
2
|
+
|
|
3
|
+
import android.graphics.Rect
|
|
4
|
+
import android.text.StaticLayout
|
|
5
|
+
import com.apollohg.editor.ProseViewerError
|
|
6
|
+
|
|
7
|
+
internal data class ProseLayoutKey(
|
|
8
|
+
val semanticKey: String,
|
|
9
|
+
val widthPx: Int,
|
|
10
|
+
val themeDigest: String,
|
|
11
|
+
val nativeFontRevision: Long,
|
|
12
|
+
val fontEnvironmentRevision: Long,
|
|
13
|
+
val densityBits: Long,
|
|
14
|
+
val attachmentRevision: Long,
|
|
15
|
+
val generationIdentity: String,
|
|
16
|
+
/** Immutable semantic diagnostic context; excludes replacement revisions. */
|
|
17
|
+
val semanticGenerationIdentity: String = semanticKey
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
internal data class FabricSurfaceToken(val surfaceId: Int, val componentTag: Int)
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The state-owned Fabric incarnation. A recycled component may reuse the
|
|
24
|
+
* same surface/tag and even the same semantic generation, so every handoff
|
|
25
|
+
* operation must carry the native lease handle as well.
|
|
26
|
+
*/
|
|
27
|
+
internal data class FabricGenerationToken(
|
|
28
|
+
val surface: FabricSurfaceToken,
|
|
29
|
+
val generationIdentity: String,
|
|
30
|
+
val leaseHandle: Long
|
|
31
|
+
) {
|
|
32
|
+
init {
|
|
33
|
+
require(leaseHandle > 0) { "Fabric lease handles must be signed, non-zero Int64 values." }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** State-lifetime identity shared by all semantic/width revisions of a family. */
|
|
38
|
+
internal data class FabricLeaseOwner(val surface: FabricSurfaceToken, val leaseHandle: Long)
|
|
39
|
+
internal data class FabricLeaseKey(
|
|
40
|
+
val generation: FabricGenerationToken,
|
|
41
|
+
val layout: ProseLayoutKey
|
|
42
|
+
)
|
|
43
|
+
internal data class ProseMountKey(
|
|
44
|
+
val generationIdentity: String,
|
|
45
|
+
val widthPx: Int,
|
|
46
|
+
val densityBits: Long
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
/** Paint-only operations which Android spans cannot represent accurately. */
|
|
50
|
+
internal enum class PreparedProseFragmentKind {
|
|
51
|
+
TEXT,
|
|
52
|
+
MARKER,
|
|
53
|
+
BACKGROUND,
|
|
54
|
+
BORDER,
|
|
55
|
+
RULE,
|
|
56
|
+
ATOM,
|
|
57
|
+
STRIKE,
|
|
58
|
+
IMAGE
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
internal data class PreparedProseFragment(
|
|
62
|
+
val kind: PreparedProseFragmentKind,
|
|
63
|
+
val bounds: Rect,
|
|
64
|
+
val layout: StaticLayout? = null,
|
|
65
|
+
val layoutX: Int = bounds.left,
|
|
66
|
+
val layoutY: Int = bounds.top,
|
|
67
|
+
val labelLayout: StaticLayout? = null,
|
|
68
|
+
val labelX: Int = bounds.left,
|
|
69
|
+
val labelY: Int = bounds.top,
|
|
70
|
+
val color: Int? = null,
|
|
71
|
+
val borderColor: Int? = null,
|
|
72
|
+
val cornerRadius: Float = 0f,
|
|
73
|
+
val strokeWidth: Float = 0f,
|
|
74
|
+
val label: String? = null,
|
|
75
|
+
/** Immutable compiler identity for an inline atom; absent for non-atoms. */
|
|
76
|
+
val atomNodeType: String? = null,
|
|
77
|
+
val atomDocPos: Long? = null,
|
|
78
|
+
val atomAttrsJson: String? = null,
|
|
79
|
+
val checked: Boolean = false,
|
|
80
|
+
val box: com.apollohg.editor.EditorBoxStyle? = null,
|
|
81
|
+
val decorationBounds: Rect? = null,
|
|
82
|
+
val resizeMode: String = "contain"
|
|
83
|
+
) {
|
|
84
|
+
val retainedBytes: Long
|
|
85
|
+
get() = 160L + (layout?.text?.length ?: 0).toLong() * 4 +
|
|
86
|
+
(labelLayout?.text?.length ?: 0).toLong() * 4 +
|
|
87
|
+
(label?.length ?: 0).toLong() * 2 +
|
|
88
|
+
(atomNodeType?.length ?: 0).toLong() * 2 +
|
|
89
|
+
(atomAttrsJson?.length ?: 0).toLong() * 2
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** An immutable culling unit in document paint order. */
|
|
93
|
+
internal data class PreparedProseBlock(
|
|
94
|
+
val fragments: List<PreparedProseFragment>,
|
|
95
|
+
val bounds: Rect
|
|
96
|
+
) {
|
|
97
|
+
val topPx: Int get() = bounds.top
|
|
98
|
+
val bottomPx: Int get() = bounds.bottom
|
|
99
|
+
fun intersects(clip: Rect): Boolean = bottomPx > clip.top && topPx < clip.bottom
|
|
100
|
+
val retainedBytes: Long get() = 160L + fragments.sumOf { it.retainedBytes }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
internal data class PreparedProseInteraction(
|
|
104
|
+
val kind: Kind,
|
|
105
|
+
val rects: List<Rect>,
|
|
106
|
+
val href: String? = null,
|
|
107
|
+
val visibleText: String,
|
|
108
|
+
/** Kept as Long so the complete unsigned Rust u32 domain is lossless. */
|
|
109
|
+
val docPos: Long? = null,
|
|
110
|
+
val label: String,
|
|
111
|
+
val attrsJson: String? = null
|
|
112
|
+
) {
|
|
113
|
+
enum class Kind { LINK, MENTION }
|
|
114
|
+
val retainedBytes: Long get() = 144L + rects.size * 32L + (href?.length ?: 0) * 2L +
|
|
115
|
+
visibleText.length * 2L +
|
|
116
|
+
label.length * 2L +
|
|
117
|
+
(attrsJson?.length ?: 0) * 2L
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
internal data class PreparedProseAccessibilityNode(
|
|
121
|
+
val interactionIndex: Int,
|
|
122
|
+
val role: Role,
|
|
123
|
+
val label: String,
|
|
124
|
+
val bounds: Rect
|
|
125
|
+
) {
|
|
126
|
+
enum class Role { LINK, MENTION }
|
|
127
|
+
val retainedBytes: Long get() = 96L + label.length * 2L
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** A fully prepared artifact. StaticLayout construction is complete before publication. */
|
|
131
|
+
internal data class PreparedProseLayout(
|
|
132
|
+
val key: ProseLayoutKey,
|
|
133
|
+
val widthPx: Int,
|
|
134
|
+
val heightPx: Int,
|
|
135
|
+
val blocks: List<PreparedProseBlock>,
|
|
136
|
+
val interactions: List<PreparedProseInteraction> = emptyList(),
|
|
137
|
+
val accessibilityNodes: List<PreparedProseAccessibilityNode> = emptyList(),
|
|
138
|
+
val imageAttachments: List<ViewerImageAttachment> = emptyList(),
|
|
139
|
+
val retainedBytes: Long,
|
|
140
|
+
val error: ProseViewerError? = null,
|
|
141
|
+
val viewerAtoms: List<PreparedViewerAtom> = emptyList(),
|
|
142
|
+
val contentBox: com.apollohg.editor.EditorBoxStyle? = null,
|
|
143
|
+
val codeHighlighting: com.apollohg.editor.NativeCodeHighlightingConfig? = null,
|
|
144
|
+
val codeHighlightBlocks: List<com.apollohg.editor.CodeHighlightBlock> = emptyList(),
|
|
145
|
+
val highlightedCodeKeys: Set<String> = emptySet()
|
|
146
|
+
) {
|
|
147
|
+
val hasMonotonicBlockBounds = (1 until blocks.size).all {
|
|
148
|
+
blocks[it - 1].topPx <= blocks[it].topPx && blocks[it - 1].bottomPx <= blocks[it].bottomPx
|
|
149
|
+
}
|
|
150
|
+
val fragmentKinds: Set<PreparedProseFragmentKind> get() = blocks.flatMapTo(
|
|
151
|
+
linkedSetOf()
|
|
152
|
+
) { block ->
|
|
153
|
+
block.fragments.map { it.kind }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
inline fun forEachBlockIntersecting(clip: Rect, action: (PreparedProseBlock) -> Unit) {
|
|
157
|
+
if (!hasMonotonicBlockBounds) {
|
|
158
|
+
for (block in blocks) if (block.intersects(clip)) action(block)
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
var lower = 0
|
|
162
|
+
var upper = blocks.size
|
|
163
|
+
while (lower < upper) {
|
|
164
|
+
val middle = (lower + upper) ushr 1
|
|
165
|
+
if (blocks[middle].bottomPx > clip.top) upper = middle else lower = middle + 1
|
|
166
|
+
}
|
|
167
|
+
while (lower < blocks.size) {
|
|
168
|
+
val block = blocks[lower]
|
|
169
|
+
if (block.topPx >= clip.bottom) return
|
|
170
|
+
action(block)
|
|
171
|
+
lower += 1
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
inline fun forEachFragmentIntersecting(clip: Rect, action: (PreparedProseFragment) -> Unit) =
|
|
176
|
+
forEachBlockIntersecting(clip) { block ->
|
|
177
|
+
block.fragments.filterTo(mutableListOf()) {
|
|
178
|
+
Rect.intersects(it.bounds, clip)
|
|
179
|
+
}.forEach(action)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
companion object {
|
|
183
|
+
fun error(key: ProseLayoutKey, widthPx: Int, error: ProseViewerError) =
|
|
184
|
+
PreparedProseLayout(key, widthPx, 0, emptyList(), retainedBytes = 0, error = error)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
package com.apollohg.editor.viewer
|
|
2
|
+
|
|
3
|
+
import com.apollohg.editor.BuildConfig
|
|
4
|
+
import java.util.Collections
|
|
5
|
+
import java.util.IdentityHashMap
|
|
6
|
+
import java.util.concurrent.CompletableFuture
|
|
7
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
8
|
+
import kotlin.math.abs
|
|
9
|
+
|
|
10
|
+
internal const val PIXEL_GRID_ROUNDING_SLACK_PX = 1
|
|
11
|
+
|
|
12
|
+
/** Byte-bounded unmounted LRU plus exact Fabric and direct immutable owners. */
|
|
13
|
+
internal class PreparedProseLayoutCache(
|
|
14
|
+
private val byteBudget: Long = 32L * 1024L * 1024L,
|
|
15
|
+
private val pendingLeaseBudget: Int = 256
|
|
16
|
+
) {
|
|
17
|
+
private val lock = Any()
|
|
18
|
+
private val inFlight =
|
|
19
|
+
ConcurrentHashMap<ProseLayoutKey, CompletableFuture<PreparedProseLayout>>()
|
|
20
|
+
private val completed = LinkedHashMap<ProseLayoutKey, PreparedProseLayout>(16, 0.75f, true)
|
|
21
|
+
|
|
22
|
+
// Access-order makes oldest pending work the first evictable candidate.
|
|
23
|
+
private val pendingLeases = LinkedHashMap<FabricLeaseKey, PreparedProseLayout>(16, 0.75f, true)
|
|
24
|
+
private val mountedLeases = LinkedHashMap<FabricLeaseKey, PreparedProseLayout>(16, 0.75f, true)
|
|
25
|
+
private val directMounted = mutableMapOf<String, PreparedProseLayout>()
|
|
26
|
+
private val mountIndex = mutableMapOf<ProseMountKey, ProseLayoutKey>()
|
|
27
|
+
private val publishedKeys = mutableSetOf<ProseLayoutKey>()
|
|
28
|
+
private var benchmarkCensusKeys: MutableSet<ProseLayoutKey>? = null
|
|
29
|
+
|
|
30
|
+
fun value(
|
|
31
|
+
key: ProseLayoutKey,
|
|
32
|
+
fabricGeneration: FabricGenerationToken? = null,
|
|
33
|
+
shouldCreateFabricLease: () -> Boolean = { true },
|
|
34
|
+
build: () -> PreparedProseLayout
|
|
35
|
+
): PreparedProseLayout {
|
|
36
|
+
val started = PreparedProseInstrumentation.now()
|
|
37
|
+
synchronized(lock) {
|
|
38
|
+
benchmarkCensusKeys?.add(key)
|
|
39
|
+
completed[key]?.let {
|
|
40
|
+
createPendingLeaseIfActiveLocked(it, fabricGeneration, shouldCreateFabricLease)
|
|
41
|
+
PreparedProseInstrumentation.cacheLookup(started, true)
|
|
42
|
+
return it
|
|
43
|
+
}
|
|
44
|
+
// Completed entries are deliberately disposable. Any live owner is
|
|
45
|
+
// still an immutable complete-key source for a different surface.
|
|
46
|
+
liveLayoutLocked(key)?.let {
|
|
47
|
+
createPendingLeaseIfActiveLocked(it, fabricGeneration, shouldCreateFabricLease)
|
|
48
|
+
PreparedProseInstrumentation.cacheLookup(started, true)
|
|
49
|
+
return it
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
val fresh = CompletableFuture<PreparedProseLayout>()
|
|
53
|
+
val existing = inFlight.putIfAbsent(key, fresh)
|
|
54
|
+
if (existing != null) {
|
|
55
|
+
val layout = existing.join()
|
|
56
|
+
synchronized(lock) {
|
|
57
|
+
createPendingLeaseIfActiveLocked(layout, fabricGeneration, shouldCreateFabricLease)
|
|
58
|
+
}
|
|
59
|
+
PreparedProseInstrumentation.cacheLookup(started, true, true)
|
|
60
|
+
return layout
|
|
61
|
+
}
|
|
62
|
+
PreparedProseInstrumentation.cacheLookup(started, false)
|
|
63
|
+
val layout = try {
|
|
64
|
+
build()
|
|
65
|
+
} catch (error: Throwable) {
|
|
66
|
+
fresh.completeExceptionally(error)
|
|
67
|
+
inFlight.remove(key, fresh)
|
|
68
|
+
throw error
|
|
69
|
+
}
|
|
70
|
+
synchronized(lock) {
|
|
71
|
+
// A rival direct/live owner may have published while this caller
|
|
72
|
+
// built. Reuse it and discard the duplicate before publication.
|
|
73
|
+
val canonical = liveLayoutLocked(key) ?: completed[key] ?: layout
|
|
74
|
+
if (canonical === layout && BuildConfig.PREPARED_PROSE_INSTRUMENTATION &&
|
|
75
|
+
!publishedKeys.add(key)
|
|
76
|
+
) {
|
|
77
|
+
PreparedProseInstrumentation.duplicatePublication()
|
|
78
|
+
check(false) {
|
|
79
|
+
"Prepared prose layout published twice for a live semantic/width/revision key."
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (canonical === layout && layout.retainedBytes <= byteBudget) {
|
|
83
|
+
completed[key] = layout
|
|
84
|
+
mountIndex[mountKey(key)] = key
|
|
85
|
+
}
|
|
86
|
+
createPendingLeaseIfActiveLocked(canonical, fabricGeneration, shouldCreateFabricLease)
|
|
87
|
+
enforceBudgetLocked(preferredGeneration = fabricGeneration)
|
|
88
|
+
retireUnownedPublicationsLocked()
|
|
89
|
+
publishOwnersLocked()
|
|
90
|
+
fresh.complete(canonical)
|
|
91
|
+
inFlight.remove(key, fresh)
|
|
92
|
+
return canonical
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fun registerDirectMount(owner: String, layout: PreparedProseLayout) = synchronized(lock) {
|
|
97
|
+
directMounted[owner] = layout
|
|
98
|
+
retireUnownedPublicationsLocked()
|
|
99
|
+
publishOwnersLocked()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fun releaseDirectMount(owner: String) = synchronized(lock) {
|
|
103
|
+
directMounted.remove(owner)
|
|
104
|
+
retireUnownedPublicationsLocked()
|
|
105
|
+
publishOwnersLocked()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Fabric acquires the exact measured artifact for its active generation. */
|
|
109
|
+
fun acquireForFabricMount(
|
|
110
|
+
generation: FabricGenerationToken,
|
|
111
|
+
widthPx: Int,
|
|
112
|
+
densityBits: Long,
|
|
113
|
+
allowCompletedFallback: Boolean = false,
|
|
114
|
+
shouldAcquire: () -> Boolean = { true }
|
|
115
|
+
): PreparedProseLayout? = synchronized(lock) {
|
|
116
|
+
mountedLeases.entries.firstOrNull { (key, layout) ->
|
|
117
|
+
key.generation == generation && layout.key.densityBits == densityBits &&
|
|
118
|
+
abs(layout.key.widthPx - widthPx) <= PIXEL_GRID_ROUNDING_SLACK_PX
|
|
119
|
+
}?.let {
|
|
120
|
+
if (!shouldAcquire()) return@synchronized null
|
|
121
|
+
return@synchronized it.value
|
|
122
|
+
}
|
|
123
|
+
val lease = pendingLeases.entries
|
|
124
|
+
.filter { (key, layout) ->
|
|
125
|
+
key.generation == generation && layout.key.densityBits == densityBits &&
|
|
126
|
+
abs(layout.key.widthPx - widthPx) <= PIXEL_GRID_ROUNDING_SLACK_PX
|
|
127
|
+
}
|
|
128
|
+
.minByOrNull { abs(it.value.key.widthPx - widthPx) }
|
|
129
|
+
if (lease == null) {
|
|
130
|
+
if (!allowCompletedFallback || !shouldAcquire()) return@synchronized null
|
|
131
|
+
val key = mountIndex[ProseMountKey(generation.generationIdentity, widthPx, densityBits)]
|
|
132
|
+
?: return@synchronized null
|
|
133
|
+
val layout = completed[key] ?: return@synchronized null
|
|
134
|
+
val leaseKey = FabricLeaseKey(generation, key)
|
|
135
|
+
mountedLeases.keys
|
|
136
|
+
.filter { it.owner == leaseKey.owner && it != leaseKey }
|
|
137
|
+
.forEach(mountedLeases::remove)
|
|
138
|
+
mountedLeases[leaseKey] = layout
|
|
139
|
+
retireUnownedPublicationsLocked()
|
|
140
|
+
publishOwnersLocked()
|
|
141
|
+
return@synchronized layout
|
|
142
|
+
}
|
|
143
|
+
if (!shouldAcquire()) return@synchronized null
|
|
144
|
+
pendingLeases.remove(lease.key)
|
|
145
|
+
mountedLeases.keys
|
|
146
|
+
.filter { it.owner == lease.key.owner && it != lease.key }
|
|
147
|
+
.forEach(mountedLeases::remove)
|
|
148
|
+
mountedLeases[lease.key] = lease.value
|
|
149
|
+
retireUnownedPublicationsLocked()
|
|
150
|
+
publishOwnersLocked()
|
|
151
|
+
lease.value
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
fun releaseLease(generation: FabricGenerationToken) = synchronized(lock) {
|
|
155
|
+
pendingLeases.keys.filter { it.generation == generation }.forEach(pendingLeases::remove)
|
|
156
|
+
mountedLeases.keys.filter { it.generation == generation }.forEach(mountedLeases::remove)
|
|
157
|
+
retireUnownedPublicationsLocked()
|
|
158
|
+
publishOwnersLocked()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* A family handle may commit only one generation. Retire stale pending
|
|
163
|
+
* handoffs now, but retain an older mounted artifact until this committed
|
|
164
|
+
* generation acquires its replacement under the same owner lock.
|
|
165
|
+
*/
|
|
166
|
+
fun activateFabricGeneration(generation: FabricGenerationToken) = synchronized(lock) {
|
|
167
|
+
val owner = FabricLeaseOwner(generation.surface, generation.leaseHandle)
|
|
168
|
+
pendingLeases.keys
|
|
169
|
+
.filter { it.owner == owner && it.generation != generation }
|
|
170
|
+
.forEach(pendingLeases::remove)
|
|
171
|
+
retireUnownedPublicationsLocked()
|
|
172
|
+
publishOwnersLocked()
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
fun releaseOwner(owner: FabricLeaseOwner) = synchronized(lock) {
|
|
176
|
+
pendingLeases.keys.filter { it.owner == owner }.forEach(pendingLeases::remove)
|
|
177
|
+
mountedLeases.keys.filter { it.owner == owner }.forEach(mountedLeases::remove)
|
|
178
|
+
retireUnownedPublicationsLocked()
|
|
179
|
+
publishOwnersLocked()
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fun releasePendingLease(
|
|
183
|
+
generation: FabricGenerationToken,
|
|
184
|
+
widthPx: Int? = null,
|
|
185
|
+
densityBits: Long? = null
|
|
186
|
+
) = synchronized(lock) {
|
|
187
|
+
pendingLeases.keys.filter { key ->
|
|
188
|
+
key.generation == generation && (widthPx == null || key.layout.widthPx == widthPx) &&
|
|
189
|
+
(densityBits == null || key.layout.densityBits == densityBits)
|
|
190
|
+
}.forEach(pendingLeases::remove)
|
|
191
|
+
retireUnownedPublicationsLocked()
|
|
192
|
+
publishOwnersLocked()
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
fun releaseSurface(surface: FabricSurfaceToken) = synchronized(lock) {
|
|
196
|
+
pendingLeases.keys.filter {
|
|
197
|
+
it.generation.surface == surface
|
|
198
|
+
}.forEach(pendingLeases::remove)
|
|
199
|
+
mountedLeases.keys.filter {
|
|
200
|
+
it.generation.surface == surface
|
|
201
|
+
}.forEach(mountedLeases::remove)
|
|
202
|
+
retireUnownedPublicationsLocked()
|
|
203
|
+
publishOwnersLocked()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
fun releaseSurfaceId(surfaceId: Int) = synchronized(lock) {
|
|
207
|
+
pendingLeases.keys.filter {
|
|
208
|
+
it.generation.surface.surfaceId == surfaceId
|
|
209
|
+
}.forEach(pendingLeases::remove)
|
|
210
|
+
mountedLeases.keys.filter {
|
|
211
|
+
it.generation.surface.surfaceId == surfaceId
|
|
212
|
+
}.forEach(mountedLeases::remove)
|
|
213
|
+
retireUnownedPublicationsLocked()
|
|
214
|
+
publishOwnersLocked()
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Memory pressure removes only unmounted cache and pending handoffs. */
|
|
218
|
+
fun removeAllUnmounted() = synchronized(lock) {
|
|
219
|
+
completed.clear()
|
|
220
|
+
mountIndex.clear()
|
|
221
|
+
pendingLeases.clear()
|
|
222
|
+
retireUnownedPublicationsLocked()
|
|
223
|
+
publishOwnersLocked()
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
internal val completedCountForTesting: Int get() = synchronized(lock) { completed.size }
|
|
227
|
+
internal val retainedBytesForTesting: Long get() = synchronized(lock) { unmountedBytesLocked() }
|
|
228
|
+
internal val retainedLeaseBytesForTesting: Long get() = synchronized(lock) {
|
|
229
|
+
uniqueBytes(pendingLeases.values + mountedLeases.values)
|
|
230
|
+
}
|
|
231
|
+
internal val leaseCountForTesting: Int get() = synchronized(lock) {
|
|
232
|
+
pendingLeases.size +
|
|
233
|
+
mountedLeases.size
|
|
234
|
+
}
|
|
235
|
+
internal val pendingLeaseCountForTesting: Int get() = synchronized(lock) { pendingLeases.size }
|
|
236
|
+
internal fun beginBenchmarkCensus() = synchronized(lock) {
|
|
237
|
+
benchmarkCensusKeys = linkedSetOf()
|
|
238
|
+
}
|
|
239
|
+
internal fun endBenchmarkCensus(): Set<ProseLayoutKey> = synchronized(lock) {
|
|
240
|
+
val liveKeys = completed.keys + pendingLeases.values.map { it.key } +
|
|
241
|
+
mountedLeases.values.map { it.key } + directMounted.values.map { it.key }
|
|
242
|
+
val resident = benchmarkCensusKeys.orEmpty().intersect(liveKeys.toSet())
|
|
243
|
+
benchmarkCensusKeys = null
|
|
244
|
+
resident
|
|
245
|
+
}
|
|
246
|
+
internal fun hasLease(generation: FabricGenerationToken): Boolean = synchronized(lock) {
|
|
247
|
+
pendingLeases.keys.any { it.generation == generation } ||
|
|
248
|
+
mountedLeases.keys.any { it.generation == generation }
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private fun createPendingLeaseIfActiveLocked(
|
|
252
|
+
layout: PreparedProseLayout,
|
|
253
|
+
generation: FabricGenerationToken?,
|
|
254
|
+
shouldCreateFabricLease: () -> Boolean
|
|
255
|
+
) {
|
|
256
|
+
if (generation != null &&
|
|
257
|
+
shouldCreateFabricLease()
|
|
258
|
+
) {
|
|
259
|
+
createPendingLeaseLocked(layout, generation)
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private fun createPendingLeaseLocked(
|
|
264
|
+
layout: PreparedProseLayout,
|
|
265
|
+
generation: FabricGenerationToken
|
|
266
|
+
) {
|
|
267
|
+
val lease = FabricLeaseKey(generation, layout.key)
|
|
268
|
+
pendingLeases.keys
|
|
269
|
+
.filter { it.owner == lease.owner && it != lease }
|
|
270
|
+
.forEach(pendingLeases::remove)
|
|
271
|
+
if (mountedLeases[lease] == null) pendingLeases[lease] = layout
|
|
272
|
+
enforceBudgetLocked(preferredGeneration = generation)
|
|
273
|
+
retireUnownedPublicationsLocked()
|
|
274
|
+
publishOwnersLocked()
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
private fun enforceBudgetLocked(preferredGeneration: FabricGenerationToken?) {
|
|
278
|
+
while (budgetedRetainedBytesLocked() > byteBudget) {
|
|
279
|
+
val completedEntry = completed.entries.firstOrNull()
|
|
280
|
+
if (completedEntry != null) {
|
|
281
|
+
completed.remove(completedEntry.key)
|
|
282
|
+
if (mountIndex[mountKey(completedEntry.key)] ==
|
|
283
|
+
completedEntry.key
|
|
284
|
+
) {
|
|
285
|
+
mountIndex.remove(mountKey(completedEntry.key))
|
|
286
|
+
}
|
|
287
|
+
continue
|
|
288
|
+
}
|
|
289
|
+
// A duplicate pending handoff can be the only exact artifact for
|
|
290
|
+
// another Fabric owner even when the same immutable object is
|
|
291
|
+
// already mounted/direct-mounted. Removing it frees zero bytes,
|
|
292
|
+
// so it cannot satisfy either retained-byte pressure or justify
|
|
293
|
+
// breaking exact-once handoff ownership.
|
|
294
|
+
val pendingEntry = pendingLeases.entries.firstOrNull {
|
|
295
|
+
it.key.generation != preferredGeneration && pendingRemovalLowersBudgetLocked(it)
|
|
296
|
+
} ?: break
|
|
297
|
+
pendingLeases.remove(pendingEntry.key)
|
|
298
|
+
}
|
|
299
|
+
// Shared immutable artifacts may make a pending handoff free zero
|
|
300
|
+
// bytes. Its owner metadata still needs a hard cap in long feeds.
|
|
301
|
+
while (pendingLeases.size > pendingLeaseBudget) {
|
|
302
|
+
val pendingEntry = pendingLeases.entries.firstOrNull {
|
|
303
|
+
it.key.generation != preferredGeneration
|
|
304
|
+
} ?: break
|
|
305
|
+
pendingLeases.remove(pendingEntry.key)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private fun liveLayoutLocked(key: ProseLayoutKey): PreparedProseLayout? =
|
|
310
|
+
(pendingLeases.values + mountedLeases.values + directMounted.values).firstOrNull {
|
|
311
|
+
it.key ==
|
|
312
|
+
key
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private fun retireUnownedPublicationsLocked() {
|
|
316
|
+
publishedKeys.retainAll(
|
|
317
|
+
(
|
|
318
|
+
completed.keys + pendingLeases.values.map { it.key } +
|
|
319
|
+
mountedLeases.values.map { it.key } +
|
|
320
|
+
directMounted.values.map { it.key }
|
|
321
|
+
).toSet()
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private fun publishOwnersLocked() {
|
|
326
|
+
PreparedProseInstrumentation.cacheUpdated(
|
|
327
|
+
unmountedBytes = unmountedBytesLocked(),
|
|
328
|
+
unmountedResidentCount = completed.size.toLong()
|
|
329
|
+
)
|
|
330
|
+
PreparedProseInstrumentation.retained(
|
|
331
|
+
PreparedProseInstrumentation.Owner.UNMOUNTED_LAYOUT,
|
|
332
|
+
"cache",
|
|
333
|
+
unmountedBytesLocked()
|
|
334
|
+
)
|
|
335
|
+
PreparedProseInstrumentation.retained(
|
|
336
|
+
PreparedProseInstrumentation.Owner.FABRIC_LEASE_HANDOFF,
|
|
337
|
+
"leases",
|
|
338
|
+
uniqueBytes(pendingLeases.values + mountedLeases.values)
|
|
339
|
+
)
|
|
340
|
+
PreparedProseInstrumentation.retained(
|
|
341
|
+
PreparedProseInstrumentation.Owner.DIRECT_MOUNTED,
|
|
342
|
+
"views",
|
|
343
|
+
uniqueBytes(directMounted.values)
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/** A shared completed reference is charged to its live mount/lease, never twice. */
|
|
348
|
+
private fun unmountedBytesLocked(): Long {
|
|
349
|
+
val live = identitySet(pendingLeases.values + mountedLeases.values + directMounted.values)
|
|
350
|
+
return uniqueBytes(completed.values.filter { it !in live })
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* The pre-mount budget counts each immutable artifact once, excluding
|
|
355
|
+
* identities already retained by mounted Fabric or direct View owners.
|
|
356
|
+
* A second pending lease for such an object is ownership metadata, not an
|
|
357
|
+
* additional allocation.
|
|
358
|
+
*/
|
|
359
|
+
private fun budgetedRetainedBytesLocked(): Long {
|
|
360
|
+
val live = identitySet(mountedLeases.values + directMounted.values)
|
|
361
|
+
return uniqueBytes((completed.values + pendingLeases.values).filter { it !in live })
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
private fun pendingRemovalLowersBudgetLocked(
|
|
365
|
+
entry: Map.Entry<FabricLeaseKey, PreparedProseLayout>
|
|
366
|
+
): Boolean {
|
|
367
|
+
val layout = entry.value
|
|
368
|
+
val mountedOrDirect = identitySet(mountedLeases.values + directMounted.values)
|
|
369
|
+
if (layout in mountedOrDirect) return false
|
|
370
|
+
if (completed.values.any { it === layout }) return false
|
|
371
|
+
return pendingLeases.any { (key, candidate) ->
|
|
372
|
+
key != entry.key && candidate === layout
|
|
373
|
+
}.not()
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
private fun identitySet(
|
|
377
|
+
layouts: Collection<PreparedProseLayout>
|
|
378
|
+
): MutableSet<PreparedProseLayout> =
|
|
379
|
+
Collections.newSetFromMap(IdentityHashMap<PreparedProseLayout, Boolean>()).apply {
|
|
380
|
+
addAll(layouts)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
private fun uniqueBytes(layouts: Collection<PreparedProseLayout>): Long {
|
|
384
|
+
val seen = identitySet(layouts)
|
|
385
|
+
return seen.sumOf { it.retainedBytes }
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
private val FabricLeaseKey.owner: FabricLeaseOwner
|
|
389
|
+
get() = FabricLeaseOwner(generation.surface, generation.leaseHandle)
|
|
390
|
+
|
|
391
|
+
private fun mountKey(key: ProseLayoutKey) =
|
|
392
|
+
ProseMountKey(key.generationIdentity, key.widthPx, key.densityBits)
|
|
393
|
+
}
|