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