@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,828 @@
1
+ package com.apollohg.editor.viewer
2
+
3
+ import com.apollohg.editor.ProseViewerError
4
+ import java.security.MessageDigest
5
+ import java.util.concurrent.CompletableFuture
6
+ import java.util.concurrent.ConcurrentHashMap
7
+ import java.util.concurrent.atomic.AtomicBoolean
8
+
9
+ internal data class PreparedMountTicket(
10
+ val generation: FabricGenerationToken,
11
+ val nativeFontRevision: Long,
12
+ val contentWidthPx: Int,
13
+ val contentOriginXPx: Int,
14
+ val contentOriginYPx: Int,
15
+ val densityBits: Int,
16
+ val artifact: PreparedProseLayout
17
+ )
18
+
19
+ /** Shared, thread-safe compiler and prepared-layout registry for View and Fabric hosts. */
20
+ internal class PreparedProseLayoutRegistry(
21
+ private val compiler: DocumentCompiler = ::compileWithRust,
22
+ private val layoutEngine: AndroidProseLayoutEngine = StaticLayoutAndroidProseLayoutEngine(),
23
+ byteBudget: Long = 32L * 1024L * 1024L,
24
+ private val compiledByteBudget: Long = 8L * 1024L * 1024L,
25
+ private val compilationFailureBudget: Int = 128,
26
+ private val themeEntryBudget: Int = 128
27
+ ) {
28
+ internal data class BenchmarkResidentCensus(val count: Int, val digest: String)
29
+ private sealed interface Compilation {
30
+ data class Document(val value: ViewerDocument) : Compilation
31
+ data class Failure(val error: ProseViewerError) : Compilation
32
+ }
33
+
34
+ private val compilerLock = Any()
35
+ private val compiled = LinkedHashMap<String, ViewerDocument>(16, 0.75f, true)
36
+ private val compilationFailures = LinkedHashMap<String, ProseViewerError>(16, 0.75f, true)
37
+
38
+ /** Resolved once per generation and bounded independently of layout entries. */
39
+ private val themes = LinkedHashMap<String, PreparedProseTheme>(16, 0.75f, true)
40
+ private val compilationInFlight = ConcurrentHashMap<String, CompletableFuture<Compilation>>()
41
+ private val documentsByFabricGeneration = mutableMapOf<FabricGenerationToken, ViewerDocument>()
42
+ private val failuresByFabricGeneration = mutableMapOf<FabricGenerationToken, ProseViewerError>()
43
+
44
+ /**
45
+ * Active C++ state-family guards. Entries exist only while Fabric holds a
46
+ * state snapshot; terminal JNI cleanup removes them rather than leaving
47
+ * process-lifetime cancellation tombstones behind.
48
+ */
49
+ private class FabricLeaseState {
50
+ val active = AtomicBoolean(true)
51
+
52
+ /** Null means Yoga may prepare before the first component commit. */
53
+ var permittedGenerationIdentity: String? = null
54
+ }
55
+
56
+ private val fabricLeaseLock = Any()
57
+
58
+ /** Bounded to currently-live state-family handles; terminal cleanup removes entries. */
59
+ private val activeFabricLeases = mutableMapOf<FabricLeaseOwner, FabricLeaseState>()
60
+ private data class FinalLayoutSpec(
61
+ val revision: Long,
62
+ val request: ProseViewerRequest,
63
+ val widthPx: Int,
64
+ val density: Float,
65
+ val contentOriginXPx: Int,
66
+ val contentOriginYPx: Int,
67
+ val surface: FabricSurfaceToken,
68
+ val leaseHandle: Long,
69
+ val fontScale: Float
70
+ )
71
+ private data class PreparedMountTicketMetadata(
72
+ val revision: Long,
73
+ val nativeFontRevision: Long,
74
+ val contentWidthPx: Int,
75
+ val contentOriginXPx: Int,
76
+ val contentOriginYPx: Int,
77
+ val densityBits: Int
78
+ )
79
+ private val finalLayoutSpecs = mutableMapOf<FabricGenerationToken, FinalLayoutSpec>()
80
+ private val preparedMountTickets =
81
+ mutableMapOf<FabricGenerationToken, PreparedMountTicketMetadata>()
82
+ private val finalPreparationInFlight =
83
+ ConcurrentHashMap<FabricGenerationToken, CompletableFuture<Boolean>>()
84
+ private var finalLayoutRevision = 0L
85
+ private val layoutCache = PreparedProseLayoutCache(byteBudget = byteBudget)
86
+ private var compiledRetainedBytes = 0L
87
+ private var themeRetainedBytes = 0L
88
+ private val themeByteBudget = 512L * 1024L
89
+
90
+ @Volatile internal var layoutPreparationCount = 0
91
+ private set
92
+
93
+ fun compileDocument(request: ProseViewerRequest): ViewerDocument {
94
+ val cacheKey = request.compiledCacheKey
95
+ synchronized(compilerLock) {
96
+ compiled[cacheKey]?.let { return it }
97
+ compilationFailures[cacheKey]?.let { throw it }
98
+ }
99
+ val fresh = CompletableFuture<Compilation>()
100
+ val existing = compilationInFlight.putIfAbsent(cacheKey, fresh)
101
+ if (existing != null) return existing.join().documentOrThrow()
102
+ val compileStarted = PreparedProseInstrumentation.now()
103
+ val result = try {
104
+ Compilation.Document(
105
+ compiler(request).also { document ->
106
+ if (!document.semanticKey.matches(Regex("[0-9a-f]{64}"))) {
107
+ throw ProseViewerError.compiler(
108
+ "viewer",
109
+ "INVALID_SEMANTIC_KEY",
110
+ "The compiler returned an invalid semantic key."
111
+ )
112
+ }
113
+ }
114
+ )
115
+ } catch (error: ProseViewerError) {
116
+ Compilation.Failure(error)
117
+ } catch (throwable: Throwable) {
118
+ Compilation.Failure(
119
+ ProseViewerError.layout(throwable.message ?: "Document compilation failed.")
120
+ )
121
+ }
122
+ PreparedProseInstrumentation.compiled(compileStarted, request.generationIdentity)
123
+ synchronized(compilerLock) {
124
+ when (result) {
125
+ is Compilation.Document -> {
126
+ compiled[cacheKey] = result.value
127
+ compiledRetainedBytes += result.value.retainedBytes
128
+ trimCompiledLocked()
129
+ PreparedProseInstrumentation.retained(
130
+ PreparedProseInstrumentation.Owner.COMPILED,
131
+ "registry",
132
+ compiledRetainedBytes
133
+ )
134
+ }
135
+
136
+ is Compilation.Failure -> {
137
+ compilationFailures[cacheKey] = result.error
138
+ while (compilationFailures.size > compilationFailureBudget) {
139
+ compilationFailures.remove(compilationFailures.entries.first().key)
140
+ }
141
+ }
142
+ }
143
+ }
144
+ fresh.complete(result)
145
+ compilationInFlight.remove(cacheKey, fresh)
146
+ return result.documentOrThrow()
147
+ }
148
+
149
+ fun measure(
150
+ request: ProseViewerRequest,
151
+ widthPx: Int,
152
+ density: Float,
153
+ fabricSurface: FabricSurfaceToken? = null,
154
+ fabricLeaseHandle: Long = 0,
155
+ compiledDocument: ViewerDocument? = null,
156
+ fontScale: Float = 1f,
157
+ measurementImageState: ViewerAttachmentRevisionState? = null,
158
+ fabricLeaseEligibility: (() -> Boolean)? = null
159
+ ): PreparedProseLayout {
160
+ val generation = fabricSurface?.takeIf { fabricLeaseHandle > 0 }
161
+ ?.let { FabricGenerationToken(it, request.generationIdentity, fabricLeaseHandle) }
162
+ val leaseActive = generation?.let(::activeLeaseFor)
163
+ val ownedGeneration = generation?.takeIf { isLeaseActive(it, leaseActive) }
164
+ if (!isValidMeasurement(widthPx, density)) {
165
+ // An old zero-width pass is not a lifecycle event. Retire only
166
+ // this handle's pending handoffs and leave every mounted layout,
167
+ // including a newer H2, untouched.
168
+ generation?.takeIf {
169
+ isLeaseActive(it, leaseActive)
170
+ }?.let { layoutCache.releasePendingLease(it) }
171
+ return invalidWidthArtifact(request)
172
+ }
173
+ val densityBits = density.toRawBits().toLong()
174
+ // Owned Fabric generations use their stable sidecar. Prospective
175
+ // generations measure with isolated state until component commit.
176
+ val imageMeasurementState = ownedGeneration?.let {
177
+ FabricAttachmentSidecars.beginIfActive(it, request.semanticGenerationIdentity) {
178
+ isLeaseActive(it, leaseActive)
179
+ }
180
+ } ?: measurementImageState ?: generation?.let {
181
+ ViewerAttachmentRevisionState().also { state ->
182
+ state.beginSemanticGeneration(request.semanticGenerationIdentity)
183
+ }
184
+ }
185
+ return try {
186
+ if (ownedGeneration != null &&
187
+ !isLeaseActive(ownedGeneration, leaseActive)
188
+ ) {
189
+ return invalidWidthArtifact(request)
190
+ }
191
+ val document = preparedDocument(request, ownedGeneration, compiledDocument, leaseActive)
192
+ if (ownedGeneration != null &&
193
+ !isLeaseActive(ownedGeneration, leaseActive)
194
+ ) {
195
+ return invalidWidthArtifact(request)
196
+ }
197
+ val theme = resolveTheme(request, density, fontScale)
198
+ val key = layoutKey(document, request, widthPx, densityBits)
199
+ layoutCache.value(key, ownedGeneration, shouldCreateFabricLease = {
200
+ ownedGeneration == null ||
201
+ (
202
+ isLeaseActive(ownedGeneration, leaseActive) &&
203
+ fabricLeaseEligibility?.invoke() != false
204
+ )
205
+ }) {
206
+ val layoutStarted = PreparedProseInstrumentation.now()
207
+ layoutPreparationCount += 1
208
+ try {
209
+ val prepare = {
210
+ layoutEngine.prepare(
211
+ document,
212
+ key,
213
+ theme,
214
+ widthPx,
215
+ density,
216
+ request.configuration.collapsesWhenEmpty,
217
+ request.semanticGenerationIdentity
218
+ )
219
+ }
220
+ val artifact = if (imageMeasurementState != null) {
221
+ FabricAttachmentSidecars.withMeasurementState(
222
+ imageMeasurementState,
223
+ prepare
224
+ )
225
+ } else {
226
+ prepare()
227
+ }
228
+ PreparedProseInstrumentation.laidOut(layoutStarted, request.generationIdentity)
229
+ artifact
230
+ } catch (error: ProseViewerError) {
231
+ PreparedProseLayout.error(key, widthPx, error)
232
+ } catch (throwable: Throwable) {
233
+ PreparedProseLayout.error(
234
+ key,
235
+ widthPx,
236
+ ProseViewerError.layout(throwable.message ?: "Layout preparation failed.")
237
+ )
238
+ }
239
+ }
240
+ } catch (error: ProseViewerError) {
241
+ cachedErrorArtifact(request, widthPx, densityBits, error, ownedGeneration, leaseActive)
242
+ }
243
+ }
244
+
245
+ /** Mount acquisition intentionally cannot invoke Rust or StaticLayout.Builder. */
246
+ fun acquireForFabricMount(
247
+ generation: FabricGenerationToken,
248
+ request: ProseViewerRequest,
249
+ widthPx: Int,
250
+ density: Float
251
+ ): PreparedProseLayout? {
252
+ if (!isValidMeasurement(widthPx, density)) return null
253
+ return layoutCache.acquireForFabricMount(
254
+ generation,
255
+ widthPx,
256
+ density.toRawBits().toLong(),
257
+ allowCompletedFallback = true
258
+ ) { isLeaseActive(generation, activeLeaseFor(generation)) }
259
+ }
260
+
261
+ fun prepareFinalLayout(
262
+ request: ProseViewerRequest,
263
+ widthPx: Int,
264
+ density: Float,
265
+ contentOriginXPx: Int,
266
+ contentOriginYPx: Int,
267
+ fabricSurface: FabricSurfaceToken,
268
+ fabricLeaseHandle: Long,
269
+ fontScale: Float = 1f
270
+ ): PreparedProseLayout {
271
+ val generation = FabricGenerationToken(
272
+ fabricSurface,
273
+ request.generationIdentity,
274
+ fabricLeaseHandle
275
+ )
276
+ val spec = synchronized(fabricLeaseLock) {
277
+ check(finalLayoutRevision < Long.MAX_VALUE) { "Final layout revision space exhausted." }
278
+ FinalLayoutSpec(
279
+ ++finalLayoutRevision,
280
+ request,
281
+ widthPx,
282
+ density,
283
+ contentOriginXPx,
284
+ contentOriginYPx,
285
+ fabricSurface,
286
+ fabricLeaseHandle,
287
+ fontScale
288
+ ).also {
289
+ if (isLeaseActiveLocked(generation)) finalLayoutSpecs[generation] = it
290
+ }
291
+ }
292
+ return prepareFinalLayoutSpec(generation, spec)
293
+ }
294
+
295
+ private fun prepareFinalLayoutSpec(
296
+ generation: FabricGenerationToken,
297
+ spec: FinalLayoutSpec
298
+ ): PreparedProseLayout {
299
+ val artifact = measure(
300
+ spec.request,
301
+ spec.widthPx,
302
+ spec.density,
303
+ spec.surface,
304
+ spec.leaseHandle,
305
+ fontScale = spec.fontScale,
306
+ fabricLeaseEligibility = {
307
+ synchronized(fabricLeaseLock) {
308
+ isLeaseActiveLocked(generation) && finalLayoutSpecs[generation] === spec
309
+ }
310
+ }
311
+ )
312
+ if (
313
+ artifact.widthPx != spec.widthPx ||
314
+ artifact.key.densityBits != spec.density.toRawBits().toLong()
315
+ ) {
316
+ return artifact
317
+ }
318
+ val metadata = PreparedMountTicketMetadata(
319
+ spec.revision,
320
+ spec.request.nativeFontRevision,
321
+ spec.widthPx,
322
+ spec.contentOriginXPx,
323
+ spec.contentOriginYPx,
324
+ spec.density.toRawBits()
325
+ )
326
+ synchronized(fabricLeaseLock) {
327
+ if (
328
+ isLeaseActiveLocked(generation) &&
329
+ finalLayoutSpecs[generation] === spec
330
+ ) {
331
+ preparedMountTickets[generation] = metadata
332
+ }
333
+ }
334
+ return artifact
335
+ }
336
+
337
+ fun acquirePreparedMountTicket(
338
+ generation: FabricGenerationToken,
339
+ expectedNativeFontRevision: Long? = null
340
+ ): PreparedMountTicket? {
341
+ val metadata = synchronized(fabricLeaseLock) {
342
+ if (isLeaseActiveLocked(generation)) {
343
+ preparedMountTickets[generation]?.takeIf {
344
+ expectedNativeFontRevision == null ||
345
+ it.nativeFontRevision == expectedNativeFontRevision
346
+ }
347
+ } else {
348
+ null
349
+ }
350
+ } ?: return null
351
+ val artifact = layoutCache.acquireForFabricMount(
352
+ generation,
353
+ metadata.contentWidthPx,
354
+ metadata.densityBits.toLong()
355
+ ) {
356
+ synchronized(fabricLeaseLock) {
357
+ isLeaseActiveLocked(generation) && preparedMountTickets[generation] === metadata
358
+ }
359
+ } ?: return null
360
+ return PreparedMountTicket(
361
+ generation,
362
+ metadata.nativeFontRevision,
363
+ metadata.contentWidthPx,
364
+ metadata.contentOriginXPx,
365
+ metadata.contentOriginYPx,
366
+ metadata.densityBits,
367
+ artifact
368
+ )
369
+ }
370
+
371
+ fun prepareForFabricMount(
372
+ generation: FabricGenerationToken,
373
+ onPrepared: (Boolean) -> Unit
374
+ ): Boolean {
375
+ val spec = synchronized(fabricLeaseLock) {
376
+ if (isLeaseActiveLocked(generation)) {
377
+ finalLayoutSpecs[generation]
378
+ } else {
379
+ null
380
+ }
381
+ } ?: return false
382
+ val fresh = CompletableFuture<Boolean>()
383
+ val existing = finalPreparationInFlight.putIfAbsent(generation, fresh)
384
+ val future = existing ?: fresh
385
+ if (existing == null) {
386
+ CompletableFuture.runAsync {
387
+ runCatching {
388
+ prepareFinalLayoutSpec(generation, spec)
389
+ synchronized(fabricLeaseLock) {
390
+ isLeaseActiveLocked(generation) &&
391
+ finalLayoutSpecs[generation] === spec &&
392
+ preparedMountTickets[generation]?.revision == spec.revision
393
+ }
394
+ }.fold(fresh::complete, fresh::completeExceptionally)
395
+ }
396
+ }
397
+ future.whenComplete { ticket, _ ->
398
+ finalPreparationInFlight.remove(generation, future)
399
+ onPrepared(ticket)
400
+ }
401
+ return true
402
+ }
403
+
404
+ fun releaseFabricGeneration(generation: FabricGenerationToken) {
405
+ if (!isLeaseActive(generation, activeLeaseFor(generation))) return
406
+ synchronized(fabricLeaseLock) {
407
+ finalLayoutSpecs.remove(generation)
408
+ preparedMountTickets.remove(generation)
409
+ }
410
+ finalPreparationInFlight.remove(generation)?.cancel(false)
411
+ layoutCache.releaseLease(generation)
412
+ FabricAttachmentSidecars.remove(generation)
413
+ synchronized(compilerLock) {
414
+ documentsByFabricGeneration.remove(generation)
415
+ failuresByFabricGeneration.remove(generation)
416
+ }
417
+ }
418
+
419
+ /** Called by C++ before a state-family's first Yoga measurement. */
420
+ fun registerFabricLease(surface: FabricSurfaceToken, leaseHandle: Long) {
421
+ if (leaseHandle <= 0) return
422
+ synchronized(fabricLeaseLock) {
423
+ val owner = FabricLeaseOwner(surface, leaseHandle)
424
+ // Java terminal cleanup leaves an inactive record until the C++
425
+ // state-family reaches its final destructor. A delayed Yoga bind
426
+ // must never recreate or reactivate that same incarnation.
427
+ if (activeFabricLeases.containsKey(owner)) return
428
+ activeFabricLeases[owner] = FabricLeaseState()
429
+ }
430
+ }
431
+
432
+ /**
433
+ * Commits the one generation permitted to publish for this state-family
434
+ * handle. Earlier pre-commit Yoga work is rejected after this point;
435
+ * the new generation's already-running work remains permitted.
436
+ */
437
+ fun activateFabricGeneration(generation: FabricGenerationToken) {
438
+ val owner = FabricLeaseOwner(generation.surface, generation.leaseHandle)
439
+ synchronized(fabricLeaseLock) {
440
+ val state = activeFabricLeases[owner] ?: return
441
+ if (!state.active.get()) return
442
+ state.permittedGenerationIdentity = generation.generationIdentity
443
+ finalLayoutSpecs.keys
444
+ .filter {
445
+ FabricLeaseOwner(it.surface, it.leaseHandle) == owner && it != generation
446
+ }
447
+ .forEach(finalLayoutSpecs::remove)
448
+ preparedMountTickets.keys
449
+ .filter {
450
+ FabricLeaseOwner(it.surface, it.leaseHandle) == owner && it != generation
451
+ }
452
+ .forEach(preparedMountTickets::remove)
453
+ }
454
+ finalPreparationInFlight.keys
455
+ .filter { FabricLeaseOwner(it.surface, it.leaseHandle) == owner && it != generation }
456
+ .forEach { finalPreparationInFlight.remove(it)?.cancel(false) }
457
+ synchronized(compilerLock) {
458
+ val tokens = (documentsByFabricGeneration.keys + failuresByFabricGeneration.keys)
459
+ .filter {
460
+ FabricLeaseOwner(it.surface, it.leaseHandle) == owner && it != generation
461
+ }
462
+ .toSet()
463
+ tokens.forEach {
464
+ documentsByFabricGeneration.remove(it)
465
+ failuresByFabricGeneration.remove(it)
466
+ }
467
+ }
468
+ // Cache and sidecars own independent locks. No registry lock is held
469
+ // while crossing either boundary, avoiding a cache/compiler inversion.
470
+ layoutCache.activateFabricGeneration(generation)
471
+ FabricAttachmentSidecars.removeOtherGenerations(owner, generation)
472
+ }
473
+
474
+ /**
475
+ * Java-side terminal cleanup for an exact state-family. This deliberately
476
+ * keeps an inactive lifecycle record so a delayed C++ Yoga callback cannot
477
+ * re-register the same handle. Only [finalizeFabricLease] removes it.
478
+ */
479
+ fun deactivateFabricLease(surface: FabricSurfaceToken, leaseHandle: Long) {
480
+ if (leaseHandle <= 0) return
481
+ val owner = FabricLeaseOwner(surface, leaseHandle)
482
+ synchronized(fabricLeaseLock) {
483
+ // A View can terminally recycle before Yoga's first bind. Create
484
+ // its inactive guard now so any later bind is rejected.
485
+ (
486
+ activeFabricLeases[owner] ?: FabricLeaseState().also {
487
+ activeFabricLeases[owner] = it
488
+ }
489
+ ).active.set(false)
490
+ }
491
+ sweepFabricOwner(owner)
492
+ }
493
+
494
+ /**
495
+ * Called only by the C++ PreparedProseViewerLeaseLifecycle final callback.
496
+ * It is intentionally idempotent: Java may already have swept resources,
497
+ * or a state-family may have ended before it ever reached a View.
498
+ */
499
+ fun finalizeFabricLease(surface: FabricSurfaceToken, leaseHandle: Long) {
500
+ if (leaseHandle <= 0) return
501
+ val owner = FabricLeaseOwner(surface, leaseHandle)
502
+ synchronized(fabricLeaseLock) {
503
+ activeFabricLeases.remove(owner)?.active?.set(false)
504
+ }
505
+ sweepFabricOwner(owner)
506
+ }
507
+
508
+ private fun sweepFabricOwner(owner: FabricLeaseOwner) {
509
+ synchronized(fabricLeaseLock) {
510
+ finalLayoutSpecs.keys.filter { FabricLeaseOwner(it.surface, it.leaseHandle) == owner }
511
+ .forEach(finalLayoutSpecs::remove)
512
+ preparedMountTickets.keys.filter {
513
+ FabricLeaseOwner(it.surface, it.leaseHandle) == owner
514
+ }
515
+ .forEach(preparedMountTickets::remove)
516
+ }
517
+ finalPreparationInFlight.keys.filter {
518
+ FabricLeaseOwner(it.surface, it.leaseHandle) == owner
519
+ }
520
+ .forEach { finalPreparationInFlight.remove(it)?.cancel(false) }
521
+ layoutCache.releaseOwner(owner)
522
+ FabricAttachmentSidecars.remove(owner)
523
+ synchronized(compilerLock) {
524
+ documentsByFabricGeneration.keys.removeAll {
525
+ it.surface == owner.surface &&
526
+ it.leaseHandle == owner.leaseHandle
527
+ }
528
+ failuresByFabricGeneration.keys.removeAll {
529
+ it.surface == owner.surface &&
530
+ it.leaseHandle == owner.leaseHandle
531
+ }
532
+ }
533
+ }
534
+
535
+ fun deactivateFabricSurface(surface: FabricSurfaceToken) {
536
+ synchronized(fabricLeaseLock) {
537
+ activeFabricLeases.keys.filter { it.surface == surface }
538
+ .forEach { activeFabricLeases[it]?.active?.set(false) }
539
+ finalLayoutSpecs.keys.filter { it.surface == surface }.forEach(finalLayoutSpecs::remove)
540
+ preparedMountTickets.keys.filter {
541
+ it.surface == surface
542
+ }.forEach(preparedMountTickets::remove)
543
+ }
544
+ finalPreparationInFlight.keys.filter { it.surface == surface }
545
+ .forEach { finalPreparationInFlight.remove(it)?.cancel(false) }
546
+ layoutCache.releaseSurface(surface)
547
+ FabricAttachmentSidecars.remove(surface)
548
+ synchronized(compilerLock) {
549
+ documentsByFabricGeneration.keys.removeAll { it.surface == surface }
550
+ failuresByFabricGeneration.keys.removeAll { it.surface == surface }
551
+ }
552
+ }
553
+
554
+ /**
555
+ * Surface shutdown is broader than per-view recycling: Yoga may have
556
+ * measured components that never mounted, so no ViewState remains to name
557
+ * their exact component token. Deactivate every known handle and sweep
558
+ * their resources; C++ finalization later removes the bounded records.
559
+ */
560
+ fun deactivateFabricSurfaceId(surfaceId: Int) {
561
+ synchronized(fabricLeaseLock) {
562
+ activeFabricLeases.keys.filter { it.surface.surfaceId == surfaceId }
563
+ .forEach { activeFabricLeases[it]?.active?.set(false) }
564
+ finalLayoutSpecs.keys.filter {
565
+ it.surface.surfaceId == surfaceId
566
+ }.forEach(finalLayoutSpecs::remove)
567
+ preparedMountTickets.keys.filter {
568
+ it.surface.surfaceId == surfaceId
569
+ }.forEach(preparedMountTickets::remove)
570
+ }
571
+ finalPreparationInFlight.keys.filter { it.surface.surfaceId == surfaceId }
572
+ .forEach { finalPreparationInFlight.remove(it)?.cancel(false) }
573
+ layoutCache.releaseSurfaceId(surfaceId)
574
+ FabricAttachmentSidecars.removeSurface(surfaceId)
575
+ synchronized(compilerLock) {
576
+ documentsByFabricGeneration.keys.removeAll { it.surface.surfaceId == surfaceId }
577
+ failuresByFabricGeneration.keys.removeAll { it.surface.surfaceId == surfaceId }
578
+ }
579
+ }
580
+
581
+ /** A stale mount can retire only the exact unmounted handoff it requested. */
582
+ fun releaseFabricMountMiss(generation: FabricGenerationToken, widthPx: Int, density: Float) {
583
+ if (!isValidMeasurement(widthPx, density)) return
584
+ if (!isLeaseActive(generation, activeLeaseFor(generation))) return
585
+ layoutCache.releasePendingLease(generation, widthPx, density.toRawBits().toLong())
586
+ synchronized(compilerLock) {
587
+ if (!hasFabricLease(generation)) {
588
+ documentsByFabricGeneration.remove(generation)
589
+ failuresByFabricGeneration.remove(generation)
590
+ }
591
+ }
592
+ }
593
+
594
+ fun registerDirectMounted(owner: String, layout: PreparedProseLayout) =
595
+ layoutCache.registerDirectMount(owner, layout)
596
+ fun releaseDirectMounted(owner: String) = layoutCache.releaseDirectMount(owner)
597
+
598
+ internal fun beginBenchmarkResidentCensus() = layoutCache.beginBenchmarkCensus()
599
+
600
+ internal fun endBenchmarkResidentCensus(): BenchmarkResidentCensus {
601
+ val keys = layoutCache.endBenchmarkCensus()
602
+ val material = keys
603
+ .map { it.toString() }
604
+ .sorted()
605
+ .joinToString("\n")
606
+ val digest = MessageDigest.getInstance("SHA-256")
607
+ .digest(material.toByteArray(Charsets.UTF_8))
608
+ .joinToString("") { "%02x".format(it) }
609
+ return BenchmarkResidentCensus(count = keys.size, digest = digest)
610
+ }
611
+
612
+ fun didReceiveMemoryWarning() {
613
+ PreparedProseInstrumentation.invalidated(
614
+ PreparedProseInstrumentation.InvalidationReason.MEMORY_PRESSURE
615
+ )
616
+ PreparedProseInstrumentation.capturePreResetSnapshot()
617
+ layoutCache.removeAllUnmounted()
618
+ synchronized(compilerLock) {
619
+ compiled.clear()
620
+ compilationFailures.clear()
621
+ themes.clear()
622
+ documentsByFabricGeneration.clear()
623
+ failuresByFabricGeneration.clear()
624
+ compiledRetainedBytes = 0
625
+ themeRetainedBytes = 0
626
+ }
627
+ PreparedProseInstrumentation.retained(
628
+ PreparedProseInstrumentation.Owner.COMPILED,
629
+ "registry",
630
+ 0L
631
+ )
632
+ PreparedProseInstrumentation.cacheUpdated(compiledBytes = 0L, compiledResidentCount = 0L)
633
+ PreparedProseInstrumentation.capturePostResetSnapshot()
634
+ }
635
+
636
+ internal val preparedLayoutCacheCountForTesting: Int
637
+ get() = layoutCache.completedCountForTesting
638
+ internal val layoutRetainedBytesForTesting: Long get() = layoutCache.retainedBytesForTesting
639
+ internal val fabricLeaseCountForTesting: Int get() = layoutCache.leaseCountForTesting
640
+ internal val fabricGenerationPinCountForTesting: Int get() = synchronized(compilerLock) {
641
+ documentsByFabricGeneration.size + failuresByFabricGeneration.size
642
+ }
643
+ internal val preparedThemeCountForTesting: Int get() = synchronized(compilerLock) {
644
+ themes.size
645
+ }
646
+ internal val activeFabricLeaseCountForTesting: Int get() = synchronized(fabricLeaseLock) {
647
+ activeFabricLeases.size
648
+ }
649
+ internal fun permittedFabricGenerationForTesting(owner: FabricLeaseOwner): String? =
650
+ synchronized(fabricLeaseLock) { activeFabricLeases[owner]?.permittedGenerationIdentity }
651
+ private fun hasFabricLease(generation: FabricGenerationToken): Boolean =
652
+ layoutCache.hasLease(generation)
653
+
654
+ private fun preparedDocument(
655
+ request: ProseViewerRequest,
656
+ generation: FabricGenerationToken?,
657
+ suppliedDocument: ViewerDocument?,
658
+ leaseActive: FabricLeaseState?
659
+ ): ViewerDocument {
660
+ if (generation != null) {
661
+ synchronized(compilerLock) {
662
+ documentsByFabricGeneration[generation]?.let { return it }
663
+ failuresByFabricGeneration[generation]?.let { throw it }
664
+ }
665
+ }
666
+ return try {
667
+ // Pins deliberately retain only compiler semantics. Theme paints are
668
+ // density-local measurement inputs and must never cross a density change.
669
+ val semanticDocument = suppliedDocument ?: compileDocument(request)
670
+ if (generation != null) {
671
+ synchronized(compilerLock) {
672
+ if (isLeaseActive(generation, leaseActive)) {
673
+ documentsByFabricGeneration[generation] =
674
+ semanticDocument
675
+ }
676
+ }
677
+ }
678
+ semanticDocument
679
+ } catch (error: ProseViewerError) {
680
+ if (generation != null) {
681
+ synchronized(compilerLock) {
682
+ if (isLeaseActive(generation, leaseActive)) {
683
+ failuresByFabricGeneration[generation] =
684
+ error
685
+ }
686
+ }
687
+ }
688
+ throw error
689
+ }
690
+ }
691
+
692
+ private fun cachedErrorArtifact(
693
+ request: ProseViewerRequest,
694
+ widthPx: Int,
695
+ densityBits: Long,
696
+ error: ProseViewerError,
697
+ fabricGeneration: FabricGenerationToken?,
698
+ leaseActive: FabricLeaseState?
699
+ ): PreparedProseLayout {
700
+ val key = ProseLayoutKey(
701
+ semanticKey = "error:${request.compiledCacheKey}",
702
+ widthPx = widthPx,
703
+ themeDigest = request.themeDigest,
704
+ nativeFontRevision = request.nativeFontRevision,
705
+ fontEnvironmentRevision = request.fontEnvironmentRevision,
706
+ densityBits = densityBits,
707
+ attachmentRevision = request.attachmentRevision,
708
+ generationIdentity = request.generationIdentity,
709
+ semanticGenerationIdentity = request.semanticGenerationIdentity
710
+ )
711
+ return layoutCache.value(key, fabricGeneration, shouldCreateFabricLease = {
712
+ fabricGeneration == null || isLeaseActive(fabricGeneration, leaseActive)
713
+ }) { PreparedProseLayout.error(key, widthPx, error) }
714
+ }
715
+
716
+ private fun invalidWidthArtifact(request: ProseViewerRequest): PreparedProseLayout {
717
+ val key = ProseLayoutKey(
718
+ semanticKey = "error:${request.compiledCacheKey}",
719
+ widthPx = 0,
720
+ themeDigest = request.themeDigest,
721
+ nativeFontRevision = request.nativeFontRevision,
722
+ fontEnvironmentRevision = request.fontEnvironmentRevision,
723
+ densityBits = 0,
724
+ attachmentRevision = request.attachmentRevision,
725
+ generationIdentity = request.generationIdentity,
726
+ semanticGenerationIdentity = request.semanticGenerationIdentity
727
+ )
728
+ return PreparedProseLayout.error(key, 0, ProseViewerError.invalidWidth())
729
+ }
730
+
731
+ private fun layoutKey(
732
+ document: ViewerDocument,
733
+ request: ProseViewerRequest,
734
+ widthPx: Int,
735
+ densityBits: Long
736
+ ) = ProseLayoutKey(
737
+ semanticKey = document.semanticKey,
738
+ widthPx = widthPx,
739
+ themeDigest = request.themeDigest,
740
+ nativeFontRevision = request.nativeFontRevision,
741
+ fontEnvironmentRevision = request.fontEnvironmentRevision,
742
+ densityBits = densityBits,
743
+ attachmentRevision = request.attachmentRevision,
744
+ generationIdentity = request.generationIdentity,
745
+ semanticGenerationIdentity = request.semanticGenerationIdentity
746
+ )
747
+
748
+ private fun trimCompiledLocked() {
749
+ while (compiledRetainedBytes > compiledByteBudget && compiled.isNotEmpty()) {
750
+ val oldest = compiled.entries.first()
751
+ compiled.remove(oldest.key)
752
+ compiledRetainedBytes -= oldest.value.retainedBytes
753
+ }
754
+ PreparedProseInstrumentation.retained(
755
+ PreparedProseInstrumentation.Owner.COMPILED,
756
+ "registry",
757
+ compiledRetainedBytes
758
+ )
759
+ PreparedProseInstrumentation.cacheUpdated(
760
+ compiledBytes = compiledRetainedBytes,
761
+ compiledResidentCount = compiled.size.toLong()
762
+ )
763
+ }
764
+
765
+ private fun resolveTheme(
766
+ request: ProseViewerRequest,
767
+ density: Float,
768
+ fontScale: Float
769
+ ): PreparedProseTheme = synchronized(compilerLock) {
770
+ val key = "${request.generationIdentity}:${density.toRawBits()}:${fontScale.toRawBits()}"
771
+ themes[key]?.let { return@synchronized it }
772
+ val resolved = PreparedProseTheme.resolve(
773
+ request.configuration.themeJson,
774
+ density,
775
+ fontScale,
776
+ request.semanticGenerationIdentity
777
+ )
778
+ val highlighting = com.apollohg.editor.NativeCodeHighlightingConfig.fromJson(
779
+ org.json.JSONObject(request.configuration.configJson).optJSONObject("codeHighlighting")
780
+ )
781
+ highlighting?.let { com.apollohg.editor.CodeHighlightingRegistry.provider(it.provider) }
782
+ val configured = resolved.copy(codeHighlighting = highlighting)
783
+ themes[key] = configured
784
+ themeRetainedBytes += resolved.retainedBytes
785
+ while ((themeRetainedBytes > themeByteBudget || themes.size > themeEntryBudget) &&
786
+ themes.isNotEmpty()
787
+ ) {
788
+ val oldest = themes.entries.first()
789
+ themes.remove(oldest.key)
790
+ themeRetainedBytes -= oldest.value.retainedBytes
791
+ }
792
+ configured
793
+ }
794
+
795
+ private fun Compilation.documentOrThrow(): ViewerDocument = when (this) {
796
+ is Compilation.Document -> value
797
+ is Compilation.Failure -> throw error
798
+ }
799
+
800
+ private fun isValidMeasurement(widthPx: Int, density: Float): Boolean =
801
+ widthPx > 0 && density.isFinite() && density > 0f
802
+
803
+ private fun activeLeaseFor(generation: FabricGenerationToken): FabricLeaseState? =
804
+ synchronized(fabricLeaseLock) {
805
+ activeFabricLeases[FabricLeaseOwner(generation.surface, generation.leaseHandle)]
806
+ }
807
+
808
+ private fun isLeaseActiveLocked(generation: FabricGenerationToken): Boolean = isLeaseActive(
809
+ generation,
810
+ activeFabricLeases[FabricLeaseOwner(generation.surface, generation.leaseHandle)]
811
+ )
812
+
813
+ private fun isLeaseActive(
814
+ generation: FabricGenerationToken,
815
+ lease: FabricLeaseState?
816
+ ): Boolean = lease?.active?.get() == true && synchronized(fabricLeaseLock) {
817
+ activeFabricLeases[FabricLeaseOwner(generation.surface, generation.leaseHandle)] ===
818
+ lease &&
819
+ (
820
+ lease.permittedGenerationIdentity == null ||
821
+ lease.permittedGenerationIdentity == generation.generationIdentity
822
+ )
823
+ }
824
+
825
+ companion object {
826
+ val shared = PreparedProseLayoutRegistry()
827
+ }
828
+ }