@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,42 +1,42 @@
|
|
|
1
|
-
package com.renderrichtext.spans
|
|
2
|
-
|
|
3
|
-
import android.graphics.Paint
|
|
4
|
-
import android.text.Spanned
|
|
5
|
-
import android.text.StaticLayout
|
|
6
|
-
import android.text.TextPaint
|
|
7
|
-
import android.text.style.LeadingMarginSpan
|
|
8
|
-
|
|
9
|
-
internal object InlineBackgroundGeometry {
|
|
10
|
-
/**
|
|
11
|
-
* Returns the x position of [index] relative to the line's left edge. The measuring layout keeps
|
|
12
|
-
* the line's spans, so a LeadingMarginSpan is already folded into getPrimaryHorizontal — only the
|
|
13
|
-
* early return, which builds no layout, adds [leadingMargin] itself.
|
|
14
|
-
*/
|
|
15
|
-
fun horizontalOffset(
|
|
16
|
-
text: CharSequence,
|
|
17
|
-
lineStart: Int,
|
|
18
|
-
lineEnd: Int,
|
|
19
|
-
index: Int,
|
|
20
|
-
paint: Paint,
|
|
21
|
-
leadingMargin: Int,
|
|
22
|
-
): Float {
|
|
23
|
-
if (index <= lineStart) return leadingMargin.toFloat()
|
|
24
|
-
val lineText = text.subSequence(lineStart, lineEnd)
|
|
25
|
-
val textPaint = paint as? TextPaint ?: TextPaint(paint)
|
|
26
|
-
val layout = StaticLayout.Builder.obtain(lineText, 0, lineText.length, textPaint, 10000).build()
|
|
27
|
-
return layout.getPrimaryHorizontal(index - lineStart)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
fun leadingMarginAt(
|
|
31
|
-
text: Spanned,
|
|
32
|
-
lineStart: Int,
|
|
33
|
-
): Int {
|
|
34
|
-
if (lineStart >= text.length) return 0
|
|
35
|
-
val spans = text.getSpans(lineStart, lineStart + 1, LeadingMarginSpan::class.java)
|
|
36
|
-
var margin = 0
|
|
37
|
-
for (span in spans) {
|
|
38
|
-
margin += span.getLeadingMargin(false)
|
|
39
|
-
}
|
|
40
|
-
return margin
|
|
41
|
-
}
|
|
42
|
-
}
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Paint
|
|
4
|
+
import android.text.Spanned
|
|
5
|
+
import android.text.StaticLayout
|
|
6
|
+
import android.text.TextPaint
|
|
7
|
+
import android.text.style.LeadingMarginSpan
|
|
8
|
+
|
|
9
|
+
internal object InlineBackgroundGeometry {
|
|
10
|
+
/**
|
|
11
|
+
* Returns the x position of [index] relative to the line's left edge. The measuring layout keeps
|
|
12
|
+
* the line's spans, so a LeadingMarginSpan is already folded into getPrimaryHorizontal — only the
|
|
13
|
+
* early return, which builds no layout, adds [leadingMargin] itself.
|
|
14
|
+
*/
|
|
15
|
+
fun horizontalOffset(
|
|
16
|
+
text: CharSequence,
|
|
17
|
+
lineStart: Int,
|
|
18
|
+
lineEnd: Int,
|
|
19
|
+
index: Int,
|
|
20
|
+
paint: Paint,
|
|
21
|
+
leadingMargin: Int,
|
|
22
|
+
): Float {
|
|
23
|
+
if (index <= lineStart) return leadingMargin.toFloat()
|
|
24
|
+
val lineText = text.subSequence(lineStart, lineEnd)
|
|
25
|
+
val textPaint = paint as? TextPaint ?: TextPaint(paint)
|
|
26
|
+
val layout = StaticLayout.Builder.obtain(lineText, 0, lineText.length, textPaint, 10000).build()
|
|
27
|
+
return layout.getPrimaryHorizontal(index - lineStart)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
fun leadingMarginAt(
|
|
31
|
+
text: Spanned,
|
|
32
|
+
lineStart: Int,
|
|
33
|
+
): Int {
|
|
34
|
+
if (lineStart >= text.length) return 0
|
|
35
|
+
val spans = text.getSpans(lineStart, lineStart + 1, LeadingMarginSpan::class.java)
|
|
36
|
+
var margin = 0
|
|
37
|
+
for (span in spans) {
|
|
38
|
+
margin += span.getLeadingMargin(false)
|
|
39
|
+
}
|
|
40
|
+
return margin
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
package com.renderrichtext.spans
|
|
2
|
-
|
|
3
|
-
import android.graphics.Paint
|
|
4
|
-
import kotlin.math.ceil
|
|
5
|
-
import kotlin.math.floor
|
|
6
|
-
import android.text.style.LineHeightSpan as AndroidLineHeightSpan
|
|
7
|
-
|
|
8
|
-
class LineHeightSpan(
|
|
9
|
-
height: Float,
|
|
10
|
-
) : AndroidLineHeightSpan {
|
|
11
|
-
private val lineHeight: Int = ceil(height.toDouble()).toInt()
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Distributes positive leading evenly above and below the line to reach
|
|
15
|
-
* lineHeight.
|
|
16
|
-
*
|
|
17
|
-
* When the line's natural content is already at least as tall as lineHeight
|
|
18
|
-
* (leading <= 0), we keep the natural metrics and return early. Forcing the
|
|
19
|
-
* smaller lineHeight by shrinking ascent/descent clips tall glyphs (e.g.
|
|
20
|
-
* stacked combining marks) and drags the whole line up (issue #643); letting
|
|
21
|
-
* the line grow to fit its content avoids that. Normally-sized lines have
|
|
22
|
-
* positive leading and are unaffected.
|
|
23
|
-
*/
|
|
24
|
-
override fun chooseHeight(
|
|
25
|
-
text: CharSequence?,
|
|
26
|
-
start: Int,
|
|
27
|
-
end: Int,
|
|
28
|
-
spanstartv: Int,
|
|
29
|
-
v: Int,
|
|
30
|
-
fm: Paint.FontMetricsInt?,
|
|
31
|
-
) {
|
|
32
|
-
if (fm == null) return
|
|
33
|
-
|
|
34
|
-
val leading = lineHeight - ((-fm.ascent) + fm.descent)
|
|
35
|
-
if (leading <= 0) return
|
|
36
|
-
fm.ascent -= ceil(leading / 2.0f).toInt()
|
|
37
|
-
fm.descent += floor(leading / 2.0f).toInt()
|
|
38
|
-
}
|
|
39
|
-
}
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Paint
|
|
4
|
+
import kotlin.math.ceil
|
|
5
|
+
import kotlin.math.floor
|
|
6
|
+
import android.text.style.LineHeightSpan as AndroidLineHeightSpan
|
|
7
|
+
|
|
8
|
+
class LineHeightSpan(
|
|
9
|
+
height: Float,
|
|
10
|
+
) : AndroidLineHeightSpan {
|
|
11
|
+
private val lineHeight: Int = ceil(height.toDouble()).toInt()
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Distributes positive leading evenly above and below the line to reach
|
|
15
|
+
* lineHeight.
|
|
16
|
+
*
|
|
17
|
+
* When the line's natural content is already at least as tall as lineHeight
|
|
18
|
+
* (leading <= 0), we keep the natural metrics and return early. Forcing the
|
|
19
|
+
* smaller lineHeight by shrinking ascent/descent clips tall glyphs (e.g.
|
|
20
|
+
* stacked combining marks) and drags the whole line up (issue #643); letting
|
|
21
|
+
* the line grow to fit its content avoids that. Normally-sized lines have
|
|
22
|
+
* positive leading and are unaffected.
|
|
23
|
+
*/
|
|
24
|
+
override fun chooseHeight(
|
|
25
|
+
text: CharSequence?,
|
|
26
|
+
start: Int,
|
|
27
|
+
end: Int,
|
|
28
|
+
spanstartv: Int,
|
|
29
|
+
v: Int,
|
|
30
|
+
fm: Paint.FontMetricsInt?,
|
|
31
|
+
) {
|
|
32
|
+
if (fm == null) return
|
|
33
|
+
|
|
34
|
+
val leading = lineHeight - ((-fm.ascent) + fm.descent)
|
|
35
|
+
if (leading <= 0) return
|
|
36
|
+
fm.ascent -= ceil(leading / 2.0f).toInt()
|
|
37
|
+
fm.descent += floor(leading / 2.0f).toInt()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1,154 +1,154 @@
|
|
|
1
|
-
package com.renderrichtext.spans
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import android.graphics.Bitmap
|
|
5
|
-
import android.net.Uri
|
|
6
|
-
import android.os.SystemClock
|
|
7
|
-
import android.util.LruCache
|
|
8
|
-
import androidx.annotation.VisibleForTesting
|
|
9
|
-
import androidx.core.graphics.scale
|
|
10
|
-
import com.renderrichtext.utils.text.ImageCache
|
|
11
|
-
import com.renderrichtext.utils.text.ImageDownloader
|
|
12
|
-
import com.renderrichtext.utils.text.LocalImageLoader
|
|
13
|
-
import java.io.File
|
|
14
|
-
import kotlin.math.max
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Original-color pill icon thumbnails, bounded by count and decoded bytes. Local
|
|
18
|
-
* sources decode synchronously through the library's local resolver; remote ones go
|
|
19
|
-
* through the shared image downloader and arrive later.
|
|
20
|
-
*/
|
|
21
|
-
internal object LinkPillIconCache {
|
|
22
|
-
// Icons are drawn at the label's font size, so they need few pixels. Local sources
|
|
23
|
-
// are sampled down by the decoder in powers of two; downloads are scaled once.
|
|
24
|
-
private const val LOCAL_MAX_DIMENSION = 512
|
|
25
|
-
private const val REMOTE_MAX_DIMENSION = 256
|
|
26
|
-
|
|
27
|
-
// Every render asks for the same icons again. A local source is trusted for this
|
|
28
|
-
// long before its file is stat'ed (or a failed decode retried); a failed download
|
|
29
|
-
// is not retried sooner than the remote window.
|
|
30
|
-
private const val LOCAL_REVALIDATE_MS = 1_000L
|
|
31
|
-
private const val REMOTE_RETRY_MS = 30_000L
|
|
32
|
-
|
|
33
|
-
private val images = ImageCache.bitmapLruCache(8 * 1024 * 1024, 64)
|
|
34
|
-
private val sources = LruCache<String, Source>(256)
|
|
35
|
-
|
|
36
|
-
private class Source(
|
|
37
|
-
val imageKey: String,
|
|
38
|
-
val checkedAt: Long,
|
|
39
|
-
val failed: Boolean,
|
|
40
|
-
val isFile: Boolean = false,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
/** Replaceable so unit tests never touch the network. */
|
|
44
|
-
@VisibleForTesting
|
|
45
|
-
internal var remoteLoader: (Context, String, Map<String, String>, (Bitmap?) -> Unit) -> Unit = ImageDownloader::download
|
|
46
|
-
|
|
47
|
-
@VisibleForTesting
|
|
48
|
-
internal var clock: () -> Long = SystemClock::uptimeMillis
|
|
49
|
-
|
|
50
|
-
fun isRemote(iconUri: String): Boolean =
|
|
51
|
-
iconUri.startsWith("http://", ignoreCase = true) || iconUri.startsWith("https://", ignoreCase = true)
|
|
52
|
-
|
|
53
|
-
/** Synchronously resolves a local icon; null for remote, empty and unreadable sources. */
|
|
54
|
-
@Synchronized
|
|
55
|
-
fun load(
|
|
56
|
-
context: Context,
|
|
57
|
-
iconUri: String,
|
|
58
|
-
): Bitmap? {
|
|
59
|
-
if (iconUri.isEmpty() || isRemote(iconUri)) return null
|
|
60
|
-
val key = localKey(context, iconUri)
|
|
61
|
-
val now = clock()
|
|
62
|
-
val known = sources.get(key)
|
|
63
|
-
// File-backed and failed sources are re-checked once the window passes.
|
|
64
|
-
if (known != null && ((!known.isFile && !known.failed) || now - known.checkedAt < LOCAL_REVALIDATE_MS)) {
|
|
65
|
-
if (known.failed) return null
|
|
66
|
-
images.get(known.imageKey)?.let { return it }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Only a real file can change underneath its URI; asset, resource, content and
|
|
70
|
-
// data sources keep one entry.
|
|
71
|
-
val file = localFile(iconUri)?.takeIf { it.isFile }
|
|
72
|
-
val imageKey = if (file != null) "$key|${file.lastModified()}|${file.length()}" else key
|
|
73
|
-
val bitmap =
|
|
74
|
-
images.get(imageKey)
|
|
75
|
-
?: runCatching { LocalImageLoader.load(context, iconUri, maxDimension = LOCAL_MAX_DIMENSION) }
|
|
76
|
-
.getOrNull()
|
|
77
|
-
?.also { images.put(imageKey, it) }
|
|
78
|
-
sources.put(key, Source(imageKey, now, failed = bitmap == null, isFile = file != null))
|
|
79
|
-
return bitmap
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
fun hasFailedRecently(
|
|
83
|
-
iconUri: String,
|
|
84
|
-
headers: Map<String, String>,
|
|
85
|
-
): Boolean =
|
|
86
|
-
synchronized(this) {
|
|
87
|
-
val known = sources.get(remoteKey(iconUri, headers))
|
|
88
|
-
known != null && known.failed && clock() - known.checkedAt < REMOTE_RETRY_MS
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
private fun remoteKey(
|
|
92
|
-
iconUri: String,
|
|
93
|
-
headers: Map<String, String>,
|
|
94
|
-
) = "remote|" + ImageCache.requestKey(iconUri, headers)
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Returns the cached remote icon, or null after starting a download that reports
|
|
98
|
-
* through [onLoaded] on the main thread, with null when the download fails. [onLoaded]
|
|
99
|
-
* can also run before this returns when the downloader already holds the image.
|
|
100
|
-
*/
|
|
101
|
-
fun loadRemote(
|
|
102
|
-
context: Context,
|
|
103
|
-
iconUri: String,
|
|
104
|
-
headers: Map<String, String>,
|
|
105
|
-
onLoaded: (Bitmap?) -> Unit,
|
|
106
|
-
): Bitmap? {
|
|
107
|
-
val key = remoteKey(iconUri, headers)
|
|
108
|
-
synchronized(this) {
|
|
109
|
-
images.get(key)?.let { return it }
|
|
110
|
-
val known = sources.get(key)
|
|
111
|
-
if (known != null && known.failed && clock() - known.checkedAt < REMOTE_RETRY_MS) return null
|
|
112
|
-
}
|
|
113
|
-
remoteLoader(context, iconUri, headers) { downloaded ->
|
|
114
|
-
val icon =
|
|
115
|
-
synchronized(this) {
|
|
116
|
-
// Every pill waiting for this download gets the same thumbnail.
|
|
117
|
-
val shared = images.get(key) ?: downloaded?.let { thumbnail(it) }?.also { images.put(key, it) }
|
|
118
|
-
sources.put(key, Source(key, clock(), failed = shared == null))
|
|
119
|
-
shared
|
|
120
|
-
}
|
|
121
|
-
onLoaded(icon)
|
|
122
|
-
}
|
|
123
|
-
return null
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private fun thumbnail(bitmap: Bitmap): Bitmap {
|
|
127
|
-
val longest = max(bitmap.width, bitmap.height)
|
|
128
|
-
if (longest <= REMOTE_MAX_DIMENSION) return bitmap
|
|
129
|
-
val ratio = REMOTE_MAX_DIMENSION.toFloat() / longest
|
|
130
|
-
return bitmap.scale((bitmap.width * ratio).toInt().coerceAtLeast(1), (bitmap.height * ratio).toInt().coerceAtLeast(1))
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Data URIs can be large: key them by a cheap fingerprint instead of retaining
|
|
134
|
-
// (or digesting) the whole payload on every render.
|
|
135
|
-
private fun localKey(
|
|
136
|
-
context: Context,
|
|
137
|
-
iconUri: String,
|
|
138
|
-
): String {
|
|
139
|
-
val source =
|
|
140
|
-
if (iconUri.startsWith("data:", ignoreCase = true)) {
|
|
141
|
-
"data|${iconUri.length}|${iconUri.hashCode()}|${iconUri.takeLast(32)}"
|
|
142
|
-
} else {
|
|
143
|
-
iconUri
|
|
144
|
-
}
|
|
145
|
-
return "${context.packageName}|$source"
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private fun localFile(iconUri: String): File? =
|
|
149
|
-
when {
|
|
150
|
-
iconUri.startsWith('/') -> File(iconUri)
|
|
151
|
-
iconUri.startsWith("file:", ignoreCase = true) -> Uri.parse(iconUri).path?.let { File(it) }
|
|
152
|
-
else -> null
|
|
153
|
-
}
|
|
154
|
-
}
|
|
1
|
+
package com.renderrichtext.spans
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.net.Uri
|
|
6
|
+
import android.os.SystemClock
|
|
7
|
+
import android.util.LruCache
|
|
8
|
+
import androidx.annotation.VisibleForTesting
|
|
9
|
+
import androidx.core.graphics.scale
|
|
10
|
+
import com.renderrichtext.utils.text.ImageCache
|
|
11
|
+
import com.renderrichtext.utils.text.ImageDownloader
|
|
12
|
+
import com.renderrichtext.utils.text.LocalImageLoader
|
|
13
|
+
import java.io.File
|
|
14
|
+
import kotlin.math.max
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Original-color pill icon thumbnails, bounded by count and decoded bytes. Local
|
|
18
|
+
* sources decode synchronously through the library's local resolver; remote ones go
|
|
19
|
+
* through the shared image downloader and arrive later.
|
|
20
|
+
*/
|
|
21
|
+
internal object LinkPillIconCache {
|
|
22
|
+
// Icons are drawn at the label's font size, so they need few pixels. Local sources
|
|
23
|
+
// are sampled down by the decoder in powers of two; downloads are scaled once.
|
|
24
|
+
private const val LOCAL_MAX_DIMENSION = 512
|
|
25
|
+
private const val REMOTE_MAX_DIMENSION = 256
|
|
26
|
+
|
|
27
|
+
// Every render asks for the same icons again. A local source is trusted for this
|
|
28
|
+
// long before its file is stat'ed (or a failed decode retried); a failed download
|
|
29
|
+
// is not retried sooner than the remote window.
|
|
30
|
+
private const val LOCAL_REVALIDATE_MS = 1_000L
|
|
31
|
+
private const val REMOTE_RETRY_MS = 30_000L
|
|
32
|
+
|
|
33
|
+
private val images = ImageCache.bitmapLruCache(8 * 1024 * 1024, 64)
|
|
34
|
+
private val sources = LruCache<String, Source>(256)
|
|
35
|
+
|
|
36
|
+
private class Source(
|
|
37
|
+
val imageKey: String,
|
|
38
|
+
val checkedAt: Long,
|
|
39
|
+
val failed: Boolean,
|
|
40
|
+
val isFile: Boolean = false,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
/** Replaceable so unit tests never touch the network. */
|
|
44
|
+
@VisibleForTesting
|
|
45
|
+
internal var remoteLoader: (Context, String, Map<String, String>, (Bitmap?) -> Unit) -> Unit = ImageDownloader::download
|
|
46
|
+
|
|
47
|
+
@VisibleForTesting
|
|
48
|
+
internal var clock: () -> Long = SystemClock::uptimeMillis
|
|
49
|
+
|
|
50
|
+
fun isRemote(iconUri: String): Boolean =
|
|
51
|
+
iconUri.startsWith("http://", ignoreCase = true) || iconUri.startsWith("https://", ignoreCase = true)
|
|
52
|
+
|
|
53
|
+
/** Synchronously resolves a local icon; null for remote, empty and unreadable sources. */
|
|
54
|
+
@Synchronized
|
|
55
|
+
fun load(
|
|
56
|
+
context: Context,
|
|
57
|
+
iconUri: String,
|
|
58
|
+
): Bitmap? {
|
|
59
|
+
if (iconUri.isEmpty() || isRemote(iconUri)) return null
|
|
60
|
+
val key = localKey(context, iconUri)
|
|
61
|
+
val now = clock()
|
|
62
|
+
val known = sources.get(key)
|
|
63
|
+
// File-backed and failed sources are re-checked once the window passes.
|
|
64
|
+
if (known != null && ((!known.isFile && !known.failed) || now - known.checkedAt < LOCAL_REVALIDATE_MS)) {
|
|
65
|
+
if (known.failed) return null
|
|
66
|
+
images.get(known.imageKey)?.let { return it }
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Only a real file can change underneath its URI; asset, resource, content and
|
|
70
|
+
// data sources keep one entry.
|
|
71
|
+
val file = localFile(iconUri)?.takeIf { it.isFile }
|
|
72
|
+
val imageKey = if (file != null) "$key|${file.lastModified()}|${file.length()}" else key
|
|
73
|
+
val bitmap =
|
|
74
|
+
images.get(imageKey)
|
|
75
|
+
?: runCatching { LocalImageLoader.load(context, iconUri, maxDimension = LOCAL_MAX_DIMENSION) }
|
|
76
|
+
.getOrNull()
|
|
77
|
+
?.also { images.put(imageKey, it) }
|
|
78
|
+
sources.put(key, Source(imageKey, now, failed = bitmap == null, isFile = file != null))
|
|
79
|
+
return bitmap
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
fun hasFailedRecently(
|
|
83
|
+
iconUri: String,
|
|
84
|
+
headers: Map<String, String>,
|
|
85
|
+
): Boolean =
|
|
86
|
+
synchronized(this) {
|
|
87
|
+
val known = sources.get(remoteKey(iconUri, headers))
|
|
88
|
+
known != null && known.failed && clock() - known.checkedAt < REMOTE_RETRY_MS
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private fun remoteKey(
|
|
92
|
+
iconUri: String,
|
|
93
|
+
headers: Map<String, String>,
|
|
94
|
+
) = "remote|" + ImageCache.requestKey(iconUri, headers)
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Returns the cached remote icon, or null after starting a download that reports
|
|
98
|
+
* through [onLoaded] on the main thread, with null when the download fails. [onLoaded]
|
|
99
|
+
* can also run before this returns when the downloader already holds the image.
|
|
100
|
+
*/
|
|
101
|
+
fun loadRemote(
|
|
102
|
+
context: Context,
|
|
103
|
+
iconUri: String,
|
|
104
|
+
headers: Map<String, String>,
|
|
105
|
+
onLoaded: (Bitmap?) -> Unit,
|
|
106
|
+
): Bitmap? {
|
|
107
|
+
val key = remoteKey(iconUri, headers)
|
|
108
|
+
synchronized(this) {
|
|
109
|
+
images.get(key)?.let { return it }
|
|
110
|
+
val known = sources.get(key)
|
|
111
|
+
if (known != null && known.failed && clock() - known.checkedAt < REMOTE_RETRY_MS) return null
|
|
112
|
+
}
|
|
113
|
+
remoteLoader(context, iconUri, headers) { downloaded ->
|
|
114
|
+
val icon =
|
|
115
|
+
synchronized(this) {
|
|
116
|
+
// Every pill waiting for this download gets the same thumbnail.
|
|
117
|
+
val shared = images.get(key) ?: downloaded?.let { thumbnail(it) }?.also { images.put(key, it) }
|
|
118
|
+
sources.put(key, Source(key, clock(), failed = shared == null))
|
|
119
|
+
shared
|
|
120
|
+
}
|
|
121
|
+
onLoaded(icon)
|
|
122
|
+
}
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
private fun thumbnail(bitmap: Bitmap): Bitmap {
|
|
127
|
+
val longest = max(bitmap.width, bitmap.height)
|
|
128
|
+
if (longest <= REMOTE_MAX_DIMENSION) return bitmap
|
|
129
|
+
val ratio = REMOTE_MAX_DIMENSION.toFloat() / longest
|
|
130
|
+
return bitmap.scale((bitmap.width * ratio).toInt().coerceAtLeast(1), (bitmap.height * ratio).toInt().coerceAtLeast(1))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Data URIs can be large: key them by a cheap fingerprint instead of retaining
|
|
134
|
+
// (or digesting) the whole payload on every render.
|
|
135
|
+
private fun localKey(
|
|
136
|
+
context: Context,
|
|
137
|
+
iconUri: String,
|
|
138
|
+
): String {
|
|
139
|
+
val source =
|
|
140
|
+
if (iconUri.startsWith("data:", ignoreCase = true)) {
|
|
141
|
+
"data|${iconUri.length}|${iconUri.hashCode()}|${iconUri.takeLast(32)}"
|
|
142
|
+
} else {
|
|
143
|
+
iconUri
|
|
144
|
+
}
|
|
145
|
+
return "${context.packageName}|$source"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private fun localFile(iconUri: String): File? =
|
|
149
|
+
when {
|
|
150
|
+
iconUri.startsWith('/') -> File(iconUri)
|
|
151
|
+
iconUri.startsWith("file:", ignoreCase = true) -> Uri.parse(iconUri).path?.let { File(it) }
|
|
152
|
+
else -> null
|
|
153
|
+
}
|
|
154
|
+
}
|