react-native-enriched 0.2.1 → 0.4.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.
- package/README.md +21 -16
- package/android/build.gradle +77 -72
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +21 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +7 -0
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.cpp +276 -0
- package/android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec/EventEmitters.h +239 -0
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +10 -0
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +251 -0
- package/android/gradle.properties +5 -5
- package/android/lint.gradle +70 -0
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewPackage.kt → ReactNativeEnrichedPackage.kt} +4 -5
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/AsyncDrawable.kt +50 -15
- package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
- package/android/src/main/java/com/swmansion/enriched/common/EnrichedConstants.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/common/EnrichedStyle.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/{spans/utils → common}/ForceRedrawSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/common/MentionStyle.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/ResourceManager.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{utils → common/parser}/EnrichedParser.java +228 -160
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBlockQuoteSpan.kt +53 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedBoldSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedCheckboxListSpan.kt +91 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedCodeBlockSpan.kt +12 -14
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH1Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH2Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH3Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH4Span.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH5Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedH6Span.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedImageSpan.kt +68 -51
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedInlineCodeSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedLinkSpan.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedMentionSpan.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedOrderedListSpan.kt +21 -29
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedStrikeThroughSpan.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedUnderlineSpan.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedUnorderedListSpan.kt +13 -17
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedBlockSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedHeadingSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedParagraphSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedZeroWidthSpaceSpan.kt +2 -3
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputConnectionWrapper.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputSpannableFactory.kt +83 -0
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputView.kt → textinput/EnrichedTextInputView.kt} +322 -157
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewLayoutManager.kt → textinput/EnrichedTextInputViewLayoutManager.kt} +4 -2
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewManager.kt → textinput/EnrichedTextInputViewManager.kt} +182 -66
- package/android/src/main/java/com/swmansion/enriched/{MeasurementStore.kt → textinput/MeasurementStore.kt} +75 -25
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/MentionHandler.kt +22 -12
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeHtmlEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeSelectionEvent.kt +11 -10
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeStateEvent.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnChangeTextEvent.kt +30 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputBlurEvent.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputFocusEvent.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnInputKeyPressEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnLinkDetectedEvent.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionDetectedEvent.kt +11 -10
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionEvent.kt +10 -9
- package/android/src/main/java/com/swmansion/enriched/textinput/events/OnPasteImagesEvent.kt +47 -0
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnRequestHtmlResultEvent.kt +2 -3
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBlockQuoteSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputBoldSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCheckboxListSpan.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputCodeBlockSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH1Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH2Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH3Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH4Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH5Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputH6Span.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputImageSpan.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputInlineCodeSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputItalicSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputLinkSpan.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputMentionSpan.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputOrderedListSpan.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputStrikeThroughSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnderlineSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedInputUnorderedListSpan.kt +14 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/EnrichedSpans.kt +241 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/spans/interfaces/EnrichedInputSpan.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/HtmlStyle.kt +129 -57
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/InlineStyles.kt +30 -13
- package/android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt +263 -0
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParagraphStyles.kt +94 -34
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParametrizedStyles.kt +143 -67
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedEditableFactory.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSelection.kt +84 -54
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpanState.kt +304 -0
- package/android/src/main/java/com/swmansion/enriched/{utils/Utils.kt → textinput/utils/EnrichedSpannable.kt} +22 -31
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannableStringBuilder.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/RichContentReceiver.kt +127 -0
- package/android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt +106 -0
- package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedSpanWatcher.kt +56 -24
- package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedTextWatcher.kt +37 -14
- package/android/src/main/new_arch/CMakeLists.txt +7 -1
- package/android/src/main/new_arch/ReactNativeEnrichedSpec.cpp +11 -0
- package/android/src/main/new_arch/ReactNativeEnrichedSpec.h +15 -0
- package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputMeasurementManager.h +1 -1
- package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputShadowNode.h +2 -2
- package/android/src/main/new_arch/react/renderer/components/ReactNativeEnrichedSpec/conversions.h +46 -0
- package/ios/EnrichedTextInputView.h +2 -1
- package/ios/EnrichedTextInputView.mm +603 -60
- package/ios/config/InputConfig.h +28 -0
- package/ios/config/InputConfig.mm +237 -8
- package/ios/extensions/ImageExtension.h +35 -0
- package/ios/extensions/ImageExtension.mm +156 -0
- package/ios/{utils → extensions}/LayoutManagerExtension.mm +115 -95
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.cpp +276 -0
- package/ios/generated/ReactNativeEnrichedSpec/EventEmitters.h +239 -0
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +10 -0
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +251 -0
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/RCTComponentViewHelpers.h +95 -0
- package/ios/inputParser/InputParser.mm +218 -18
- package/ios/inputTextView/InputTextView.mm +118 -0
- package/ios/{attachments → interfaces}/ImageAttachment.h +1 -0
- package/ios/interfaces/ImageAttachment.mm +46 -0
- package/ios/interfaces/LinkRegexConfig.h +19 -0
- package/ios/interfaces/LinkRegexConfig.mm +37 -0
- package/ios/{utils → interfaces}/MentionStyleProps.mm +2 -2
- package/ios/{utils → interfaces}/StyleHeaders.h +22 -1
- package/ios/{utils → interfaces}/StyleTypeEnum.h +4 -0
- package/ios/internals/EnrichedTextInputViewState.cpp +6 -6
- package/ios/styles/BlockQuoteStyle.mm +5 -5
- package/ios/styles/BoldStyle.mm +21 -6
- package/ios/styles/CheckboxListStyle.mm +321 -0
- package/ios/styles/CodeBlockStyle.mm +5 -5
- package/ios/styles/H1Style.mm +3 -0
- package/ios/styles/H2Style.mm +3 -0
- package/ios/styles/H3Style.mm +3 -0
- package/ios/styles/H4Style.mm +20 -0
- package/ios/styles/H5Style.mm +20 -0
- package/ios/styles/H6Style.mm +20 -0
- package/ios/styles/HeadingStyleBase.mm +161 -72
- package/ios/styles/ImageStyle.mm +5 -5
- package/ios/styles/InlineCodeStyle.mm +30 -19
- package/ios/styles/ItalicStyle.mm +5 -5
- package/ios/styles/LinkStyle.mm +98 -40
- package/ios/styles/MentionStyle.mm +4 -4
- package/ios/styles/OrderedListStyle.mm +5 -5
- package/ios/styles/StrikethroughStyle.mm +5 -5
- package/ios/styles/UnderlineStyle.mm +5 -5
- package/ios/styles/UnorderedListStyle.mm +5 -5
- package/ios/utils/CheckboxHitTestUtils.h +10 -0
- package/ios/utils/CheckboxHitTestUtils.mm +123 -0
- package/ios/utils/ParagraphAttributesUtils.h +4 -0
- package/ios/utils/ParagraphAttributesUtils.mm +142 -45
- package/ios/utils/ParagraphsUtils.mm +4 -4
- package/ios/utils/TextBlockTapGestureRecognizer.h +17 -0
- package/ios/utils/TextBlockTapGestureRecognizer.mm +56 -0
- package/ios/utils/ZeroWidthSpaceUtils.mm +14 -3
- package/lib/module/EnrichedTextInput.js +57 -11
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +175 -18
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +18 -0
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
- package/lib/module/utils/nullthrows.js +9 -0
- package/lib/module/utils/nullthrows.js.map +1 -0
- package/lib/module/utils/regexParser.js +46 -0
- package/lib/module/utils/regexParser.js.map +1 -0
- package/lib/typescript/src/EnrichedTextInput.d.ts +20 -51
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/{EnrichedTextInputNativeComponent.d.ts → spec/EnrichedTextInputNativeComponent.d.ts} +154 -18
- package/lib/typescript/src/spec/EnrichedTextInputNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +58 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
- package/lib/typescript/src/utils/nullthrows.d.ts +2 -0
- package/lib/typescript/src/utils/nullthrows.d.ts.map +1 -0
- package/lib/typescript/src/utils/regexParser.d.ts +3 -0
- package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
- package/package.json +13 -9
- package/src/EnrichedTextInput.tsx +88 -63
- package/src/index.tsx +5 -1
- package/src/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +175 -18
- package/src/types.ts +59 -0
- package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +20 -5
- package/src/utils/nullthrows.ts +7 -0
- package/src/utils/regexParser.ts +56 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +0 -128
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +0 -102
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +0 -28
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +0 -30
- package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +0 -27
- package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +0 -27
- package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +0 -30
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +0 -44
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +0 -16
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +0 -23
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +0 -23
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +0 -23
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +0 -27
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +0 -15
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +0 -30
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +0 -42
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +0 -136
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +0 -14
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +0 -14
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +0 -4
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +0 -4
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +0 -4
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +0 -4
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +0 -8
- package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +0 -172
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +0 -204
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +0 -22
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +0 -26
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +0 -26
- package/ios/attachments/ImageAttachment.mm +0 -34
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +0 -128
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +0 -102
- package/lib/module/normalizeHtmlStyle.js.map +0 -1
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
- package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.cpp +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.h +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.cpp +0 -0
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.h +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputComponentDescriptor.h +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputMeasurementManager.cpp +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputShadowNode.cpp +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputState.cpp +0 -0
- /package/android/src/main/new_arch/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/EnrichedTextInputState.h +0 -0
- /package/ios/{utils → extensions}/ColorExtension.h +0 -0
- /package/ios/{utils → extensions}/ColorExtension.mm +0 -0
- /package/ios/{utils → extensions}/FontExtension.h +0 -0
- /package/ios/{utils → extensions}/FontExtension.mm +0 -0
- /package/ios/{utils → extensions}/LayoutManagerExtension.h +0 -0
- /package/ios/{utils → extensions}/StringExtension.h +0 -0
- /package/ios/{utils → extensions}/StringExtension.mm +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.cpp +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ShadowNodes.h +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.cpp +0 -0
- /package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/States.h +0 -0
- /package/ios/{utils → interfaces}/BaseStyleProtocol.h +0 -0
- /package/ios/{utils → interfaces}/ImageData.h +0 -0
- /package/ios/{utils → interfaces}/ImageData.mm +0 -0
- /package/ios/{utils → interfaces}/LinkData.h +0 -0
- /package/ios/{utils → interfaces}/LinkData.mm +0 -0
- /package/ios/{attachments → interfaces}/MediaAttachment.h +0 -0
- /package/ios/{attachments → interfaces}/MediaAttachment.mm +0 -0
- /package/ios/{utils → interfaces}/MentionParams.h +0 -0
- /package/ios/{utils → interfaces}/MentionParams.mm +0 -0
- /package/ios/{utils → interfaces}/MentionStyleProps.h +0 -0
- /package/ios/{utils → interfaces}/StylePair.h +0 -0
- /package/ios/{utils → interfaces}/StylePair.mm +0 -0
- /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
- /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
package/ios/config/InputConfig.h
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#pragma once
|
|
2
|
+
#import "LinkRegexConfig.h"
|
|
2
3
|
#import "MentionStyleProps.h"
|
|
3
4
|
#import "TextDecorationLineEnum.h"
|
|
4
5
|
#import <UIKit/UIKit.h>
|
|
@@ -29,6 +30,18 @@
|
|
|
29
30
|
- (void)setH3FontSize:(CGFloat)newValue;
|
|
30
31
|
- (BOOL)h3Bold;
|
|
31
32
|
- (void)setH3Bold:(BOOL)newValue;
|
|
33
|
+
- (CGFloat)h4FontSize;
|
|
34
|
+
- (void)setH4FontSize:(CGFloat)newValue;
|
|
35
|
+
- (BOOL)h4Bold;
|
|
36
|
+
- (void)setH4Bold:(BOOL)newValue;
|
|
37
|
+
- (CGFloat)h5FontSize;
|
|
38
|
+
- (void)setH5FontSize:(CGFloat)newValue;
|
|
39
|
+
- (BOOL)h5Bold;
|
|
40
|
+
- (void)setH5Bold:(BOOL)newValue;
|
|
41
|
+
- (CGFloat)h6FontSize;
|
|
42
|
+
- (void)setH6FontSize:(CGFloat)newValue;
|
|
43
|
+
- (BOOL)h6Bold;
|
|
44
|
+
- (void)setH6Bold:(BOOL)newValue;
|
|
32
45
|
- (UIColor *)blockquoteBorderColor;
|
|
33
46
|
- (void)setBlockquoteBorderColor:(UIColor *)newValue;
|
|
34
47
|
- (CGFloat)blockquoteBorderWidth;
|
|
@@ -70,4 +83,19 @@
|
|
|
70
83
|
- (void)setCodeBlockBgColor:(UIColor *)newValue;
|
|
71
84
|
- (CGFloat)codeBlockBorderRadius;
|
|
72
85
|
- (void)setCodeBlockBorderRadius:(CGFloat)newValue;
|
|
86
|
+
- (LinkRegexConfig *)linkRegexConfig;
|
|
87
|
+
- (void)setLinkRegexConfig:(LinkRegexConfig *)newValue;
|
|
88
|
+
- (NSRegularExpression *)parsedLinkRegex;
|
|
89
|
+
- (void)invalidateFonts;
|
|
90
|
+
- (NSNumber *)scaledPrimaryFontSize;
|
|
91
|
+
- (CGFloat)checkboxListBoxSize;
|
|
92
|
+
- (void)setCheckboxListBoxSize:(CGFloat)newValue;
|
|
93
|
+
- (CGFloat)checkboxListGapWidth;
|
|
94
|
+
- (void)setCheckboxListGapWidth:(CGFloat)newValue;
|
|
95
|
+
- (CGFloat)checkboxListMarginLeft;
|
|
96
|
+
- (void)setCheckboxListMarginLeft:(CGFloat)newValue;
|
|
97
|
+
- (UIColor *)checkboxListBoxColor;
|
|
98
|
+
- (void)setCheckboxListBoxColor:(UIColor *)newValue;
|
|
99
|
+
- (UIImage *)checkboxCheckedImage;
|
|
100
|
+
- (UIImage *)checkboxUncheckedImage;
|
|
73
101
|
@end
|
|
@@ -17,6 +17,12 @@
|
|
|
17
17
|
BOOL _h2Bold;
|
|
18
18
|
CGFloat _h3FontSize;
|
|
19
19
|
BOOL _h3Bold;
|
|
20
|
+
CGFloat _h4FontSize;
|
|
21
|
+
BOOL _h4Bold;
|
|
22
|
+
CGFloat _h5FontSize;
|
|
23
|
+
BOOL _h5Bold;
|
|
24
|
+
CGFloat _h6FontSize;
|
|
25
|
+
BOOL _h6Bold;
|
|
20
26
|
UIColor *_blockquoteBorderColor;
|
|
21
27
|
CGFloat _blockquoteBorderWidth;
|
|
22
28
|
CGFloat _blockquoteGapWidth;
|
|
@@ -39,8 +45,14 @@
|
|
|
39
45
|
UIColor *_codeBlockFgColor;
|
|
40
46
|
CGFloat _codeBlockBorderRadius;
|
|
41
47
|
UIColor *_codeBlockBgColor;
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
LinkRegexConfig *_linkRegexConfig;
|
|
49
|
+
NSRegularExpression *_parsedLinkRegex;
|
|
50
|
+
CGFloat _checkboxListBoxSize;
|
|
51
|
+
CGFloat _checkboxListGapWidth;
|
|
52
|
+
CGFloat _checkboxListMarginLeft;
|
|
53
|
+
UIColor *_checkboxListBoxColor;
|
|
54
|
+
UIImage *_checkboxCheckedImage;
|
|
55
|
+
UIImage *_checkboxUncheckedImage;
|
|
44
56
|
}
|
|
45
57
|
|
|
46
58
|
- (instancetype)init {
|
|
@@ -66,6 +78,12 @@
|
|
|
66
78
|
copy->_h2Bold = _h2Bold;
|
|
67
79
|
copy->_h3FontSize = _h3FontSize;
|
|
68
80
|
copy->_h3Bold = _h3Bold;
|
|
81
|
+
copy->_h4FontSize = _h4FontSize;
|
|
82
|
+
copy->_h4Bold = _h4Bold;
|
|
83
|
+
copy->_h5FontSize = _h5FontSize;
|
|
84
|
+
copy->_h5Bold = _h5Bold;
|
|
85
|
+
copy->_h6FontSize = _h6FontSize;
|
|
86
|
+
copy->_h6Bold = _h6Bold;
|
|
69
87
|
copy->_blockquoteBorderColor = [_blockquoteBorderColor copy];
|
|
70
88
|
copy->_blockquoteBorderWidth = _blockquoteBorderWidth;
|
|
71
89
|
copy->_blockquoteGapWidth = _blockquoteGapWidth;
|
|
@@ -87,6 +105,14 @@
|
|
|
87
105
|
copy->_codeBlockFgColor = [_codeBlockFgColor copy];
|
|
88
106
|
copy->_codeBlockBgColor = [_codeBlockBgColor copy];
|
|
89
107
|
copy->_codeBlockBorderRadius = _codeBlockBorderRadius;
|
|
108
|
+
copy->_linkRegexConfig = [_linkRegexConfig copy];
|
|
109
|
+
copy->_parsedLinkRegex = [_parsedLinkRegex copy];
|
|
110
|
+
copy->_checkboxListBoxSize = _checkboxListBoxSize;
|
|
111
|
+
copy->_checkboxListGapWidth = _checkboxListGapWidth;
|
|
112
|
+
copy->_checkboxListMarginLeft = _checkboxListMarginLeft;
|
|
113
|
+
copy->_checkboxListBoxColor = [_checkboxListBoxColor copy];
|
|
114
|
+
copy->_checkboxCheckedImage = _checkboxCheckedImage;
|
|
115
|
+
copy->_checkboxUncheckedImage = _checkboxUncheckedImage;
|
|
90
116
|
return copy;
|
|
91
117
|
}
|
|
92
118
|
|
|
@@ -146,7 +172,7 @@
|
|
|
146
172
|
|
|
147
173
|
_primaryFont = [RCTFont updateFont:nullptr
|
|
148
174
|
withFamily:[self primaryFontFamily]
|
|
149
|
-
size:[self
|
|
175
|
+
size:[self scaledPrimaryFontSize]
|
|
150
176
|
weight:newFontWeight
|
|
151
177
|
style:nullptr
|
|
152
178
|
variant:nullptr
|
|
@@ -159,7 +185,7 @@
|
|
|
159
185
|
if (_monospacedFontNeedsRecreation) {
|
|
160
186
|
_monospacedFontNeedsRecreation = NO;
|
|
161
187
|
_monospacedFont = [UIFont
|
|
162
|
-
monospacedSystemFontOfSize:[[self
|
|
188
|
+
monospacedSystemFontOfSize:[[self scaledPrimaryFontSize] floatValue]
|
|
163
189
|
weight:[[self primaryFontWeight] floatValue]];
|
|
164
190
|
}
|
|
165
191
|
return _monospacedFont;
|
|
@@ -175,7 +201,7 @@
|
|
|
175
201
|
}
|
|
176
202
|
|
|
177
203
|
- (CGFloat)h1FontSize {
|
|
178
|
-
return _h1FontSize;
|
|
204
|
+
return [[UIFontMetrics defaultMetrics] scaledValueForValue:_h1FontSize];
|
|
179
205
|
}
|
|
180
206
|
|
|
181
207
|
- (void)setH1FontSize:(CGFloat)newValue {
|
|
@@ -191,7 +217,7 @@
|
|
|
191
217
|
}
|
|
192
218
|
|
|
193
219
|
- (CGFloat)h2FontSize {
|
|
194
|
-
return _h2FontSize;
|
|
220
|
+
return [[UIFontMetrics defaultMetrics] scaledValueForValue:_h2FontSize];
|
|
195
221
|
}
|
|
196
222
|
|
|
197
223
|
- (void)setH2FontSize:(CGFloat)newValue {
|
|
@@ -207,7 +233,7 @@
|
|
|
207
233
|
}
|
|
208
234
|
|
|
209
235
|
- (CGFloat)h3FontSize {
|
|
210
|
-
return _h3FontSize;
|
|
236
|
+
return [[UIFontMetrics defaultMetrics] scaledValueForValue:_h3FontSize];
|
|
211
237
|
}
|
|
212
238
|
|
|
213
239
|
- (void)setH3FontSize:(CGFloat)newValue {
|
|
@@ -222,6 +248,54 @@
|
|
|
222
248
|
_h3Bold = newValue;
|
|
223
249
|
}
|
|
224
250
|
|
|
251
|
+
- (CGFloat)h4FontSize {
|
|
252
|
+
return [[UIFontMetrics defaultMetrics] scaledValueForValue:_h4FontSize];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
- (void)setH4FontSize:(CGFloat)newValue {
|
|
256
|
+
_h4FontSize = newValue;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
- (BOOL)h4Bold {
|
|
260
|
+
return _h4Bold;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
- (void)setH4Bold:(BOOL)newValue {
|
|
264
|
+
_h4Bold = newValue;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
- (CGFloat)h5FontSize {
|
|
268
|
+
return [[UIFontMetrics defaultMetrics] scaledValueForValue:_h5FontSize];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
- (void)setH5FontSize:(CGFloat)newValue {
|
|
272
|
+
_h5FontSize = newValue;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
- (BOOL)h5Bold {
|
|
276
|
+
return _h5Bold;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
- (void)setH5Bold:(BOOL)newValue {
|
|
280
|
+
_h5Bold = newValue;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
- (CGFloat)h6FontSize {
|
|
284
|
+
return [[UIFontMetrics defaultMetrics] scaledValueForValue:_h6FontSize];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
- (void)setH6FontSize:(CGFloat)newValue {
|
|
288
|
+
_h6FontSize = newValue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
- (BOOL)h6Bold {
|
|
292
|
+
return _h6Bold;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
- (void)setH6Bold:(BOOL)newValue {
|
|
296
|
+
_h6Bold = newValue;
|
|
297
|
+
}
|
|
298
|
+
|
|
225
299
|
- (UIColor *)blockquoteBorderColor {
|
|
226
300
|
return _blockquoteBorderColor;
|
|
227
301
|
}
|
|
@@ -318,7 +392,7 @@
|
|
|
318
392
|
|
|
319
393
|
_orderedListMarkerFont = [RCTFont updateFont:nullptr
|
|
320
394
|
withFamily:[self primaryFontFamily]
|
|
321
|
-
size:[self
|
|
395
|
+
size:[self scaledPrimaryFontSize]
|
|
322
396
|
weight:newFontWeight
|
|
323
397
|
style:nullptr
|
|
324
398
|
variant:nullptr
|
|
@@ -417,4 +491,159 @@
|
|
|
417
491
|
_codeBlockBorderRadius = newValue;
|
|
418
492
|
}
|
|
419
493
|
|
|
494
|
+
- (LinkRegexConfig *)linkRegexConfig {
|
|
495
|
+
return _linkRegexConfig;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
- (void)setLinkRegexConfig:(LinkRegexConfig *)newValue {
|
|
499
|
+
_linkRegexConfig = newValue;
|
|
500
|
+
|
|
501
|
+
// try initializing the native regular expression if it applies
|
|
502
|
+
if (_linkRegexConfig.isDefault || _linkRegexConfig.isDisabled) {
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
NSError *regexInitError;
|
|
507
|
+
NSRegularExpressionOptions options =
|
|
508
|
+
(_linkRegexConfig.caseInsensitive ? NSRegularExpressionCaseInsensitive
|
|
509
|
+
: 0) |
|
|
510
|
+
(_linkRegexConfig.dotAll ? NSRegularExpressionDotMatchesLineSeparators
|
|
511
|
+
: 0);
|
|
512
|
+
NSRegularExpression *userRegex =
|
|
513
|
+
[NSRegularExpression regularExpressionWithPattern:_linkRegexConfig.pattern
|
|
514
|
+
options:options
|
|
515
|
+
error:®exInitError];
|
|
516
|
+
|
|
517
|
+
if (regexInitError) {
|
|
518
|
+
RCTLogWarn(@"[EnrichedTextInput]: Couldn't parse the user-defined link "
|
|
519
|
+
@"regex, falling back to a default regex.");
|
|
520
|
+
_parsedLinkRegex = nullptr;
|
|
521
|
+
} else {
|
|
522
|
+
_parsedLinkRegex = userRegex;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
- (NSRegularExpression *)parsedLinkRegex {
|
|
527
|
+
return _parsedLinkRegex;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
- (void)invalidateFonts {
|
|
531
|
+
_primaryFontNeedsRecreation = YES;
|
|
532
|
+
_monospacedFontNeedsRecreation = YES;
|
|
533
|
+
_olMarkerFontNeedsRecreation = YES;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
- (NSNumber *)scaledPrimaryFontSize {
|
|
537
|
+
CGFloat scaledSize = [[UIFontMetrics defaultMetrics]
|
|
538
|
+
scaledValueForValue:[[self primaryFontSize] floatValue]];
|
|
539
|
+
return @(scaledSize);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
- (CGFloat)checkboxListBoxSize {
|
|
543
|
+
return _checkboxListBoxSize;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
- (void)setCheckboxListBoxSize:(CGFloat)newValue {
|
|
547
|
+
if (_checkboxListBoxSize != newValue) {
|
|
548
|
+
_checkboxListBoxSize = newValue;
|
|
549
|
+
// Invalidate checkbox images because box size changed
|
|
550
|
+
_checkboxCheckedImage = nil;
|
|
551
|
+
_checkboxUncheckedImage = nil;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
- (CGFloat)checkboxListGapWidth {
|
|
556
|
+
return _checkboxListGapWidth;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
- (void)setCheckboxListGapWidth:(CGFloat)newValue {
|
|
560
|
+
_checkboxListGapWidth = newValue;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
- (CGFloat)checkboxListMarginLeft {
|
|
564
|
+
return _checkboxListMarginLeft;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
- (void)setCheckboxListMarginLeft:(CGFloat)newValue {
|
|
568
|
+
_checkboxListMarginLeft = newValue;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
- (UIColor *)checkboxListBoxColor {
|
|
572
|
+
return _checkboxListBoxColor;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
- (void)setCheckboxListBoxColor:(UIColor *)newValue {
|
|
576
|
+
if (_checkboxListBoxColor != newValue) {
|
|
577
|
+
_checkboxListBoxColor = newValue;
|
|
578
|
+
// Invalidate checkbox images because color changed
|
|
579
|
+
_checkboxCheckedImage = nil;
|
|
580
|
+
_checkboxUncheckedImage = nil;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
- (UIImage *)checkboxCheckedImage {
|
|
585
|
+
if (!_checkboxCheckedImage) {
|
|
586
|
+
_checkboxCheckedImage = [self generateCheckboxImage:YES];
|
|
587
|
+
}
|
|
588
|
+
return _checkboxCheckedImage;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
- (UIImage *)checkboxUncheckedImage {
|
|
592
|
+
if (!_checkboxUncheckedImage) {
|
|
593
|
+
_checkboxUncheckedImage = [self generateCheckboxImage:NO];
|
|
594
|
+
}
|
|
595
|
+
return _checkboxUncheckedImage;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
- (UIImage *)generateCheckboxImage:(BOOL)isChecked {
|
|
599
|
+
CGFloat boxSize = self.checkboxListBoxSize;
|
|
600
|
+
UIColor *boxColor = self.checkboxListBoxColor ?: [UIColor blackColor];
|
|
601
|
+
|
|
602
|
+
UIGraphicsBeginImageContextWithOptions(CGSizeMake(boxSize, boxSize), NO, 0.0);
|
|
603
|
+
CGRect localRect = CGRectMake(0, 0, boxSize, boxSize);
|
|
604
|
+
CGFloat cornerRadius = boxSize * 0.15f;
|
|
605
|
+
CGFloat strokeWidth = boxSize * 0.1f;
|
|
606
|
+
CGRect insetRect =
|
|
607
|
+
CGRectInset(localRect, strokeWidth / 2.0, strokeWidth / 2.0);
|
|
608
|
+
|
|
609
|
+
// Draw Box
|
|
610
|
+
UIBezierPath *boxPath = [UIBezierPath bezierPathWithRoundedRect:insetRect
|
|
611
|
+
cornerRadius:cornerRadius];
|
|
612
|
+
[boxPath setLineWidth:strokeWidth];
|
|
613
|
+
|
|
614
|
+
if (isChecked) {
|
|
615
|
+
[[boxColor colorWithAlphaComponent:1.0] setFill];
|
|
616
|
+
[boxPath fill];
|
|
617
|
+
[[boxColor colorWithAlphaComponent:1.0] setStroke];
|
|
618
|
+
[boxPath stroke];
|
|
619
|
+
|
|
620
|
+
// Draw Checkmark
|
|
621
|
+
UIBezierPath *checkPath = [UIBezierPath bezierPath];
|
|
622
|
+
CGFloat startX = insetRect.origin.x + insetRect.size.width * 0.25;
|
|
623
|
+
CGFloat startY = insetRect.origin.y + insetRect.size.height * 0.5;
|
|
624
|
+
CGFloat midX = insetRect.origin.x + insetRect.size.width * 0.45;
|
|
625
|
+
CGFloat midY = insetRect.origin.y + insetRect.size.height * 0.65;
|
|
626
|
+
CGFloat endX = insetRect.origin.x + insetRect.size.width * 0.75;
|
|
627
|
+
CGFloat endY = insetRect.origin.y + insetRect.size.height * 0.35;
|
|
628
|
+
|
|
629
|
+
[checkPath moveToPoint:CGPointMake(startX, startY)];
|
|
630
|
+
[checkPath addLineToPoint:CGPointMake(midX, midY)];
|
|
631
|
+
[checkPath addLineToPoint:CGPointMake(endX, endY)];
|
|
632
|
+
|
|
633
|
+
[checkPath setLineWidth:strokeWidth * 1.5];
|
|
634
|
+
[[UIColor whiteColor] setStroke];
|
|
635
|
+
[checkPath setLineCapStyle:kCGLineCapRound];
|
|
636
|
+
[checkPath setLineJoinStyle:kCGLineJoinRound];
|
|
637
|
+
[checkPath stroke];
|
|
638
|
+
} else {
|
|
639
|
+
[[boxColor colorWithAlphaComponent:1.0] setStroke];
|
|
640
|
+
[boxPath stroke];
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
|
|
644
|
+
UIGraphicsEndImageContext();
|
|
645
|
+
|
|
646
|
+
return result;
|
|
647
|
+
}
|
|
648
|
+
|
|
420
649
|
@end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
UIImage (animatedGIF)
|
|
5
|
+
|
|
6
|
+
This category adds class methods to `UIImage` to create an animated
|
|
7
|
+
`UIImage` from an animated GIF.
|
|
8
|
+
*/
|
|
9
|
+
@interface UIImage (ImageExtension)
|
|
10
|
+
|
|
11
|
+
/*
|
|
12
|
+
UIImage *animation = [UIImage animatedImageWithAnimatedGIFData:theData];
|
|
13
|
+
|
|
14
|
+
I interpret `theData` as a GIF. I create an animated `UIImage` using the
|
|
15
|
+
source images in the GIF.
|
|
16
|
+
|
|
17
|
+
The GIF stores a separate duration for each frame, in units of centiseconds
|
|
18
|
+
(hundredths of a second). However, a `UIImage` only has a single, total
|
|
19
|
+
`duration` property, which is a floating-point number.
|
|
20
|
+
|
|
21
|
+
To handle this mismatch, I add each source image (from the GIF) to
|
|
22
|
+
`animation` a varying number of times to match the ratios between the frame
|
|
23
|
+
durations in the GIF.
|
|
24
|
+
|
|
25
|
+
For example, suppose the GIF contains three frames. Frame 0 has duration 3.
|
|
26
|
+
Frame 1 has duration 9. Frame 2 has duration 15. I divide each duration by
|
|
27
|
+
the greatest common denominator of all the durations, which is 3, and add
|
|
28
|
+
each frame the resulting number of times. Thus `animation` will contain
|
|
29
|
+
frame 0 3/3 = 1 time, then frame 1 9/3 = 3 times, then frame 2 15/3 = 5
|
|
30
|
+
times. I set `animation.duration` to (3+9+15)/100 = 0.27 seconds.
|
|
31
|
+
*/
|
|
32
|
+
+ (UIImage *_Nullable)animatedImageWithAnimatedGIFData:
|
|
33
|
+
(NSData *_Nonnull)theData;
|
|
34
|
+
|
|
35
|
+
@end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#import "ImageExtension.h"
|
|
2
|
+
#import <ImageIO/ImageIO.h>
|
|
3
|
+
#include <cmath>
|
|
4
|
+
#include <vector>
|
|
5
|
+
|
|
6
|
+
#if __has_feature(objc_arc)
|
|
7
|
+
#define toCF (__bridge CFTypeRef)
|
|
8
|
+
#define fromCF (__bridge id)
|
|
9
|
+
#else
|
|
10
|
+
#define toCF (CFTypeRef)
|
|
11
|
+
#define fromCF (id)
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
// implementation from:
|
|
15
|
+
// https://github.com/mayoff/uiimage-from-animated-gif/blob/master/uiimage-from-animated-gif/UIImage%2BanimatedGIF.m
|
|
16
|
+
@implementation UIImage (ImageExtension)
|
|
17
|
+
|
|
18
|
+
static int delayCentisecondsForImageAtIndex(CGImageSourceRef const source,
|
|
19
|
+
size_t const i) {
|
|
20
|
+
int delayCentiseconds = 1;
|
|
21
|
+
CFDictionaryRef const properties =
|
|
22
|
+
CGImageSourceCopyPropertiesAtIndex(source, i, NULL);
|
|
23
|
+
if (properties) {
|
|
24
|
+
CFDictionaryRef const gifProperties = (CFDictionaryRef)CFDictionaryGetValue(
|
|
25
|
+
properties, kCGImagePropertyGIFDictionary);
|
|
26
|
+
if (gifProperties) {
|
|
27
|
+
NSNumber *number = fromCF CFDictionaryGetValue(
|
|
28
|
+
gifProperties, kCGImagePropertyGIFUnclampedDelayTime);
|
|
29
|
+
if (number == NULL || [number doubleValue] == 0) {
|
|
30
|
+
number = fromCF CFDictionaryGetValue(gifProperties,
|
|
31
|
+
kCGImagePropertyGIFDelayTime);
|
|
32
|
+
}
|
|
33
|
+
if ([number doubleValue] > 0) {
|
|
34
|
+
// Even though the GIF stores the delay as an integer number of
|
|
35
|
+
// centiseconds, ImageIO “helpfully” converts that to seconds for us.
|
|
36
|
+
delayCentiseconds = (int)lrint([number doubleValue] * 100);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
CFRelease(properties);
|
|
40
|
+
}
|
|
41
|
+
return delayCentiseconds;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Changed to use std::vector references instead of C-arrays
|
|
45
|
+
static void createImagesAndDelays(CGImageSourceRef source, size_t count,
|
|
46
|
+
std::vector<CGImageRef> &imagesOut,
|
|
47
|
+
std::vector<int> &delayCentisecondsOut) {
|
|
48
|
+
for (size_t i = 0; i < count; ++i) {
|
|
49
|
+
imagesOut[i] = CGImageSourceCreateImageAtIndex(source, i, NULL);
|
|
50
|
+
delayCentisecondsOut[i] = delayCentisecondsForImageAtIndex(source, i);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static int sum(const std::vector<int> &values) {
|
|
55
|
+
int theSum = 0;
|
|
56
|
+
for (int value : values) {
|
|
57
|
+
theSum += value;
|
|
58
|
+
}
|
|
59
|
+
return theSum;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static int pairGCD(int a, int b) {
|
|
63
|
+
if (a < b)
|
|
64
|
+
return pairGCD(b, a);
|
|
65
|
+
while (true) {
|
|
66
|
+
int const r = a % b;
|
|
67
|
+
if (r == 0)
|
|
68
|
+
return b;
|
|
69
|
+
a = b;
|
|
70
|
+
b = r;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static int vectorGCD(const std::vector<int> &values) {
|
|
75
|
+
if (values.empty())
|
|
76
|
+
return 1;
|
|
77
|
+
|
|
78
|
+
int gcd = values[0];
|
|
79
|
+
for (size_t i = 1; i < values.size(); ++i) {
|
|
80
|
+
// Note that after I process the first few elements of the vector, `gcd`
|
|
81
|
+
// will probably be smaller than any remaining element. By passing the
|
|
82
|
+
// smaller value as the second argument to `pairGCD`, I avoid making it swap
|
|
83
|
+
// the arguments.
|
|
84
|
+
gcd = pairGCD(values[i], gcd);
|
|
85
|
+
}
|
|
86
|
+
return gcd;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static NSArray *frameArray(const std::vector<CGImageRef> &images,
|
|
90
|
+
const std::vector<int> &delayCentiseconds,
|
|
91
|
+
int const totalDurationCentiseconds) {
|
|
92
|
+
int const gcd = vectorGCD(delayCentiseconds);
|
|
93
|
+
size_t const frameCount = totalDurationCentiseconds / gcd;
|
|
94
|
+
|
|
95
|
+
// Replaced VLA with NSMutableArray for safety and OBJ-C++ compatibility
|
|
96
|
+
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:frameCount];
|
|
97
|
+
|
|
98
|
+
for (size_t i = 0; i < images.size(); ++i) {
|
|
99
|
+
UIImage *const frame = [UIImage imageWithCGImage:images[i]];
|
|
100
|
+
for (size_t j = delayCentiseconds[i] / gcd; j > 0; --j) {
|
|
101
|
+
[frames addObject:frame];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return frames;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
static void releaseImages(const std::vector<CGImageRef> &images) {
|
|
108
|
+
for (CGImageRef image : images) {
|
|
109
|
+
if (image)
|
|
110
|
+
CGImageRelease(image);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static UIImage *
|
|
115
|
+
animatedImageWithAnimatedGIFImageSource(CGImageSourceRef const source) {
|
|
116
|
+
size_t const count = CGImageSourceGetCount(source);
|
|
117
|
+
if (count == 0) {
|
|
118
|
+
return nil;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Replaced VLAs (variable length arrays) with std::vector
|
|
122
|
+
std::vector<CGImageRef> images(count);
|
|
123
|
+
std::vector<int> delayCentiseconds(count); // in centiseconds
|
|
124
|
+
|
|
125
|
+
createImagesAndDelays(source, count, images, delayCentiseconds);
|
|
126
|
+
|
|
127
|
+
int const totalDurationCentiseconds = sum(delayCentiseconds);
|
|
128
|
+
NSArray *const frames =
|
|
129
|
+
frameArray(images, delayCentiseconds, totalDurationCentiseconds);
|
|
130
|
+
|
|
131
|
+
UIImage *const animation = [UIImage
|
|
132
|
+
animatedImageWithImages:frames
|
|
133
|
+
duration:(NSTimeInterval)totalDurationCentiseconds /
|
|
134
|
+
100.0];
|
|
135
|
+
|
|
136
|
+
releaseImages(images);
|
|
137
|
+
return animation;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static UIImage *animatedImageWithAnimatedGIFReleasingImageSource(
|
|
141
|
+
CGImageSourceRef CF_RELEASES_ARGUMENT source) {
|
|
142
|
+
if (source) {
|
|
143
|
+
UIImage *const image = animatedImageWithAnimatedGIFImageSource(source);
|
|
144
|
+
CFRelease(source);
|
|
145
|
+
return image;
|
|
146
|
+
} else {
|
|
147
|
+
return nil;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
+ (UIImage *)animatedImageWithAnimatedGIFData:(NSData *)data {
|
|
152
|
+
return animatedImageWithAnimatedGIFReleasingImageSource(
|
|
153
|
+
CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@end
|