@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.
Files changed (494) hide show
  1. package/LICENSE +160 -0
  2. package/README.md +259 -0
  3. package/RUST-STANDARD-LIBRARY-NOTICES.html +8266 -0
  4. package/ReactNativeProseEditor.podspec +59 -0
  5. package/THIRD_PARTY_NOTICES.md +31155 -0
  6. package/android/build.gradle +188 -0
  7. package/android/consumer-rules.pro +18 -0
  8. package/android/expo/build.gradle +17 -0
  9. package/android/src/debug/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +7 -0
  10. package/android/src/main/assets/editor-icons/MaterialIcons.json +2236 -0
  11. package/android/src/main/assets/editor-icons/MaterialIcons.ttf +0 -0
  12. package/android/src/main/java/com/apollohg/editor/AndroidApiCompat.kt +19 -0
  13. package/android/src/main/java/com/apollohg/editor/AndroidCollaborationTransport.kt +860 -0
  14. package/android/src/main/java/com/apollohg/editor/CaretGeometry.kt +91 -0
  15. package/android/src/main/java/com/apollohg/editor/CodeHighlighting.kt +141 -0
  16. package/android/src/main/java/com/apollohg/editor/DecodedBitmapBudget.kt +250 -0
  17. package/android/src/main/java/com/apollohg/editor/EditorAddons.kt +133 -0
  18. package/android/src/main/java/com/apollohg/editor/EditorBlockSpacing.kt +51 -0
  19. package/android/src/main/java/com/apollohg/editor/EditorBoxDrawable.kt +16 -0
  20. package/android/src/main/java/com/apollohg/editor/EditorBoxDrawing.kt +234 -0
  21. package/android/src/main/java/com/apollohg/editor/EditorCheckboxSpan.kt +87 -0
  22. package/android/src/main/java/com/apollohg/editor/EditorCodeHighlighting.kt +120 -0
  23. package/android/src/main/java/com/apollohg/editor/EditorDecorationLayer.java +18 -0
  24. package/android/src/main/java/com/apollohg/editor/EditorDocumentLayout.kt +626 -0
  25. package/android/src/main/java/com/apollohg/editor/EditorEditText.kt +1042 -0
  26. package/android/src/main/java/com/apollohg/editor/EditorEditTextAnnotations.kt +191 -0
  27. package/android/src/main/java/com/apollohg/editor/EditorEditTextCaret.kt +100 -0
  28. package/android/src/main/java/com/apollohg/editor/EditorEditTextClipboard.kt +101 -0
  29. package/android/src/main/java/com/apollohg/editor/EditorEditTextComposition.kt +220 -0
  30. package/android/src/main/java/com/apollohg/editor/EditorEditTextConfiguration.kt +316 -0
  31. package/android/src/main/java/com/apollohg/editor/EditorEditTextCorrection.kt +303 -0
  32. package/android/src/main/java/com/apollohg/editor/EditorEditTextDeferredUpdates.kt +327 -0
  33. package/android/src/main/java/com/apollohg/editor/EditorEditTextDeletion.kt +258 -0
  34. package/android/src/main/java/com/apollohg/editor/EditorEditTextDiagnostics.kt +83 -0
  35. package/android/src/main/java/com/apollohg/editor/EditorEditTextDragDrop.kt +67 -0
  36. package/android/src/main/java/com/apollohg/editor/EditorEditTextExternalComposition.kt +357 -0
  37. package/android/src/main/java/com/apollohg/editor/EditorEditTextHardwareInput.kt +277 -0
  38. package/android/src/main/java/com/apollohg/editor/EditorEditTextImages.kt +280 -0
  39. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputLifecycle.kt +183 -0
  40. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputPreparation.kt +79 -0
  41. package/android/src/main/java/com/apollohg/editor/EditorEditTextInputTraits.kt +384 -0
  42. package/android/src/main/java/com/apollohg/editor/EditorEditTextLayout.kt +100 -0
  43. package/android/src/main/java/com/apollohg/editor/EditorEditTextNativeMutation.kt +243 -0
  44. package/android/src/main/java/com/apollohg/editor/EditorEditTextPlaceholder.kt +154 -0
  45. package/android/src/main/java/com/apollohg/editor/EditorEditTextRenderPatch.kt +347 -0
  46. package/android/src/main/java/com/apollohg/editor/EditorEditTextRendering.kt +313 -0
  47. package/android/src/main/java/com/apollohg/editor/EditorEditTextRustCommands.kt +281 -0
  48. package/android/src/main/java/com/apollohg/editor/EditorEditTextSelection.kt +352 -0
  49. package/android/src/main/java/com/apollohg/editor/EditorEditTextState.kt +113 -0
  50. package/android/src/main/java/com/apollohg/editor/EditorEditTextTaskMarkers.kt +92 -0
  51. package/android/src/main/java/com/apollohg/editor/EditorEditTextTextCommit.kt +327 -0
  52. package/android/src/main/java/com/apollohg/editor/EditorEditTextToolbar.kt +84 -0
  53. package/android/src/main/java/com/apollohg/editor/EditorEditTextUpdates.kt +245 -0
  54. package/android/src/main/java/com/apollohg/editor/EditorGlyphHeightCursorDrawable.kt +42 -0
  55. package/android/src/main/java/com/apollohg/editor/EditorHeightBehavior.kt +13 -0
  56. package/android/src/main/java/com/apollohg/editor/EditorInputConnection.kt +923 -0
  57. package/android/src/main/java/com/apollohg/editor/EditorInputCoordinates.kt +191 -0
  58. package/android/src/main/java/com/apollohg/editor/EditorInputCorrection.kt +107 -0
  59. package/android/src/main/java/com/apollohg/editor/EditorInputCursorGeometry.kt +128 -0
  60. package/android/src/main/java/com/apollohg/editor/EditorInputSnapshots.kt +134 -0
  61. package/android/src/main/java/com/apollohg/editor/EditorInputSurroundingDeletion.kt +321 -0
  62. package/android/src/main/java/com/apollohg/editor/EditorKeyboardToolbarView.kt +851 -0
  63. package/android/src/main/java/com/apollohg/editor/EditorMentionStyle.kt +192 -0
  64. package/android/src/main/java/com/apollohg/editor/EditorReconciliationWatcher.kt +46 -0
  65. package/android/src/main/java/com/apollohg/editor/EditorStyleSheet.kt +303 -0
  66. package/android/src/main/java/com/apollohg/editor/EditorStyleSheetSpans.kt +253 -0
  67. package/android/src/main/java/com/apollohg/editor/EditorSurfaceInputConnection.kt +67 -0
  68. package/android/src/main/java/com/apollohg/editor/EditorTextDecorationDrawing.kt +143 -0
  69. package/android/src/main/java/com/apollohg/editor/EditorTextSurface.kt +712 -0
  70. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceDragDrop.kt +94 -0
  71. package/android/src/main/java/com/apollohg/editor/EditorTextSurfaceInteraction.kt +708 -0
  72. package/android/src/main/java/com/apollohg/editor/EditorTheme.kt +650 -0
  73. package/android/src/main/java/com/apollohg/editor/EditorV2Adapter.kt +912 -0
  74. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterMutations.kt +402 -0
  75. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterRendering.kt +123 -0
  76. package/android/src/main/java/com/apollohg/editor/EditorV2AdapterSelection.kt +203 -0
  77. package/android/src/main/java/com/apollohg/editor/EditorV2Backend.kt +120 -0
  78. package/android/src/main/java/com/apollohg/editor/EditorV2Driver.kt +87 -0
  79. package/android/src/main/java/com/apollohg/editor/EditorV2Registry.kt +97 -0
  80. package/android/src/main/java/com/apollohg/editor/EditorV2RenderValidation.kt +409 -0
  81. package/android/src/main/java/com/apollohg/editor/ExpoAutoGrowStyleSizePublisher.kt +34 -0
  82. package/android/src/main/java/com/apollohg/editor/ImageResizeOverlayView.kt +266 -0
  83. package/android/src/main/java/com/apollohg/editor/ImeTextCoordinateMapper.kt +102 -0
  84. package/android/src/main/java/com/apollohg/editor/KeyboardToolbarImeAnimationController.kt +101 -0
  85. package/android/src/main/java/com/apollohg/editor/MentionSuggestionChipView.kt +234 -0
  86. package/android/src/main/java/com/apollohg/editor/NativeCollaborationTransportRegistry.kt +493 -0
  87. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoView.kt +813 -0
  88. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewAtoms.kt +68 -0
  89. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewBinding.kt +126 -0
  90. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewDiagnostics.kt +208 -0
  91. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewErrors.kt +146 -0
  92. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewEvents.kt +150 -0
  93. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewExternalComposition.kt +39 -0
  94. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewFocus.kt +176 -0
  95. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewLifecycle.kt +302 -0
  96. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewMentions.kt +259 -0
  97. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewNativeActions.kt +179 -0
  98. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewOutsideTap.kt +214 -0
  99. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPendingUpdates.kt +376 -0
  100. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewProperties.kt +234 -0
  101. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewPropertyRetries.kt +197 -0
  102. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewToolbar.kt +285 -0
  103. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewTypes.kt +28 -0
  104. package/android/src/main/java/com/apollohg/editor/NativeEditorExpoViewUpdates.kt +271 -0
  105. package/android/src/main/java/com/apollohg/editor/NativeEditorModule.kt +687 -0
  106. package/android/src/main/java/com/apollohg/editor/NativeEditorOutsideTapDispatcher.kt +380 -0
  107. package/android/src/main/java/com/apollohg/editor/NativeEditorV2Numbers.kt +45 -0
  108. package/android/src/main/java/com/apollohg/editor/NativeEditorViewRegistry.kt +372 -0
  109. package/android/src/main/java/com/apollohg/editor/NativeImagePipeline.kt +22 -0
  110. package/android/src/main/java/com/apollohg/editor/NativeToolbar.kt +193 -0
  111. package/android/src/main/java/com/apollohg/editor/NativeToolbarIcons.kt +177 -0
  112. package/android/src/main/java/com/apollohg/editor/NativeToolbarItem.kt +274 -0
  113. package/android/src/main/java/com/apollohg/editor/OkHttpCollaborationSocket.kt +102 -0
  114. package/android/src/main/java/com/apollohg/editor/OrderedListMarkerFormatter.kt +130 -0
  115. package/android/src/main/java/com/apollohg/editor/PointerTransparentView.java +18 -0
  116. package/android/src/main/java/com/apollohg/editor/PositionBridge.kt +128 -0
  117. package/android/src/main/java/com/apollohg/editor/ProseViewerView.kt +854 -0
  118. package/android/src/main/java/com/apollohg/editor/RemoteSelectionOverlayView.kt +314 -0
  119. package/android/src/main/java/com/apollohg/editor/RenderBlockSpans.kt +314 -0
  120. package/android/src/main/java/com/apollohg/editor/RenderBridge.kt +224 -0
  121. package/android/src/main/java/com/apollohg/editor/RenderBridgeBlockStyles.kt +407 -0
  122. package/android/src/main/java/com/apollohg/editor/RenderBridgeElements.kt +544 -0
  123. package/android/src/main/java/com/apollohg/editor/RenderBridgeInlineAndAtoms.kt +631 -0
  124. package/android/src/main/java/com/apollohg/editor/RenderBridgeParagraphs.kt +215 -0
  125. package/android/src/main/java/com/apollohg/editor/RenderImageDecoder.kt +748 -0
  126. package/android/src/main/java/com/apollohg/editor/RenderImageLoader.kt +900 -0
  127. package/android/src/main/java/com/apollohg/editor/RenderLayoutConstants.kt +117 -0
  128. package/android/src/main/java/com/apollohg/editor/RenderMediaSpans.kt +337 -0
  129. package/android/src/main/java/com/apollohg/editor/RenderParagraphSpans.kt +182 -0
  130. package/android/src/main/java/com/apollohg/editor/RichTextEditorView.kt +951 -0
  131. package/android/src/main/java/com/apollohg/editor/SharedNativeImagePipeline.kt +78 -0
  132. package/android/src/main/java/com/apollohg/editor/UniffiEditorV2Backend.kt +261 -0
  133. package/android/src/main/java/com/apollohg/editor/viewer/AndroidProseLayoutEngine.kt +1656 -0
  134. package/android/src/main/java/com/apollohg/editor/viewer/FabricAttachmentSidecars.kt +80 -0
  135. package/android/src/main/java/com/apollohg/editor/viewer/FabricLeaseHandleBridge.kt +59 -0
  136. package/android/src/main/java/com/apollohg/editor/viewer/FallbackSelectionGeometry.kt +450 -0
  137. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseDrawingView.kt +678 -0
  138. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseInstrumentation.kt +608 -0
  139. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayout.kt +186 -0
  140. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutCache.kt +393 -0
  141. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseLayoutRegistry.kt +828 -0
  142. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseTheme.kt +316 -0
  143. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerManager.kt +900 -0
  144. package/android/src/main/java/com/apollohg/editor/viewer/PreparedProseViewerPackage.kt +16 -0
  145. package/android/src/main/java/com/apollohg/editor/viewer/PreparedViewerAtoms.kt +89 -0
  146. package/android/src/main/java/com/apollohg/editor/viewer/ViewerCodeHighlighting.kt +91 -0
  147. package/android/src/main/java/com/apollohg/editor/viewer/ViewerDocument.kt +453 -0
  148. package/android/src/main/java/com/apollohg/editor/viewer/ViewerFontEnvironment.kt +282 -0
  149. package/android/src/main/java/com/apollohg/editor/viewer/ViewerImagePipeline.kt +460 -0
  150. package/android/src/main/jni/CMakeLists.txt +85 -0
  151. package/android/src/main/jni/PreparedProseViewerMeasurementsManager.cpp +334 -0
  152. package/android/src/main/jni/ReactNativeProseEditorSpec.h +17 -0
  153. package/android/src/main/jni/reactnativeproseeditor.h +6 -0
  154. package/android/src/main/res/values/attrs.xml +6 -0
  155. package/android/src/release/java/com/apollohg/editor/viewer/PreparedProseDrawInstrumentation.kt +9 -0
  156. package/app.plugin.js +62 -0
  157. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseMeasurementsManager.h +62 -0
  158. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerComponentDescriptor.h +30 -0
  159. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.cpp +192 -0
  160. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.h +46 -0
  161. package/common/cpp/react/renderer/components/PreparedProseViewer/PreparedProseViewerState.h +145 -0
  162. package/dist/AtomHost.d.ts +17 -0
  163. package/dist/AtomHost.js +135 -0
  164. package/dist/DefaultAtomChip.d.ts +2 -0
  165. package/dist/DefaultAtomChip.js +22 -0
  166. package/dist/EditorAddon.d.ts +32 -0
  167. package/dist/EditorAddon.js +29 -0
  168. package/dist/EditorAddonNormalization.d.ts +6 -0
  169. package/dist/EditorAddonNormalization.js +48 -0
  170. package/dist/EditorMentionThemeNormalization.d.ts +8 -0
  171. package/dist/EditorMentionThemeNormalization.js +22 -0
  172. package/dist/EditorMentionThemeValidation.d.ts +12 -0
  173. package/dist/EditorMentionThemeValidation.js +95 -0
  174. package/dist/EditorStyleSheet.d.ts +4 -0
  175. package/dist/EditorStyleSheet.js +10 -0
  176. package/dist/EditorStyleSheetNormalization.d.ts +3 -0
  177. package/dist/EditorStyleSheetNormalization.js +226 -0
  178. package/dist/EditorStyleSheetTypes.d.ts +151 -0
  179. package/dist/EditorStyleSheetTypes.js +2 -0
  180. package/dist/EditorTheme.d.ts +117 -0
  181. package/dist/EditorTheme.js +41 -0
  182. package/dist/EditorToolbar.d.ts +4 -0
  183. package/dist/EditorToolbar.js +17 -0
  184. package/dist/EditorToolbarComponent.d.ts +13 -0
  185. package/dist/EditorToolbarComponent.js +24 -0
  186. package/dist/EditorToolbarItems.d.ts +9 -0
  187. package/dist/EditorToolbarItems.js +58 -0
  188. package/dist/EditorToolbarRegistry.d.ts +59 -0
  189. package/dist/EditorToolbarRegistry.js +175 -0
  190. package/dist/EditorToolbarTypes.d.ts +273 -0
  191. package/dist/EditorToolbarTypes.js +2 -0
  192. package/dist/EditorToolbarVisuals.d.ts +154 -0
  193. package/dist/EditorToolbarVisuals.js +228 -0
  194. package/dist/EditorUpdateRevision.d.ts +8 -0
  195. package/dist/EditorUpdateRevision.js +22 -0
  196. package/dist/ExternalTextComposition.d.ts +45 -0
  197. package/dist/ExternalTextComposition.js +537 -0
  198. package/dist/ImageLoadingPolicy.d.ts +54 -0
  199. package/dist/ImageLoadingPolicy.js +60 -0
  200. package/dist/NativeEditorBoundaryError.d.ts +111 -0
  201. package/dist/NativeEditorBoundaryError.js +268 -0
  202. package/dist/NativeEditorBridge.d.ts +9 -0
  203. package/dist/NativeEditorBridge.js +37 -0
  204. package/dist/NativeEditorCollaborationTransport.d.ts +154 -0
  205. package/dist/NativeEditorCollaborationTransport.js +275 -0
  206. package/dist/NativeEditorCreateConfig.d.ts +16 -0
  207. package/dist/NativeEditorCreateConfig.js +249 -0
  208. package/dist/NativeEditorCreateJson.d.ts +76 -0
  209. package/dist/NativeEditorCreateJson.js +474 -0
  210. package/dist/NativeEditorCreateValidation.d.ts +32 -0
  211. package/dist/NativeEditorCreateValidation.js +150 -0
  212. package/dist/NativeEditorDocumentBridge.d.ts +72 -0
  213. package/dist/NativeEditorDocumentBridge.js +305 -0
  214. package/dist/NativeEditorDocumentHandle.d.ts +70 -0
  215. package/dist/NativeEditorDocumentHandle.js +89 -0
  216. package/dist/NativeEditorLocalAwareness.d.ts +34 -0
  217. package/dist/NativeEditorLocalAwareness.js +153 -0
  218. package/dist/NativeEditorNativeModule.d.ts +48 -0
  219. package/dist/NativeEditorNativeModule.js +34 -0
  220. package/dist/NativeEditorRenderNormalization.d.ts +22 -0
  221. package/dist/NativeEditorRenderNormalization.js +274 -0
  222. package/dist/NativeEditorResultNormalization.d.ts +108 -0
  223. package/dist/NativeEditorResultNormalization.js +400 -0
  224. package/dist/NativeEditorTypes.d.ts +318 -0
  225. package/dist/NativeEditorTypes.js +15 -0
  226. package/dist/NativeEditorV2Decimal.d.ts +5 -0
  227. package/dist/NativeEditorV2Decimal.js +18 -0
  228. package/dist/NativeProseViewer.d.ts +122 -0
  229. package/dist/NativeProseViewer.js +130 -0
  230. package/dist/NativeRichTextEditor.d.ts +3 -0
  231. package/dist/NativeRichTextEditor.js +6 -0
  232. package/dist/ResourceLimits.d.ts +100 -0
  233. package/dist/ResourceLimits.js +80 -0
  234. package/dist/RichTextEditor.d.ts +4 -0
  235. package/dist/RichTextEditor.js +25 -0
  236. package/dist/RichTextEditorNativeTypes.d.ts +122 -0
  237. package/dist/RichTextEditorNativeTypes.js +2 -0
  238. package/dist/RichTextEditorNativeView.d.ts +12 -0
  239. package/dist/RichTextEditorNativeView.js +15 -0
  240. package/dist/RichTextEditorSerialization.d.ts +53 -0
  241. package/dist/RichTextEditorSerialization.js +283 -0
  242. package/dist/RichTextEditorTypes.d.ts +281 -0
  243. package/dist/RichTextEditorTypes.js +2 -0
  244. package/dist/ViewerConfiguration.d.ts +22 -0
  245. package/dist/ViewerConfiguration.js +6 -0
  246. package/dist/YjsCollaboration.d.ts +146 -0
  247. package/dist/YjsCollaboration.js +496 -0
  248. package/dist/addons.d.ts +193 -0
  249. package/dist/addons.js +122 -0
  250. package/dist/atomConstants.d.ts +3 -0
  251. package/dist/atomConstants.js +6 -0
  252. package/dist/atomInstances.d.ts +35 -0
  253. package/dist/atomInstances.js +79 -0
  254. package/dist/atomPolicy.d.ts +4 -0
  255. package/dist/atomPolicy.js +47 -0
  256. package/dist/atomUpdates.d.ts +2 -0
  257. package/dist/atomUpdates.js +38 -0
  258. package/dist/atoms.d.ts +92 -0
  259. package/dist/atoms.js +222 -0
  260. package/dist/attributeValidation.d.ts +4 -0
  261. package/dist/attributeValidation.js +97 -0
  262. package/dist/contentExpression.d.ts +6 -0
  263. package/dist/contentExpression.js +335 -0
  264. package/dist/index.d.ts +21 -0
  265. package/dist/index.js +78 -0
  266. package/dist/listMarkers.d.ts +15 -0
  267. package/dist/listMarkers.js +21 -0
  268. package/dist/schemaDefinition.d.ts +143 -0
  269. package/dist/schemaDefinition.js +206 -0
  270. package/dist/schemaDocument.d.ts +17 -0
  271. package/dist/schemaDocument.js +69 -0
  272. package/dist/schemaDocumentConstruction.d.ts +5 -0
  273. package/dist/schemaDocumentConstruction.js +125 -0
  274. package/dist/schemaNormalization.d.ts +29 -0
  275. package/dist/schemaNormalization.js +313 -0
  276. package/dist/schemaPresets.d.ts +68 -0
  277. package/dist/schemaPresets.js +198 -0
  278. package/dist/schemaResolution.d.ts +9 -0
  279. package/dist/schemaResolution.js +211 -0
  280. package/dist/schemas.d.ts +5 -0
  281. package/dist/schemas.js +28 -0
  282. package/dist/specs/PreparedProseViewerNativeComponent.d.ts +37 -0
  283. package/dist/specs/PreparedProseViewerNativeComponent.js +6 -0
  284. package/dist/useEditorToolbarInteractions.d.ts +12 -0
  285. package/dist/useEditorToolbarInteractions.js +218 -0
  286. package/dist/useEditorToolbarItems.d.ts +8 -0
  287. package/dist/useEditorToolbarItems.js +280 -0
  288. package/dist/useEditorToolbarPresentation.d.ts +4 -0
  289. package/dist/useEditorToolbarPresentation.js +203 -0
  290. package/dist/useEditorToolbarState.d.ts +63 -0
  291. package/dist/useEditorToolbarState.js +108 -0
  292. package/dist/useFocusPreservingFrames.d.ts +17 -0
  293. package/dist/useFocusPreservingFrames.js +108 -0
  294. package/dist/useNativeEditor.d.ts +66 -0
  295. package/dist/useNativeEditor.js +370 -0
  296. package/dist/useRichTextEditorCommands.d.ts +21 -0
  297. package/dist/useRichTextEditorCommands.js +299 -0
  298. package/dist/useRichTextEditorEvents.d.ts +18 -0
  299. package/dist/useRichTextEditorEvents.js +216 -0
  300. package/dist/useRichTextEditorMentions.d.ts +11 -0
  301. package/dist/useRichTextEditorMentions.js +316 -0
  302. package/dist/useRichTextEditorPresentation.d.ts +5 -0
  303. package/dist/useRichTextEditorPresentation.js +178 -0
  304. package/dist/useRichTextEditorState.d.ts +180 -0
  305. package/dist/useRichTextEditorState.js +405 -0
  306. package/dist/useRichTextEditorUpdates.d.ts +10 -0
  307. package/dist/useRichTextEditorUpdates.js +308 -0
  308. package/dist/useViewerAtoms.d.ts +38 -0
  309. package/dist/useViewerAtoms.js +288 -0
  310. package/expo-module.config.json +13 -0
  311. package/ios/EditorAddons.swift +354 -0
  312. package/ios/EditorCodeHighlighting.swift +184 -0
  313. package/ios/EditorCore.xcframework/Info.plist +44 -0
  314. package/ios/EditorCore.xcframework/ios-arm64/libeditor_core.a +0 -0
  315. package/ios/EditorCore.xcframework/ios-arm64_x86_64-simulator/libeditor_core.a +0 -0
  316. package/ios/EditorInteractionOverlays.swift +697 -0
  317. package/ios/EditorLayoutManager.swift +971 -0
  318. package/ios/EditorNodeTypes.swift +37 -0
  319. package/ios/EditorStyleSheet.swift +461 -0
  320. package/ios/EditorTextView+AttributedPatch.swift +305 -0
  321. package/ios/EditorTextView+Binding.swift +61 -0
  322. package/ios/EditorTextView+Caret.swift +333 -0
  323. package/ios/EditorTextView+Commands.swift +203 -0
  324. package/ios/EditorTextView+Delegate.swift +65 -0
  325. package/ios/EditorTextView+Diagnostics.swift +225 -0
  326. package/ios/EditorTextView+DragDrop.swift +290 -0
  327. package/ios/EditorTextView+ExternalComposition.swift +364 -0
  328. package/ios/EditorTextView+Images.swift +354 -0
  329. package/ios/EditorTextView+InputTraits.swift +200 -0
  330. package/ios/EditorTextView+KeyboardInput.swift +318 -0
  331. package/ios/EditorTextView+Layout.swift +245 -0
  332. package/ios/EditorTextView+MarkedText.swift +267 -0
  333. package/ios/EditorTextView+NativeInputLifecycle.swift +372 -0
  334. package/ios/EditorTextView+NativeMutation.swift +471 -0
  335. package/ios/EditorTextView+Reconciliation.swift +97 -0
  336. package/ios/EditorTextView+RenderPatch.swift +573 -0
  337. package/ios/EditorTextView+Rendering.swift +539 -0
  338. package/ios/EditorTextView+Selection.swift +542 -0
  339. package/ios/EditorTextView.swift +953 -0
  340. package/ios/EditorTheme.swift +626 -0
  341. package/ios/EditorV2Adapter+Commands.swift +204 -0
  342. package/ios/EditorV2Adapter+Envelope.swift +238 -0
  343. package/ios/EditorV2Adapter+Mutation.swift +392 -0
  344. package/ios/EditorV2Adapter+Registry.swift +185 -0
  345. package/ios/EditorV2Adapter+RenderState.swift +360 -0
  346. package/ios/EditorV2Adapter+RenderValidation.swift +420 -0
  347. package/ios/EditorV2Adapter+Selection.swift +329 -0
  348. package/ios/EditorV2Adapter+TextCommands.swift +430 -0
  349. package/ios/EditorV2Adapter.swift +376 -0
  350. package/ios/EditorV2Shadow.swift +353 -0
  351. package/ios/Generated_editor_core.swift +2378 -0
  352. package/ios/NativeCodeHighlighting.swift +159 -0
  353. package/ios/NativeCollaborationSocket.swift +144 -0
  354. package/ios/NativeCollaborationTransport+Protocol.swift +258 -0
  355. package/ios/NativeCollaborationTransport+Socket.swift +379 -0
  356. package/ios/NativeCollaborationTransport+Validation.swift +103 -0
  357. package/ios/NativeCollaborationTransport.swift +322 -0
  358. package/ios/NativeCollaborationTransportRegistry.swift +521 -0
  359. package/ios/NativeEditorExpoView+AccessoryRetry.swift +219 -0
  360. package/ios/NativeEditorExpoView+Binding.swift +268 -0
  361. package/ios/NativeEditorExpoView+Diagnostics.swift +66 -0
  362. package/ios/NativeEditorExpoView+Events.swift +131 -0
  363. package/ios/NativeEditorExpoView+Focus.swift +169 -0
  364. package/ios/NativeEditorExpoView+MentionRetry.swift +288 -0
  365. package/ios/NativeEditorExpoView+Mentions.swift +288 -0
  366. package/ios/NativeEditorExpoView+Properties.swift +300 -0
  367. package/ios/NativeEditorExpoView+Toolbar.swift +86 -0
  368. package/ios/NativeEditorExpoView+Updates.swift +312 -0
  369. package/ios/NativeEditorExpoView.swift +349 -0
  370. package/ios/NativeEditorModule.swift +856 -0
  371. package/ios/NativeEditorViewRegistry.swift +226 -0
  372. package/ios/NativeToolbar+ButtonStyle.swift +214 -0
  373. package/ios/NativeToolbar+Buttons.swift +228 -0
  374. package/ios/NativeToolbar+Diagnostics.swift +114 -0
  375. package/ios/NativeToolbar+Menu.swift +101 -0
  376. package/ios/NativeToolbar+Models.swift +519 -0
  377. package/ios/NativeToolbar+Placeholder.swift +39 -0
  378. package/ios/NativeToolbar.swift +612 -0
  379. package/ios/OrderedListMarkerFormatter.swift +103 -0
  380. package/ios/PositionBridge.swift +596 -0
  381. package/ios/ProseViewerView.swift +462 -0
  382. package/ios/RenderBridge+Atoms.swift +288 -0
  383. package/ios/RenderBridge+Attachments.swift +246 -0
  384. package/ios/RenderBridge+BlockBoundaries.swift +313 -0
  385. package/ios/RenderBridge+Style.swift +343 -0
  386. package/ios/RenderBridge.swift +704 -0
  387. package/ios/RichTextEditorView.swift +930 -0
  388. package/ios/SharedNativeImagePipeline+Cache.swift +189 -0
  389. package/ios/SharedNativeImagePipeline+Transport.swift +328 -0
  390. package/ios/SharedNativeImagePipeline.swift +533 -0
  391. package/ios/Viewer/CoreTextProseLayoutEngine+AttributedText.swift +436 -0
  392. package/ios/Viewer/CoreTextProseLayoutEngine+Models.swift +322 -0
  393. package/ios/Viewer/CoreTextProseLayoutEngine.swift +635 -0
  394. package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.h +4 -0
  395. package/ios/Viewer/Fabric/PREPPreparedProseViewerComponentView.mm +767 -0
  396. package/ios/Viewer/Fabric/PreparedProseMeasurementsManager.mm +118 -0
  397. package/ios/Viewer/NativeSVGImageDecoder.h +9 -0
  398. package/ios/Viewer/NativeSVGImageDecoder.mm +106 -0
  399. package/ios/Viewer/NativeSVGPreflight.h +11 -0
  400. package/ios/Viewer/NativeSVGPreflight.mm +219 -0
  401. package/ios/Viewer/PreparedProseDrawingView.swift +639 -0
  402. package/ios/Viewer/PreparedProseInstrumentation.swift +387 -0
  403. package/ios/Viewer/PreparedProseLayout.swift +326 -0
  404. package/ios/Viewer/PreparedProseLayoutCache.swift +766 -0
  405. package/ios/Viewer/PreparedProseLayoutRegistry+Artifacts.swift +377 -0
  406. package/ios/Viewer/PreparedProseLayoutRegistry+Fabric.swift +582 -0
  407. package/ios/Viewer/PreparedProseLayoutRegistry+FabricOwnership.swift +128 -0
  408. package/ios/Viewer/PreparedProseLayoutRegistry.swift +381 -0
  409. package/ios/Viewer/ViewerDocument.swift +575 -0
  410. package/ios/Viewer/ViewerFontEnvironment.swift +283 -0
  411. package/ios/Viewer/ViewerImagePipeline.swift +478 -0
  412. package/ios/editor_coreFFI/editor_coreFFI.h +1023 -0
  413. package/ios/editor_coreFFI/module.modulemap +7 -0
  414. package/package.json +151 -0
  415. package/react-native.config.js +17 -0
  416. package/rust/android/arm64-v8a/libeditor_core.so +0 -0
  417. package/rust/android/armeabi-v7a/libeditor_core.so +0 -0
  418. package/rust/android/x86/libeditor_core.so +0 -0
  419. package/rust/android/x86_64/libeditor_core.so +0 -0
  420. package/rust/bindings/kotlin/uniffi/editor_core/editor_core.kt +3146 -0
  421. package/src/AtomHost.tsx +180 -0
  422. package/src/DefaultAtomChip.tsx +27 -0
  423. package/src/EditorAddon.ts +65 -0
  424. package/src/EditorAddonNormalization.ts +49 -0
  425. package/src/EditorMentionThemeNormalization.ts +25 -0
  426. package/src/EditorMentionThemeValidation.ts +133 -0
  427. package/src/EditorStyleSheet.ts +9 -0
  428. package/src/EditorStyleSheetNormalization.ts +219 -0
  429. package/src/EditorStyleSheetTypes.ts +189 -0
  430. package/src/EditorTheme.ts +196 -0
  431. package/src/EditorToolbar.tsx +31 -0
  432. package/src/EditorToolbarComponent.tsx +23 -0
  433. package/src/EditorToolbarItems.tsx +64 -0
  434. package/src/EditorToolbarRegistry.tsx +254 -0
  435. package/src/EditorToolbarTypes.tsx +322 -0
  436. package/src/EditorToolbarVisuals.tsx +270 -0
  437. package/src/EditorUpdateRevision.ts +26 -0
  438. package/src/ExternalTextComposition.ts +658 -0
  439. package/src/ImageLoadingPolicy.ts +125 -0
  440. package/src/NativeEditorBoundaryError.ts +345 -0
  441. package/src/NativeEditorBridge.ts +93 -0
  442. package/src/NativeEditorCollaborationTransport.ts +493 -0
  443. package/src/NativeEditorCreateConfig.ts +326 -0
  444. package/src/NativeEditorCreateJson.ts +579 -0
  445. package/src/NativeEditorCreateValidation.ts +178 -0
  446. package/src/NativeEditorDocumentBridge.ts +485 -0
  447. package/src/NativeEditorDocumentHandle.ts +168 -0
  448. package/src/NativeEditorLocalAwareness.ts +168 -0
  449. package/src/NativeEditorNativeModule.ts +97 -0
  450. package/src/NativeEditorRenderNormalization.ts +320 -0
  451. package/src/NativeEditorResultNormalization.ts +469 -0
  452. package/src/NativeEditorTypes.ts +366 -0
  453. package/src/NativeEditorV2Decimal.ts +13 -0
  454. package/src/NativeProseViewer.tsx +356 -0
  455. package/src/NativeRichTextEditor.tsx +33 -0
  456. package/src/ResourceLimits.ts +187 -0
  457. package/src/RichTextEditor.tsx +27 -0
  458. package/src/RichTextEditorNativeTypes.tsx +144 -0
  459. package/src/RichTextEditorNativeView.tsx +21 -0
  460. package/src/RichTextEditorSerialization.tsx +381 -0
  461. package/src/RichTextEditorTypes.tsx +327 -0
  462. package/src/ViewerConfiguration.ts +23 -0
  463. package/src/YjsCollaboration.ts +692 -0
  464. package/src/addons.ts +311 -0
  465. package/src/atomConstants.ts +3 -0
  466. package/src/atomInstances.ts +123 -0
  467. package/src/atomPolicy.ts +47 -0
  468. package/src/atomUpdates.ts +52 -0
  469. package/src/atoms.ts +379 -0
  470. package/src/attributeValidation.ts +116 -0
  471. package/src/contentExpression.ts +338 -0
  472. package/src/index.ts +295 -0
  473. package/src/listMarkers.ts +18 -0
  474. package/src/schemaDefinition.ts +395 -0
  475. package/src/schemaDocument.ts +92 -0
  476. package/src/schemaDocumentConstruction.ts +148 -0
  477. package/src/schemaNormalization.ts +367 -0
  478. package/src/schemaPresets.ts +250 -0
  479. package/src/schemaResolution.ts +242 -0
  480. package/src/schemas.ts +43 -0
  481. package/src/specs/PreparedProseViewerNativeComponent.ts +40 -0
  482. package/src/useEditorToolbarInteractions.tsx +329 -0
  483. package/src/useEditorToolbarItems.tsx +390 -0
  484. package/src/useEditorToolbarPresentation.tsx +483 -0
  485. package/src/useEditorToolbarState.tsx +172 -0
  486. package/src/useFocusPreservingFrames.ts +171 -0
  487. package/src/useNativeEditor.ts +534 -0
  488. package/src/useRichTextEditorCommands.tsx +478 -0
  489. package/src/useRichTextEditorEvents.tsx +342 -0
  490. package/src/useRichTextEditorMentions.tsx +441 -0
  491. package/src/useRichTextEditorPresentation.tsx +563 -0
  492. package/src/useRichTextEditorState.tsx +620 -0
  493. package/src/useRichTextEditorUpdates.tsx +403 -0
  494. package/src/useViewerAtoms.tsx +427 -0
@@ -0,0 +1,767 @@
1
+ #import "PREPPreparedProseViewerComponentView.h"
2
+
3
+ #if __has_include("ReactNativeProseEditor-Swift.h")
4
+ #import "ReactNativeProseEditor-Swift.h"
5
+ #else
6
+ #error "ReactNativeProseEditor Swift compatibility header is unavailable; verify the pod module name and consumer codegen"
7
+ #endif
8
+ #import <React/RCTConversions.h>
9
+
10
+ #include <react/renderer/components/PreparedProseViewer/PreparedProseViewerComponentDescriptor.h>
11
+ #include <react/renderer/components/PreparedProseViewer/PreparedProseViewerShadowNode.h>
12
+ #include <react/renderer/components/PreparedProseViewer/PreparedProseViewerState.h>
13
+ #include <react/renderer/components/ReactNativeProseEditorSpec/EventEmitters.h>
14
+ #include <react/renderer/components/ReactNativeProseEditorSpec/Props.h>
15
+ #include <react/renderer/core/ConcreteComponentDescriptor.h>
16
+
17
+ #include <cmath>
18
+ #include <cstdint>
19
+ #include <cstring>
20
+ #include <limits>
21
+ #include <memory>
22
+ #include <optional>
23
+ #include <string>
24
+
25
+ using namespace facebook::react;
26
+
27
+ namespace {
28
+
29
+ NSString *StringFromStdString(const std::string &value) {
30
+ return [[NSString alloc] initWithBytes:value.data()
31
+ length:value.size()
32
+ encoding:NSUTF8StringEncoding] ?: @"";
33
+ }
34
+
35
+ NSString *OptionalStringFromStdString(const std::optional<std::string> &value) {
36
+ return value ? StringFromStdString(*value) : nil;
37
+ }
38
+
39
+ NSString *SourceKind(const PreparedProseViewerProps &props) {
40
+ return props.sourceKind == PreparedProseViewerSourceKind::Html ? @"html" : @"json";
41
+ }
42
+
43
+ bool HasEquivalentGenerationProps(
44
+ const PreparedProseViewerProps &left,
45
+ const PreparedProseViewerProps &right) {
46
+ return left.sourceKind == right.sourceKind && left.source == right.source &&
47
+ left.configJson == right.configJson && left.themeJson == right.themeJson &&
48
+ left.imagePolicyJson == right.imagePolicyJson &&
49
+ left.imagesEnabled == right.imagesEnabled &&
50
+ left.collapsesWhenEmpty == right.collapsesWhenEmpty &&
51
+ left.fontEnvironmentRevision == right.fontEnvironmentRevision;
52
+ }
53
+
54
+ // Attachment publication belongs to the immutable source/configuration, not
55
+ // to Fabric's derived attachment/font revisions or a layout-only replacement.
56
+ uint64_t Revision(const PreparedProseViewerShadowNode::ConcreteState::Shared &state, bool attachment) {
57
+ if (!state) {
58
+ return 0;
59
+ }
60
+ const auto &data = state->getData();
61
+ return attachment ? data.attachmentRevision : data.nativeFontRevision;
62
+ }
63
+
64
+ CGFloat NativeFontScale(const PreparedProseViewerShadowNode::ConcreteState::Shared &state) {
65
+ if (!state) return 1;
66
+ const auto value = state->getData().nativeFontScale;
67
+ return std::isfinite(value) && value > 0 ? static_cast<CGFloat>(value) : 1;
68
+ }
69
+
70
+ int32_t UserInterfaceStyle(const PreparedProseViewerShadowNode::ConcreteState::Shared &state) {
71
+ if (!state) return 0;
72
+ return state->getData().userInterfaceStyle;
73
+ }
74
+
75
+ int32_t AccessibilityContrast(const PreparedProseViewerShadowNode::ConcreteState::Shared &state) {
76
+ if (!state) return 0;
77
+ return state->getData().accessibilityContrast;
78
+ }
79
+
80
+ int32_t EffectiveUserInterfaceStyle(UIView *view) {
81
+ return view.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? 2 : 1;
82
+ }
83
+
84
+ int32_t EffectiveAccessibilityContrast(UIView *view) {
85
+ return view.traitCollection.accessibilityContrast == UIAccessibilityContrastHigh ? 1 : 0;
86
+ }
87
+
88
+ uint64_t LeaseHandle(const PreparedProseViewerShadowNode::ConcreteState::Shared &state) {
89
+ return state ? state->getData().leaseHandle : 0;
90
+ }
91
+
92
+ void DeactivateLease(
93
+ const PreparedProseViewerShadowNode::ConcreteState::Shared &state,
94
+ uint64_t leaseHandle) {
95
+ if (!state || state->getData().leaseHandle != leaseHandle) return;
96
+ const auto &lifecycle = state->getData().leaseLifecycle;
97
+ if (lifecycle) lifecycle->deactivate();
98
+ }
99
+
100
+ uint64_t ScaleBits(CGFloat scale) {
101
+ const double value = scale;
102
+ uint64_t bits = 0;
103
+ static_assert(sizeof(bits) == sizeof(value));
104
+ std::memcpy(&bits, &value, sizeof(bits));
105
+ return bits;
106
+ }
107
+
108
+ std::optional<long long> RoundedWidthPixels(CGFloat width, CGFloat scale) {
109
+ if (!std::isfinite(width) || width <= 0 || !std::isfinite(scale) ||
110
+ scale <= 0) {
111
+ return std::nullopt;
112
+ }
113
+ const double physicalWidth = static_cast<double>(width) * static_cast<double>(scale);
114
+ if (!std::isfinite(physicalWidth) || physicalWidth <= 0) {
115
+ return std::nullopt;
116
+ }
117
+ const double roundedWidth = std::round(physicalWidth);
118
+ const double largestConvertible = std::nextafter(
119
+ static_cast<double>(std::numeric_limits<long long>::max()), 0.0);
120
+ if (!std::isfinite(roundedWidth) || roundedWidth <= 0 ||
121
+ roundedWidth > largestConvertible) {
122
+ return std::nullopt;
123
+ }
124
+ return static_cast<long long>(roundedWidth);
125
+ }
126
+
127
+ uint64_t FontEnvironmentRevision(const PreparedProseViewerProps &props) {
128
+ const double value = static_cast<double>(props.fontEnvironmentRevision);
129
+ const double largestConvertible = std::nextafter(
130
+ static_cast<double>(std::numeric_limits<uint64_t>::max()), 0.0);
131
+ return std::isfinite(value) && value > 0 && value <= largestConvertible
132
+ ? static_cast<uint64_t>(value)
133
+ : 0;
134
+ }
135
+
136
+ NSString *MeasurementIdentity(NSString *generation, CGFloat width, CGFloat scale, uint64_t leaseHandle) {
137
+ const auto widthPixels = RoundedWidthPixels(width, scale);
138
+ return [NSString stringWithFormat:@"%@\x1f%@\x1f%llu\x1f%llu",
139
+ generation,
140
+ widthPixels ? [NSString stringWithFormat:@"%lld", *widthPixels] : @"invalid",
141
+ static_cast<unsigned long long>(ScaleBits(scale)),
142
+ static_cast<unsigned long long>(leaseHandle)];
143
+ }
144
+
145
+ bool HasUsableLayoutMetrics(const LayoutMetrics &layoutMetrics) {
146
+ const auto contentFrame = layoutMetrics.getContentFrame();
147
+ return RoundedWidthPixels(contentFrame.size.width, layoutMetrics.pointScaleFactor).has_value();
148
+ }
149
+
150
+ int64_t SurfaceIdFromState(
151
+ const PreparedProseViewerShadowNode::ConcreteState::Shared &state) {
152
+ return state ? static_cast<int64_t>(state->getData().surfaceId) : 0;
153
+ }
154
+
155
+ int64_t ComponentTagFromState(
156
+ const PreparedProseViewerShadowNode::ConcreteState::Shared &state) {
157
+ return state ? static_cast<int64_t>(state->getData().componentTag) : 0;
158
+ }
159
+
160
+ } // namespace
161
+
162
+ @interface PREPPreparedProseViewerComponentView () <PreparedProseDrawingViewInteractionDelegate>
163
+ @end
164
+
165
+ @implementation PREPPreparedProseViewerComponentView {
166
+ PREPPreparedProseDrawingView *_drawingView;
167
+ std::shared_ptr<const PreparedProseViewerProps> _viewerProps;
168
+ PreparedProseViewerShadowNode::ConcreteState::Shared _viewerState;
169
+ LayoutMetrics _layoutMetrics;
170
+ BOOL _hasReceivedUsableLayoutMetrics;
171
+ NSString *_reportedErrorGeneration;
172
+ NSString *_installedMeasurementIdentity;
173
+ NSString *_ownedGeneration;
174
+ NSString *_ownedSemanticGeneration;
175
+ int64_t _ownedSurfaceId;
176
+ int64_t _ownedComponentTag;
177
+ uint64_t _ownedLeaseHandle;
178
+ BOOL _hasOwnedSurface;
179
+ id _codeHighlightingObserver;
180
+ id _codeHighlightingFailureObserver;
181
+ id _imageMetadataObserver;
182
+ id _imageResourceObserver;
183
+ id _fontEnvironmentObserver;
184
+ uint64_t _lastFontEnvironmentRevision;
185
+ CGFloat _fontEnvironmentScale;
186
+ int32_t _requestedUserInterfaceStyle;
187
+ int32_t _requestedAccessibilityContrast;
188
+ }
189
+
190
+ + (ComponentDescriptorProvider)componentDescriptorProvider
191
+ {
192
+ return concreteComponentDescriptorProvider<PreparedProseViewerComponentDescriptor>();
193
+ }
194
+
195
+ - (instancetype)initWithFrame:(CGRect)frame
196
+ {
197
+ if (self = [super initWithFrame:frame]) {
198
+ _drawingView = [PREPPreparedProseDrawingView new];
199
+ _drawingView.interactionDelegate = self;
200
+ _drawingView.backgroundColor = UIColor.clearColor;
201
+ _drawingView.isAccessibilityElement = NO;
202
+ self.isAccessibilityElement = NO;
203
+ [self addSubview:_drawingView];
204
+ __weak PREPPreparedProseViewerComponentView *weakSelf = self;
205
+ _codeHighlightingObserver = [[NSNotificationCenter defaultCenter]
206
+ addObserverForName:PREPPreparedProseDrawingView.codeHighlightingDidResolve
207
+ object:_drawingView queue:NSOperationQueue.mainQueue
208
+ usingBlock:^(NSNotification *note) { [weakSelf handleCodeHighlighting:note]; }];
209
+ _codeHighlightingFailureObserver = [[NSNotificationCenter defaultCenter]
210
+ addObserverForName:PREPPreparedProseDrawingView.codeHighlightingDidFail
211
+ object:_drawingView queue:NSOperationQueue.mainQueue
212
+ usingBlock:^(NSNotification *note) { [weakSelf handleCodeHighlightingFailure:note]; }];
213
+ _imageMetadataObserver = [[NSNotificationCenter defaultCenter]
214
+ addObserverForName:PREPPreparedProseDrawingView.imageMetadataDidResolve
215
+ object:_drawingView
216
+ queue:NSOperationQueue.mainQueue
217
+ usingBlock:^(NSNotification *note) {
218
+ [weakSelf handleImageMetadata:note];
219
+ }];
220
+ _imageResourceObserver = [[NSNotificationCenter defaultCenter]
221
+ addObserverForName:PREPPreparedProseDrawingView.imageResourceDidFail
222
+ object:_drawingView
223
+ queue:NSOperationQueue.mainQueue
224
+ usingBlock:^(__unused NSNotification *note) {
225
+ [weakSelf handleImageResourceFailure:note];
226
+ }];
227
+ PREPViewerFontEnvironment *fontEnvironment = [PREPViewerFontEnvironment sharedEnvironment];
228
+ [fontEnvironment refreshContentSizeCategory];
229
+ _fontEnvironmentScale = [fontEnvironment currentFontScale];
230
+ _requestedUserInterfaceStyle = 0;
231
+ _requestedAccessibilityContrast = 0;
232
+ _fontEnvironmentObserver = [[NSNotificationCenter defaultCenter]
233
+ addObserverForName:PREPViewerFontEnvironment.didInvalidateNotification
234
+ object:fontEnvironment
235
+ queue:NSOperationQueue.mainQueue
236
+ usingBlock:^(NSNotification *note) {
237
+ [weakSelf handleFontEnvironmentInvalidation:note];
238
+ }];
239
+ }
240
+ return self;
241
+ }
242
+
243
+ - (void)dealloc
244
+ {
245
+ // Deallocation can follow a Fabric discard without prepareForRecycle. This
246
+ // helper is idempotent and talks only to the stable registry token; it never
247
+ // asks a detached UIView for its current tag or root surface.
248
+ [self releaseAllFabricOwnership];
249
+ if (_codeHighlightingObserver) [[NSNotificationCenter defaultCenter] removeObserver:_codeHighlightingObserver];
250
+ if (_codeHighlightingFailureObserver) [[NSNotificationCenter defaultCenter] removeObserver:_codeHighlightingFailureObserver];
251
+ if (_imageMetadataObserver) [[NSNotificationCenter defaultCenter] removeObserver:_imageMetadataObserver];
252
+ if (_imageResourceObserver) [[NSNotificationCenter defaultCenter] removeObserver:_imageResourceObserver];
253
+ if (_fontEnvironmentObserver) [[NSNotificationCenter defaultCenter] removeObserver:_fontEnvironmentObserver];
254
+ }
255
+
256
+ - (BOOL)preparedProseDrawingView:(PREPPreparedProseDrawingView *)view
257
+ didActivateLink:(NSString *)href
258
+ text:(NSString *)text
259
+ {
260
+ const auto eventEmitter = std::static_pointer_cast<const PreparedProseViewerEventEmitter>(_eventEmitter);
261
+ if (!eventEmitter) return NO;
262
+ eventEmitter->onPressLink({
263
+ .href = std::string(href.UTF8String ?: ""),
264
+ .text = std::string(text.UTF8String ?: ""),
265
+ });
266
+ return YES;
267
+ }
268
+
269
+ - (BOOL)preparedProseDrawingView:(PREPPreparedProseDrawingView *)view
270
+ didActivateMention:(uint32_t)docPos
271
+ label:(NSString *)label
272
+ attrsJSON:(NSString *)attrsJSON
273
+ {
274
+ const auto eventEmitter = std::static_pointer_cast<const PreparedProseViewerEventEmitter>(_eventEmitter);
275
+ if (!eventEmitter) return NO;
276
+ eventEmitter->onPressMention({
277
+ // Codegen's Double contract preserves the complete UInt32 domain in JS.
278
+ .docPos = static_cast<double>(docPos),
279
+ .label = std::string(label.UTF8String ?: ""),
280
+ .attrsJson = std::string(attrsJSON.UTF8String ?: ""),
281
+ });
282
+ return YES;
283
+ }
284
+
285
+ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
286
+ {
287
+ [super updateProps:props oldProps:oldProps];
288
+ const auto nextProps = std::static_pointer_cast<const PreparedProseViewerProps>(props);
289
+ // Link permission filters the installed interaction/accessibility host; it
290
+ // does not alter the prepared render generation or its Fabric lease.
291
+ const BOOL generationChanged =
292
+ !_viewerProps || !HasEquivalentGenerationProps(*_viewerProps, *nextProps);
293
+ if (generationChanged) {
294
+ [self beginNewGenerationTerminatingCurrentLease:NO];
295
+ }
296
+ _viewerProps = nextProps;
297
+ [self beginSemanticImageGenerationIfPossible];
298
+ _drawingView.linkInteractionsEnabled = nextProps->enableLinkTaps;
299
+ if (generationChanged && _hasReceivedUsableLayoutMetrics) {
300
+ [self installMeasuredArtifactIfAttached];
301
+ }
302
+ }
303
+
304
+ - (void)updateState:(const State::Shared &)state oldState:(const State::Shared &)oldState
305
+ {
306
+ [super updateState:state oldState:oldState];
307
+ const auto nextState = std::static_pointer_cast<const PreparedProseViewerShadowNode::ConcreteState>(state);
308
+ const BOOL leaseChanged = _viewerState && LeaseHandle(_viewerState) != LeaseHandle(nextState);
309
+ if (!_viewerState || Revision(_viewerState, true) != Revision(nextState, true) ||
310
+ Revision(_viewerState, false) != Revision(nextState, false) ||
311
+ NativeFontScale(_viewerState) != NativeFontScale(nextState) ||
312
+ leaseChanged) {
313
+ // Revisions and same-family width updates are replacements, not a
314
+ // teardown. Only a genuinely different state incarnation retires the
315
+ // previous lifecycle guard.
316
+ [self beginNewGenerationTerminatingCurrentLease:leaseChanged];
317
+ }
318
+ _viewerState = nextState;
319
+ _requestedUserInterfaceStyle = UserInterfaceStyle(_viewerState);
320
+ _requestedAccessibilityContrast = AccessibilityContrast(_viewerState);
321
+ const auto userInterfaceStyle = EffectiveUserInterfaceStyle(self);
322
+ const auto accessibilityContrast = EffectiveAccessibilityContrast(self);
323
+ if (UserInterfaceStyle(_viewerState) != userInterfaceStyle ||
324
+ AccessibilityContrast(_viewerState) != accessibilityContrast) {
325
+ [self invalidateAppearanceWithUserInterfaceStyle:userInterfaceStyle
326
+ accessibilityContrast:accessibilityContrast];
327
+ return;
328
+ }
329
+ if (NativeFontScale(_viewerState) != _fontEnvironmentScale) {
330
+ [self invalidateNativeFontEnvironmentWithScale:_fontEnvironmentScale];
331
+ }
332
+ [self beginSemanticImageGenerationIfPossible];
333
+ if (_hasReceivedUsableLayoutMetrics) {
334
+ [self installMeasuredArtifactIfAttached];
335
+ }
336
+ }
337
+
338
+ - (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
339
+ oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
340
+ {
341
+ [super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
342
+ _layoutMetrics = layoutMetrics;
343
+ _drawingView.frame = RCTCGRectFromRect(layoutMetrics.getContentFrame());
344
+ if (!HasUsableLayoutMetrics(layoutMetrics)) {
345
+ _hasReceivedUsableLayoutMetrics = NO;
346
+ return;
347
+ }
348
+ _hasReceivedUsableLayoutMetrics = YES;
349
+ [self installMeasuredArtifactIfAttached];
350
+ [_drawingView updateConfiguredImagesForVisibleWindow];
351
+ }
352
+
353
+ - (void)didMoveToSuperview
354
+ {
355
+ [super didMoveToSuperview];
356
+ if (self.superview == nil) {
357
+ // Detachment is a normal Fabric transaction boundary. The state-owned
358
+ // lifetime guard performs terminal cleanup if this family is discarded;
359
+ // retaining a same-family lease here lets an ordinary reattachment mount
360
+ // the already prepared artifact without reminting a handle.
361
+ [_drawingView cancelConfiguredImages];
362
+ return;
363
+ }
364
+ // Fabric can provide props, state, and metrics before native attachment.
365
+ [self installMeasuredArtifactIfAttached];
366
+ [_drawingView updateConfiguredImagesForVisibleWindow];
367
+ }
368
+
369
+ - (void)didMoveToWindow
370
+ {
371
+ [super didMoveToWindow];
372
+ if (self.window == nil) {
373
+ return;
374
+ }
375
+ [self installMeasuredArtifactIfAttached];
376
+ [_drawingView updateConfiguredImagesForVisibleWindow];
377
+ }
378
+
379
+ - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
380
+ {
381
+ [super traitCollectionDidChange:previousTraitCollection];
382
+ [self invalidateAppearanceWithUserInterfaceStyle:EffectiveUserInterfaceStyle(self)
383
+ accessibilityContrast:EffectiveAccessibilityContrast(self)];
384
+ }
385
+
386
+ - (void)prepareForRecycle
387
+ {
388
+ [self releaseAllFabricOwnership];
389
+ [super prepareForRecycle];
390
+ _viewerProps.reset();
391
+ _viewerState.reset();
392
+ [_drawingView cancelConfiguredImages];
393
+ [_drawingView resetIntrinsicImagePublication];
394
+ [_drawingView installWithLayout:nil];
395
+ _hasReceivedUsableLayoutMetrics = NO;
396
+ _reportedErrorGeneration = nil;
397
+ _installedMeasurementIdentity = nil;
398
+ _ownedGeneration = nil;
399
+ _ownedSemanticGeneration = nil;
400
+ _ownedLeaseHandle = 0;
401
+ }
402
+
403
+ - (void)beginNewGenerationTerminatingCurrentLease:(BOOL)terminal
404
+ {
405
+ // Ordinary props/state revisions are committed by
406
+ // installMeasuredArtifactIfAttached, where the registry can atomically
407
+ // permit G2 before retiring G1's pending work. Releasing here would let a
408
+ // delayed G1 Yoga callback win that race and would blank the old mount.
409
+ if (terminal) {
410
+ [self releaseFabricOwnershipTerminatingLease:YES];
411
+ }
412
+ [_drawingView cancelConfiguredImages];
413
+ // Keep the last complete artifact visible while a new generation has no
414
+ // representable layout metrics. The install gate clears it only
415
+ // after independently validating the replacement measurement.
416
+ _installedMeasurementIdentity = nil;
417
+ }
418
+
419
+ - (void)beginSemanticImageGenerationIfPossible
420
+ {
421
+ if (!_viewerProps || !_viewerState) return;
422
+ const auto &props = *_viewerProps;
423
+ const auto semanticGeneration = [[PREPPreparedProseLayoutRegistry sharedRegistry]
424
+ fabricSemanticGenerationIdentitySourceKind:SourceKind(props)
425
+ source:StringFromStdString(props.source)
426
+ configJSON:StringFromStdString(props.configJson)
427
+ themeJSON:OptionalStringFromStdString(props.themeJson)
428
+ imagePolicyJSON:OptionalStringFromStdString(props.imagePolicyJson)
429
+ imagesEnabled:props.imagesEnabled
430
+ collapsesWhenEmpty:props.collapsesWhenEmpty
431
+ attachmentRevision:Revision(_viewerState, true)
432
+ nativeFontRevision:Revision(_viewerState, false)
433
+ nativeFontScale:NativeFontScale(_viewerState)
434
+ fontEnvironmentRevision:FontEnvironmentRevision(props)
435
+ userInterfaceStyle:UserInterfaceStyle(_viewerState)
436
+ accessibilityContrast:AccessibilityContrast(_viewerState)];
437
+ [_drawingView beginSemanticImageGeneration:semanticGeneration];
438
+ }
439
+
440
+ - (void)releaseFabricOwnershipTerminatingLease:(BOOL)terminal
441
+ {
442
+ // A state handle represents the Fabric family lifetime, not one props,
443
+ // image, font, or width revision. Only recycle/family teardown may
444
+ // deactivate it; ordinary replacement releases its old generation key.
445
+ const auto stateLeaseHandle = LeaseHandle(_viewerState);
446
+ if (terminal && stateLeaseHandle != 0) {
447
+ DeactivateLease(_viewerState, stateLeaseHandle);
448
+ }
449
+ if (!_hasOwnedSurface) {
450
+ return;
451
+ }
452
+ const auto leaseHandle = _ownedLeaseHandle != 0 ? _ownedLeaseHandle : stateLeaseHandle;
453
+ if (terminal) {
454
+ // A replacement can retain a mounted G1 while G2 is the only current
455
+ // generation. Terminal recycle must sweep the state-family owner, not
456
+ // merely G2; this API intentionally works after the handle is inactive.
457
+ // The C++ lifecycle guard may subsequently repeat this exact cleanup.
458
+ [[PREPPreparedProseLayoutRegistry sharedRegistry]
459
+ releaseFabricLeaseSurfaceId:_ownedSurfaceId
460
+ componentTag:_ownedComponentTag
461
+ leaseHandle:leaseHandle];
462
+ _hasOwnedSurface = NO;
463
+ _ownedGeneration = nil;
464
+ _ownedLeaseHandle = 0;
465
+ return;
466
+ }
467
+ if (!_ownedGeneration) {
468
+ return;
469
+ }
470
+ [[PREPPreparedProseLayoutRegistry sharedRegistry]
471
+ releaseFabricGenerationSurfaceId:_ownedSurfaceId
472
+ componentTag:_ownedComponentTag
473
+ generationIdentity:_ownedGeneration
474
+ leaseHandle:leaseHandle];
475
+ _hasOwnedSurface = NO;
476
+ _ownedGeneration = nil;
477
+ _ownedLeaseHandle = 0;
478
+ }
479
+
480
+ - (void)releaseAllFabricOwnership
481
+ {
482
+ // Recycling is terminal for this exact state-carried lease incarnation.
483
+ [self releaseFabricOwnershipTerminatingLease:YES];
484
+ }
485
+
486
+ - (void)emitAtomLayout
487
+ {
488
+ if (!_viewerProps || !_eventEmitter) return;
489
+ NSString *themeJSON = OptionalStringFromStdString(_viewerProps->themeJson);
490
+ NSData *data = [themeJSON dataUsingEncoding:NSUTF8StringEncoding];
491
+ if (!data) return;
492
+ id root = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
493
+ if (![root isKindOfClass:[NSDictionary class]]) return;
494
+ id atoms = root[@"viewerAtoms"];
495
+ if (![atoms isKindOfClass:[NSDictionary class]]) return;
496
+ NSString *generation = atoms[@"generation"];
497
+ NSString *revision = atoms[@"revision"];
498
+ if (![generation isKindOfClass:[NSString class]] || ![revision isKindOfClass:[NSString class]]) return;
499
+ const auto emitter = std::static_pointer_cast<const PreparedProseViewerEventEmitter>(_eventEmitter);
500
+ emitter->onAtomLayout({
501
+ .generation = std::string(generation.UTF8String),
502
+ .revision = std::string(revision.UTF8String),
503
+ .layoutWidth = _drawingView.bounds.size.width,
504
+ .atomsJson = std::string([_drawingView atomLayoutsJSONWithOrigin:_drawingView.frame.origin].UTF8String),
505
+ });
506
+ }
507
+
508
+ - (void)installMeasuredArtifactIfAttached
509
+ {
510
+ // This is a deliberate lifecycle test seam: updateProps, updateState,
511
+ // updateLayoutMetrics, didMoveToSuperview, and didMoveToWindow all enter
512
+ // through this gate.
513
+ // It must never acquire or dispatch while the component is detached.
514
+ if (self.superview == nil || !_viewerProps || !_viewerState ||
515
+ !_hasReceivedUsableLayoutMetrics || !HasUsableLayoutMetrics(_layoutMetrics)) {
516
+ return;
517
+ }
518
+ const auto &props = *_viewerProps;
519
+ const auto contentFrame = _layoutMetrics.getContentFrame();
520
+ const CGFloat width = contentFrame.size.width;
521
+ const CGFloat scale = _layoutMetrics.pointScaleFactor;
522
+ const auto surfaceId = SurfaceIdFromState(_viewerState);
523
+ const auto componentTag = ComponentTagFromState(_viewerState);
524
+ if (surfaceId <= 0 || componentTag <= 0) {
525
+ return;
526
+ }
527
+ const auto leaseHandle = LeaseHandle(_viewerState);
528
+ // State is the Fabric handoff. Until the shadow node has committed its
529
+ // opaque handle this view has no authority to acquire or release anything.
530
+ if (leaseHandle == 0) {
531
+ return;
532
+ }
533
+ const auto generation = [[PREPPreparedProseLayoutRegistry sharedRegistry]
534
+ fabricGenerationIdentitySourceKind:SourceKind(props)
535
+ source:StringFromStdString(props.source)
536
+ configJSON:StringFromStdString(props.configJson)
537
+ themeJSON:OptionalStringFromStdString(props.themeJson)
538
+ imagePolicyJSON:OptionalStringFromStdString(props.imagePolicyJson)
539
+ imagesEnabled:props.imagesEnabled
540
+ collapsesWhenEmpty:props.collapsesWhenEmpty
541
+ attachmentRevision:Revision(_viewerState, true)
542
+ nativeFontRevision:Revision(_viewerState, false)
543
+ nativeFontScale:NativeFontScale(_viewerState)
544
+ fontEnvironmentRevision:FontEnvironmentRevision(props)
545
+ userInterfaceStyle:UserInterfaceStyle(_viewerState)
546
+ accessibilityContrast:AccessibilityContrast(_viewerState)];
547
+ const auto measurementIdentityString = MeasurementIdentity(generation, width, scale, leaseHandle);
548
+ const auto semanticGeneration = [[PREPPreparedProseLayoutRegistry sharedRegistry]
549
+ fabricSemanticGenerationIdentitySourceKind:SourceKind(props)
550
+ source:StringFromStdString(props.source)
551
+ configJSON:StringFromStdString(props.configJson)
552
+ themeJSON:OptionalStringFromStdString(props.themeJson)
553
+ imagePolicyJSON:OptionalStringFromStdString(props.imagePolicyJson)
554
+ imagesEnabled:props.imagesEnabled
555
+ collapsesWhenEmpty:props.collapsesWhenEmpty
556
+ attachmentRevision:Revision(_viewerState, true)
557
+ nativeFontRevision:Revision(_viewerState, false)
558
+ nativeFontScale:NativeFontScale(_viewerState)
559
+ fontEnvironmentRevision:FontEnvironmentRevision(props)
560
+ userInterfaceStyle:UserInterfaceStyle(_viewerState)
561
+ accessibilityContrast:AccessibilityContrast(_viewerState)];
562
+ // This is the props/state commit boundary for the state-family handle.
563
+ // Commit G2 before touching G1 ownership or attempting mount acquisition:
564
+ // delayed G1 Yoga callbacks are rejected, while an already-running G2
565
+ // measurement remains permitted to publish its exact handoff.
566
+ [[PREPPreparedProseLayoutRegistry sharedRegistry]
567
+ activateFabricGenerationSurfaceId:surfaceId
568
+ componentTag:componentTag
569
+ generationIdentity:generation
570
+ leaseHandle:leaseHandle];
571
+ if (_hasOwnedSurface && _ownedSurfaceId == surfaceId &&
572
+ _ownedComponentTag == componentTag &&
573
+ [_ownedGeneration isEqualToString:generation] &&
574
+ _ownedLeaseHandle == leaseHandle &&
575
+ [_installedMeasurementIdentity isEqualToString:measurementIdentityString]) {
576
+ [self emitAtomLayout];
577
+ return;
578
+ }
579
+ if (_hasOwnedSurface &&
580
+ (_ownedSurfaceId != surfaceId || _ownedComponentTag != componentTag ||
581
+ _ownedLeaseHandle != leaseHandle)) {
582
+ // A reused view may have a different root/token before the previous
583
+ // lifecycle callback finishes. Release only the persisted owner, never
584
+ // the current UIView tag, which React Native may already have reset.
585
+ [self releaseFabricOwnershipTerminatingLease:NO];
586
+ }
587
+ const BOOL preservesMountedArtifactForReplacement =
588
+ _hasOwnedSurface && _ownedSurfaceId == surfaceId &&
589
+ _ownedComponentTag == componentTag &&
590
+ _ownedLeaseHandle == leaseHandle &&
591
+ _installedMeasurementIdentity != nil;
592
+ if (![_installedMeasurementIdentity isEqualToString:measurementIdentityString]) {
593
+ // Width-only replacement is two-phase: retain the currently installed
594
+ // artifact until the exact new Yoga handoff is acquired. A missing or
595
+ // pressure-evicted replacement must not blank the view or release the
596
+ // old mounted lease. Semantic/recycled-owner changes still clear first.
597
+ if (!preservesMountedArtifactForReplacement) {
598
+ [_drawingView installWithLayout:nil];
599
+ _installedMeasurementIdentity = nil;
600
+ }
601
+ }
602
+
603
+ // Establish ownership before acquisition. A mount miss otherwise leaves a
604
+ // measurement-pinned compiler result or failure alive with no installed
605
+ // component to release it.
606
+ _ownedSurfaceId = surfaceId;
607
+ _ownedComponentTag = componentTag;
608
+ _ownedLeaseHandle = leaseHandle;
609
+ _hasOwnedSurface = YES;
610
+ _ownedGeneration = generation;
611
+ [_drawingView bindFabricAttachmentStateSurfaceId:_ownedSurfaceId
612
+ componentTag:_ownedComponentTag
613
+ leaseHandle:leaseHandle];
614
+ const BOOL installed = [[PREPPreparedProseLayoutRegistry sharedRegistry]
615
+ installCachedLayoutInDrawingView:_drawingView
616
+ surfaceId:_ownedSurfaceId
617
+ componentTag:_ownedComponentTag
618
+ leaseHandle:leaseHandle
619
+ sourceKind:SourceKind(props)
620
+ source:StringFromStdString(props.source)
621
+ configJSON:StringFromStdString(props.configJson)
622
+ themeJSON:OptionalStringFromStdString(props.themeJson)
623
+ imagePolicyJSON:OptionalStringFromStdString(props.imagePolicyJson)
624
+ imagesEnabled:props.imagesEnabled
625
+ collapsesWhenEmpty:props.collapsesWhenEmpty
626
+ attachmentRevision:Revision(_viewerState, true)
627
+ nativeFontRevision:Revision(_viewerState, false)
628
+ nativeFontScale:NativeFontScale(_viewerState)
629
+ fontEnvironmentRevision:FontEnvironmentRevision(props)
630
+ userInterfaceStyle:UserInterfaceStyle(_viewerState)
631
+ accessibilityContrast:AccessibilityContrast(_viewerState)
632
+ widthPoints:width
633
+ scale:scale];
634
+ if (!installed) {
635
+ // The lease and generation pin were created by Yoga, but Fabric found no
636
+ // artifact to install. A width replacement may have an older mounted
637
+ // artifact, which remains valid until a replacement successfully mounts.
638
+ if (preservesMountedArtifactForReplacement) {
639
+ return;
640
+ }
641
+ [[PREPPreparedProseLayoutRegistry sharedRegistry]
642
+ releaseFabricMountMissSurfaceId:_ownedSurfaceId
643
+ componentTag:_ownedComponentTag
644
+ generationIdentity:_ownedGeneration
645
+ leaseHandle:_ownedLeaseHandle
646
+ widthPoints:width
647
+ scale:scale];
648
+ _hasOwnedSurface = NO;
649
+ _ownedGeneration = nil;
650
+ _ownedLeaseHandle = 0;
651
+ return;
652
+ }
653
+ _ownedSemanticGeneration = semanticGeneration;
654
+ [_drawingView configureImagesWithGeneration:semanticGeneration
655
+ imagesEnabled:props.imagesEnabled
656
+ policyJSON:OptionalStringFromStdString(props.imagePolicyJson)];
657
+ [_drawingView updateConfiguredImagesForVisibleWindow];
658
+ _installedMeasurementIdentity = measurementIdentityString;
659
+ [self emitAtomLayout];
660
+ if (!_drawingView.errorCode) {
661
+ return;
662
+ }
663
+ if ([_reportedErrorGeneration isEqualToString:semanticGeneration]) {
664
+ return;
665
+ }
666
+ _reportedErrorGeneration = semanticGeneration;
667
+ const auto eventEmitter = std::static_pointer_cast<const PreparedProseViewerEventEmitter>(_eventEmitter);
668
+ if (eventEmitter) {
669
+ eventEmitter->onError({
670
+ .domain = std::string(_drawingView.errorDomain.UTF8String ?: "viewer"),
671
+ .code = std::string(_drawingView.errorCode.UTF8String),
672
+ .message = std::string(_drawingView.errorMessage.UTF8String ?: "Preparation failed"),
673
+ .fatal = true,
674
+ });
675
+ }
676
+ }
677
+
678
+ - (void)handleCodeHighlighting:(NSNotification *)note
679
+ {
680
+ NSString *generation = note.userInfo[@"generation"];
681
+ if (!generation || !_viewerState || ![_ownedSemanticGeneration isEqualToString:generation]) return;
682
+ [self invalidateNativeFontEnvironmentWithScale:NativeFontScale(_viewerState)];
683
+ }
684
+
685
+ - (void)handleCodeHighlightingFailure:(NSNotification *)note
686
+ {
687
+ NSString *generation = note.userInfo[@"generation"];
688
+ if (!generation || !_viewerState || ![_ownedSemanticGeneration isEqualToString:generation]) return;
689
+ const auto emitter = std::static_pointer_cast<const PreparedProseViewerEventEmitter>(_eventEmitter);
690
+ NSString *message = note.userInfo[@"message"];
691
+ if (emitter) emitter->onError({.domain = "addon", .code = "CODE_HIGHLIGHTING_FAILED",
692
+ .message = std::string(message.UTF8String ?: "Code highlighting failed"), .fatal = false});
693
+ }
694
+
695
+ - (void)handleImageMetadata:(NSNotification *)note
696
+ {
697
+ NSString *generation = note.userInfo[@"generation"];
698
+ if (!generation || !_viewerState || ![_ownedSemanticGeneration isEqualToString:generation]) return;
699
+ _viewerState->updateState(
700
+ [](const PreparedProseViewerShadowNode::ConcreteState::Data &oldData)
701
+ -> PreparedProseViewerShadowNode::ConcreteState::SharedData {
702
+ auto nextData = oldData;
703
+ nextData.attachmentRevision += 1;
704
+ return std::make_shared<const PreparedProseViewerShadowNode::ConcreteState::Data>(nextData);
705
+ });
706
+ }
707
+
708
+ - (void)invalidateNativeFontEnvironmentWithScale:(CGFloat)scale
709
+ {
710
+ if (!_viewerState) return;
711
+ _viewerState->updateState(
712
+ [scale](const PreparedProseViewerShadowNode::ConcreteState::Data &oldData)
713
+ -> PreparedProseViewerShadowNode::ConcreteState::SharedData {
714
+ auto nextData = oldData;
715
+ nextData.nativeFontRevision += 1;
716
+ nextData.nativeFontScale = std::isfinite(scale) && scale > 0 ? scale : 1;
717
+ return std::make_shared<const PreparedProseViewerShadowNode::ConcreteState::Data>(nextData);
718
+ });
719
+ }
720
+
721
+ - (void)invalidateAppearanceWithUserInterfaceStyle:(int32_t)userInterfaceStyle
722
+ accessibilityContrast:(int32_t)accessibilityContrast
723
+ {
724
+ if (!_viewerState ||
725
+ (_requestedUserInterfaceStyle == userInterfaceStyle &&
726
+ _requestedAccessibilityContrast == accessibilityContrast)) return;
727
+ _requestedUserInterfaceStyle = userInterfaceStyle;
728
+ _requestedAccessibilityContrast = accessibilityContrast;
729
+ _viewerState->updateState(
730
+ [userInterfaceStyle, accessibilityContrast](
731
+ const PreparedProseViewerShadowNode::ConcreteState::Data &oldData)
732
+ -> PreparedProseViewerShadowNode::ConcreteState::SharedData {
733
+ auto nextData = oldData;
734
+ nextData.nativeFontRevision += 1;
735
+ nextData.userInterfaceStyle = userInterfaceStyle;
736
+ nextData.accessibilityContrast = accessibilityContrast;
737
+ return std::make_shared<const PreparedProseViewerShadowNode::ConcreteState::Data>(nextData);
738
+ });
739
+ }
740
+
741
+ - (void)handleFontEnvironmentInvalidation:(NSNotification *)note
742
+ {
743
+ NSNumber *revision = note.userInfo[@"revision"];
744
+ if (!revision || revision.unsignedLongLongValue <= _lastFontEnvironmentRevision) return;
745
+ _lastFontEnvironmentRevision = revision.unsignedLongLongValue;
746
+ NSNumber *scale = note.userInfo[@"scale"];
747
+ _fontEnvironmentScale = std::isfinite(scale.doubleValue) && scale.doubleValue > 0
748
+ ? scale.doubleValue
749
+ : 1;
750
+ [self invalidateNativeFontEnvironmentWithScale:_fontEnvironmentScale];
751
+ }
752
+
753
+ - (void)handleImageResourceFailure:(NSNotification *)note
754
+ {
755
+ NSString *generation = note.userInfo[@"generation"];
756
+ if (!generation || ![generation isEqualToString:_ownedSemanticGeneration]) return;
757
+ const auto eventEmitter = std::static_pointer_cast<const PreparedProseViewerEventEmitter>(_eventEmitter);
758
+ if (!eventEmitter) return;
759
+ eventEmitter->onError({
760
+ .domain = "viewer.resource",
761
+ .code = "RESOURCE_LOAD_FAILED",
762
+ .message = "An image resource could not be loaded.",
763
+ .fatal = false,
764
+ });
765
+ }
766
+
767
+ @end