@mathers101/react-native-render-rich-text 0.1.10 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -20
- package/README.md +140 -140
- package/ReactNativeRenderRichText.podspec +23 -23
- package/android/build.gradle +86 -86
- package/android/consumer-rules.pro +3 -3
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextLayoutManager.kt +24 -24
- package/android/src/main/java/com/renderrichtext/EnrichedTiptapTextPackage.kt +13 -13
- package/android/src/main/java/com/renderrichtext/MeasurementStore.kt +644 -644
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibilityLabels.kt +17 -17
- package/android/src/main/java/com/renderrichtext/accessibility/AccessibleTiptapTextView.kt +112 -112
- package/android/src/main/java/com/renderrichtext/accessibility/TiptapAccessibilityHelper.kt +576 -576
- package/android/src/main/java/com/renderrichtext/events/CodeBlockPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ContextMenuItemPressEvent.kt +28 -28
- package/android/src/main/java/com/renderrichtext/events/CopyPressEvent.kt +24 -24
- package/android/src/main/java/com/renderrichtext/events/ImagePressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/LatexErrorEvent.kt +29 -29
- package/android/src/main/java/com/renderrichtext/events/LinkLongPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/LinkPressEvent.kt +23 -23
- package/android/src/main/java/com/renderrichtext/events/MentionLongPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/MentionPressEvent.kt +25 -25
- package/android/src/main/java/com/renderrichtext/events/TaskListItemPressEvent.kt +26 -26
- package/android/src/main/java/com/renderrichtext/math/LatexErrorReporter.kt +9 -9
- package/android/src/main/java/com/renderrichtext/parser/Parser.kt +59 -59
- package/android/src/main/java/com/renderrichtext/parser/TextLinkMatching.kt +35 -35
- package/android/src/main/java/com/renderrichtext/renderer/BaselineShiftRenderer.kt +45 -45
- package/android/src/main/java/com/renderrichtext/renderer/BlankLineRenderer.kt +39 -39
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteRenderer.kt +243 -243
- package/android/src/main/java/com/renderrichtext/renderer/BlockquoteTextRenderer.kt +56 -56
- package/android/src/main/java/com/renderrichtext/renderer/CodeBlockRenderer.kt +135 -135
- package/android/src/main/java/com/renderrichtext/renderer/CodeRenderer.kt +37 -37
- package/android/src/main/java/com/renderrichtext/renderer/EmphasisRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/HeadingRenderer.kt +81 -81
- package/android/src/main/java/com/renderrichtext/renderer/HighlightRenderer.kt +26 -26
- package/android/src/main/java/com/renderrichtext/renderer/LineBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/LinkRenderer.kt +90 -90
- package/android/src/main/java/com/renderrichtext/renderer/ListContextManager.kt +109 -109
- package/android/src/main/java/com/renderrichtext/renderer/ListItemRenderer.kt +211 -211
- package/android/src/main/java/com/renderrichtext/renderer/ListRenderer.kt +133 -133
- package/android/src/main/java/com/renderrichtext/renderer/MentionRenderer.kt +85 -85
- package/android/src/main/java/com/renderrichtext/renderer/ParagraphRenderer.kt +91 -91
- package/android/src/main/java/com/renderrichtext/renderer/Renderer.kt +148 -148
- package/android/src/main/java/com/renderrichtext/renderer/SoftBreakRenderer.kt +17 -17
- package/android/src/main/java/com/renderrichtext/renderer/SpanStyleCache.kt +143 -143
- package/android/src/main/java/com/renderrichtext/renderer/StrikethroughRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/StrongRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/renderer/TextRenderer.kt +31 -31
- package/android/src/main/java/com/renderrichtext/renderer/ThematicBreakRenderer.kt +46 -46
- package/android/src/main/java/com/renderrichtext/renderer/UnderlineRenderer.kt +28 -28
- package/android/src/main/java/com/renderrichtext/spans/BaseListSpan.kt +164 -164
- package/android/src/main/java/com/renderrichtext/spans/BaselineShiftSpan.kt +27 -27
- package/android/src/main/java/com/renderrichtext/spans/BlockquoteSpan.kt +302 -302
- package/android/src/main/java/com/renderrichtext/spans/CodeBackgroundSpan.kt +205 -205
- package/android/src/main/java/com/renderrichtext/spans/CodeBlockSpan.kt +216 -216
- package/android/src/main/java/com/renderrichtext/spans/CodeSpan.kt +32 -32
- package/android/src/main/java/com/renderrichtext/spans/EmphasisSpan.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/FadeInSpan.kt +29 -29
- package/android/src/main/java/com/renderrichtext/spans/HeadingSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/HighlightSpan.kt +80 -80
- package/android/src/main/java/com/renderrichtext/spans/ImageSpan.kt +481 -481
- package/android/src/main/java/com/renderrichtext/spans/InlineBackgroundGeometry.kt +42 -42
- package/android/src/main/java/com/renderrichtext/spans/LineHeightSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/LinkPillIconCache.kt +154 -154
- package/android/src/main/java/com/renderrichtext/spans/LinkPillSpan.kt +381 -381
- package/android/src/main/java/com/renderrichtext/spans/LinkSpan.kt +68 -68
- package/android/src/main/java/com/renderrichtext/spans/ListItemSpacingSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/ListMarkerAnchorSpan.kt +38 -38
- package/android/src/main/java/com/renderrichtext/spans/MarginBottomSpan.kt +76 -76
- package/android/src/main/java/com/renderrichtext/spans/MentionChipSpan.kt +132 -132
- package/android/src/main/java/com/renderrichtext/spans/MentionSpan.kt +46 -46
- package/android/src/main/java/com/renderrichtext/spans/OrderedListSpan.kt +127 -127
- package/android/src/main/java/com/renderrichtext/spans/SpoilerSpan.kt +33 -33
- package/android/src/main/java/com/renderrichtext/spans/StrikethroughSpan.kt +12 -12
- package/android/src/main/java/com/renderrichtext/spans/StrongSpan.kt +39 -39
- package/android/src/main/java/com/renderrichtext/spans/TaskListSpan.kt +143 -143
- package/android/src/main/java/com/renderrichtext/spans/TextSpan.kt +26 -26
- package/android/src/main/java/com/renderrichtext/spans/ThematicBreakSpan.kt +69 -69
- package/android/src/main/java/com/renderrichtext/spans/UnorderedListSpan.kt +96 -96
- package/android/src/main/java/com/renderrichtext/spoiler/SpoilerStubs.kt +46 -46
- package/android/src/main/java/com/renderrichtext/styles/BaseBlockStyle.kt +11 -11
- package/android/src/main/java/com/renderrichtext/styles/BlockquoteStyle.kt +83 -83
- package/android/src/main/java/com/renderrichtext/styles/CodeBlockStyle.kt +80 -80
- package/android/src/main/java/com/renderrichtext/styles/CodeStyle.kt +26 -26
- package/android/src/main/java/com/renderrichtext/styles/EmphasisStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/FactoidStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/HeadingStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/HighlightStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ImageStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/InlineImageStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/InlineMathStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/LinkPillContent.kt +36 -36
- package/android/src/main/java/com/renderrichtext/styles/LinkPillStyle.kt +44 -44
- package/android/src/main/java/com/renderrichtext/styles/LinkStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/LinkVariantEntry.kt +34 -34
- package/android/src/main/java/com/renderrichtext/styles/ListStyle.kt +65 -65
- package/android/src/main/java/com/renderrichtext/styles/MathStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/MentionStyle.kt +19 -19
- package/android/src/main/java/com/renderrichtext/styles/ParagraphStyle.kt +33 -33
- package/android/src/main/java/com/renderrichtext/styles/SpoilerStyle.kt +27 -27
- package/android/src/main/java/com/renderrichtext/styles/StrikethroughStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/StrongStyle.kt +21 -21
- package/android/src/main/java/com/renderrichtext/styles/StyleConfig.kt +411 -411
- package/android/src/main/java/com/renderrichtext/styles/StyleParser.kt +92 -92
- package/android/src/main/java/com/renderrichtext/styles/SubscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/SuperscriptStyle.kt +16 -16
- package/android/src/main/java/com/renderrichtext/styles/TableStyle.kt +75 -75
- package/android/src/main/java/com/renderrichtext/styles/TaskListStyle.kt +29 -29
- package/android/src/main/java/com/renderrichtext/styles/TextAlignment.kt +32 -32
- package/android/src/main/java/com/renderrichtext/styles/ThematicBreakStyle.kt +23 -23
- package/android/src/main/java/com/renderrichtext/styles/UnderlineStyle.kt +17 -17
- package/android/src/main/java/com/renderrichtext/styles/VideoStyle.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/BorderStyleUtils.kt +86 -86
- package/android/src/main/java/com/renderrichtext/utils/common/BreakStrategyUtils.kt +32 -32
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockHighlighter.kt +36 -36
- package/android/src/main/java/com/renderrichtext/utils/common/CodeBlockNode.kt +42 -42
- package/android/src/main/java/com/renderrichtext/utils/common/EllipsizeUtils.kt +27 -27
- package/android/src/main/java/com/renderrichtext/utils/common/EnrichedTiptapAncestorUtils.kt +10 -10
- package/android/src/main/java/com/renderrichtext/utils/common/FeatureFlags.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRecognitionProps.kt +31 -31
- package/android/src/main/java/com/renderrichtext/utils/common/LinkRegexConfig.kt +56 -56
- package/android/src/main/java/com/renderrichtext/utils/common/MotionPreferences.kt +18 -18
- package/android/src/main/java/com/renderrichtext/utils/common/ReadableMapExtensions.kt +28 -28
- package/android/src/main/java/com/renderrichtext/utils/common/layout/RTLUtils.kt +6 -6
- package/android/src/main/java/com/renderrichtext/utils/common/serialization/TiptapASTSerializer.kt +368 -368
- package/android/src/main/java/com/renderrichtext/utils/text/ImageCache.kt +88 -88
- package/android/src/main/java/com/renderrichtext/utils/text/ImageDownloader.kt +203 -203
- package/android/src/main/java/com/renderrichtext/utils/text/LocalImageLoader.kt +167 -167
- package/android/src/main/java/com/renderrichtext/utils/text/TailFadeInAnimator.kt +84 -84
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/HTMLGenerator.kt +1105 -1105
- package/android/src/main/java/com/renderrichtext/utils/text/conversion/TiptapExtractor.kt +423 -423
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/ParagraphUtils.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/SpannableExtensions.kt +9 -9
- package/android/src/main/java/com/renderrichtext/utils/text/extensions/TextPaintExtensions.kt +76 -76
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/CheckboxTouchHelper.kt +61 -61
- package/android/src/main/java/com/renderrichtext/utils/text/interaction/TaskListTapUtils.kt +286 -286
- package/android/src/main/java/com/renderrichtext/utils/text/span/ApplyLineHeight.kt +39 -39
- package/android/src/main/java/com/renderrichtext/utils/text/span/BlockSpacing.kt +142 -142
- package/android/src/main/java/com/renderrichtext/utils/text/span/SpanFlags.kt +43 -43
- package/android/src/main/java/com/renderrichtext/utils/text/span/WidthAwareSpans.kt +30 -30
- package/android/src/main/java/com/renderrichtext/utils/text/view/CodeBlockPressHost.kt +15 -15
- package/android/src/main/java/com/renderrichtext/utils/text/view/ImagePressHost.kt +19 -19
- package/android/src/main/java/com/renderrichtext/utils/text/view/SelectionActionMode.kt +235 -235
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextSelectionColors.kt +48 -48
- package/android/src/main/java/com/renderrichtext/utils/text/view/TextViewSetup.kt +119 -119
- package/android/src/main/java/com/renderrichtext/views/ContextMenuPopup.kt +217 -217
- package/android/src/main/java/com/renderrichtext/views/CopyGlyph.kt +101 -101
- package/android/src/main/java/com/renderrichtext/views/WrapGlyph.kt +40 -40
- package/android/src/main/jni/CMakeLists.txt +52 -52
- package/android/src/main/jni/react/renderer/components/RichTextSpec/ComponentDescriptors.h +30 -30
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextComponentDescriptor.h +29 -29
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.cpp +45 -45
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextMeasurementManager.h +21 -21
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.cpp +38 -38
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextShadowNode.h +53 -53
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.cpp +9 -9
- package/android/src/main/jni/react/renderer/components/RichTextSpec/TiptapTextState.h +24 -24
- package/android/src/main/jni/react/renderer/components/RichTextSpec/conversions.h +40 -40
- package/cpp/parser/TiptapParser.hpp +13 -13
- package/cpp/vendor/nlohmann/json.hpp +24765 -24765
- package/ios/EnrichedTiptapText.h +27 -27
- package/ios/attachments/ENRMImageAttachment.h +51 -51
- package/ios/attachments/ENRMImageAttachment.m +398 -398
- package/ios/attachments/ENRMLinkPillAttachment.h +47 -47
- package/ios/attachments/ENRMLinkPillAttachment.m +324 -324
- package/ios/attachments/ENRMLinkPillIconCache.h +28 -28
- package/ios/attachments/ENRMLinkPillIconCache.m +181 -181
- package/ios/attachments/ENRMLinkPillText.h +27 -27
- package/ios/attachments/ENRMLinkPillText.m +118 -118
- package/ios/attachments/ENRMMathInlineAttachment.h +7 -7
- package/ios/attachments/ENRMMathInlineAttachment.m +4 -4
- package/ios/attachments/ThematicBreakAttachment.h +15 -15
- package/ios/attachments/ThematicBreakAttachment.m +33 -33
- package/ios/internals/ENRMViewFreeMeasurement.h +208 -208
- package/ios/internals/EnrichedTiptapTextComponentDescriptor.h +19 -19
- package/ios/internals/EnrichedTiptapTextShadowNode.h +43 -43
- package/ios/internals/EnrichedTiptapTextShadowNode.mm +69 -69
- package/ios/internals/EnrichedTiptapTextState.h +24 -24
- package/ios/internals/MeasurementCache.h +308 -308
- package/ios/internals/ShadowMeasurementUtils.h +145 -145
- package/ios/parser/ENRMTextLinkAttributes.h +7 -7
- package/ios/parser/ENRMTiptapParser.h +33 -33
- package/ios/parser/ENRMTiptapParser.mm +73 -73
- package/ios/parser/TiptapASTNode.m +52 -52
- package/ios/renderer/AttributedRenderer.h +23 -23
- package/ios/renderer/AttributedRenderer.m +229 -229
- package/ios/renderer/BaseRenderer.h +33 -33
- package/ios/renderer/BaseRenderer.m +46 -46
- package/ios/renderer/BaselineShiftTextAttributes.h +10 -10
- package/ios/renderer/BaselineShiftTextAttributes.m +26 -26
- package/ios/renderer/BlankLineRenderer.h +4 -4
- package/ios/renderer/BlankLineRenderer.m +51 -51
- package/ios/renderer/BlockquoteRenderer.h +6 -6
- package/ios/renderer/BlockquoteRenderer.m +258 -258
- package/ios/renderer/CodeBlockRenderer.h +9 -9
- package/ios/renderer/CodeBlockRenderer.m +99 -99
- package/ios/renderer/CodeRenderer.h +9 -9
- package/ios/renderer/CodeRenderer.m +69 -69
- package/ios/renderer/ENRMBlockquoteTextRenderer.h +25 -25
- package/ios/renderer/ENRMBlockquoteTextRenderer.m +48 -48
- package/ios/renderer/EmphasisRenderer.h +5 -5
- package/ios/renderer/EmphasisRenderer.m +99 -99
- package/ios/renderer/HeadingRenderer.h +6 -6
- package/ios/renderer/HeadingRenderer.m +102 -102
- package/ios/renderer/HighlightRenderer.h +7 -7
- package/ios/renderer/HighlightRenderer.m +33 -33
- package/ios/renderer/LinkRenderer.h +6 -6
- package/ios/renderer/LinkRenderer.m +157 -157
- package/ios/renderer/ListItemRenderer.h +24 -24
- package/ios/renderer/ListItemRenderer.m +283 -283
- package/ios/renderer/ListRenderer.h +13 -13
- package/ios/renderer/ListRenderer.m +126 -126
- package/ios/renderer/MentionRenderer.h +9 -9
- package/ios/renderer/MentionRenderer.m +96 -96
- package/ios/renderer/NodeRenderer.h +8 -8
- package/ios/renderer/ParagraphRenderer.h +6 -6
- package/ios/renderer/ParagraphRenderer.m +85 -85
- package/ios/renderer/RenderContext.h +145 -145
- package/ios/renderer/RenderContext.m +402 -402
- package/ios/renderer/RendererFactory.h +12 -12
- package/ios/renderer/StrikethroughRenderer.h +5 -5
- package/ios/renderer/StrikethroughRenderer.m +30 -30
- package/ios/renderer/StrongRenderer.h +5 -5
- package/ios/renderer/StrongRenderer.m +87 -87
- package/ios/renderer/TextRenderer.h +6 -6
- package/ios/renderer/TextRenderer.m +18 -18
- package/ios/renderer/ThematicBreakRenderer.h +4 -4
- package/ios/renderer/ThematicBreakRenderer.m +41 -41
- package/ios/renderer/UnderlineRenderer.h +4 -4
- package/ios/renderer/UnderlineRenderer.m +41 -41
- package/ios/styles/ENRMFontSlot.h +12 -12
- package/ios/styles/ENRMFontSlot.m +24 -24
- package/ios/styles/StyleConfig.h +488 -488
- package/ios/styles/StyleConfig.mm +2820 -2820
- package/ios/utils/AccessibilityInfo.h +35 -35
- package/ios/utils/AccessibilityInfo.m +24 -24
- package/ios/utils/BlockquoteBorder.h +26 -26
- package/ios/utils/BlockquoteBorder.m +294 -294
- package/ios/utils/CodeBackground.h +19 -19
- package/ios/utils/CodeBackground.m +196 -196
- package/ios/utils/CodeBlockBackground.h +17 -17
- package/ios/utils/CodeBlockBackground.m +102 -102
- package/ios/utils/ContextMenuUtils.h +76 -76
- package/ios/utils/ContextMenuUtils.mm +75 -75
- package/ios/utils/ENRMAccessibilityLabels.h +40 -40
- package/ios/utils/ENRMAccessibilityLabels.m +5 -5
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -24
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -37
- package/ios/utils/ENRMAtomicSize.h +65 -65
- package/ios/utils/ENRMCodeBlockContent.h +37 -37
- package/ios/utils/ENRMCodeBlockContent.mm +89 -89
- package/ios/utils/ENRMFeatureFlags.h +25 -25
- package/ios/utils/ENRMImageDownloader.h +30 -30
- package/ios/utils/ENRMImageDownloader.m +168 -168
- package/ios/utils/ENRMLatexErrorCoordinator.h +27 -27
- package/ios/utils/ENRMLatexErrorCoordinator.mm +75 -75
- package/ios/utils/ENRMLatexErrorReporting.h +13 -13
- package/ios/utils/ENRMLinkContextMenus.h +93 -93
- package/ios/utils/ENRMLinkContextMenus.m +178 -178
- package/ios/utils/ENRMLinkRegexConfig.h +30 -30
- package/ios/utils/ENRMLinkRegexConfig.mm +104 -104
- package/ios/utils/ENRMLinkRegexProps.h +23 -23
- package/ios/utils/ENRMLocalImageLoader.h +35 -35
- package/ios/utils/ENRMLocalImageLoader.m +111 -111
- package/ios/utils/ENRMMenuAction.h +27 -27
- package/ios/utils/ENRMMenuAction.m +33 -33
- package/ios/utils/ENRMSpoilerOverlayManager.h +15 -15
- package/ios/utils/ENRMSpoilerOverlayManager.m +19 -19
- package/ios/utils/ENRMSpoilerTapUtils.h +6 -6
- package/ios/utils/ENRMSpoilerTapUtils.m +11 -11
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -16
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -161
- package/ios/utils/ENRMTextHitTest.h +23 -23
- package/ios/utils/ENRMTextHitTest.m +20 -20
- package/ios/utils/ENRMTextInteractionUtils.h +20 -20
- package/ios/utils/ENRMTextInteractionUtils.m +15 -15
- package/ios/utils/ENRMTextRenderer.h +38 -38
- package/ios/utils/ENRMTextRenderer.m +54 -54
- package/ios/utils/ENRMTextViewSetup.h +132 -132
- package/ios/utils/ENRMUIKit.h +429 -429
- package/ios/utils/EditMenuUtils.h +105 -105
- package/ios/utils/EditMenuUtils.m +143 -143
- package/ios/utils/FontScaleObserver.h +10 -10
- package/ios/utils/FontScaleObserver.m +55 -55
- package/ios/utils/FontUtils.h +31 -31
- package/ios/utils/FontUtils.m +63 -63
- package/ios/utils/HTMLGenerator.h +25 -25
- package/ios/utils/HTMLGenerator.m +1041 -1041
- package/ios/utils/HeightUpdateUtils.h +25 -25
- package/ios/utils/ImageRequestHeaderUtils.h +35 -35
- package/ios/utils/LastElementUtils.h +97 -97
- package/ios/utils/LinkContextMenuUtils.h +55 -55
- package/ios/utils/LinkPillContentUtils.h +46 -46
- package/ios/utils/ListMarkerDrawer.h +15 -15
- package/ios/utils/ListMarkerDrawer.m +239 -239
- package/ios/utils/MentionBackground.h +26 -26
- package/ios/utils/MentionBackground.m +86 -86
- package/ios/utils/ParagraphStyleUtils.h +87 -87
- package/ios/utils/ParagraphStyleUtils.m +484 -484
- package/ios/utils/PasteboardUtils.h +48 -48
- package/ios/utils/PasteboardUtils.m +166 -166
- package/ios/utils/RTFExportUtils.h +24 -24
- package/ios/utils/RTFExportUtils.m +299 -299
- package/ios/utils/SelectionColorUtils.h +14 -14
- package/ios/utils/StylePropsUtils.h +1340 -1340
- package/ios/utils/TaskListTapUtils.h +6 -6
- package/ios/utils/TaskListTapUtils.m +14 -14
- package/ios/utils/TextViewLayoutManager.h +14 -14
- package/ios/utils/TiptapAccessibilityElementBuilder.h +43 -43
- package/ios/utils/TiptapAccessibilityElementBuilder.m +432 -432
- package/ios/utils/TiptapExtractor.h +17 -17
- package/ios/utils/TiptapExtractor.m +367 -367
- package/ios/views/ENRMTiptapTextView.h +25 -25
- package/ios/views/ENRMTiptapTextView.m +247 -247
- package/package.json +65 -70
- package/react-native.config.js +10 -10
- package/src/admonitionDefaults.ts +58 -58
- package/src/darkModeTextStyle.ts +99 -99
- package/src/headingDefaults.ts +21 -21
- package/src/index.tsx +4 -4
- package/src/linkVariantUtils.ts +120 -120
- package/src/normalizeTiptapStyle.ts +397 -397
- package/src/rn-globals.d.ts +1 -1
- package/src/styleUtils.ts +107 -107
- package/src/types/TiptapStyle.ts +532 -532
- package/src/types/TiptapStyleInternal.ts +299 -299
- package/src/types/linkPill.ts +9 -9
- package/src/utils/isDev.ts +4 -4
|
@@ -1,167 +1,167 @@
|
|
|
1
|
-
package com.renderrichtext.utils.text
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.graphics.Bitmap
|
|
5
|
-
import android.net.Uri
|
|
6
|
-
import android.util.Base64
|
|
7
|
-
import android.util.Log
|
|
8
|
-
import java.io.FileNotFoundException
|
|
9
|
-
import java.io.InputStream
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Loads tiptap images from non-network sources (issue #377).
|
|
13
|
-
*
|
|
14
|
-
* React Native's asset system produces different URI shapes for the same
|
|
15
|
-
* `require('./img.png')` depending on environment, and none of them are plain
|
|
16
|
-
* file paths in a bundled app:
|
|
17
|
-
* - Metro dev server: `http://host:8081/assets/...` (handled by [ImageDownloader])
|
|
18
|
-
* - Release APK: a bare drawable resource name, e.g. `src_assets_logo`
|
|
19
|
-
* (RN's `AssetSourceResolver.resourceIdentifierWithoutScale`)
|
|
20
|
-
* - Sideloaded JS bundle: `file:///.../drawable-xhdpi/src_assets_logo.png`
|
|
21
|
-
* - expo-updates embedded assets: `file:///android_res/drawable/<name>.png`
|
|
22
|
-
* - expo-asset downloads: percent-encoded `file://` paths in the cache dir
|
|
23
|
-
*
|
|
24
|
-
* Resolution mirrors RN core: `ImageSource.computeUri` treats a scheme-less
|
|
25
|
-
* source as a resource name, and `ResourceDrawableIdHelper` normalizes names
|
|
26
|
-
* by lowercasing, replacing `-` with `_`, and accepting numeric resource ids. The
|
|
27
|
-
* `android_res`/`android_asset` and drawable/raw lookups follow expo-asset's
|
|
28
|
-
* `ResourceAsset.kt`. `content://`, `asset://`, `res://` and `data:` URIs are
|
|
29
|
-
* supported for parity with RN's Fresco pipeline. All decodes are downsampled
|
|
30
|
-
* to screen width like the network path.
|
|
31
|
-
*/
|
|
32
|
-
object LocalImageLoader {
|
|
33
|
-
private const val TAG = "LocalImageLoader"
|
|
34
|
-
private const val ASSET_PATH_PREFIX = "/android_asset/"
|
|
35
|
-
private const val RES_PATH_PREFIX = "/android_res/"
|
|
36
|
-
private const val BASE64_MARKER = "base64,"
|
|
37
|
-
|
|
38
|
-
fun load(
|
|
39
|
-
context: Context,
|
|
40
|
-
source: String,
|
|
41
|
-
maxDimension: Int? = null,
|
|
42
|
-
): Bitmap? =
|
|
43
|
-
try {
|
|
44
|
-
val uri = Uri.parse(source)
|
|
45
|
-
when (uri.scheme?.lowercase()) {
|
|
46
|
-
null -> {
|
|
47
|
-
if (source.startsWith('/')) {
|
|
48
|
-
ImageDownloader.decodeFileDownsampled(context, source, maxDimension)
|
|
49
|
-
} else {
|
|
50
|
-
decodeResourceByName(context, source, maxDimension)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
"file" -> {
|
|
55
|
-
loadFileUri(context, uri, maxDimension)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
"asset" -> {
|
|
59
|
-
decodeStream(context, maxDimension) { context.assets.open(schemelessPath(uri)) }
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
"content" -> {
|
|
63
|
-
decodeStream(context, maxDimension) {
|
|
64
|
-
context.contentResolver.openInputStream(uri) ?: throw FileNotFoundException(source)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
"res" -> {
|
|
69
|
-
decodeResourceByName(context, schemelessPath(uri), maxDimension)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
"data" -> {
|
|
73
|
-
decodeDataUri(context, source, maxDimension)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
else -> {
|
|
77
|
-
Log.w(TAG, "Unsupported image URI scheme: $source")
|
|
78
|
-
null
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
} catch (_: OutOfMemoryError) {
|
|
82
|
-
Log.e(TAG, "OOM loading local image: $source")
|
|
83
|
-
null
|
|
84
|
-
} catch (e: Exception) {
|
|
85
|
-
Log.w(TAG, "Failed to load local image: $source", e)
|
|
86
|
-
null
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private fun loadFileUri(
|
|
90
|
-
context: Context,
|
|
91
|
-
uri: Uri,
|
|
92
|
-
maxDimension: Int?,
|
|
93
|
-
): Bitmap? {
|
|
94
|
-
val path = uri.path ?: return null
|
|
95
|
-
return when {
|
|
96
|
-
path.startsWith(ASSET_PATH_PREFIX) -> {
|
|
97
|
-
decodeStream(context, maxDimension) { context.assets.open(path.removePrefix(ASSET_PATH_PREFIX)) }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
path.startsWith(RES_PATH_PREFIX) -> {
|
|
101
|
-
decodeAndroidRes(context, uri, maxDimension)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
else -> {
|
|
105
|
-
ImageDownloader.decodeFileDownsampled(context, path, maxDimension)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Resolves `file:///android_res/<dir>[-qualifier]/<file>[.<ext>]` by stripping
|
|
112
|
-
* density qualifiers and the file extension, then looking the resource up by name.
|
|
113
|
-
*/
|
|
114
|
-
private fun decodeAndroidRes(
|
|
115
|
-
context: Context,
|
|
116
|
-
uri: Uri,
|
|
117
|
-
maxDimension: Int?,
|
|
118
|
-
): Bitmap? {
|
|
119
|
-
val segments = uri.pathSegments
|
|
120
|
-
if (segments.size < 3) return null
|
|
121
|
-
val directory = segments[1].substringBefore('-')
|
|
122
|
-
val name = segments[2].substringBeforeLast('.')
|
|
123
|
-
val resId = context.resources.getIdentifier(name, directory, context.packageName)
|
|
124
|
-
if (resId == 0) {
|
|
125
|
-
Log.w(TAG, "No $directory resource named: $name")
|
|
126
|
-
return null
|
|
127
|
-
}
|
|
128
|
-
return decodeStream(context, maxDimension) { context.resources.openRawResource(resId) }
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
private fun decodeResourceByName(
|
|
132
|
-
context: Context,
|
|
133
|
-
name: String,
|
|
134
|
-
maxDimension: Int?,
|
|
135
|
-
): Bitmap? {
|
|
136
|
-
if (name.isEmpty()) return null
|
|
137
|
-
val normalized = name.lowercase().replace('-', '_')
|
|
138
|
-
val resId =
|
|
139
|
-
normalized.toIntOrNull()
|
|
140
|
-
?: context.resources.getIdentifier(normalized, "drawable", context.packageName).takeIf { it != 0 }
|
|
141
|
-
?: context.resources.getIdentifier(normalized, "raw", context.packageName)
|
|
142
|
-
if (resId == 0) {
|
|
143
|
-
Log.w(TAG, "No drawable or raw resource named: $normalized")
|
|
144
|
-
return null
|
|
145
|
-
}
|
|
146
|
-
return decodeStream(context, maxDimension) { context.resources.openRawResource(resId) }
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private fun decodeDataUri(
|
|
150
|
-
context: Context,
|
|
151
|
-
source: String,
|
|
152
|
-
maxDimension: Int?,
|
|
153
|
-
): Bitmap? {
|
|
154
|
-
val marker = source.indexOf(BASE64_MARKER)
|
|
155
|
-
if (marker == -1) return null
|
|
156
|
-
val bytes = Base64.decode(source.substring(marker + BASE64_MARKER.length), Base64.DEFAULT)
|
|
157
|
-
return ImageDownloader.decodeBytesDownsampled(context, bytes, maxDimension)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
private inline fun decodeStream(
|
|
161
|
-
context: Context,
|
|
162
|
-
maxDimension: Int?,
|
|
163
|
-
open: () -> InputStream,
|
|
164
|
-
): Bitmap? = open().use { ImageDownloader.decodeBytesDownsampled(context, it.readBytes(), maxDimension) }
|
|
165
|
-
|
|
166
|
-
private fun schemelessPath(uri: Uri): String = (uri.host.orEmpty() + uri.path.orEmpty()).trimStart('/')
|
|
167
|
-
}
|
|
1
|
+
package com.renderrichtext.utils.text
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.net.Uri
|
|
6
|
+
import android.util.Base64
|
|
7
|
+
import android.util.Log
|
|
8
|
+
import java.io.FileNotFoundException
|
|
9
|
+
import java.io.InputStream
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Loads tiptap images from non-network sources (issue #377).
|
|
13
|
+
*
|
|
14
|
+
* React Native's asset system produces different URI shapes for the same
|
|
15
|
+
* `require('./img.png')` depending on environment, and none of them are plain
|
|
16
|
+
* file paths in a bundled app:
|
|
17
|
+
* - Metro dev server: `http://host:8081/assets/...` (handled by [ImageDownloader])
|
|
18
|
+
* - Release APK: a bare drawable resource name, e.g. `src_assets_logo`
|
|
19
|
+
* (RN's `AssetSourceResolver.resourceIdentifierWithoutScale`)
|
|
20
|
+
* - Sideloaded JS bundle: `file:///.../drawable-xhdpi/src_assets_logo.png`
|
|
21
|
+
* - expo-updates embedded assets: `file:///android_res/drawable/<name>.png`
|
|
22
|
+
* - expo-asset downloads: percent-encoded `file://` paths in the cache dir
|
|
23
|
+
*
|
|
24
|
+
* Resolution mirrors RN core: `ImageSource.computeUri` treats a scheme-less
|
|
25
|
+
* source as a resource name, and `ResourceDrawableIdHelper` normalizes names
|
|
26
|
+
* by lowercasing, replacing `-` with `_`, and accepting numeric resource ids. The
|
|
27
|
+
* `android_res`/`android_asset` and drawable/raw lookups follow expo-asset's
|
|
28
|
+
* `ResourceAsset.kt`. `content://`, `asset://`, `res://` and `data:` URIs are
|
|
29
|
+
* supported for parity with RN's Fresco pipeline. All decodes are downsampled
|
|
30
|
+
* to screen width like the network path.
|
|
31
|
+
*/
|
|
32
|
+
object LocalImageLoader {
|
|
33
|
+
private const val TAG = "LocalImageLoader"
|
|
34
|
+
private const val ASSET_PATH_PREFIX = "/android_asset/"
|
|
35
|
+
private const val RES_PATH_PREFIX = "/android_res/"
|
|
36
|
+
private const val BASE64_MARKER = "base64,"
|
|
37
|
+
|
|
38
|
+
fun load(
|
|
39
|
+
context: Context,
|
|
40
|
+
source: String,
|
|
41
|
+
maxDimension: Int? = null,
|
|
42
|
+
): Bitmap? =
|
|
43
|
+
try {
|
|
44
|
+
val uri = Uri.parse(source)
|
|
45
|
+
when (uri.scheme?.lowercase()) {
|
|
46
|
+
null -> {
|
|
47
|
+
if (source.startsWith('/')) {
|
|
48
|
+
ImageDownloader.decodeFileDownsampled(context, source, maxDimension)
|
|
49
|
+
} else {
|
|
50
|
+
decodeResourceByName(context, source, maxDimension)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
"file" -> {
|
|
55
|
+
loadFileUri(context, uri, maxDimension)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
"asset" -> {
|
|
59
|
+
decodeStream(context, maxDimension) { context.assets.open(schemelessPath(uri)) }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
"content" -> {
|
|
63
|
+
decodeStream(context, maxDimension) {
|
|
64
|
+
context.contentResolver.openInputStream(uri) ?: throw FileNotFoundException(source)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
"res" -> {
|
|
69
|
+
decodeResourceByName(context, schemelessPath(uri), maxDimension)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
"data" -> {
|
|
73
|
+
decodeDataUri(context, source, maxDimension)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
else -> {
|
|
77
|
+
Log.w(TAG, "Unsupported image URI scheme: $source")
|
|
78
|
+
null
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch (_: OutOfMemoryError) {
|
|
82
|
+
Log.e(TAG, "OOM loading local image: $source")
|
|
83
|
+
null
|
|
84
|
+
} catch (e: Exception) {
|
|
85
|
+
Log.w(TAG, "Failed to load local image: $source", e)
|
|
86
|
+
null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private fun loadFileUri(
|
|
90
|
+
context: Context,
|
|
91
|
+
uri: Uri,
|
|
92
|
+
maxDimension: Int?,
|
|
93
|
+
): Bitmap? {
|
|
94
|
+
val path = uri.path ?: return null
|
|
95
|
+
return when {
|
|
96
|
+
path.startsWith(ASSET_PATH_PREFIX) -> {
|
|
97
|
+
decodeStream(context, maxDimension) { context.assets.open(path.removePrefix(ASSET_PATH_PREFIX)) }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
path.startsWith(RES_PATH_PREFIX) -> {
|
|
101
|
+
decodeAndroidRes(context, uri, maxDimension)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
else -> {
|
|
105
|
+
ImageDownloader.decodeFileDownsampled(context, path, maxDimension)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Resolves `file:///android_res/<dir>[-qualifier]/<file>[.<ext>]` by stripping
|
|
112
|
+
* density qualifiers and the file extension, then looking the resource up by name.
|
|
113
|
+
*/
|
|
114
|
+
private fun decodeAndroidRes(
|
|
115
|
+
context: Context,
|
|
116
|
+
uri: Uri,
|
|
117
|
+
maxDimension: Int?,
|
|
118
|
+
): Bitmap? {
|
|
119
|
+
val segments = uri.pathSegments
|
|
120
|
+
if (segments.size < 3) return null
|
|
121
|
+
val directory = segments[1].substringBefore('-')
|
|
122
|
+
val name = segments[2].substringBeforeLast('.')
|
|
123
|
+
val resId = context.resources.getIdentifier(name, directory, context.packageName)
|
|
124
|
+
if (resId == 0) {
|
|
125
|
+
Log.w(TAG, "No $directory resource named: $name")
|
|
126
|
+
return null
|
|
127
|
+
}
|
|
128
|
+
return decodeStream(context, maxDimension) { context.resources.openRawResource(resId) }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private fun decodeResourceByName(
|
|
132
|
+
context: Context,
|
|
133
|
+
name: String,
|
|
134
|
+
maxDimension: Int?,
|
|
135
|
+
): Bitmap? {
|
|
136
|
+
if (name.isEmpty()) return null
|
|
137
|
+
val normalized = name.lowercase().replace('-', '_')
|
|
138
|
+
val resId =
|
|
139
|
+
normalized.toIntOrNull()
|
|
140
|
+
?: context.resources.getIdentifier(normalized, "drawable", context.packageName).takeIf { it != 0 }
|
|
141
|
+
?: context.resources.getIdentifier(normalized, "raw", context.packageName)
|
|
142
|
+
if (resId == 0) {
|
|
143
|
+
Log.w(TAG, "No drawable or raw resource named: $normalized")
|
|
144
|
+
return null
|
|
145
|
+
}
|
|
146
|
+
return decodeStream(context, maxDimension) { context.resources.openRawResource(resId) }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private fun decodeDataUri(
|
|
150
|
+
context: Context,
|
|
151
|
+
source: String,
|
|
152
|
+
maxDimension: Int?,
|
|
153
|
+
): Bitmap? {
|
|
154
|
+
val marker = source.indexOf(BASE64_MARKER)
|
|
155
|
+
if (marker == -1) return null
|
|
156
|
+
val bytes = Base64.decode(source.substring(marker + BASE64_MARKER.length), Base64.DEFAULT)
|
|
157
|
+
return ImageDownloader.decodeBytesDownsampled(context, bytes, maxDimension)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private inline fun decodeStream(
|
|
161
|
+
context: Context,
|
|
162
|
+
maxDimension: Int?,
|
|
163
|
+
open: () -> InputStream,
|
|
164
|
+
): Bitmap? = open().use { ImageDownloader.decodeBytesDownsampled(context, it.readBytes(), maxDimension) }
|
|
165
|
+
|
|
166
|
+
private fun schemelessPath(uri: Uri): String = (uri.host.orEmpty() + uri.path.orEmpty()).trimStart('/')
|
|
167
|
+
}
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
package com.renderrichtext.utils.text
|
|
2
|
-
|
|
3
|
-
import android.animation.Animator
|
|
4
|
-
import android.animation.AnimatorListenerAdapter
|
|
5
|
-
import android.animation.ValueAnimator
|
|
6
|
-
import android.text.Spannable
|
|
7
|
-
import android.view.animation.LinearInterpolator
|
|
8
|
-
import android.widget.TextView
|
|
9
|
-
import com.renderrichtext.spans.FadeInSpan
|
|
10
|
-
import com.renderrichtext.utils.common.isReducedMotionEnabled
|
|
11
|
-
import java.lang.ref.WeakReference
|
|
12
|
-
|
|
13
|
-
class TailFadeInAnimator(
|
|
14
|
-
textView: TextView,
|
|
15
|
-
) {
|
|
16
|
-
private val viewRef = WeakReference(textView)
|
|
17
|
-
|
|
18
|
-
private val activeAnimations = mutableMapOf<FadeInSpan, ValueAnimator>()
|
|
19
|
-
|
|
20
|
-
fun animate(
|
|
21
|
-
tailStart: Int,
|
|
22
|
-
tailEnd: Int,
|
|
23
|
-
) {
|
|
24
|
-
if (tailEnd <= tailStart) return
|
|
25
|
-
|
|
26
|
-
val textView = viewRef.get() ?: return
|
|
27
|
-
val spannable = textView.text as? Spannable ?: return
|
|
28
|
-
|
|
29
|
-
if (isReducedMotionEnabled(textView.context)) return
|
|
30
|
-
|
|
31
|
-
val fadeSpan = FadeInSpan().apply { alpha = 0f }
|
|
32
|
-
spannable.setSpan(fadeSpan, tailStart, tailEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
33
|
-
|
|
34
|
-
val animator =
|
|
35
|
-
ValueAnimator.ofFloat(0f, 1f).apply {
|
|
36
|
-
duration = FADE_DURATION_MS
|
|
37
|
-
interpolator = LinearInterpolator()
|
|
38
|
-
|
|
39
|
-
addUpdateListener { anim ->
|
|
40
|
-
fadeSpan.alpha = anim.animatedValue as Float
|
|
41
|
-
val tv = viewRef.get() ?: return@addUpdateListener
|
|
42
|
-
val currentSpannable = tv.text as? Spannable ?: return@addUpdateListener
|
|
43
|
-
|
|
44
|
-
val end = minOf(tailEnd, currentSpannable.length)
|
|
45
|
-
if (end > tailStart) {
|
|
46
|
-
currentSpannable.setSpan(fadeSpan, tailStart, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
47
|
-
}
|
|
48
|
-
tv.invalidate()
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
addListener(
|
|
52
|
-
object : AnimatorListenerAdapter() {
|
|
53
|
-
override fun onAnimationEnd(animation: Animator) {
|
|
54
|
-
cleanup(fadeSpan)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
override fun onAnimationCancel(animation: Animator) {
|
|
58
|
-
cleanup(fadeSpan)
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
activeAnimations[fadeSpan] = animator
|
|
65
|
-
animator.start()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private fun cleanup(span: FadeInSpan) {
|
|
69
|
-
activeAnimations.remove(span)
|
|
70
|
-
val spannable = viewRef.get()?.text as? Spannable ?: return
|
|
71
|
-
span.alpha = 1f
|
|
72
|
-
spannable.removeSpan(span)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
fun cancelAll() {
|
|
76
|
-
val spans = activeAnimations.keys.toList()
|
|
77
|
-
spans.forEach { activeAnimations[it]?.cancel() }
|
|
78
|
-
activeAnimations.clear()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
companion object {
|
|
82
|
-
private const val FADE_DURATION_MS = 150L
|
|
83
|
-
}
|
|
84
|
-
}
|
|
1
|
+
package com.renderrichtext.utils.text
|
|
2
|
+
|
|
3
|
+
import android.animation.Animator
|
|
4
|
+
import android.animation.AnimatorListenerAdapter
|
|
5
|
+
import android.animation.ValueAnimator
|
|
6
|
+
import android.text.Spannable
|
|
7
|
+
import android.view.animation.LinearInterpolator
|
|
8
|
+
import android.widget.TextView
|
|
9
|
+
import com.renderrichtext.spans.FadeInSpan
|
|
10
|
+
import com.renderrichtext.utils.common.isReducedMotionEnabled
|
|
11
|
+
import java.lang.ref.WeakReference
|
|
12
|
+
|
|
13
|
+
class TailFadeInAnimator(
|
|
14
|
+
textView: TextView,
|
|
15
|
+
) {
|
|
16
|
+
private val viewRef = WeakReference(textView)
|
|
17
|
+
|
|
18
|
+
private val activeAnimations = mutableMapOf<FadeInSpan, ValueAnimator>()
|
|
19
|
+
|
|
20
|
+
fun animate(
|
|
21
|
+
tailStart: Int,
|
|
22
|
+
tailEnd: Int,
|
|
23
|
+
) {
|
|
24
|
+
if (tailEnd <= tailStart) return
|
|
25
|
+
|
|
26
|
+
val textView = viewRef.get() ?: return
|
|
27
|
+
val spannable = textView.text as? Spannable ?: return
|
|
28
|
+
|
|
29
|
+
if (isReducedMotionEnabled(textView.context)) return
|
|
30
|
+
|
|
31
|
+
val fadeSpan = FadeInSpan().apply { alpha = 0f }
|
|
32
|
+
spannable.setSpan(fadeSpan, tailStart, tailEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
33
|
+
|
|
34
|
+
val animator =
|
|
35
|
+
ValueAnimator.ofFloat(0f, 1f).apply {
|
|
36
|
+
duration = FADE_DURATION_MS
|
|
37
|
+
interpolator = LinearInterpolator()
|
|
38
|
+
|
|
39
|
+
addUpdateListener { anim ->
|
|
40
|
+
fadeSpan.alpha = anim.animatedValue as Float
|
|
41
|
+
val tv = viewRef.get() ?: return@addUpdateListener
|
|
42
|
+
val currentSpannable = tv.text as? Spannable ?: return@addUpdateListener
|
|
43
|
+
|
|
44
|
+
val end = minOf(tailEnd, currentSpannable.length)
|
|
45
|
+
if (end > tailStart) {
|
|
46
|
+
currentSpannable.setSpan(fadeSpan, tailStart, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
47
|
+
}
|
|
48
|
+
tv.invalidate()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
addListener(
|
|
52
|
+
object : AnimatorListenerAdapter() {
|
|
53
|
+
override fun onAnimationEnd(animation: Animator) {
|
|
54
|
+
cleanup(fadeSpan)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
override fun onAnimationCancel(animation: Animator) {
|
|
58
|
+
cleanup(fadeSpan)
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
activeAnimations[fadeSpan] = animator
|
|
65
|
+
animator.start()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private fun cleanup(span: FadeInSpan) {
|
|
69
|
+
activeAnimations.remove(span)
|
|
70
|
+
val spannable = viewRef.get()?.text as? Spannable ?: return
|
|
71
|
+
span.alpha = 1f
|
|
72
|
+
spannable.removeSpan(span)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fun cancelAll() {
|
|
76
|
+
val spans = activeAnimations.keys.toList()
|
|
77
|
+
spans.forEach { activeAnimations[it]?.cancel() }
|
|
78
|
+
activeAnimations.clear()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
companion object {
|
|
82
|
+
private const val FADE_DURATION_MS = 150L
|
|
83
|
+
}
|
|
84
|
+
}
|