@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,387 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import QuartzCore
|
|
3
|
+
|
|
4
|
+
/// Debug/device-only accounting. Samples belong to the traversal that caused
|
|
5
|
+
/// them; a phase transition is serialized with every producer under `lock`.
|
|
6
|
+
/// Percentiles use nearest-rank: sorted[ceil(p * n) - 1].
|
|
7
|
+
enum PreparedProseInstrumentation {
|
|
8
|
+
enum Owner: String, CaseIterable { case compiled, unmountedLayout, fabricLeaseHandoff, directMounted, image, sidecars, other }
|
|
9
|
+
enum InvalidationReason: String { case content, width, attachment, font, appearance, memoryPressure, cacheReset, reuse }
|
|
10
|
+
enum TraversalPhase: String, CaseIterable { case cold, warm, imagesDisabled, reset }
|
|
11
|
+
enum ViewerWorkKind: String, Codable { case layout, draw, lifecycle }
|
|
12
|
+
struct ViewerWorkSpan: Equatable {
|
|
13
|
+
let startNanos: UInt64
|
|
14
|
+
let endNanos: UInt64
|
|
15
|
+
let kind: ViewerWorkKind
|
|
16
|
+
}
|
|
17
|
+
struct FrameClassification: Equatable {
|
|
18
|
+
let nominalFrameCount: Int
|
|
19
|
+
let isDelayed: Bool
|
|
20
|
+
}
|
|
21
|
+
struct FrameCallbackSample: Codable {
|
|
22
|
+
let callbackTimestampNanos: UInt64
|
|
23
|
+
let callbackDurationNanos: UInt64
|
|
24
|
+
let targetLeadNanos: Int64
|
|
25
|
+
}
|
|
26
|
+
struct CacheSnapshot: Codable, Equatable {
|
|
27
|
+
var unmountedCurrentBytes = 0
|
|
28
|
+
var unmountedHighWaterBytes = 0
|
|
29
|
+
var unmountedCurrentResidentCount = 0
|
|
30
|
+
var unmountedHighWaterResidentCount = 0
|
|
31
|
+
var compiledCurrentBytes = 0
|
|
32
|
+
var compiledCurrentResidentCount = 0
|
|
33
|
+
}
|
|
34
|
+
struct DelayedInterval: Codable {
|
|
35
|
+
let startNanos: UInt64
|
|
36
|
+
let endNanos: UInt64
|
|
37
|
+
let rawDeltaNanos: UInt64
|
|
38
|
+
let viewerLayoutNanos: UInt64
|
|
39
|
+
let viewerDrawNanos: UInt64
|
|
40
|
+
let viewerLifecycleNanos: UInt64
|
|
41
|
+
let viewerWorkUnionNanos: UInt64
|
|
42
|
+
let viewerCaused: Bool
|
|
43
|
+
}
|
|
44
|
+
struct PhaseSamples: Codable {
|
|
45
|
+
var compileNanos: [UInt64] = []; var layoutNanos: [UInt64] = []; var combinedCompileLayoutNanos: [UInt64] = []
|
|
46
|
+
var cacheLookupNanos: [UInt64] = []; var drawNanos: [UInt64] = []; var rawFrameDeltasNanos: [UInt64] = []
|
|
47
|
+
var frameCallbackSamples: [FrameCallbackSample] = []
|
|
48
|
+
var compileCount = 0; var layoutCount = 0; var cacheHits = 0; var cacheMisses = 0; var cacheWaits = 0; var drawCount = 0; var visibleBlocksDrawn = 0
|
|
49
|
+
var imageRequestCount = 0; var imageMetadataCount = 0; var imageDecodeCount = 0
|
|
50
|
+
var nominalFrameCount = 0; var onTimeNominalFrameCount = 0; var delayedIntervalCount = 0; var viewerCausedDelayedIntervals: [DelayedInterval] = []
|
|
51
|
+
var invalidations: [String: Int] = [:]
|
|
52
|
+
}
|
|
53
|
+
struct WindowEvidence: Codable {
|
|
54
|
+
let windowId: String
|
|
55
|
+
let entryIds: [String]
|
|
56
|
+
let phase: String
|
|
57
|
+
let residentKeyCount: Int
|
|
58
|
+
let residentKeyDigest: String
|
|
59
|
+
let cache: CacheSnapshot
|
|
60
|
+
let compileCount: Int
|
|
61
|
+
let layoutCount: Int
|
|
62
|
+
let cacheMisses: Int
|
|
63
|
+
}
|
|
64
|
+
struct Snapshot: Codable {
|
|
65
|
+
let schemaVersion: Int
|
|
66
|
+
let percentileDefinition: String
|
|
67
|
+
let nominalFramePeriodNanos: UInt64
|
|
68
|
+
let singleTickToleranceNanos: UInt64
|
|
69
|
+
let phaseSamples: [String: PhaseSamples]
|
|
70
|
+
let windowEvidence: [WindowEvidence]
|
|
71
|
+
let preResetSnapshot: CacheSnapshot
|
|
72
|
+
let postResetSnapshot: CacheSnapshot
|
|
73
|
+
let duplicatePublications: Int
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static let nominalFramePeriodNanos: UInt64 = 16_666_667
|
|
77
|
+
static let singleTickToleranceNanos: UInt64 = 1_000_000
|
|
78
|
+
static let benchmarkPreferredFrameRate: Float = 60
|
|
79
|
+
private static let lock = NSLock(); private static let sampleLimit = 20_000
|
|
80
|
+
private static var enabled = false; private static var phase: TraversalPhase?
|
|
81
|
+
private static var samples: [TraversalPhase: PhaseSamples] = [:]
|
|
82
|
+
private static var completedPhases: Set<TraversalPhase> = []
|
|
83
|
+
private static var pendingCompileNanos: [TraversalPhase: [String: UInt64]] = [:]
|
|
84
|
+
private static var viewerWorkSpans: [TraversalPhase: [ViewerWorkSpan]] = [:]
|
|
85
|
+
private static var cacheSnapshot = CacheSnapshot(); private static var preResetSnapshot = CacheSnapshot(); private static var postResetSnapshot = CacheSnapshot()
|
|
86
|
+
private static var windowEvidence: [WindowEvidence] = []; private static var duplicatePublications = 0
|
|
87
|
+
private static var previousDisplayTimestampNanos: UInt64 = 0; private static var previousMonotonicNanos: UInt64 = 0
|
|
88
|
+
|
|
89
|
+
static func classifyFrame(rawDeltaNanos: UInt64, nominalFramePeriodNanos: UInt64, singleTickToleranceNanos: UInt64) -> FrameClassification {
|
|
90
|
+
precondition(nominalFramePeriodNanos > 0)
|
|
91
|
+
if rawDeltaNanos <= nominalFramePeriodNanos + singleTickToleranceNanos { return .init(nominalFrameCount: 1, isDelayed: false) }
|
|
92
|
+
return .init(nominalFrameCount: Int((rawDeltaNanos + nominalFramePeriodNanos - 1) / nominalFramePeriodNanos), isDelayed: true)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static func cadencePassRatio(rawFrameDeltasNanos: [UInt64]) -> Double {
|
|
96
|
+
let classifications = rawFrameDeltasNanos.map {
|
|
97
|
+
classifyFrame(
|
|
98
|
+
rawDeltaNanos: $0,
|
|
99
|
+
nominalFramePeriodNanos: nominalFramePeriodNanos,
|
|
100
|
+
singleTickToleranceNanos: singleTickToleranceNanos
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
let nominalSlots = classifications.reduce(0) { $0 + $1.nominalFrameCount }
|
|
104
|
+
guard nominalSlots > 0 else { return 0 }
|
|
105
|
+
let onTimeSlots = classifications.reduce(0) { $0 + ($1.isDelayed ? 0 : $1.nominalFrameCount) }
|
|
106
|
+
return Double(onTimeSlots) / Double(nominalSlots)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Benchmark-only cadence control. This is deliberately not used by
|
|
110
|
+
/// production viewer display links, whose cadence remains system-managed.
|
|
111
|
+
static func configureBenchmarkCadence(_ displayLink: CADisplayLink) {
|
|
112
|
+
displayLink.preferredFrameRateRange = CAFrameRateRange(
|
|
113
|
+
minimum: benchmarkPreferredFrameRate,
|
|
114
|
+
maximum: benchmarkPreferredFrameRate,
|
|
115
|
+
preferred: benchmarkPreferredFrameRate
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
static func viewerCaused(
|
|
120
|
+
_ start: UInt64,
|
|
121
|
+
_ end: UInt64,
|
|
122
|
+
_ spans: [ViewerWorkSpan],
|
|
123
|
+
rawDeltaNanos: UInt64,
|
|
124
|
+
nominalFramePeriodNanos: UInt64
|
|
125
|
+
) -> Bool {
|
|
126
|
+
let lateness = rawDeltaNanos > nominalFramePeriodNanos
|
|
127
|
+
? rawDeltaNanos - nominalFramePeriodNanos
|
|
128
|
+
: 0
|
|
129
|
+
return lateness > 0 && viewerWorkNanos(start, end, spans) >= lateness
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static func viewerWorkNanos(_ start: UInt64, _ end: UInt64, _ spans: [ViewerWorkSpan]) -> UInt64 {
|
|
133
|
+
mergedWorkNanos(start, end, spans)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
static func beginBenchmark() {
|
|
137
|
+
#if DEBUG
|
|
138
|
+
lock.lock(); enabled = true; resetLocked(); lock.unlock()
|
|
139
|
+
#endif
|
|
140
|
+
}
|
|
141
|
+
static func reset() {
|
|
142
|
+
#if DEBUG
|
|
143
|
+
lock.lock(); resetLocked(); lock.unlock()
|
|
144
|
+
#endif
|
|
145
|
+
}
|
|
146
|
+
static func beginPhase(_ value: TraversalPhase, preservingDisplayLinkBaseline: Bool = false) {
|
|
147
|
+
#if DEBUG
|
|
148
|
+
lock.lock()
|
|
149
|
+
guard enabled else { lock.unlock(); return }
|
|
150
|
+
phase = value; completedPhases.remove(value)
|
|
151
|
+
if !preservingDisplayLinkBaseline {
|
|
152
|
+
previousDisplayTimestampNanos = 0; previousMonotonicNanos = 0
|
|
153
|
+
}
|
|
154
|
+
lock.unlock()
|
|
155
|
+
#endif
|
|
156
|
+
}
|
|
157
|
+
static func transitionPhase(_ value: TraversalPhase) {
|
|
158
|
+
#if DEBUG
|
|
159
|
+
lock.lock()
|
|
160
|
+
guard enabled else { lock.unlock(); return }
|
|
161
|
+
if let phase { completedPhases.insert(phase); viewerWorkSpans[phase] = [] }
|
|
162
|
+
phase = value; completedPhases.remove(value)
|
|
163
|
+
lock.unlock()
|
|
164
|
+
#endif
|
|
165
|
+
}
|
|
166
|
+
static func endPhase() {
|
|
167
|
+
#if DEBUG
|
|
168
|
+
lock.lock()
|
|
169
|
+
if let phase { completedPhases.insert(phase); viewerWorkSpans[phase] = [] }
|
|
170
|
+
phase = nil; previousDisplayTimestampNanos = 0; previousMonotonicNanos = 0
|
|
171
|
+
lock.unlock()
|
|
172
|
+
#endif
|
|
173
|
+
}
|
|
174
|
+
static func beginTraversal(_ value: TraversalPhase) { beginPhase(value) }
|
|
175
|
+
static func endTraversal() { endPhase() }
|
|
176
|
+
|
|
177
|
+
static func displayLinkDidTick(_ displayLink: CADisplayLink) {
|
|
178
|
+
#if DEBUG
|
|
179
|
+
recordDisplayLinkTick(
|
|
180
|
+
callbackTimestampNanos: timeIntervalNanos(displayLink.timestamp),
|
|
181
|
+
observedMonotonicNanos: DispatchTime.now().uptimeNanoseconds,
|
|
182
|
+
callbackDurationNanos: timeIntervalNanos(displayLink.duration),
|
|
183
|
+
targetLeadNanos: signedTimeIntervalNanos(displayLink.targetTimestamp - displayLink.timestamp)
|
|
184
|
+
)
|
|
185
|
+
#endif
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
static func recordDisplayLinkTick(
|
|
189
|
+
callbackTimestampNanos: UInt64,
|
|
190
|
+
observedMonotonicNanos: UInt64,
|
|
191
|
+
callbackDurationNanos: UInt64,
|
|
192
|
+
targetLeadNanos: Int64
|
|
193
|
+
) {
|
|
194
|
+
#if DEBUG
|
|
195
|
+
lock.lock(); defer { lock.unlock() }
|
|
196
|
+
guard enabled, let phase else { return }
|
|
197
|
+
mutate(phase) { sample in
|
|
198
|
+
append(
|
|
199
|
+
.init(
|
|
200
|
+
callbackTimestampNanos: callbackTimestampNanos,
|
|
201
|
+
callbackDurationNanos: callbackDurationNanos,
|
|
202
|
+
targetLeadNanos: targetLeadNanos
|
|
203
|
+
),
|
|
204
|
+
to: &sample.frameCallbackSamples
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
defer { previousDisplayTimestampNanos = callbackTimestampNanos; previousMonotonicNanos = observedMonotonicNanos }
|
|
208
|
+
guard previousDisplayTimestampNanos > 0, previousMonotonicNanos > 0,
|
|
209
|
+
callbackTimestampNanos > previousDisplayTimestampNanos
|
|
210
|
+
else { return }
|
|
211
|
+
let rawDeltaNanos = callbackTimestampNanos - previousDisplayTimestampNanos
|
|
212
|
+
guard rawDeltaNanos > 0 else { return }
|
|
213
|
+
let intervalStart = previousMonotonicNanos
|
|
214
|
+
let intervalEnd = observedMonotonicNanos
|
|
215
|
+
let spans = viewerWorkSpans[phase] ?? []
|
|
216
|
+
mutate(phase) { sample in
|
|
217
|
+
append(rawDeltaNanos, to: &sample.rawFrameDeltasNanos)
|
|
218
|
+
let classification = classifyFrame(rawDeltaNanos: rawDeltaNanos, nominalFramePeriodNanos: nominalFramePeriodNanos, singleTickToleranceNanos: singleTickToleranceNanos)
|
|
219
|
+
sample.nominalFrameCount += classification.nominalFrameCount
|
|
220
|
+
if !classification.isDelayed { sample.onTimeNominalFrameCount += classification.nominalFrameCount }
|
|
221
|
+
if classification.isDelayed {
|
|
222
|
+
sample.delayedIntervalCount += 1
|
|
223
|
+
let caused = viewerCaused(
|
|
224
|
+
intervalStart,
|
|
225
|
+
intervalEnd,
|
|
226
|
+
spans,
|
|
227
|
+
rawDeltaNanos: rawDeltaNanos,
|
|
228
|
+
nominalFramePeriodNanos: nominalFramePeriodNanos
|
|
229
|
+
)
|
|
230
|
+
let interval = DelayedInterval(
|
|
231
|
+
startNanos: intervalStart,
|
|
232
|
+
endNanos: intervalEnd,
|
|
233
|
+
rawDeltaNanos: rawDeltaNanos,
|
|
234
|
+
viewerLayoutNanos: clippedWork(intervalStart, intervalEnd, spans, kind: .layout),
|
|
235
|
+
viewerDrawNanos: clippedWork(intervalStart, intervalEnd, spans, kind: .draw),
|
|
236
|
+
viewerLifecycleNanos: clippedWork(intervalStart, intervalEnd, spans, kind: .lifecycle),
|
|
237
|
+
viewerWorkUnionNanos: viewerWorkNanos(intervalStart, intervalEnd, spans),
|
|
238
|
+
viewerCaused: caused
|
|
239
|
+
)
|
|
240
|
+
if caused { append(interval, to: &sample.viewerCausedDelayedIntervals) }
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
viewerWorkSpans[phase] = spans.filter { $0.endNanos > intervalStart }
|
|
244
|
+
#endif
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static func recordViewerWork(startNanos: UInt64, endNanos: UInt64, kind: ViewerWorkKind) {
|
|
248
|
+
#if DEBUG
|
|
249
|
+
guard startNanos < endNanos else { return }
|
|
250
|
+
lock.lock(); defer { lock.unlock() }
|
|
251
|
+
guard enabled, let phase else { return }
|
|
252
|
+
viewerWorkSpans[phase, default: []].append(.init(startNanos: startNanos, endNanos: endNanos, kind: kind))
|
|
253
|
+
#endif
|
|
254
|
+
}
|
|
255
|
+
static func snapshotCache() -> CacheSnapshot {
|
|
256
|
+
#if DEBUG
|
|
257
|
+
lock.lock(); defer { lock.unlock() }; return cacheSnapshot
|
|
258
|
+
#else
|
|
259
|
+
return CacheSnapshot()
|
|
260
|
+
#endif
|
|
261
|
+
}
|
|
262
|
+
static func capturePreResetSnapshot() {
|
|
263
|
+
#if DEBUG
|
|
264
|
+
lock.lock(); if enabled { preResetSnapshot = cacheSnapshot }; lock.unlock()
|
|
265
|
+
#endif
|
|
266
|
+
}
|
|
267
|
+
static func capturePostResetSnapshot() {
|
|
268
|
+
#if DEBUG
|
|
269
|
+
lock.lock(); if enabled { postResetSnapshot = cacheSnapshot }; lock.unlock()
|
|
270
|
+
#endif
|
|
271
|
+
}
|
|
272
|
+
struct PhaseCounters {
|
|
273
|
+
var compileCount = 0
|
|
274
|
+
var layoutCount = 0
|
|
275
|
+
var cacheMisses = 0
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
static func phaseCounters() -> PhaseCounters {
|
|
279
|
+
#if DEBUG
|
|
280
|
+
lock.lock(); defer { lock.unlock() }
|
|
281
|
+
guard let phase else { return PhaseCounters() }
|
|
282
|
+
let value = samples[phase] ?? PhaseSamples()
|
|
283
|
+
return PhaseCounters(compileCount: value.compileCount, layoutCount: value.layoutCount, cacheMisses: value.cacheMisses)
|
|
284
|
+
#else
|
|
285
|
+
return PhaseCounters()
|
|
286
|
+
#endif
|
|
287
|
+
}
|
|
288
|
+
static func recordWindow(
|
|
289
|
+
windowId: String,
|
|
290
|
+
entryIds: [String],
|
|
291
|
+
phase: TraversalPhase,
|
|
292
|
+
residentKeyCount: Int,
|
|
293
|
+
residentKeyDigest: String,
|
|
294
|
+
cache: CacheSnapshot,
|
|
295
|
+
counters: PhaseCounters
|
|
296
|
+
) {
|
|
297
|
+
#if DEBUG
|
|
298
|
+
lock.lock(); defer { lock.unlock() }
|
|
299
|
+
guard enabled else { return }
|
|
300
|
+
windowEvidence.append(
|
|
301
|
+
.init(
|
|
302
|
+
windowId: windowId,
|
|
303
|
+
entryIds: entryIds,
|
|
304
|
+
phase: phase.rawValue,
|
|
305
|
+
residentKeyCount: residentKeyCount,
|
|
306
|
+
residentKeyDigest: residentKeyDigest,
|
|
307
|
+
cache: cache,
|
|
308
|
+
compileCount: counters.compileCount,
|
|
309
|
+
layoutCount: counters.layoutCount,
|
|
310
|
+
cacheMisses: counters.cacheMisses
|
|
311
|
+
)
|
|
312
|
+
)
|
|
313
|
+
#endif
|
|
314
|
+
}
|
|
315
|
+
static func cacheUpdated(unmountedBytes: Int? = nil, unmountedResidentCount: Int? = nil, compiledBytes: Int? = nil, compiledResidentCount: Int? = nil) {
|
|
316
|
+
#if DEBUG
|
|
317
|
+
lock.lock(); defer { lock.unlock() }
|
|
318
|
+
guard enabled else { return }
|
|
319
|
+
if let unmountedBytes { cacheSnapshot.unmountedCurrentBytes = max(0, unmountedBytes); cacheSnapshot.unmountedHighWaterBytes = max(cacheSnapshot.unmountedHighWaterBytes, cacheSnapshot.unmountedCurrentBytes) }
|
|
320
|
+
if let unmountedResidentCount { cacheSnapshot.unmountedCurrentResidentCount = max(0, unmountedResidentCount); cacheSnapshot.unmountedHighWaterResidentCount = max(cacheSnapshot.unmountedHighWaterResidentCount, cacheSnapshot.unmountedCurrentResidentCount) }
|
|
321
|
+
if let compiledBytes { cacheSnapshot.compiledCurrentBytes = max(0, compiledBytes) }
|
|
322
|
+
if let compiledResidentCount { cacheSnapshot.compiledCurrentResidentCount = max(0, compiledResidentCount) }
|
|
323
|
+
#endif
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static func exportJSON() -> String {
|
|
327
|
+
#if DEBUG
|
|
328
|
+
lock.lock()
|
|
329
|
+
let exportedPhases = [TraversalPhase.cold, .warm, .imagesDisabled]
|
|
330
|
+
let completedSamples = Dictionary(uniqueKeysWithValues: exportedPhases.map { ($0.rawValue, samples[$0] ?? PhaseSamples()) })
|
|
331
|
+
let snapshot = Snapshot(schemaVersion: 3, percentileDefinition: "nearest-rank: sorted[ceil(p*n)-1]", nominalFramePeriodNanos: nominalFramePeriodNanos, singleTickToleranceNanos: singleTickToleranceNanos, phaseSamples: completedSamples, windowEvidence: windowEvidence, preResetSnapshot: preResetSnapshot, postResetSnapshot: postResetSnapshot, duplicatePublications: duplicatePublications)
|
|
332
|
+
lock.unlock()
|
|
333
|
+
return String(data: (try? JSONEncoder().encode(snapshot)) ?? Data("{}".utf8), encoding: .utf8) ?? "{}"
|
|
334
|
+
#else
|
|
335
|
+
return "{}"
|
|
336
|
+
#endif
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
@inline(__always) static func now() -> UInt64 {
|
|
340
|
+
#if DEBUG
|
|
341
|
+
lock.lock(); let active = enabled; lock.unlock(); return active ? DispatchTime.now().uptimeNanoseconds : 0
|
|
342
|
+
#else
|
|
343
|
+
return 0
|
|
344
|
+
#endif
|
|
345
|
+
}
|
|
346
|
+
@inline(__always) static func compiled(_ start: UInt64, generation: String) { record(start) { phase, elapsed, _ in mutate(phase) { samples in samples.compileCount += 1; append(elapsed, to: &samples.compileNanos) }; pendingCompileNanos[phase, default: [:]][generation] = elapsed } }
|
|
347
|
+
@inline(__always) static func laidOut(_ start: UInt64, generation: String) { record(start) { phase, elapsed, end in mutate(phase) { samples in samples.layoutCount += 1; append(elapsed, to: &samples.layoutNanos); if let compile = pendingCompileNanos[phase]?.removeValue(forKey: generation) { append(compile + elapsed, to: &samples.combinedCompileLayoutNanos) } }; recordViewerWorkLocked(startNanos: start, endNanos: end, kind: .layout, phase: phase) } }
|
|
348
|
+
@inline(__always) static func cacheLookup(_ start: UInt64, hit: Bool, waited: Bool = false) { record(start) { phase, elapsed, _ in mutate(phase) { samples in append(elapsed, to: &samples.cacheLookupNanos); if hit { samples.cacheHits += 1 } else { samples.cacheMisses += 1 }; if waited { samples.cacheWaits += 1 } } } }
|
|
349
|
+
@inline(__always) static func drew(_ start: UInt64, visibleBlocks: Int) { record(start) { phase, elapsed, end in mutate(phase) { samples in append(elapsed, to: &samples.drawNanos); samples.drawCount += 1; samples.visibleBlocksDrawn += visibleBlocks }; recordViewerWorkLocked(startNanos: start, endNanos: end, kind: .draw, phase: phase) } }
|
|
350
|
+
static func imageRequested() { incrementImageCounter { $0.imageRequestCount += 1 } }
|
|
351
|
+
static func imageMetadataRead() { incrementImageCounter { $0.imageMetadataCount += 1 } }
|
|
352
|
+
static func imageDecoded() { incrementImageCounter { $0.imageDecodeCount += 1 } }
|
|
353
|
+
static func retained(_ owner: Owner, scope: String, bytes: Int) { }
|
|
354
|
+
static func invalidated(_ reason: InvalidationReason) {
|
|
355
|
+
#if DEBUG
|
|
356
|
+
lock.lock(); if enabled, let phase { mutate(phase) { samples in samples.invalidations[reason.rawValue, default: 0] += 1 } }; lock.unlock()
|
|
357
|
+
#endif
|
|
358
|
+
}
|
|
359
|
+
static func duplicatePublication() {
|
|
360
|
+
#if DEBUG
|
|
361
|
+
lock.lock(); if enabled { duplicatePublications += 1 }; lock.unlock()
|
|
362
|
+
#endif
|
|
363
|
+
}
|
|
364
|
+
private static func record(_ start: UInt64, _ body: (TraversalPhase, UInt64, UInt64) -> Void) {
|
|
365
|
+
#if DEBUG
|
|
366
|
+
guard start != 0 else { return }; lock.lock(); defer { lock.unlock() }; guard enabled, let phase else { return }; let end = DispatchTime.now().uptimeNanoseconds; body(phase, end - start, end)
|
|
367
|
+
#endif
|
|
368
|
+
}
|
|
369
|
+
private static func incrementImageCounter(_ body: (inout PhaseSamples) -> Void) {
|
|
370
|
+
#if DEBUG
|
|
371
|
+
lock.lock(); defer { lock.unlock() }; guard enabled, let phase else { return }; mutate(phase, body)
|
|
372
|
+
#endif
|
|
373
|
+
}
|
|
374
|
+
private static func recordViewerWorkLocked(startNanos: UInt64, endNanos: UInt64, kind: ViewerWorkKind, phase: TraversalPhase) { guard startNanos < endNanos else { return }; viewerWorkSpans[phase, default: []].append(.init(startNanos: startNanos, endNanos: endNanos, kind: kind)) }
|
|
375
|
+
private static func clippedWork(_ start: UInt64, _ end: UInt64, _ spans: [ViewerWorkSpan], kind: ViewerWorkKind) -> UInt64 {
|
|
376
|
+
mergedWorkNanos(start, end, spans.filter { $0.kind == kind })
|
|
377
|
+
}
|
|
378
|
+
private static func mergedWorkNanos(_ start: UInt64, _ end: UInt64, _ spans: [ViewerWorkSpan]) -> UInt64 {
|
|
379
|
+
let clipped = spans.compactMap { span -> Range<UInt64>? in let lower = max(start, span.startNanos), upper = min(end, span.endNanos); return lower < upper ? lower..<upper : nil }.sorted { $0.lowerBound < $1.lowerBound }
|
|
380
|
+
return clipped.reduce(into: [Range<UInt64>]()) { merged, range in if let last = merged.last, range.lowerBound <= last.upperBound { merged[merged.count - 1] = last.lowerBound..<max(last.upperBound, range.upperBound) } else { merged.append(range) } }.reduce(0) { $0 + ($1.upperBound - $1.lowerBound) }
|
|
381
|
+
}
|
|
382
|
+
private static func mutate(_ phase: TraversalPhase, _ body: (inout PhaseSamples) -> Void) { var value = samples[phase] ?? PhaseSamples(); body(&value); samples[phase] = value }
|
|
383
|
+
private static func append<T>(_ value: T, to samples: inout [T]) { if samples.count < sampleLimit { samples.append(value) } }
|
|
384
|
+
private static func timeIntervalNanos(_ seconds: CFTimeInterval) -> UInt64 { guard seconds.isFinite, seconds > 0 else { return 0 }; return UInt64((seconds * 1_000_000_000).rounded(.towardZero)) }
|
|
385
|
+
private static func signedTimeIntervalNanos(_ seconds: CFTimeInterval) -> Int64 { guard seconds.isFinite else { return 0 }; return Int64((seconds * 1_000_000_000).rounded(.towardZero)) }
|
|
386
|
+
private static func resetLocked() { phase = nil; samples = [:]; completedPhases = []; pendingCompileNanos = [:]; viewerWorkSpans = [:]; cacheSnapshot = CacheSnapshot(); preResetSnapshot = CacheSnapshot(); postResetSnapshot = CacheSnapshot(); windowEvidence = []; duplicatePublications = 0; previousDisplayTimestampNanos = 0; previousMonotonicNanos = 0 }
|
|
387
|
+
}
|