@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,678 @@
1
+ package com.apollohg.editor.viewer
2
+
3
+ import android.content.Context
4
+ import android.content.res.Configuration
5
+ import android.graphics.Canvas
6
+ import android.graphics.Paint
7
+ import android.graphics.Rect
8
+ import android.graphics.RectF
9
+ import android.os.Bundle
10
+ import android.util.AttributeSet
11
+ import android.view.MotionEvent
12
+ import android.view.View
13
+ import android.view.ViewConfiguration
14
+ import android.view.ViewTreeObserver
15
+ import android.view.accessibility.AccessibilityEvent
16
+ import android.view.accessibility.AccessibilityManager
17
+ import android.view.accessibility.AccessibilityNodeInfo
18
+ import android.view.accessibility.AccessibilityNodeProvider
19
+ import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
20
+ import com.apollohg.editor.AndroidApiCompat
21
+ import com.apollohg.editor.DecodedBitmapBudget
22
+ import com.apollohg.editor.DecodedBitmapLease
23
+
24
+ /** Rendering-only consumer of fully prepared StaticLayout and geometry fragments. */
25
+ internal class PreparedProseDrawingView @JvmOverloads constructor(
26
+ context: Context,
27
+ attrs: AttributeSet? = null
28
+ ) : View(context, attrs) {
29
+ private val accessibilityManager = context.getSystemService(AccessibilityManager::class.java)
30
+ var preparedLayout: PreparedProseLayout? = null
31
+ private set
32
+ var onCodeHighlightsReady: (() -> Unit)? = null
33
+ private val codeHighlighting = ViewerCodeHighlighting(this)
34
+ var onUsableMetricsChanged: (() -> Unit)? = null
35
+ var onVisibleRectChanged: ((Rect) -> Unit)? = null
36
+ var onFontConfigurationChanged: ((Configuration) -> Unit)? = null
37
+ var onInteractionActivated: ((PreparedProseInteraction) -> Boolean)? = null
38
+ private val imagePixelsLock = Any()
39
+ private val imagePixels = mutableMapOf<String, DecodedBitmapLease>()
40
+
41
+ /** Map overhead only; decoded allocation bytes are charged by the shared lease budget. */
42
+ internal val retainedImagePixelsBytesForTesting: Long
43
+ get() = synchronized(imagePixelsLock) { retainedImagePixelsBytes(imagePixels) }
44
+
45
+ /** False when a public host owns this view's virtual subtree and notifications. */
46
+ var publishesAccessibilitySubtree: Boolean = true
47
+ internal var accessibilityVisibilityForTesting: ((Rect) -> Boolean)? = null
48
+ var linkInteractionsEnabled: Boolean = true
49
+ set(value) {
50
+ if (field == value) return
51
+ clearVirtualAccessibilityFocus()
52
+ field = value
53
+ announceAccessibilitySubtreeChanged()
54
+ }
55
+ var mentionInteractionsEnabled: Boolean = false
56
+ set(value) {
57
+ if (field == value) return
58
+ clearVirtualAccessibilityFocus()
59
+ field = value
60
+ announceAccessibilitySubtreeChanged()
61
+ }
62
+ private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
63
+ private val touchSlop = ViewConfiguration.get(context).scaledTouchSlop.toFloat()
64
+ private var pendingTap: PendingTap? = null
65
+ private var focusedVirtualNode: FocusedVirtualNode? = null
66
+ private var contentOriginXPx = 0
67
+ private var contentOriginYPx = 0
68
+ private val scrollChangedListener = ViewTreeObserver.OnScrollChangedListener {
69
+ reconcileVirtualAccessibilityFocus()
70
+ }
71
+
72
+ init {
73
+ DecodedBitmapBudget.shared(context)
74
+ }
75
+
76
+ internal companion object {
77
+ const val IMAGE_PIXEL_MAP_RETAINED_BYTES = 48L
78
+ const val IMAGE_PIXEL_ENTRY_RETAINED_BYTES = 48L
79
+
80
+ fun retainedImagePixelsBytes(pixels: Map<String, *>): Long {
81
+ if (pixels.isEmpty()) return 0L
82
+ var retained = IMAGE_PIXEL_MAP_RETAINED_BYTES
83
+ pixels.values.forEach {
84
+ retained = saturatingAdd(retained, IMAGE_PIXEL_ENTRY_RETAINED_BYTES)
85
+ }
86
+ return retained
87
+ }
88
+
89
+ private fun saturatingAdd(left: Long, right: Long): Long =
90
+ if (right > 0 && left > Long.MAX_VALUE - right) Long.MAX_VALUE else left + right
91
+
92
+ private fun saturatingMultiply(left: Long, right: Long): Long = when {
93
+ left <= 0L || right <= 0L -> 0L
94
+ left > Long.MAX_VALUE / right -> Long.MAX_VALUE
95
+ else -> left * right
96
+ }
97
+ }
98
+
99
+ fun putImageLease(id: String, lease: DecodedBitmapLease) {
100
+ synchronized(imagePixelsLock) { imagePixels.put(id, lease) }?.close()
101
+ reportRetainedImagePixels()
102
+ postInvalidate()
103
+ }
104
+
105
+ fun removeImageLeases(ids: Set<String>) {
106
+ val released = synchronized(imagePixelsLock) { ids.mapNotNull(imagePixels::remove) }
107
+ if (released.isEmpty()) return
108
+ released.forEach(DecodedBitmapLease::close)
109
+ reportRetainedImagePixels()
110
+ postInvalidate()
111
+ }
112
+
113
+ fun clearImageLeases() {
114
+ val released = synchronized(imagePixelsLock) {
115
+ imagePixels.values.toList().also { imagePixels.clear() }
116
+ }
117
+ if (released.isEmpty()) return
118
+ released.forEach(DecodedBitmapLease::close)
119
+ reportRetainedImagePixels()
120
+ postInvalidate()
121
+ }
122
+
123
+ private fun reportRetainedImagePixels() {
124
+ PreparedProseInstrumentation.retained(
125
+ PreparedProseInstrumentation.Owner.IMAGE,
126
+ "drawing-${System.identityHashCode(this)}",
127
+ synchronized(imagePixelsLock) { retainedImagePixelsBytes(imagePixels) }
128
+ )
129
+ }
130
+
131
+ /**
132
+ * Publishes a prepared artifact. Replacement owners suppress the transient
133
+ * clear announcement and let the final install report the one logical
134
+ * subtree transition; focus-cleared events remain immediate.
135
+ */
136
+ fun install(
137
+ layout: PreparedProseLayout?,
138
+ announceAccessibilitySubtree: Boolean = true,
139
+ contentOriginXPx: Int = 0,
140
+ contentOriginYPx: Int = 0
141
+ ) {
142
+ if (
143
+ preparedLayout === layout &&
144
+ this.contentOriginXPx == contentOriginXPx &&
145
+ this.contentOriginYPx == contentOriginYPx
146
+ ) {
147
+ return
148
+ }
149
+ clearVirtualAccessibilityFocus()
150
+ preparedLayout = layout
151
+ codeHighlighting.update()
152
+ this.contentOriginXPx = contentOriginXPx
153
+ this.contentOriginYPx = contentOriginYPx
154
+ if (announceAccessibilitySubtree) announceAccessibilitySubtreeChanged()
155
+ invalidate()
156
+ }
157
+
158
+ override fun onDraw(canvas: Canvas) {
159
+ super.onDraw(canvas)
160
+ reconcileVirtualAccessibilityFocus()
161
+ val artifact = preparedLayout ?: return
162
+ val saved = canvas.save()
163
+ canvas.translate(contentOriginXPx.toFloat(), contentOriginYPx.toFloat())
164
+ canvas.clipRect(0, 0, artifact.widthPx, artifact.heightPx)
165
+ try {
166
+ artifact.contentBox?.let {
167
+ com.apollohg.editor.EditorBoxDrawing.draw(
168
+ canvas,
169
+ RectF(0f, 0f, artifact.widthPx.toFloat(), artifact.heightPx.toFloat()),
170
+ it
171
+ )
172
+ }
173
+ recordPreparedProseDraw {
174
+ onVisibleRectChanged?.invoke(Rect(canvas.clipBounds))
175
+ val visible = mutableListOf<PreparedProseFragment>()
176
+ var visibleBlockCount = 0
177
+ artifact.forEachBlockIntersecting(canvas.clipBounds) { block ->
178
+ visible +=
179
+ block.fragments
180
+ visibleBlockCount += 1
181
+ }
182
+ // Phases stay global across blocks: later code backgrounds cannot cover
183
+ // an earlier quote border, and text/labels always remain foreground.
184
+ visible.forEach { drawBackground(canvas, it) }
185
+ visible.forEach { drawBorderOrRule(canvas, it) }
186
+ visible.forEach { drawForeground(canvas, it) }
187
+ visibleBlockCount
188
+ }
189
+ } finally {
190
+ canvas.restoreToCount(saved)
191
+ }
192
+ }
193
+
194
+ private fun drawBackground(canvas: Canvas, fragment: PreparedProseFragment) {
195
+ if (fragment.kind != PreparedProseFragmentKind.BACKGROUND &&
196
+ fragment.kind != PreparedProseFragmentKind.ATOM &&
197
+ fragment.kind != PreparedProseFragmentKind.IMAGE
198
+ ) {
199
+ return
200
+ }
201
+ fragment.box?.let { box ->
202
+ val saved = canvas.save()
203
+ canvas.clipRect(fragment.bounds)
204
+ com.apollohg.editor.EditorBoxDrawing.draw(
205
+ canvas,
206
+ RectF(fragment.decorationBounds ?: fragment.bounds),
207
+ box
208
+ )
209
+ canvas.restoreToCount(saved)
210
+ return
211
+ }
212
+ paint.style = Paint.Style.FILL
213
+ paint.color = fragment.color ?: return
214
+ canvas.drawRoundRect(
215
+ RectF(fragment.bounds),
216
+ fragment.cornerRadius,
217
+ fragment.cornerRadius,
218
+ paint
219
+ )
220
+ }
221
+
222
+ private fun drawBorderOrRule(canvas: Canvas, fragment: PreparedProseFragment) {
223
+ when (fragment.kind) {
224
+ PreparedProseFragmentKind.BORDER, PreparedProseFragmentKind.RULE -> {
225
+ paint.style = Paint.Style.FILL
226
+ paint.color = fragment.color ?: return
227
+ canvas.drawRect(fragment.bounds, paint)
228
+ }
229
+
230
+ PreparedProseFragmentKind.ATOM -> if (fragment.strokeWidth > 0f) {
231
+ paint.style = Paint.Style.STROKE
232
+ paint.strokeWidth = fragment.strokeWidth
233
+ paint.color = fragment.borderColor ?: fragment.color ?: return
234
+ val inset = fragment.strokeWidth / 2f
235
+ canvas.drawRoundRect(
236
+ RectF(fragment.bounds).apply { inset(inset, inset) },
237
+ maxOf(
238
+ 0f,
239
+ fragment.cornerRadius - inset
240
+ ),
241
+ maxOf(0f, fragment.cornerRadius - inset),
242
+ paint
243
+ )
244
+ }
245
+
246
+ else -> Unit
247
+ }
248
+ }
249
+
250
+ private fun drawForeground(canvas: Canvas, fragment: PreparedProseFragment) {
251
+ when (fragment.kind) {
252
+ PreparedProseFragmentKind.TEXT, PreparedProseFragmentKind.MARKER -> {
253
+ fragment.layout?.let { layout ->
254
+ val saved = canvas.save()
255
+ canvas.translate(fragment.layoutX.toFloat(), fragment.layoutY.toFloat())
256
+ layout.draw(canvas)
257
+ com.apollohg.editor.EditorTextDecorationDrawing.draw(canvas, layout)
258
+ canvas.restoreToCount(saved)
259
+ }
260
+ ?: if (fragment.kind ==
261
+ PreparedProseFragmentKind.MARKER
262
+ ) {
263
+ drawTaskMarker(canvas, fragment)
264
+ } else {
265
+ Unit
266
+ }
267
+ }
268
+
269
+ PreparedProseFragmentKind.ATOM -> fragment.labelLayout?.let { layout ->
270
+ val saved = canvas.save()
271
+ canvas.translate(fragment.labelX.toFloat(), fragment.labelY.toFloat())
272
+ layout.draw(canvas)
273
+ com.apollohg.editor.EditorTextDecorationDrawing.draw(canvas, layout)
274
+ canvas.restoreToCount(saved)
275
+ }
276
+
277
+ PreparedProseFragmentKind.STRIKE -> {
278
+ paint.style = Paint.Style.FILL
279
+ paint.color = fragment.color ?: return
280
+ canvas.drawRect(fragment.bounds, paint)
281
+ }
282
+
283
+ PreparedProseFragmentKind.IMAGE -> {
284
+ val attachment =
285
+ preparedLayout?.imageAttachments?.firstOrNull { it.bounds == fragment.bounds }
286
+ ?: return
287
+ val bitmap =
288
+ synchronized(imagePixelsLock) { imagePixels[attachment.id]?.bitmap } ?: return
289
+ fragment.box?.let {
290
+ com.apollohg.editor.EditorBoxDrawing.drawImage(
291
+ canvas,
292
+ bitmap,
293
+ RectF(fragment.bounds),
294
+ it,
295
+ fragment.resizeMode
296
+ )
297
+ } ?: canvas.drawBitmap(bitmap, null, fragment.bounds, paint)
298
+ }
299
+
300
+ else -> Unit
301
+ }
302
+ }
303
+
304
+ private fun drawTaskMarker(canvas: Canvas, fragment: PreparedProseFragment) {
305
+ val bounds = RectF(fragment.bounds)
306
+ fragment.box?.let {
307
+ com.apollohg.editor.drawCheckbox(
308
+ canvas,
309
+ bounds,
310
+ it,
311
+ fragment.checked,
312
+ fragment.borderColor ?: fragment.color ?: android.graphics.Color.BLACK
313
+ )
314
+ return
315
+ }
316
+ val inset = maxOf(1f, bounds.height() * 0.2f)
317
+ val box = RectF(bounds).apply { inset(inset, inset) }
318
+ paint.style = Paint.Style.STROKE
319
+ paint.strokeWidth = maxOf(1f, box.width() * 0.1f)
320
+ paint.color = fragment.color ?: return
321
+ canvas.drawRoundRect(box, box.width() * 0.2f, box.width() * 0.2f, paint)
322
+ if (!fragment.checked) return
323
+ paint.style = Paint.Style.STROKE
324
+ paint.strokeWidth = maxOf(1.4f, box.width() * 0.12f)
325
+ paint.strokeCap = Paint.Cap.ROUND
326
+ paint.strokeJoin = Paint.Join.ROUND
327
+ val path = android.graphics.Path().apply {
328
+ moveTo(box.left + box.width() * 0.2f, box.centerY())
329
+ lineTo(box.left + box.width() * 0.43f, box.bottom - box.height() * 0.2f)
330
+ lineTo(box.right - box.width() * 0.16f, box.top + box.height() * 0.2f)
331
+ }
332
+ canvas.drawPath(path, paint)
333
+ paint.strokeCap = Paint.Cap.BUTT
334
+ paint.strokeJoin = Paint.Join.MITER
335
+ }
336
+
337
+ override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
338
+ super.onSizeChanged(width, height, oldWidth, oldHeight)
339
+ reconcileVirtualAccessibilityFocus()
340
+ if (width > 0) onUsableMetricsChanged?.invoke()
341
+ }
342
+
343
+ override fun onAttachedToWindow() {
344
+ super.onAttachedToWindow()
345
+ codeHighlighting.update()
346
+ viewTreeObserver.addOnScrollChangedListener(scrollChangedListener)
347
+ reconcileVirtualAccessibilityFocus()
348
+ if (width > 0) onUsableMetricsChanged?.invoke()
349
+ }
350
+
351
+ override fun onDetachedFromWindow() {
352
+ codeHighlighting.cancel()
353
+ if (viewTreeObserver.isAlive) {
354
+ viewTreeObserver.removeOnScrollChangedListener(scrollChangedListener)
355
+ }
356
+ clearVirtualAccessibilityFocus()
357
+ super.onDetachedFromWindow()
358
+ }
359
+
360
+ override fun onVisibilityChanged(changedView: View, visibility: Int) {
361
+ super.onVisibilityChanged(changedView, visibility)
362
+ reconcileVirtualAccessibilityFocus()
363
+ }
364
+
365
+ override fun onWindowVisibilityChanged(visibility: Int) {
366
+ super.onWindowVisibilityChanged(visibility)
367
+ reconcileVirtualAccessibilityFocus()
368
+ }
369
+
370
+ override fun onConfigurationChanged(newConfig: Configuration) {
371
+ super.onConfigurationChanged(newConfig)
372
+ onFontConfigurationChanged?.invoke(newConfig)
373
+ }
374
+
375
+ override fun onTouchEvent(event: MotionEvent): Boolean {
376
+ val contentX = event.x - contentOriginXPx
377
+ val contentY = event.y - contentOriginYPx
378
+ fun targetAt(): PreparedProseInteraction? =
379
+ preparedLayout?.interactions?.firstOrNull { interaction ->
380
+ if (contentX < 0f || contentY < 0f) return@firstOrNull false
381
+ interactionEnabled(interaction.kind) &&
382
+ interaction.rects.any { it.contains(contentX.toInt(), contentY.toInt()) }
383
+ }
384
+ when (event.actionMasked) {
385
+ MotionEvent.ACTION_DOWN -> {
386
+ pendingTap =
387
+ if (event.pointerCount ==
388
+ 1
389
+ ) {
390
+ targetAt()?.let {
391
+ PendingTap(
392
+ it,
393
+ event.getPointerId(event.actionIndex),
394
+ event.x,
395
+ event.y
396
+ )
397
+ }
398
+ } else {
399
+ null
400
+ }
401
+ return pendingTap != null
402
+ }
403
+
404
+ MotionEvent.ACTION_MOVE -> {
405
+ pendingTap?.let { tap ->
406
+ if (event.pointerCount != 1 ||
407
+ event.findPointerIndex(tap.pointerId) < 0 ||
408
+ exceedsSlop(event, tap)
409
+ ) {
410
+ pendingTap = null
411
+ }
412
+ }
413
+ return pendingTap != null
414
+ }
415
+
416
+ MotionEvent.ACTION_CANCEL,
417
+ MotionEvent.ACTION_POINTER_DOWN,
418
+ MotionEvent.ACTION_POINTER_UP -> {
419
+ pendingTap =
420
+ null
421
+ return false
422
+ }
423
+
424
+ MotionEvent.ACTION_UP -> {
425
+ val tap = pendingTap
426
+ pendingTap = null
427
+ if (tap != null && event.pointerCount == 1 &&
428
+ event.getPointerId(event.actionIndex) == tap.pointerId &&
429
+ !exceedsSlop(event, tap) &&
430
+ targetAt() == tap.target
431
+ ) {
432
+ return onInteractionActivated?.invoke(tap.target) ?: false
433
+ }
434
+ }
435
+ }
436
+ return false
437
+ }
438
+
439
+ private fun exceedsSlop(event: MotionEvent, tap: PendingTap): Boolean {
440
+ val dx = event.x - tap.downX
441
+ val dy = event.y - tap.downY
442
+ return dx * dx + dy * dy > touchSlop * touchSlop
443
+ }
444
+
445
+ private data class PendingTap(
446
+ val target: PreparedProseInteraction,
447
+ val pointerId: Int,
448
+ val downX: Float,
449
+ val downY: Float
450
+ )
451
+
452
+ override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) {
453
+ super.onInitializeAccessibilityNodeInfo(info)
454
+ info.className = android.widget.TextView::class.java.name
455
+ nodes().indices.forEach { info.addChild(this, it + 1) }
456
+ }
457
+
458
+ override fun getAccessibilityNodeProvider(): AccessibilityNodeProvider = provider
459
+
460
+ // The replacement constructors are API 30 and this module's minSdk is 24;
461
+ // on API 30+ obtain() only delegates to them. setBoundsInParent has no
462
+ // replacement at all, and API 24-28 services still read it.
463
+ @Suppress("DEPRECATION")
464
+ private val provider = object : AccessibilityNodeProvider() {
465
+ override fun createAccessibilityNodeInfo(id: Int): AccessibilityNodeInfo? {
466
+ if (id ==
467
+ View.NO_ID
468
+ ) {
469
+ return AccessibilityNodeInfo.obtain(
470
+ this@PreparedProseDrawingView
471
+ ).also(::onInitializeAccessibilityNodeInfo)
472
+ }
473
+ val node = nodes().getOrNull(id - 1) ?: return null
474
+ val parentBounds = Rect(node.bounds).apply {
475
+ offset(contentOriginXPx, contentOriginYPx)
476
+ }
477
+ val screen = accessibilityScreenBounds(node)
478
+ val visibleToUser = accessibilityNodeVisibleOnScreen(screen)
479
+ reconcileVirtualAccessibilityFocus()
480
+ val identity = identity(node)
481
+ return AccessibilityNodeInfo.obtain().apply {
482
+ packageName = context.packageName
483
+ className = android.widget.Button::class.java.name
484
+ setSource(this@PreparedProseDrawingView, id)
485
+ setParent(this@PreparedProseDrawingView)
486
+ text = node.label
487
+ contentDescription = node.label
488
+ isClickable = true
489
+ isFocusable = true
490
+ AndroidApiCompat.setScreenReaderFocusable(this, true)
491
+ isAccessibilityFocused = focusedVirtualNode?.identity == identity
492
+ isVisibleToUser = visibleToUser
493
+ setBoundsInParent(parentBounds)
494
+ setBoundsInScreen(screen)
495
+ addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK)
496
+ addAction(
497
+ if (isAccessibilityFocused) {
498
+ AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS
499
+ } else {
500
+ AccessibilityNodeInfo.AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS
501
+ }
502
+ )
503
+ AccessibilityNodeInfoCompat.wrap(this).roleDescription =
504
+ if (node.role == PreparedProseAccessibilityNode.Role.LINK) "link" else "mention"
505
+ }
506
+ }
507
+
508
+ override fun performAction(id: Int, action: Int, arguments: Bundle?): Boolean {
509
+ val node = nodes().getOrNull(id - 1) ?: return false
510
+ return when (action) {
511
+ AccessibilityNodeInfo.ACTION_CLICK -> if (accessibilityNodeVisible(node)) {
512
+ preparedLayout?.interactions?.getOrNull(node.interactionIndex)?.let {
513
+ onInteractionActivated?.invoke(it) ?: false
514
+ } ?: false
515
+ } else {
516
+ false
517
+ }
518
+
519
+ AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS ->
520
+ requestVirtualAccessibilityFocus(
521
+ id
522
+ )
523
+
524
+ AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS ->
525
+ clearVirtualAccessibilityFocus(
526
+ id
527
+ )
528
+
529
+ else -> false
530
+ }
531
+ }
532
+ }
533
+
534
+ private fun nodes(): List<PreparedProseAccessibilityNode> =
535
+ preparedLayout?.accessibilityNodes.orEmpty().filter { node ->
536
+ when (node.role) {
537
+ PreparedProseAccessibilityNode.Role.LINK -> linkInteractionsEnabled
538
+ PreparedProseAccessibilityNode.Role.MENTION -> mentionInteractionsEnabled
539
+ }
540
+ }
541
+
542
+ private fun interactionEnabled(kind: PreparedProseInteraction.Kind): Boolean = when (kind) {
543
+ PreparedProseInteraction.Kind.LINK -> linkInteractionsEnabled
544
+ PreparedProseInteraction.Kind.MENTION -> mentionInteractionsEnabled
545
+ }
546
+
547
+ private fun requestVirtualAccessibilityFocus(id: Int): Boolean {
548
+ val node = nodes().getOrNull(id - 1) ?: return false
549
+ if (!accessibilityNodeVisible(node)) return false
550
+ val identity = identity(node)
551
+ if (focusedVirtualNode?.identity == identity) return false
552
+ clearVirtualAccessibilityFocus()
553
+ focusedVirtualNode = FocusedVirtualNode(id, identity)
554
+ invalidate()
555
+ sendVirtualAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
556
+ return true
557
+ }
558
+
559
+ private fun clearVirtualAccessibilityFocus(
560
+ id: Int = focusedVirtualNode?.virtualId ?: View.NO_ID
561
+ ): Boolean {
562
+ val focused = focusedVirtualNode ?: return false
563
+ if (id == View.NO_ID || id != focused.virtualId) return false
564
+ focusedVirtualNode = null
565
+ invalidate()
566
+ sendVirtualAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED)
567
+ return true
568
+ }
569
+
570
+ private fun reconcileVirtualAccessibilityFocus() {
571
+ val focused = focusedVirtualNode ?: return
572
+ val nodes = nodes()
573
+ val index = nodes.indexOfFirst { identity(it) == focused.identity }
574
+ if (index < 0 || index + 1 != focused.virtualId) {
575
+ clearVirtualAccessibilityFocus(focused.virtualId)
576
+ return
577
+ }
578
+ if (!accessibilityNodeVisible(nodes[index])) {
579
+ clearVirtualAccessibilityFocus(focused.virtualId)
580
+ }
581
+ }
582
+
583
+ private fun accessibilityNodeVisible(node: PreparedProseAccessibilityNode): Boolean =
584
+ accessibilityScreenBounds(node).let { bounds ->
585
+ accessibilityVisibilityForTesting?.invoke(bounds)
586
+ ?: accessibilityNodeVisibleOnScreen(bounds)
587
+ }
588
+
589
+ private fun accessibilityScreenBounds(node: PreparedProseAccessibilityNode): Rect {
590
+ val bounds = Rect(node.bounds).apply { offset(contentOriginXPx, contentOriginYPx) }
591
+ val location = IntArray(2)
592
+ getLocationOnScreen(location)
593
+ bounds.offset(location[0], location[1])
594
+ return bounds
595
+ }
596
+
597
+ private fun identity(node: PreparedProseAccessibilityNode) = AccessibilityNodeIdentity(
598
+ preparedLayout?.key?.generationIdentity,
599
+ node.interactionIndex,
600
+ node.role,
601
+ node.label
602
+ )
603
+
604
+ // AccessibilityEvent(Int) is API 30; see the node provider above.
605
+ @Suppress("DEPRECATION")
606
+ private fun sendVirtualAccessibilityEvent(id: Int, type: Int) {
607
+ if (!accessibilityManager.isEnabled) return
608
+ val event = AccessibilityEvent.obtain(type).apply {
609
+ packageName = context.packageName
610
+ className = android.widget.Button::class.java.name
611
+ setSource(this@PreparedProseDrawingView, id)
612
+ }
613
+ parent?.requestSendAccessibilityEvent(this, event)
614
+ }
615
+
616
+ /** Publishes a logical prepared-subtree transition without changing its artifact. */
617
+ @Suppress("DEPRECATION")
618
+ internal fun announceAccessibilitySubtreeChanged() {
619
+ if (!publishesAccessibilitySubtree || !accessibilityManager.isEnabled) return
620
+ val event = AccessibilityEvent.obtain(
621
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
622
+ ).apply {
623
+ packageName = context.packageName
624
+ className = android.widget.TextView::class.java.name
625
+ contentChangeTypes = AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE
626
+ setSource(this@PreparedProseDrawingView)
627
+ }
628
+ parent?.requestSendAccessibilityEvent(this, event)
629
+ }
630
+
631
+ private data class AccessibilityNodeIdentity(
632
+ val generation: String?,
633
+ val interactionIndex: Int,
634
+ val role: PreparedProseAccessibilityNode.Role,
635
+ val label: String
636
+ )
637
+
638
+ private data class FocusedVirtualNode(
639
+ val virtualId: Int,
640
+ val identity: AccessibilityNodeIdentity
641
+ )
642
+ }
643
+
644
+ internal fun View.accessibilityNodeVisibleOnScreen(screenBounds: Rect): Boolean {
645
+ val visibleBounds = Rect()
646
+ val hasGlobalVisibleBounds = getGlobalVisibleRect(visibleBounds)
647
+ return accessibilityBoundsVisible(
648
+ screenBounds,
649
+ visibleBounds.takeIf { hasGlobalVisibleBounds },
650
+ isShown,
651
+ windowVisibility == View.VISIBLE,
652
+ hasVisibleAlpha()
653
+ )
654
+ }
655
+
656
+ internal fun accessibilityBoundsVisible(
657
+ screenBounds: Rect,
658
+ globalVisibleBounds: Rect?,
659
+ shown: Boolean,
660
+ windowVisible: Boolean,
661
+ alphaVisible: Boolean
662
+ ): Boolean {
663
+ if (!shown || !windowVisible || !alphaVisible || globalVisibleBounds?.isEmpty != false) {
664
+ return false
665
+ }
666
+ return Rect(globalVisibleBounds).run {
667
+ intersect(screenBounds) && !isEmpty
668
+ }
669
+ }
670
+
671
+ private fun View.hasVisibleAlpha(): Boolean {
672
+ var current: View? = this
673
+ while (current != null) {
674
+ if (current.alpha <= 0f) return false
675
+ current = current.parent as? View
676
+ }
677
+ return true
678
+ }