@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,478 @@
|
|
|
1
|
+
import UIKit
|
|
2
|
+
|
|
3
|
+
/// The bounded editor owner is the shared native transport/cache implementation.
|
|
4
|
+
/// This alias makes the cross-surface boundary explicit without forking policy.
|
|
5
|
+
typealias NativeImagePipeline = RenderImageLoadOwner
|
|
6
|
+
|
|
7
|
+
/// Immutable geometry produced by preparation. Pixels are deliberately kept
|
|
8
|
+
/// outside `PreparedProseLayout`, so image completion cannot mutate layout.
|
|
9
|
+
struct ViewerImageAttachment: Hashable {
|
|
10
|
+
/// Compiler/admission ceiling. Publication storage is a compact bitset,
|
|
11
|
+
/// but preparation still caps adversarial attachment artifacts.
|
|
12
|
+
static let maximumAdmittedAttachments = 8_192
|
|
13
|
+
/// Ordinal within the immutable prepared artifact. This is the compact
|
|
14
|
+
/// publication-state address; `id` remains source-qualified cache identity.
|
|
15
|
+
let ordinal: Int
|
|
16
|
+
let id: String
|
|
17
|
+
let source: String
|
|
18
|
+
let bounds: CGRect
|
|
19
|
+
let declaredSize: CGSize?
|
|
20
|
+
|
|
21
|
+
init(
|
|
22
|
+
ordinal: Int = -1,
|
|
23
|
+
id: String,
|
|
24
|
+
source: String,
|
|
25
|
+
bounds: CGRect,
|
|
26
|
+
declaredSize: CGSize?
|
|
27
|
+
) {
|
|
28
|
+
self.ordinal = ordinal
|
|
29
|
+
self.id = id
|
|
30
|
+
self.source = source
|
|
31
|
+
self.bounds = bounds
|
|
32
|
+
self.declaredSize = declaredSize
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
var hasDeclaredSize: Bool { (declaredSize?.width ?? 0) > 0 && (declaredSize?.height ?? 0) > 0 }
|
|
36
|
+
|
|
37
|
+
struct SourceMetadata {
|
|
38
|
+
let id: String
|
|
39
|
+
let source: String
|
|
40
|
+
let declaredSize: CGSize?
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static func sourceAndDeclaredSize(in block: ViewerBlock) -> SourceMetadata? {
|
|
44
|
+
guard let atom = block.inlines.compactMap({ inline -> (UInt32, String)? in
|
|
45
|
+
guard case let .atom(nodeType, docPos, attrsJSON, _) = inline,
|
|
46
|
+
nodeType == "image" else { return nil }
|
|
47
|
+
return (docPos, attrsJSON)
|
|
48
|
+
}).first,
|
|
49
|
+
let values = try? JSONSerialization.jsonObject(with: Data(atom.1.utf8)) as? [String: Any],
|
|
50
|
+
let source = values["src"] as? String, !source.isEmpty else { return nil }
|
|
51
|
+
func dimension(_ name: String) -> CGFloat? {
|
|
52
|
+
guard let value = values[name] as? NSNumber else { return nil }
|
|
53
|
+
let dimension = CGFloat(truncating: value)
|
|
54
|
+
return dimension.isFinite && dimension > 0 ? dimension : nil
|
|
55
|
+
}
|
|
56
|
+
let width = dimension("width")
|
|
57
|
+
let height = dimension("height")
|
|
58
|
+
let declared = width.flatMap { declaredWidth in height.map { CGSize(width: declaredWidth, height: $0) } }
|
|
59
|
+
return SourceMetadata(id: "\(atom.0):\(source)", source: source, declaredSize: declared)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// The only mutable image-metadata state. It records the first valid intrinsic
|
|
64
|
+
/// size atomically and advances the attachment revision exactly once per id.
|
|
65
|
+
final class ViewerImageIntrinsicStore {
|
|
66
|
+
static let shared = ViewerImageIntrinsicStore()
|
|
67
|
+
|
|
68
|
+
private struct Entry {
|
|
69
|
+
let size: CGSize
|
|
70
|
+
var access: UInt64
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private let lock = NSLock()
|
|
74
|
+
private var entryLimit: Int
|
|
75
|
+
private var access: UInt64 = 0
|
|
76
|
+
private var values: [String: Entry] = [:]
|
|
77
|
+
|
|
78
|
+
init(entryLimit: Int = 256) { self.entryLimit = max(1, entryLimit) }
|
|
79
|
+
|
|
80
|
+
/// Preparation may only see its explicitly scoped local sidecar. The
|
|
81
|
+
/// process cache remains global, but an LRU miss never scans another host.
|
|
82
|
+
func size(for id: String) -> CGSize? {
|
|
83
|
+
lock.lock()
|
|
84
|
+
if var entry = values[id] {
|
|
85
|
+
access &+= 1
|
|
86
|
+
entry.access = access
|
|
87
|
+
values[id] = entry
|
|
88
|
+
lock.unlock()
|
|
89
|
+
return entry.size
|
|
90
|
+
}
|
|
91
|
+
lock.unlock()
|
|
92
|
+
return FabricAttachmentSidecars.currentMeasurementState?.intrinsicSize(forSourceQualifiedID: id)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Test-only global-LRU inspection. `size(for:)` may consult its scoped
|
|
96
|
+
/// owner, so it cannot prove an LRU eviction on its own.
|
|
97
|
+
func globalSize(for id: String) -> CGSize? {
|
|
98
|
+
lock.withLock { values[id]?.size }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// Test-only control of the actual process-global LRU. `size(for:)` keeps
|
|
102
|
+
/// its scoped-sidecar fallback, while this inspection proves eviction.
|
|
103
|
+
func clearAndSetEntryLimitForTesting(_ limit: Int = 256) {
|
|
104
|
+
lock.withLock {
|
|
105
|
+
entryLimit = max(1, limit)
|
|
106
|
+
access = 0
|
|
107
|
+
values.removeAll(keepingCapacity: false)
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
func store(_ size: CGSize, for id: String) {
|
|
112
|
+
guard size.width.isFinite, size.height.isFinite, size.width > 0, size.height > 0 else { return }
|
|
113
|
+
lock.lock()
|
|
114
|
+
defer { lock.unlock() }
|
|
115
|
+
access &+= 1
|
|
116
|
+
values[id] = Entry(size: size, access: access)
|
|
117
|
+
while values.count > entryLimit,
|
|
118
|
+
let oldest = values.min(by: { lhs, rhs in
|
|
119
|
+
lhs.value.access == rhs.value.access ? lhs.key < rhs.key : lhs.value.access < rhs.value.access
|
|
120
|
+
}) {
|
|
121
|
+
values.removeValue(forKey: oldest.key)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Per-surface publication state. It retains compact ordinal metadata plus a
|
|
127
|
+
/// bitset, so the global LRU is only an optimization. It resets only for a
|
|
128
|
+
/// semantic replacement or recycle/teardown, never request cancellation.
|
|
129
|
+
final class ViewerAttachmentRevisionState {
|
|
130
|
+
/// Project accounting convention: fixed owner plus one header per retained
|
|
131
|
+
/// proportional collection. Payload is charged below at native stride.
|
|
132
|
+
static let fixedRetainedBytes = 160
|
|
133
|
+
static let collectionRetainedBytes = 32
|
|
134
|
+
private let lock = NSLock()
|
|
135
|
+
private var publishedBits: [UInt8] = []
|
|
136
|
+
private var reportedErrorBits: [UInt8] = []
|
|
137
|
+
private var intrinsicSizes: [CGSize] = []
|
|
138
|
+
private var sourceQualifiedIDs: [String?] = []
|
|
139
|
+
private var attachmentOrdinals: [Int] = []
|
|
140
|
+
private var admittedAttachmentCount = 0
|
|
141
|
+
private var semanticGenerationIdentity: String?
|
|
142
|
+
private(set) var revision: UInt64 = 0
|
|
143
|
+
|
|
144
|
+
/// Exact per-surface retained state. This is not an immutable layout cost:
|
|
145
|
+
/// it belongs to the mounted host, including both bitsets, dimensions,
|
|
146
|
+
/// source identity references, ordinal addresses, collection headers, and
|
|
147
|
+
/// explicitly scoped preparation ownership.
|
|
148
|
+
var retainedPublicationBytesForTesting: Int {
|
|
149
|
+
lock.withLock {
|
|
150
|
+
Self.fixedRetainedBytes
|
|
151
|
+
+ Self.collectionRetainedBytes * 5
|
|
152
|
+
+ publishedBits.count
|
|
153
|
+
+ reportedErrorBits.count
|
|
154
|
+
+ intrinsicSizes.count * MemoryLayout<CGSize>.stride
|
|
155
|
+
+ sourceQualifiedIDs.count * MemoryLayout<String?>.stride
|
|
156
|
+
+ attachmentOrdinals.count * MemoryLayout<Int>.stride
|
|
157
|
+
+ sourceQualifiedIDs.compactMap { $0 }.reduce(0) { $0 + $1.utf8.count * 2 }
|
|
158
|
+
+ (semanticGenerationIdentity?.utf8.count ?? 0) * 2
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// Returns true exactly when a true semantic replacement has cleared all
|
|
163
|
+
/// generation-scoped correctness state. State-revision reinstalls return
|
|
164
|
+
/// false and preserve metadata/error publication.
|
|
165
|
+
@discardableResult
|
|
166
|
+
func beginSemanticGeneration(_ identity: String) -> Bool {
|
|
167
|
+
let changed = lock.withLock {
|
|
168
|
+
guard semanticGenerationIdentity != identity else { return false }
|
|
169
|
+
clearLocked()
|
|
170
|
+
semanticGenerationIdentity = identity
|
|
171
|
+
return true
|
|
172
|
+
}
|
|
173
|
+
return changed
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
func admit(attachmentCount: Int) {
|
|
177
|
+
let count = max(0, attachmentCount)
|
|
178
|
+
lock.withLock {
|
|
179
|
+
guard admittedAttachmentCount != count else { return }
|
|
180
|
+
admittedAttachmentCount = count
|
|
181
|
+
publishedBits = Array(repeating: 0, count: (count + 7) / 8)
|
|
182
|
+
reportedErrorBits = Array(repeating: 0, count: (count + 7) / 8)
|
|
183
|
+
intrinsicSizes = Array(repeating: .zero, count: count)
|
|
184
|
+
sourceQualifiedIDs = Array(repeating: nil, count: count)
|
|
185
|
+
attachmentOrdinals = Array(0..<count)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
func reset() {
|
|
190
|
+
lock.withLock {
|
|
191
|
+
clearLocked()
|
|
192
|
+
semanticGenerationIdentity = nil
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@discardableResult
|
|
197
|
+
func recordIntrinsicSize(_ size: CGSize, for id: String, ordinal: Int, declaredSize: CGSize?) -> Bool {
|
|
198
|
+
guard declaredSize == nil, size.width.isFinite, size.height.isFinite, size.width > 0, size.height > 0 else { return false }
|
|
199
|
+
lock.lock(); defer { lock.unlock() }
|
|
200
|
+
guard ordinal >= 0, ordinal < admittedAttachmentCount else { return false }
|
|
201
|
+
let byteIndex = ordinal / 8
|
|
202
|
+
let mask = UInt8(1 << (ordinal % 8))
|
|
203
|
+
guard publishedBits[byteIndex] & mask == 0 else { return false }
|
|
204
|
+
publishedBits[byteIndex] |= mask
|
|
205
|
+
intrinsicSizes[ordinal] = size
|
|
206
|
+
sourceQualifiedIDs[ordinal] = id
|
|
207
|
+
ViewerImageIntrinsicStore.shared.store(size, for: id)
|
|
208
|
+
revision &+= 1
|
|
209
|
+
return true
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
func intrinsicSize(for ordinal: Int) -> CGSize? {
|
|
213
|
+
lock.withLock {
|
|
214
|
+
guard ordinal >= 0, ordinal < admittedAttachmentCount else { return nil }
|
|
215
|
+
let mask = UInt8(1 << (ordinal % 8))
|
|
216
|
+
return publishedBits[ordinal / 8] & mask == 0 ? nil : intrinsicSizes[ordinal]
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
@discardableResult
|
|
221
|
+
func recordResourceFailure(for ordinal: Int) -> Bool {
|
|
222
|
+
lock.withLock {
|
|
223
|
+
guard ordinal >= 0, ordinal < admittedAttachmentCount else { return false }
|
|
224
|
+
let byteIndex = ordinal / 8
|
|
225
|
+
let mask = UInt8(1 << (ordinal % 8))
|
|
226
|
+
guard reportedErrorBits[byteIndex] & mask == 0 else { return false }
|
|
227
|
+
reportedErrorBits[byteIndex] |= mask
|
|
228
|
+
return true
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
fileprivate func intrinsicSize(forSourceQualifiedID id: String) -> CGSize? {
|
|
233
|
+
lock.withLock {
|
|
234
|
+
guard let index = sourceQualifiedIDs.firstIndex(where: { $0 == id }) else { return nil }
|
|
235
|
+
let ordinal = attachmentOrdinals[index]
|
|
236
|
+
let mask = UInt8(1 << (ordinal % 8))
|
|
237
|
+
return publishedBits[ordinal / 8] & mask == 0 ? nil : intrinsicSizes[ordinal]
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private func clearLocked() {
|
|
242
|
+
publishedBits.removeAll(keepingCapacity: false)
|
|
243
|
+
reportedErrorBits.removeAll(keepingCapacity: false)
|
|
244
|
+
intrinsicSizes.removeAll(keepingCapacity: false)
|
|
245
|
+
sourceQualifiedIDs.removeAll(keepingCapacity: false)
|
|
246
|
+
attachmentOrdinals.removeAll(keepingCapacity: false)
|
|
247
|
+
admittedAttachmentCount = 0
|
|
248
|
+
revision = 0
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/// Fabric preparation has no mounted UIView to own mutable image publication.
|
|
254
|
+
/// Keep that state at the stable surface/component token and install it into a
|
|
255
|
+
/// thread-local measurement scope before Core Text can inspect intrinsic data.
|
|
256
|
+
final class FabricAttachmentSidecars {
|
|
257
|
+
private static let lock = NSLock()
|
|
258
|
+
private struct Owner: Hashable {
|
|
259
|
+
let surface: FabricSurfaceToken
|
|
260
|
+
let leaseHandle: UInt64
|
|
261
|
+
}
|
|
262
|
+
private static var states: [Owner: ViewerAttachmentRevisionState] = [:]
|
|
263
|
+
private static let measurementStateKey = "com.apollohg.editor.viewer.fabricImageMeasurementState"
|
|
264
|
+
|
|
265
|
+
static var currentMeasurementState: ViewerAttachmentRevisionState? {
|
|
266
|
+
Thread.current.threadDictionary[measurementStateKey] as? ViewerAttachmentRevisionState
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
static func begin(
|
|
270
|
+
_ surface: FabricSurfaceToken,
|
|
271
|
+
leaseHandle: UInt64 = 0,
|
|
272
|
+
semanticIdentity: String
|
|
273
|
+
) -> ViewerAttachmentRevisionState {
|
|
274
|
+
lock.withLock {
|
|
275
|
+
let owner = Owner(surface: surface, leaseHandle: leaseHandle)
|
|
276
|
+
let state = states[owner] ?? ViewerAttachmentRevisionState()
|
|
277
|
+
states[owner] = state
|
|
278
|
+
_ = state.beginSemanticGeneration(semanticIdentity)
|
|
279
|
+
return state
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
static func withMeasurementState<T>(_ state: ViewerAttachmentRevisionState, _ body: () throws -> T) rethrows -> T {
|
|
284
|
+
let dictionary = Thread.current.threadDictionary
|
|
285
|
+
let previous = dictionary[measurementStateKey]
|
|
286
|
+
dictionary[measurementStateKey] = state
|
|
287
|
+
defer {
|
|
288
|
+
if let previous { dictionary[measurementStateKey] = previous } else { dictionary.removeObject(forKey: measurementStateKey) }
|
|
289
|
+
}
|
|
290
|
+
return try body()
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
static func state(
|
|
294
|
+
for surface: FabricSurfaceToken,
|
|
295
|
+
leaseHandle: UInt64 = 0
|
|
296
|
+
) -> ViewerAttachmentRevisionState? {
|
|
297
|
+
lock.withLock { states[Owner(surface: surface, leaseHandle: leaseHandle)] }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
static func remove(_ surface: FabricSurfaceToken, leaseHandle: UInt64? = nil) {
|
|
301
|
+
lock.withLock {
|
|
302
|
+
let owners = states.keys.filter {
|
|
303
|
+
$0.surface == surface && (leaseHandle == nil || $0.leaseHandle == leaseHandle)
|
|
304
|
+
}
|
|
305
|
+
owners.forEach { states.removeValue(forKey: $0)?.reset() }
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
static func remove(surfaceId: Int64) {
|
|
310
|
+
lock.withLock {
|
|
311
|
+
states.keys.filter { $0.surface.surfaceId == surfaceId }.forEach { states.removeValue(forKey: $0)?.reset() }
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/// Bounded/cancellable viewer facade over the editor's existing native image
|
|
317
|
+
/// owner. The owner retains validation, fetch/decode limits, cache ownership,
|
|
318
|
+
/// receipts, deadlines and error isolation; this facade adds viewport and
|
|
319
|
+
/// generation ownership without changing editor behaviour.
|
|
320
|
+
final class ViewerImagePipeline {
|
|
321
|
+
typealias PixelCompletion = (_ attachment: ViewerImageAttachment, _ image: UIImage) -> Void
|
|
322
|
+
typealias MetadataCompletion = (_ attachment: ViewerImageAttachment, _ size: CGSize) -> Void
|
|
323
|
+
|
|
324
|
+
static let prefetchMargin: CGFloat = 480
|
|
325
|
+
|
|
326
|
+
private let owner: NativeImagePipeline
|
|
327
|
+
private let lock = NSLock()
|
|
328
|
+
private var generation = ""
|
|
329
|
+
private var enabled = false
|
|
330
|
+
private var receipts: [String: NativeImagePipeline.ImageLoadReceipt] = [:]
|
|
331
|
+
private var requested = Set<String>()
|
|
332
|
+
private(set) var requestCountForTesting = 0
|
|
333
|
+
var onPixels: PixelCompletion?
|
|
334
|
+
var onIntrinsicMetadata: MetadataCompletion?
|
|
335
|
+
/// Deliberately carries no source URL; hosts map it to their public error contract.
|
|
336
|
+
var onResourceFailure: ((ViewerImageAttachment) -> Void)?
|
|
337
|
+
|
|
338
|
+
init(policy: ImageLoadingPolicy) {
|
|
339
|
+
owner = NativeImagePipeline(policy: policy)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
func begin(generation: String, imagesEnabled: Bool, policy: ImageLoadingPolicy? = nil) {
|
|
343
|
+
lock.lock()
|
|
344
|
+
let nextPolicy = policy ?? owner.policy
|
|
345
|
+
if self.generation == generation, enabled == imagesEnabled, owner.policy == nextPolicy {
|
|
346
|
+
lock.unlock()
|
|
347
|
+
return
|
|
348
|
+
}
|
|
349
|
+
owner.cancelAll()
|
|
350
|
+
if owner.policy != nextPolicy { owner.updatePolicy(nextPolicy) }
|
|
351
|
+
self.generation = generation
|
|
352
|
+
enabled = imagesEnabled
|
|
353
|
+
receipts.removeAll()
|
|
354
|
+
requested.removeAll()
|
|
355
|
+
requestCountForTesting = 0
|
|
356
|
+
lock.unlock()
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
func cancel() {
|
|
360
|
+
lock.lock()
|
|
361
|
+
generation = ""
|
|
362
|
+
enabled = false
|
|
363
|
+
receipts.values.forEach { $0.cancel() }
|
|
364
|
+
receipts.removeAll()
|
|
365
|
+
requested.removeAll()
|
|
366
|
+
lock.unlock()
|
|
367
|
+
owner.cancelAll()
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
func acceptsCompletion(generation: String) -> Bool {
|
|
371
|
+
lock.lock(); defer { lock.unlock() }
|
|
372
|
+
return enabled && !self.generation.isEmpty && self.generation == generation
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
@discardableResult
|
|
376
|
+
func updateVisibleRect(_ visibleRect: CGRect, attachments: [ViewerImageAttachment]) -> Set<String> {
|
|
377
|
+
guard visibleRect.origin.x.isFinite, visibleRect.origin.y.isFinite,
|
|
378
|
+
visibleRect.size.width.isFinite, visibleRect.size.height.isFinite,
|
|
379
|
+
!visibleRect.isNull, !visibleRect.isEmpty else { return [] }
|
|
380
|
+
let expanded = visibleRect.insetBy(dx: -Self.prefetchMargin, dy: -Self.prefetchMargin)
|
|
381
|
+
let eligible = attachments.filter { $0.ordinal >= 0 && !$0.source.isEmpty && $0.bounds.intersects(expanded) }
|
|
382
|
+
let eligibleIDs = Set(eligible.map(\.id))
|
|
383
|
+
struct PendingLoads {
|
|
384
|
+
let generation: String
|
|
385
|
+
let attachments: [ViewerImageAttachment]
|
|
386
|
+
let cancellations: [NativeImagePipeline.ImageLoadReceipt]
|
|
387
|
+
}
|
|
388
|
+
let start: PendingLoads? = lock.withLock {
|
|
389
|
+
guard enabled, !generation.isEmpty else { return nil }
|
|
390
|
+
let leaving = requested.subtracting(eligibleIDs)
|
|
391
|
+
let cancellations = leaving.compactMap { receipts.removeValue(forKey: $0) }
|
|
392
|
+
requested.subtract(leaving)
|
|
393
|
+
let next = eligible.filter { requested.insert($0.id).inserted }
|
|
394
|
+
requestCountForTesting += next.count
|
|
395
|
+
return PendingLoads(generation: generation, attachments: next, cancellations: cancellations)
|
|
396
|
+
}
|
|
397
|
+
guard let start else { return eligibleIDs }
|
|
398
|
+
let currentGeneration = start.generation
|
|
399
|
+
start.cancellations.forEach { $0.cancel() }
|
|
400
|
+
for attachment in start.attachments {
|
|
401
|
+
let receipt = owner.startImageLoad(
|
|
402
|
+
source: attachment.source,
|
|
403
|
+
completion: { [weak self] image in
|
|
404
|
+
guard let self,
|
|
405
|
+
self.acceptsCompletion(generation: currentGeneration, attachmentID: attachment.id)
|
|
406
|
+
else { return }
|
|
407
|
+
guard let image else {
|
|
408
|
+
self.reportFailure(attachment, generation: currentGeneration)
|
|
409
|
+
return
|
|
410
|
+
}
|
|
411
|
+
let size = image.size.applying(CGAffineTransform(scaleX: image.scale, y: image.scale))
|
|
412
|
+
guard size.width.isFinite, size.height.isFinite, size.width > 0, size.height > 0 else {
|
|
413
|
+
self.reportFailure(attachment, generation: currentGeneration)
|
|
414
|
+
return
|
|
415
|
+
}
|
|
416
|
+
PreparedProseInstrumentation.imageMetadataRead()
|
|
417
|
+
self.onIntrinsicMetadata?(attachment, size)
|
|
418
|
+
guard self.acceptsCompletion(generation: currentGeneration, attachmentID: attachment.id)
|
|
419
|
+
else { return }
|
|
420
|
+
PreparedProseInstrumentation.imageDecoded()
|
|
421
|
+
self.onPixels?(attachment, image)
|
|
422
|
+
},
|
|
423
|
+
onAcceptedStart: PreparedProseInstrumentation.imageRequested
|
|
424
|
+
)
|
|
425
|
+
if let receipt {
|
|
426
|
+
let shouldRetain = lock.withLock { () -> Bool in
|
|
427
|
+
guard enabled, generation == currentGeneration else { return false }
|
|
428
|
+
receipts[attachment.id] = receipt
|
|
429
|
+
return true
|
|
430
|
+
}
|
|
431
|
+
if !shouldRetain { receipt.cancel() }
|
|
432
|
+
} else {
|
|
433
|
+
reportFailure(attachment, generation: currentGeneration)
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return eligibleIDs
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
func leaveViewport() {
|
|
440
|
+
let cancellations = lock.withLock {
|
|
441
|
+
let values = Array(receipts.values)
|
|
442
|
+
receipts.removeAll()
|
|
443
|
+
requested.removeAll()
|
|
444
|
+
return values
|
|
445
|
+
}
|
|
446
|
+
cancellations.forEach { $0.cancel() }
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
private func acceptsCompletion(generation: String, attachmentID: String) -> Bool {
|
|
450
|
+
lock.withLock {
|
|
451
|
+
enabled && !self.generation.isEmpty && self.generation == generation
|
|
452
|
+
&& requested.contains(attachmentID)
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
private func reportFailure(_ attachment: ViewerImageAttachment, generation: String) {
|
|
457
|
+
let callback: ((ViewerImageAttachment) -> Void)? = lock.withLock {
|
|
458
|
+
guard enabled, self.generation == generation else { return nil }
|
|
459
|
+
return onResourceFailure
|
|
460
|
+
}
|
|
461
|
+
callback?(attachment)
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
internal func reportFailureForTesting(_ attachment: ViewerImageAttachment) {
|
|
465
|
+
lock.lock()
|
|
466
|
+
let currentGeneration = generation
|
|
467
|
+
lock.unlock()
|
|
468
|
+
reportFailure(attachment, generation: currentGeneration)
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
private extension NSLock {
|
|
473
|
+
func withLock<T>(_ body: () -> T) -> T {
|
|
474
|
+
lock()
|
|
475
|
+
defer { unlock() }
|
|
476
|
+
return body()
|
|
477
|
+
}
|
|
478
|
+
}
|