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
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#import "EnrichedTextInputView.h"
|
|
2
2
|
#import "CoreText/CoreText.h"
|
|
3
|
+
#import "ImageAttachment.h"
|
|
3
4
|
#import "LayoutManagerExtension.h"
|
|
4
5
|
#import "ParagraphAttributesUtils.h"
|
|
5
6
|
#import "RCTFabricComponentsPlugins.h"
|
|
6
7
|
#import "StringExtension.h"
|
|
7
8
|
#import "StyleHeaders.h"
|
|
9
|
+
#import "TextBlockTapGestureRecognizer.h"
|
|
8
10
|
#import "UIView+React.h"
|
|
9
11
|
#import "WordsUtils.h"
|
|
10
12
|
#import "ZeroWidthSpaceUtils.h"
|
|
@@ -16,10 +18,18 @@
|
|
|
16
18
|
#import <folly/dynamic.h>
|
|
17
19
|
#import <react/utils/ManagedObjectWrapper.h>
|
|
18
20
|
|
|
21
|
+
#define GET_STYLE_STATE(TYPE_ENUM) \
|
|
22
|
+
{ \
|
|
23
|
+
.isActive = [self isStyleActive:TYPE_ENUM], \
|
|
24
|
+
.isBlocking = [self isStyle:TYPE_ENUM activeInMap:blockingStyles], \
|
|
25
|
+
.isConflicting = [self isStyle:TYPE_ENUM activeInMap:conflictingStyles] \
|
|
26
|
+
}
|
|
27
|
+
|
|
19
28
|
using namespace facebook::react;
|
|
20
29
|
|
|
21
30
|
@interface EnrichedTextInputView () <RCTEnrichedTextInputViewViewProtocol,
|
|
22
|
-
UITextViewDelegate,
|
|
31
|
+
UITextViewDelegate,
|
|
32
|
+
UIGestureRecognizerDelegate, NSObject>
|
|
23
33
|
|
|
24
34
|
@end
|
|
25
35
|
|
|
@@ -27,6 +37,7 @@ using namespace facebook::react;
|
|
|
27
37
|
EnrichedTextInputViewShadowNode::ConcreteState::Shared _state;
|
|
28
38
|
int _componentViewHeightUpdateCounter;
|
|
29
39
|
NSMutableSet<NSNumber *> *_activeStyles;
|
|
40
|
+
NSMutableSet<NSNumber *> *_blockedStyles;
|
|
30
41
|
LinkData *_recentlyActiveLinkData;
|
|
31
42
|
NSRange _recentlyActiveLinkRange;
|
|
32
43
|
NSString *_recentInputString;
|
|
@@ -37,6 +48,8 @@ using namespace facebook::react;
|
|
|
37
48
|
UILabel *_placeholderLabel;
|
|
38
49
|
UIColor *_placeholderColor;
|
|
39
50
|
BOOL _emitFocusBlur;
|
|
51
|
+
BOOL _emitTextChange;
|
|
52
|
+
NSMutableDictionary<NSValue *, UIImageView *> *_attachmentViews;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
55
|
// MARK: - Component utils
|
|
@@ -72,6 +85,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
72
85
|
- (void)setDefaults {
|
|
73
86
|
_componentViewHeightUpdateCounter = 0;
|
|
74
87
|
_activeStyles = [[NSMutableSet alloc] init];
|
|
88
|
+
_blockedStyles = [[NSMutableSet alloc] init];
|
|
75
89
|
_recentlyActiveLinkRange = NSMakeRange(0, 0);
|
|
76
90
|
_recentlyActiveMentionRange = NSMakeRange(0, 0);
|
|
77
91
|
recentlyChangedRange = NSMakeRange(0, 0);
|
|
@@ -80,6 +94,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
80
94
|
_emitHtml = NO;
|
|
81
95
|
blockEmitting = NO;
|
|
82
96
|
_emitFocusBlur = YES;
|
|
97
|
+
_emitTextChange = NO;
|
|
83
98
|
|
|
84
99
|
defaultTypingAttributes =
|
|
85
100
|
[[NSMutableDictionary<NSAttributedStringKey, id> alloc] init];
|
|
@@ -98,10 +113,15 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
98
113
|
@([H1Style getStyleType]) : [[H1Style alloc] initWithInput:self],
|
|
99
114
|
@([H2Style getStyleType]) : [[H2Style alloc] initWithInput:self],
|
|
100
115
|
@([H3Style getStyleType]) : [[H3Style alloc] initWithInput:self],
|
|
116
|
+
@([H4Style getStyleType]) : [[H4Style alloc] initWithInput:self],
|
|
117
|
+
@([H5Style getStyleType]) : [[H5Style alloc] initWithInput:self],
|
|
118
|
+
@([H6Style getStyleType]) : [[H6Style alloc] initWithInput:self],
|
|
101
119
|
@([UnorderedListStyle getStyleType]) :
|
|
102
120
|
[[UnorderedListStyle alloc] initWithInput:self],
|
|
103
121
|
@([OrderedListStyle getStyleType]) :
|
|
104
122
|
[[OrderedListStyle alloc] initWithInput:self],
|
|
123
|
+
@([CheckboxListStyle getStyleType]) :
|
|
124
|
+
[[CheckboxListStyle alloc] initWithInput:self],
|
|
105
125
|
@([BlockQuoteStyle getStyleType]) :
|
|
106
126
|
[[BlockQuoteStyle alloc] initWithInput:self],
|
|
107
127
|
@([CodeBlockStyle getStyleType]) :
|
|
@@ -124,48 +144,90 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
124
144
|
@[ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]) ],
|
|
125
145
|
@([H1Style getStyleType]) : @[
|
|
126
146
|
@([H2Style getStyleType]), @([H3Style getStyleType]),
|
|
127
|
-
@([
|
|
128
|
-
@([
|
|
147
|
+
@([H4Style getStyleType]), @([H5Style getStyleType]),
|
|
148
|
+
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
|
|
149
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
150
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
129
151
|
],
|
|
130
152
|
@([H2Style getStyleType]) : @[
|
|
131
153
|
@([H1Style getStyleType]), @([H3Style getStyleType]),
|
|
132
|
-
@([
|
|
133
|
-
@([
|
|
154
|
+
@([H4Style getStyleType]), @([H5Style getStyleType]),
|
|
155
|
+
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
|
|
156
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
157
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
134
158
|
],
|
|
135
159
|
@([H3Style getStyleType]) : @[
|
|
136
160
|
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
137
|
-
@([
|
|
138
|
-
@([
|
|
161
|
+
@([H4Style getStyleType]), @([H5Style getStyleType]),
|
|
162
|
+
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
|
|
163
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
164
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
165
|
+
],
|
|
166
|
+
@([H4Style getStyleType]) : @[
|
|
167
|
+
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
168
|
+
@([H3Style getStyleType]), @([H5Style getStyleType]),
|
|
169
|
+
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
|
|
170
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
171
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
172
|
+
],
|
|
173
|
+
@([H5Style getStyleType]) : @[
|
|
174
|
+
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
175
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
176
|
+
@([H6Style getStyleType]), @([UnorderedListStyle getStyleType]),
|
|
177
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
178
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
179
|
+
],
|
|
180
|
+
@([H6Style getStyleType]) : @[
|
|
181
|
+
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
182
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
183
|
+
@([H5Style getStyleType]), @([UnorderedListStyle getStyleType]),
|
|
184
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
185
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
139
186
|
],
|
|
140
187
|
@([UnorderedListStyle getStyleType]) : @[
|
|
141
188
|
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
142
|
-
@([H3Style getStyleType]), @([
|
|
143
|
-
@([
|
|
189
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
190
|
+
@([H5Style getStyleType]), @([H6Style getStyleType]),
|
|
191
|
+
@([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
192
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
144
193
|
],
|
|
145
194
|
@([OrderedListStyle getStyleType]) : @[
|
|
146
195
|
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
147
|
-
@([H3Style getStyleType]), @([
|
|
196
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
197
|
+
@([H5Style getStyleType]), @([H6Style getStyleType]),
|
|
198
|
+
@([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]),
|
|
199
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
200
|
+
],
|
|
201
|
+
@([CheckboxListStyle getStyleType]) : @[
|
|
202
|
+
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
203
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
204
|
+
@([H5Style getStyleType]), @([H6Style getStyleType]),
|
|
205
|
+
@([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
|
|
148
206
|
@([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
|
|
149
207
|
],
|
|
150
208
|
@([BlockQuoteStyle getStyleType]) : @[
|
|
151
209
|
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
152
|
-
@([H3Style getStyleType]), @([
|
|
153
|
-
@([
|
|
210
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
211
|
+
@([H5Style getStyleType]), @([H6Style getStyleType]),
|
|
212
|
+
@([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
|
|
213
|
+
@([CodeBlockStyle getStyleType]), @([CheckboxListStyle getStyleType])
|
|
154
214
|
],
|
|
155
215
|
@([CodeBlockStyle getStyleType]) : @[
|
|
156
216
|
@([H1Style getStyleType]), @([H2Style getStyleType]),
|
|
157
|
-
@([H3Style getStyleType]), @([
|
|
158
|
-
@([
|
|
159
|
-
@([
|
|
217
|
+
@([H3Style getStyleType]), @([H4Style getStyleType]),
|
|
218
|
+
@([H5Style getStyleType]), @([H6Style getStyleType]),
|
|
219
|
+
@([BoldStyle getStyleType]), @([ItalicStyle getStyleType]),
|
|
220
|
+
@([UnderlineStyle getStyleType]), @([StrikethroughStyle getStyleType]),
|
|
160
221
|
@([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
|
|
161
222
|
@([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]),
|
|
162
|
-
@([MentionStyle getStyleType]), @([LinkStyle getStyleType])
|
|
223
|
+
@([MentionStyle getStyleType]), @([LinkStyle getStyleType]),
|
|
224
|
+
@([CheckboxListStyle getStyleType])
|
|
163
225
|
],
|
|
164
226
|
@([ImageStyle getStyleType]) :
|
|
165
227
|
@[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ]
|
|
166
228
|
};
|
|
167
229
|
|
|
168
|
-
blockingStyles = @{
|
|
230
|
+
blockingStyles = [@{
|
|
169
231
|
@([BoldStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
|
|
170
232
|
@([ItalicStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
|
|
171
233
|
@([UnderlineStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
|
|
@@ -180,14 +242,19 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
180
242
|
@([H1Style getStyleType]) : @[],
|
|
181
243
|
@([H2Style getStyleType]) : @[],
|
|
182
244
|
@([H3Style getStyleType]) : @[],
|
|
245
|
+
@([H4Style getStyleType]) : @[],
|
|
246
|
+
@([H5Style getStyleType]) : @[],
|
|
247
|
+
@([H6Style getStyleType]) : @[],
|
|
183
248
|
@([UnorderedListStyle getStyleType]) : @[],
|
|
184
249
|
@([OrderedListStyle getStyleType]) : @[],
|
|
250
|
+
@([CheckboxListStyle getStyleType]) : @[],
|
|
185
251
|
@([BlockQuoteStyle getStyleType]) : @[],
|
|
186
252
|
@([CodeBlockStyle getStyleType]) : @[],
|
|
187
253
|
@([ImageStyle getStyleType]) : @[ @([InlineCodeStyle getStyleType]) ]
|
|
188
|
-
};
|
|
254
|
+
} mutableCopy];
|
|
189
255
|
|
|
190
256
|
parser = [[InputParser alloc] initWithInput:self];
|
|
257
|
+
_attachmentViews = [[NSMutableDictionary alloc] init];
|
|
191
258
|
}
|
|
192
259
|
|
|
193
260
|
- (void)setupTextView {
|
|
@@ -198,6 +265,10 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
198
265
|
textView.delegate = self;
|
|
199
266
|
textView.input = self;
|
|
200
267
|
textView.layoutManager.input = self;
|
|
268
|
+
textView.adjustsFontForContentSizeCategory = YES;
|
|
269
|
+
[textView addGestureRecognizer:[[TextBlockTapGestureRecognizer alloc]
|
|
270
|
+
initWithInput:self
|
|
271
|
+
action:@selector(onTextBlockTap:)]];
|
|
201
272
|
}
|
|
202
273
|
|
|
203
274
|
- (void)setupPlaceholderLabel {
|
|
@@ -216,6 +287,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
216
287
|
_placeholderLabel.lineBreakMode = NSLineBreakByTruncatingTail;
|
|
217
288
|
_placeholderLabel.text = @"";
|
|
218
289
|
_placeholderLabel.hidden = YES;
|
|
290
|
+
_placeholderLabel.adjustsFontForContentSizeCategory = YES;
|
|
219
291
|
}
|
|
220
292
|
|
|
221
293
|
// MARK: - Props
|
|
@@ -292,6 +364,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
292
364
|
|
|
293
365
|
if (newViewProps.htmlStyle.h1.bold != oldViewProps.htmlStyle.h1.bold) {
|
|
294
366
|
[newConfig setH1Bold:newViewProps.htmlStyle.h1.bold];
|
|
367
|
+
|
|
368
|
+
// Update style blocks for bold
|
|
369
|
+
newViewProps.htmlStyle.h1.bold ? [self addStyleBlock:H1 to:Bold]
|
|
370
|
+
: [self removeStyleBlock:H1 from:Bold];
|
|
371
|
+
|
|
295
372
|
stylePropChanged = YES;
|
|
296
373
|
}
|
|
297
374
|
|
|
@@ -303,6 +380,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
303
380
|
|
|
304
381
|
if (newViewProps.htmlStyle.h2.bold != oldViewProps.htmlStyle.h2.bold) {
|
|
305
382
|
[newConfig setH2Bold:newViewProps.htmlStyle.h2.bold];
|
|
383
|
+
|
|
384
|
+
// Update style blocks for bold
|
|
385
|
+
newViewProps.htmlStyle.h2.bold ? [self addStyleBlock:H2 to:Bold]
|
|
386
|
+
: [self removeStyleBlock:H2 from:Bold];
|
|
387
|
+
|
|
306
388
|
stylePropChanged = YES;
|
|
307
389
|
}
|
|
308
390
|
|
|
@@ -314,6 +396,59 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
314
396
|
|
|
315
397
|
if (newViewProps.htmlStyle.h3.bold != oldViewProps.htmlStyle.h3.bold) {
|
|
316
398
|
[newConfig setH3Bold:newViewProps.htmlStyle.h3.bold];
|
|
399
|
+
|
|
400
|
+
// Update style blocks for bold
|
|
401
|
+
newViewProps.htmlStyle.h3.bold ? [self addStyleBlock:H3 to:Bold]
|
|
402
|
+
: [self removeStyleBlock:H3 from:Bold];
|
|
403
|
+
|
|
404
|
+
stylePropChanged = YES;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (newViewProps.htmlStyle.h4.fontSize !=
|
|
408
|
+
oldViewProps.htmlStyle.h4.fontSize) {
|
|
409
|
+
[newConfig setH4FontSize:newViewProps.htmlStyle.h4.fontSize];
|
|
410
|
+
stylePropChanged = YES;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (newViewProps.htmlStyle.h4.bold != oldViewProps.htmlStyle.h4.bold) {
|
|
414
|
+
[newConfig setH4Bold:newViewProps.htmlStyle.h4.bold];
|
|
415
|
+
|
|
416
|
+
// Update style blocks for bold
|
|
417
|
+
newViewProps.htmlStyle.h4.bold ? [self addStyleBlock:H4 to:Bold]
|
|
418
|
+
: [self removeStyleBlock:H4 from:Bold];
|
|
419
|
+
|
|
420
|
+
stylePropChanged = YES;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
if (newViewProps.htmlStyle.h5.fontSize !=
|
|
424
|
+
oldViewProps.htmlStyle.h5.fontSize) {
|
|
425
|
+
[newConfig setH5FontSize:newViewProps.htmlStyle.h5.fontSize];
|
|
426
|
+
stylePropChanged = YES;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (newViewProps.htmlStyle.h5.bold != oldViewProps.htmlStyle.h5.bold) {
|
|
430
|
+
[newConfig setH5Bold:newViewProps.htmlStyle.h5.bold];
|
|
431
|
+
|
|
432
|
+
// Update style blocks for bold
|
|
433
|
+
newViewProps.htmlStyle.h5.bold ? [self addStyleBlock:H5 to:Bold]
|
|
434
|
+
: [self removeStyleBlock:H5 from:Bold];
|
|
435
|
+
|
|
436
|
+
stylePropChanged = YES;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (newViewProps.htmlStyle.h6.fontSize !=
|
|
440
|
+
oldViewProps.htmlStyle.h6.fontSize) {
|
|
441
|
+
[newConfig setH6FontSize:newViewProps.htmlStyle.h6.fontSize];
|
|
442
|
+
stylePropChanged = YES;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (newViewProps.htmlStyle.h6.bold != oldViewProps.htmlStyle.h6.bold) {
|
|
446
|
+
[newConfig setH6Bold:newViewProps.htmlStyle.h6.bold];
|
|
447
|
+
|
|
448
|
+
// Update style blocks for bold
|
|
449
|
+
newViewProps.htmlStyle.h6.bold ? [self addStyleBlock:H6 to:Bold]
|
|
450
|
+
: [self removeStyleBlock:H6 from:Bold];
|
|
451
|
+
|
|
317
452
|
stylePropChanged = YES;
|
|
318
453
|
}
|
|
319
454
|
|
|
@@ -480,6 +615,37 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
480
615
|
stylePropChanged = YES;
|
|
481
616
|
}
|
|
482
617
|
|
|
618
|
+
if (newViewProps.htmlStyle.ulCheckbox.boxSize !=
|
|
619
|
+
oldViewProps.htmlStyle.ulCheckbox.boxSize) {
|
|
620
|
+
[newConfig
|
|
621
|
+
setCheckboxListBoxSize:newViewProps.htmlStyle.ulCheckbox.boxSize];
|
|
622
|
+
stylePropChanged = YES;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
if (newViewProps.htmlStyle.ulCheckbox.gapWidth !=
|
|
626
|
+
oldViewProps.htmlStyle.ulCheckbox.gapWidth) {
|
|
627
|
+
[newConfig
|
|
628
|
+
setCheckboxListGapWidth:newViewProps.htmlStyle.ulCheckbox.gapWidth];
|
|
629
|
+
stylePropChanged = YES;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (newViewProps.htmlStyle.ulCheckbox.marginLeft !=
|
|
633
|
+
oldViewProps.htmlStyle.ulCheckbox.marginLeft) {
|
|
634
|
+
[newConfig
|
|
635
|
+
setCheckboxListMarginLeft:newViewProps.htmlStyle.ulCheckbox.marginLeft];
|
|
636
|
+
stylePropChanged = YES;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
if (newViewProps.htmlStyle.ulCheckbox.boxColor !=
|
|
640
|
+
oldViewProps.htmlStyle.ulCheckbox.boxColor) {
|
|
641
|
+
if (isColorMeaningful(newViewProps.htmlStyle.ulCheckbox.boxColor)) {
|
|
642
|
+
[newConfig setCheckboxListBoxColor:RCTUIColorFromSharedColor(
|
|
643
|
+
newViewProps.htmlStyle.ulCheckbox
|
|
644
|
+
.boxColor)];
|
|
645
|
+
stylePropChanged = YES;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
483
649
|
if (newViewProps.htmlStyle.a.textDecorationLine !=
|
|
484
650
|
oldViewProps.htmlStyle.a.textDecorationLine) {
|
|
485
651
|
NSString *objcString =
|
|
@@ -539,6 +705,8 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
539
705
|
NSString *currentHtml = [parser
|
|
540
706
|
parseToHtmlFromRange:NSMakeRange(0,
|
|
541
707
|
textView.textStorage.string.length)];
|
|
708
|
+
// we want to preserve the selection between props changes
|
|
709
|
+
NSRange prevSelectedRange = textView.selectedRange;
|
|
542
710
|
|
|
543
711
|
// now set the new config
|
|
544
712
|
config = newConfig;
|
|
@@ -566,6 +734,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
566
734
|
defaultTypingAttributes[NSParagraphStyleAttributeName] =
|
|
567
735
|
[[NSParagraphStyle alloc] init];
|
|
568
736
|
textView.typingAttributes = defaultTypingAttributes;
|
|
737
|
+
textView.selectedRange = prevSelectedRange;
|
|
569
738
|
|
|
570
739
|
// update the placeholder as well
|
|
571
740
|
[self refreshPlaceholderLabelStyles];
|
|
@@ -591,6 +760,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
591
760
|
// we've got some seemingly proper html
|
|
592
761
|
[parser replaceWholeFromHtml:initiallyProcessedHtml];
|
|
593
762
|
}
|
|
763
|
+
textView.selectedRange = NSRange(textView.textStorage.string.length, 0);
|
|
594
764
|
}
|
|
595
765
|
|
|
596
766
|
// placeholderTextColor
|
|
@@ -631,6 +801,15 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
631
801
|
[config setMentionIndicators:newIndicators];
|
|
632
802
|
}
|
|
633
803
|
|
|
804
|
+
// linkRegex
|
|
805
|
+
LinkRegexConfig *oldRegexConfig =
|
|
806
|
+
[[LinkRegexConfig alloc] initWithLinkRegexProp:oldViewProps.linkRegex];
|
|
807
|
+
LinkRegexConfig *newRegexConfig =
|
|
808
|
+
[[LinkRegexConfig alloc] initWithLinkRegexProp:newViewProps.linkRegex];
|
|
809
|
+
if (![newRegexConfig isEqualToConfig:oldRegexConfig]) {
|
|
810
|
+
[config setLinkRegexConfig:newRegexConfig];
|
|
811
|
+
}
|
|
812
|
+
|
|
634
813
|
// selection color sets both selection and cursor on iOS (just as in RN)
|
|
635
814
|
if (newViewProps.selectionColor != oldViewProps.selectionColor) {
|
|
636
815
|
if (isColorMeaningful(newViewProps.selectionColor)) {
|
|
@@ -668,6 +847,9 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
668
847
|
// isOnChangeHtmlSet
|
|
669
848
|
_emitHtml = newViewProps.isOnChangeHtmlSet;
|
|
670
849
|
|
|
850
|
+
// isOnChangeTextSet
|
|
851
|
+
_emitTextChange = newViewProps.isOnChangeTextSet;
|
|
852
|
+
|
|
671
853
|
[super updateProps:props oldProps:oldProps];
|
|
672
854
|
// run the changes callback
|
|
673
855
|
[self anyTextMayHaveBeenModified];
|
|
@@ -782,6 +964,11 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
782
964
|
// emitted
|
|
783
965
|
NSMutableSet *newActiveStyles = [_activeStyles mutableCopy];
|
|
784
966
|
|
|
967
|
+
// currently blocked styles are subject to change (e.g. bold being blocked by
|
|
968
|
+
// headings might change in reaction to prop change) so they also are kept
|
|
969
|
+
// separately
|
|
970
|
+
NSMutableSet *newBlockedStyles = [_blockedStyles mutableCopy];
|
|
971
|
+
|
|
785
972
|
// data for onLinkDetected event
|
|
786
973
|
LinkData *detectedLinkData;
|
|
787
974
|
NSRange detectedLinkRange = NSMakeRange(0, 0);
|
|
@@ -792,8 +979,14 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
792
979
|
|
|
793
980
|
for (NSNumber *type in stylesDict) {
|
|
794
981
|
id<BaseStyleProtocol> style = stylesDict[type];
|
|
982
|
+
|
|
795
983
|
BOOL wasActive = [newActiveStyles containsObject:type];
|
|
796
984
|
BOOL isActive = [style detectStyle:textView.selectedRange];
|
|
985
|
+
|
|
986
|
+
BOOL wasBlocked = [newBlockedStyles containsObject:type];
|
|
987
|
+
BOOL isBlocked = [self isStyle:(StyleType)[type integerValue]
|
|
988
|
+
activeInMap:blockingStyles];
|
|
989
|
+
|
|
797
990
|
if (wasActive != isActive) {
|
|
798
991
|
updateNeeded = YES;
|
|
799
992
|
if (isActive) {
|
|
@@ -803,6 +996,16 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
803
996
|
}
|
|
804
997
|
}
|
|
805
998
|
|
|
999
|
+
// blocked state change for a style also needs an update
|
|
1000
|
+
if (wasBlocked != isBlocked) {
|
|
1001
|
+
updateNeeded = YES;
|
|
1002
|
+
if (isBlocked) {
|
|
1003
|
+
[newBlockedStyles addObject:type];
|
|
1004
|
+
} else {
|
|
1005
|
+
[newBlockedStyles removeObject:type];
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
806
1009
|
// onLinkDetected event
|
|
807
1010
|
if (isActive && [type intValue] == [LinkStyle getStyleType]) {
|
|
808
1011
|
// get the link data
|
|
@@ -867,35 +1070,30 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
867
1070
|
if (updateNeeded) {
|
|
868
1071
|
auto emitter = [self getEventEmitter];
|
|
869
1072
|
if (emitter != nullptr) {
|
|
870
|
-
// update activeStyles only if emitter is available
|
|
1073
|
+
// update activeStyles and blockedStyles only if emitter is available
|
|
871
1074
|
_activeStyles = newActiveStyles;
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
[_activeStyles containsObject:@([BlockQuoteStyle getStyleType])],
|
|
895
|
-
.isCodeBlock =
|
|
896
|
-
[_activeStyles containsObject:@([CodeBlockStyle getStyleType])],
|
|
897
|
-
.isImage = [_activeStyles containsObject:@([ImageStyle getStyleType])],
|
|
898
|
-
});
|
|
1075
|
+
_blockedStyles = newBlockedStyles;
|
|
1076
|
+
|
|
1077
|
+
emitter->onChangeState(
|
|
1078
|
+
{.bold = GET_STYLE_STATE([BoldStyle getStyleType]),
|
|
1079
|
+
.italic = GET_STYLE_STATE([ItalicStyle getStyleType]),
|
|
1080
|
+
.underline = GET_STYLE_STATE([UnderlineStyle getStyleType]),
|
|
1081
|
+
.strikeThrough = GET_STYLE_STATE([StrikethroughStyle getStyleType]),
|
|
1082
|
+
.inlineCode = GET_STYLE_STATE([InlineCodeStyle getStyleType]),
|
|
1083
|
+
.link = GET_STYLE_STATE([LinkStyle getStyleType]),
|
|
1084
|
+
.mention = GET_STYLE_STATE([MentionStyle getStyleType]),
|
|
1085
|
+
.h1 = GET_STYLE_STATE([H1Style getStyleType]),
|
|
1086
|
+
.h2 = GET_STYLE_STATE([H2Style getStyleType]),
|
|
1087
|
+
.h3 = GET_STYLE_STATE([H3Style getStyleType]),
|
|
1088
|
+
.h4 = GET_STYLE_STATE([H4Style getStyleType]),
|
|
1089
|
+
.h5 = GET_STYLE_STATE([H5Style getStyleType]),
|
|
1090
|
+
.h6 = GET_STYLE_STATE([H6Style getStyleType]),
|
|
1091
|
+
.unorderedList = GET_STYLE_STATE([UnorderedListStyle getStyleType]),
|
|
1092
|
+
.orderedList = GET_STYLE_STATE([OrderedListStyle getStyleType]),
|
|
1093
|
+
.blockQuote = GET_STYLE_STATE([BlockQuoteStyle getStyleType]),
|
|
1094
|
+
.codeBlock = GET_STYLE_STATE([CodeBlockStyle getStyleType]),
|
|
1095
|
+
.image = GET_STYLE_STATE([ImageStyle getStyleType]),
|
|
1096
|
+
.checkboxList = GET_STYLE_STATE([CheckboxListStyle getStyleType])});
|
|
899
1097
|
}
|
|
900
1098
|
}
|
|
901
1099
|
|
|
@@ -920,6 +1118,42 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
920
1118
|
[self tryEmittingOnChangeHtmlEvent];
|
|
921
1119
|
}
|
|
922
1120
|
|
|
1121
|
+
- (bool)isStyleActive:(StyleType)type {
|
|
1122
|
+
return [_activeStyles containsObject:@(type)];
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
- (bool)isStyle:(StyleType)type activeInMap:(NSDictionary *)styleMap {
|
|
1126
|
+
NSArray *relatedStyles = styleMap[@(type)];
|
|
1127
|
+
|
|
1128
|
+
if (!relatedStyles) {
|
|
1129
|
+
return false;
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
for (NSNumber *style in relatedStyles) {
|
|
1133
|
+
if ([_activeStyles containsObject:style]) {
|
|
1134
|
+
return true;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
return false;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
- (void)addStyleBlock:(StyleType)blocking to:(StyleType)blocked {
|
|
1142
|
+
NSMutableArray *blocksArr = [blockingStyles[@(blocked)] mutableCopy];
|
|
1143
|
+
if (![blocksArr containsObject:@(blocking)]) {
|
|
1144
|
+
[blocksArr addObject:@(blocking)];
|
|
1145
|
+
blockingStyles[@(blocked)] = blocksArr;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
- (void)removeStyleBlock:(StyleType)blocking from:(StyleType)blocked {
|
|
1150
|
+
NSMutableArray *blocksArr = [blockingStyles[@(blocked)] mutableCopy];
|
|
1151
|
+
if ([blocksArr containsObject:@(blocking)]) {
|
|
1152
|
+
[blocksArr removeObject:@(blocking)];
|
|
1153
|
+
blockingStyles[@(blocked)] = blocksArr;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
923
1157
|
// MARK: - Native commands and events
|
|
924
1158
|
|
|
925
1159
|
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
|
|
@@ -960,10 +1194,19 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
960
1194
|
[self toggleParagraphStyle:[H2Style getStyleType]];
|
|
961
1195
|
} else if ([commandName isEqualToString:@"toggleH3"]) {
|
|
962
1196
|
[self toggleParagraphStyle:[H3Style getStyleType]];
|
|
1197
|
+
} else if ([commandName isEqualToString:@"toggleH4"]) {
|
|
1198
|
+
[self toggleParagraphStyle:[H4Style getStyleType]];
|
|
1199
|
+
} else if ([commandName isEqualToString:@"toggleH5"]) {
|
|
1200
|
+
[self toggleParagraphStyle:[H5Style getStyleType]];
|
|
1201
|
+
} else if ([commandName isEqualToString:@"toggleH6"]) {
|
|
1202
|
+
[self toggleParagraphStyle:[H6Style getStyleType]];
|
|
963
1203
|
} else if ([commandName isEqualToString:@"toggleUnorderedList"]) {
|
|
964
1204
|
[self toggleParagraphStyle:[UnorderedListStyle getStyleType]];
|
|
965
1205
|
} else if ([commandName isEqualToString:@"toggleOrderedList"]) {
|
|
966
1206
|
[self toggleParagraphStyle:[OrderedListStyle getStyleType]];
|
|
1207
|
+
} else if ([commandName isEqualToString:@"toggleCheckboxList"]) {
|
|
1208
|
+
BOOL checked = [args[0] boolValue];
|
|
1209
|
+
[self toggleCheckboxList:checked];
|
|
967
1210
|
} else if ([commandName isEqualToString:@"toggleBlockQuote"]) {
|
|
968
1211
|
[self toggleParagraphStyle:[BlockQuoteStyle getStyleType]];
|
|
969
1212
|
} else if ([commandName isEqualToString:@"toggleCodeBlock"]) {
|
|
@@ -974,6 +1217,10 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
974
1217
|
CGFloat imgHeight = [(NSNumber *)args[2] floatValue];
|
|
975
1218
|
|
|
976
1219
|
[self addImage:uri width:imgWidth height:imgHeight];
|
|
1220
|
+
} else if ([commandName isEqualToString:@"setSelection"]) {
|
|
1221
|
+
NSInteger start = [((NSNumber *)args[0]) integerValue];
|
|
1222
|
+
NSInteger end = [((NSNumber *)args[1]) integerValue];
|
|
1223
|
+
[self setCustomSelection:start end:end];
|
|
977
1224
|
} else if ([commandName isEqualToString:@"requestHTML"]) {
|
|
978
1225
|
NSInteger requestId = [((NSNumber *)args[0]) integerValue];
|
|
979
1226
|
[self requestHTML:requestId];
|
|
@@ -1010,9 +1257,42 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1010
1257
|
|
|
1011
1258
|
// set recentlyChangedRange and check for changes
|
|
1012
1259
|
recentlyChangedRange = NSMakeRange(0, textView.textStorage.string.length);
|
|
1260
|
+
textView.selectedRange = NSRange(textView.textStorage.string.length, 0);
|
|
1013
1261
|
[self anyTextMayHaveBeenModified];
|
|
1014
1262
|
}
|
|
1015
1263
|
|
|
1264
|
+
- (void)setCustomSelection:(NSInteger)visibleStart end:(NSInteger)visibleEnd {
|
|
1265
|
+
NSString *text = textView.textStorage.string;
|
|
1266
|
+
|
|
1267
|
+
NSUInteger actualStart = [self getActualIndex:visibleStart text:text];
|
|
1268
|
+
NSUInteger actualEnd = [self getActualIndex:visibleEnd text:text];
|
|
1269
|
+
|
|
1270
|
+
textView.selectedRange = NSMakeRange(actualStart, actualEnd - actualStart);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
// Helper: Walks through the string skipping ZWSPs to find the Nth visible
|
|
1274
|
+
// character
|
|
1275
|
+
- (NSUInteger)getActualIndex:(NSInteger)visibleIndex text:(NSString *)text {
|
|
1276
|
+
NSUInteger currentVisibleCount = 0;
|
|
1277
|
+
NSUInteger actualIndex = 0;
|
|
1278
|
+
|
|
1279
|
+
while (actualIndex < text.length) {
|
|
1280
|
+
if (currentVisibleCount == visibleIndex) {
|
|
1281
|
+
return actualIndex;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// If the current char is not a hidden space, it counts towards our visible
|
|
1285
|
+
// index.
|
|
1286
|
+
if ([text characterAtIndex:actualIndex] != 0x200B) {
|
|
1287
|
+
currentVisibleCount++;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
actualIndex++;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
return actualIndex;
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1016
1296
|
- (void)emitOnLinkDetectedEvent:(NSString *)text
|
|
1017
1297
|
url:(NSString *)url
|
|
1018
1298
|
range:(NSRange)range {
|
|
@@ -1034,6 +1314,32 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1034
1314
|
}
|
|
1035
1315
|
}
|
|
1036
1316
|
|
|
1317
|
+
- (void)emitOnPasteImagesEvent:(NSArray<NSDictionary *> *)images {
|
|
1318
|
+
auto emitter = [self getEventEmitter];
|
|
1319
|
+
if (emitter != nullptr) {
|
|
1320
|
+
std::vector<EnrichedTextInputViewEventEmitter::OnPasteImagesImages>
|
|
1321
|
+
imagesVector;
|
|
1322
|
+
imagesVector.reserve(images.count);
|
|
1323
|
+
|
|
1324
|
+
for (NSDictionary *img in images) {
|
|
1325
|
+
NSString *uri = img[@"uri"];
|
|
1326
|
+
NSString *type = img[@"type"];
|
|
1327
|
+
double width = [img[@"width"] doubleValue];
|
|
1328
|
+
double height = [img[@"height"] doubleValue];
|
|
1329
|
+
|
|
1330
|
+
EnrichedTextInputViewEventEmitter::OnPasteImagesImages imageStruct = {
|
|
1331
|
+
.uri = [uri toCppString],
|
|
1332
|
+
.type = [type toCppString],
|
|
1333
|
+
.width = width,
|
|
1334
|
+
.height = height};
|
|
1335
|
+
|
|
1336
|
+
imagesVector.push_back(imageStruct);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
emitter->onPasteImages({.images = imagesVector});
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1037
1343
|
- (void)emitOnMentionDetectedEvent:(NSString *)text
|
|
1038
1344
|
indicator:(NSString *)indicator
|
|
1039
1345
|
attributes:(NSString *)attributes {
|
|
@@ -1091,6 +1397,13 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1091
1397
|
}
|
|
1092
1398
|
}
|
|
1093
1399
|
|
|
1400
|
+
- (void)emitOnKeyPressEvent:(NSString *)key {
|
|
1401
|
+
auto emitter = [self getEventEmitter];
|
|
1402
|
+
if (emitter != nullptr) {
|
|
1403
|
+
emitter->onInputKeyPress({.key = [key toCppString]});
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1094
1407
|
// MARK: - Styles manipulation
|
|
1095
1408
|
|
|
1096
1409
|
- (void)toggleRegularStyle:(StyleType)type {
|
|
@@ -1114,6 +1427,24 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1114
1427
|
}
|
|
1115
1428
|
}
|
|
1116
1429
|
|
|
1430
|
+
- (void)toggleCheckboxList:(BOOL)checked {
|
|
1431
|
+
CheckboxListStyle *checkboxListStyleClass =
|
|
1432
|
+
(CheckboxListStyle *)stylesDict[@([CheckboxListStyle getStyleType])];
|
|
1433
|
+
if (checkboxListStyleClass == nullptr) {
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
// we always pass whole paragraph/s range to these styles
|
|
1437
|
+
NSRange paragraphRange = [textView.textStorage.string
|
|
1438
|
+
paragraphRangeForRange:textView.selectedRange];
|
|
1439
|
+
|
|
1440
|
+
if ([self handleStyleBlocksAndConflicts:[CheckboxListStyle getStyleType]
|
|
1441
|
+
range:paragraphRange]) {
|
|
1442
|
+
[checkboxListStyleClass applyStyleWithCheckedValue:checked
|
|
1443
|
+
inRange:paragraphRange];
|
|
1444
|
+
[self anyTextMayHaveBeenModified];
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1117
1448
|
- (void)addLinkAt:(NSInteger)start
|
|
1118
1449
|
end:(NSInteger)end
|
|
1119
1450
|
text:(NSString *)text
|
|
@@ -1247,6 +1578,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1247
1578
|
if (linkStyleClass != nullptr) {
|
|
1248
1579
|
[linkStyleClass manageLinkTypingAttributes];
|
|
1249
1580
|
}
|
|
1581
|
+
NSString *currentString = [textView.textStorage.string copy];
|
|
1250
1582
|
|
|
1251
1583
|
// mention typing attribtues fix and active editing
|
|
1252
1584
|
MentionStyle *mentionStyleClass =
|
|
@@ -1257,14 +1589,12 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1257
1589
|
// mention editing runs if only a selection was done (no text change)
|
|
1258
1590
|
// otherwise we would double-emit with a second call in the
|
|
1259
1591
|
// anyTextMayHaveBeenModified method
|
|
1260
|
-
if ([_recentInputString
|
|
1261
|
-
isEqualToString:[textView.textStorage.string copy]]) {
|
|
1592
|
+
if ([_recentInputString isEqualToString:currentString]) {
|
|
1262
1593
|
[mentionStyleClass manageMentionEditing];
|
|
1263
1594
|
}
|
|
1264
1595
|
}
|
|
1265
1596
|
|
|
1266
1597
|
// typing attributes for empty lines selection reset
|
|
1267
|
-
NSString *currentString = [textView.textStorage.string copy];
|
|
1268
1598
|
if (textView.selectedRange.length == 0 &&
|
|
1269
1599
|
[_recentInputString isEqualToString:currentString]) {
|
|
1270
1600
|
// no string change means only a selection changed with no character changes
|
|
@@ -1333,16 +1663,6 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1333
1663
|
[codeBlockStyle manageCodeBlockFontAndColor];
|
|
1334
1664
|
}
|
|
1335
1665
|
|
|
1336
|
-
// improper headings fix
|
|
1337
|
-
H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
|
|
1338
|
-
H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
|
|
1339
|
-
H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
|
|
1340
|
-
if (h1Style != nullptr && h2Style != nullptr && h3Style != nullptr) {
|
|
1341
|
-
[h1Style handleImproperHeadings];
|
|
1342
|
-
[h2Style handleImproperHeadings];
|
|
1343
|
-
[h3Style handleImproperHeadings];
|
|
1344
|
-
}
|
|
1345
|
-
|
|
1346
1666
|
// mentions management: removal and editing
|
|
1347
1667
|
MentionStyle *mentionStyleClass =
|
|
1348
1668
|
(MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
|
|
@@ -1380,7 +1700,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1380
1700
|
|
|
1381
1701
|
// emit onChangeText event
|
|
1382
1702
|
auto emitter = [self getEventEmitter];
|
|
1383
|
-
if (emitter != nullptr) {
|
|
1703
|
+
if (emitter != nullptr && _emitTextChange) {
|
|
1384
1704
|
// set the recent input string only if the emitter is defined
|
|
1385
1705
|
_recentInputString = [textView.textStorage.string copy];
|
|
1386
1706
|
|
|
@@ -1397,6 +1717,7 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1397
1717
|
[self tryUpdatingHeight];
|
|
1398
1718
|
// update active styles as well
|
|
1399
1719
|
[self tryUpdatingActiveStyles];
|
|
1720
|
+
[self layoutAttachments];
|
|
1400
1721
|
// update drawing - schedule debounced relayout
|
|
1401
1722
|
[self scheduleRelayoutIfNeeded];
|
|
1402
1723
|
}
|
|
@@ -1477,13 +1798,33 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1477
1798
|
}
|
|
1478
1799
|
}
|
|
1479
1800
|
|
|
1801
|
+
- (void)handleKeyPressInRange:(NSString *)text range:(NSRange)range {
|
|
1802
|
+
NSString *key = nil;
|
|
1803
|
+
|
|
1804
|
+
if (text.length == 0 && range.length > 0) {
|
|
1805
|
+
key = @"Backspace";
|
|
1806
|
+
} else if ([text isEqualToString:@"\n"]) {
|
|
1807
|
+
key = @"Enter";
|
|
1808
|
+
} else if ([text isEqualToString:@"\t"]) {
|
|
1809
|
+
key = @"Tab";
|
|
1810
|
+
} else if (text.length == 1) {
|
|
1811
|
+
key = text;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
if (key != nil) {
|
|
1815
|
+
[self emitOnKeyPressEvent:key];
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1480
1819
|
- (bool)textView:(UITextView *)textView
|
|
1481
1820
|
shouldChangeTextInRange:(NSRange)range
|
|
1482
1821
|
replacementText:(NSString *)text {
|
|
1483
1822
|
recentlyChangedRange = NSMakeRange(range.location, text.length);
|
|
1823
|
+
[self handleKeyPressInRange:text range:range];
|
|
1484
1824
|
|
|
1485
1825
|
UnorderedListStyle *uStyle = stylesDict[@([UnorderedListStyle getStyleType])];
|
|
1486
1826
|
OrderedListStyle *oStyle = stylesDict[@([OrderedListStyle getStyleType])];
|
|
1827
|
+
CheckboxListStyle *cbLStyle = stylesDict[@([CheckboxListStyle getStyleType])];
|
|
1487
1828
|
BlockQuoteStyle *bqStyle = stylesDict[@([BlockQuoteStyle getStyleType])];
|
|
1488
1829
|
CodeBlockStyle *cbStyle = stylesDict[@([CodeBlockStyle getStyleType])];
|
|
1489
1830
|
LinkStyle *linkStyle = stylesDict[@([LinkStyle getStyleType])];
|
|
@@ -1491,6 +1832,9 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1491
1832
|
H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
|
|
1492
1833
|
H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
|
|
1493
1834
|
H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
|
|
1835
|
+
H4Style *h4Style = stylesDict[@([H4Style getStyleType])];
|
|
1836
|
+
H5Style *h5Style = stylesDict[@([H5Style getStyleType])];
|
|
1837
|
+
H6Style *h6Style = stylesDict[@([H6Style getStyleType])];
|
|
1494
1838
|
|
|
1495
1839
|
// some of the changes these checks do could interfere with later checks and
|
|
1496
1840
|
// cause a crash so here I rely on short circuiting evaluation of the logical
|
|
@@ -1500,6 +1844,8 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1500
1844
|
[uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
|
|
1501
1845
|
[oStyle handleBackspaceInRange:range replacementText:text] ||
|
|
1502
1846
|
[oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
|
|
1847
|
+
[cbLStyle handleBackspaceInRange:range replacementText:text] ||
|
|
1848
|
+
[cbLStyle handleNewlinesInRange:range replacementText:text] ||
|
|
1503
1849
|
[bqStyle handleBackspaceInRange:range replacementText:text] ||
|
|
1504
1850
|
[cbStyle handleBackspaceInRange:range replacementText:text] ||
|
|
1505
1851
|
[linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
|
|
@@ -1508,12 +1854,24 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1508
1854
|
[h1Style handleNewlinesInRange:range replacementText:text] ||
|
|
1509
1855
|
[h2Style handleNewlinesInRange:range replacementText:text] ||
|
|
1510
1856
|
[h3Style handleNewlinesInRange:range replacementText:text] ||
|
|
1857
|
+
[h4Style handleNewlinesInRange:range replacementText:text] ||
|
|
1858
|
+
[h5Style handleNewlinesInRange:range replacementText:text] ||
|
|
1859
|
+
[h6Style handleNewlinesInRange:range replacementText:text] ||
|
|
1860
|
+
[h1Style handleBackspaceInRange:range replacementText:text] ||
|
|
1861
|
+
[h2Style handleBackspaceInRange:range replacementText:text] ||
|
|
1862
|
+
[h3Style handleBackspaceInRange:range replacementText:text] ||
|
|
1863
|
+
[h4Style handleBackspaceInRange:range replacementText:text] ||
|
|
1864
|
+
[h5Style handleBackspaceInRange:range replacementText:text] ||
|
|
1865
|
+
[h6Style handleBackspaceInRange:range replacementText:text] ||
|
|
1511
1866
|
[ZeroWidthSpaceUtils handleBackspaceInRange:range
|
|
1512
1867
|
replacementText:text
|
|
1513
1868
|
input:self] ||
|
|
1514
1869
|
[ParagraphAttributesUtils handleBackspaceInRange:range
|
|
1515
1870
|
replacementText:text
|
|
1516
1871
|
input:self] ||
|
|
1872
|
+
[ParagraphAttributesUtils handleResetTypingAttributesOnBackspace:range
|
|
1873
|
+
replacementText:text
|
|
1874
|
+
input:self] ||
|
|
1517
1875
|
// CRITICAL: This callback HAS TO be always evaluated last.
|
|
1518
1876
|
//
|
|
1519
1877
|
// This function is the "Generic Fallback": if no specific style claims
|
|
@@ -1558,6 +1916,90 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1558
1916
|
[self anyTextMayHaveBeenModified];
|
|
1559
1917
|
}
|
|
1560
1918
|
|
|
1919
|
+
/**
|
|
1920
|
+
* Handles iOS Dynamic Type changes (User changing font size in System
|
|
1921
|
+
* Settings).
|
|
1922
|
+
*
|
|
1923
|
+
* Unlike Android, iOS Views do not automatically rescale existing
|
|
1924
|
+
* NSAttributedStrings when the system font size changes. The text attributes
|
|
1925
|
+
* are static once drawn.
|
|
1926
|
+
*
|
|
1927
|
+
* This method detects the change and performs a "Hard Refresh" of the content.
|
|
1928
|
+
*/
|
|
1929
|
+
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
|
|
1930
|
+
[super traitCollectionDidChange:previousTraitCollection];
|
|
1931
|
+
|
|
1932
|
+
if (previousTraitCollection.preferredContentSizeCategory !=
|
|
1933
|
+
self.traitCollection.preferredContentSizeCategory) {
|
|
1934
|
+
[config invalidateFonts];
|
|
1935
|
+
|
|
1936
|
+
NSMutableDictionary *newTypingAttrs = [defaultTypingAttributes mutableCopy];
|
|
1937
|
+
newTypingAttrs[NSFontAttributeName] = [config primaryFont];
|
|
1938
|
+
|
|
1939
|
+
defaultTypingAttributes = newTypingAttrs;
|
|
1940
|
+
textView.typingAttributes = defaultTypingAttributes;
|
|
1941
|
+
|
|
1942
|
+
[self refreshPlaceholderLabelStyles];
|
|
1943
|
+
|
|
1944
|
+
NSRange prevSelectedRange = textView.selectedRange;
|
|
1945
|
+
|
|
1946
|
+
NSString *currentHtml = [parser
|
|
1947
|
+
parseToHtmlFromRange:NSMakeRange(0,
|
|
1948
|
+
textView.textStorage.string.length)];
|
|
1949
|
+
NSString *initiallyProcessedHtml =
|
|
1950
|
+
[parser initiallyProcessHtml:currentHtml];
|
|
1951
|
+
[parser replaceWholeFromHtml:initiallyProcessedHtml];
|
|
1952
|
+
|
|
1953
|
+
textView.selectedRange = prevSelectedRange;
|
|
1954
|
+
[self anyTextMayHaveBeenModified];
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
|
|
1958
|
+
- (void)onTextBlockTap:(TextBlockTapGestureRecognizer *)gr {
|
|
1959
|
+
if (gr.state != UIGestureRecognizerStateEnded)
|
|
1960
|
+
return;
|
|
1961
|
+
if (![self->textView isFirstResponder]) {
|
|
1962
|
+
[self->textView becomeFirstResponder];
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
switch (gr.tapKind) {
|
|
1966
|
+
|
|
1967
|
+
case TextBlockTapKindCheckbox: {
|
|
1968
|
+
CheckboxListStyle *checkboxStyle =
|
|
1969
|
+
(CheckboxListStyle *)stylesDict[@([CheckboxListStyle getStyleType])];
|
|
1970
|
+
|
|
1971
|
+
if (checkboxStyle) {
|
|
1972
|
+
NSUInteger charIndex = (NSUInteger)gr.characterIndex;
|
|
1973
|
+
[checkboxStyle toggleCheckedAt:charIndex];
|
|
1974
|
+
[self anyTextMayHaveBeenModified];
|
|
1975
|
+
|
|
1976
|
+
NSString *fullText = textView.textStorage.string;
|
|
1977
|
+
NSRange paragraphRange =
|
|
1978
|
+
[fullText paragraphRangeForRange:NSMakeRange(charIndex, 0)];
|
|
1979
|
+
NSUInteger endOfLineIndex = NSMaxRange(paragraphRange);
|
|
1980
|
+
|
|
1981
|
+
// If the paragraph ends with a newline, step back by 1 so the cursor
|
|
1982
|
+
// stays on the current line instead of jumping to the next one.
|
|
1983
|
+
if (endOfLineIndex > 0 && endOfLineIndex <= fullText.length) {
|
|
1984
|
+
unichar lastChar = [fullText characterAtIndex:endOfLineIndex - 1];
|
|
1985
|
+
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:lastChar]) {
|
|
1986
|
+
endOfLineIndex--;
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
// Move the cursor to the end of the currently tapped checkbox line.
|
|
1991
|
+
// Without this, the cursor may remain at its previous position,
|
|
1992
|
+
// potentially inside a different checkbox line.
|
|
1993
|
+
textView.selectedRange = NSMakeRange(endOfLineIndex, 0);
|
|
1994
|
+
}
|
|
1995
|
+
break;
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
default:
|
|
1999
|
+
break;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
|
|
1561
2003
|
// MARK: - Media attachments delegate
|
|
1562
2004
|
|
|
1563
2005
|
- (void)mediaAttachmentDidUpdate:(NSTextAttachment *)attachment {
|
|
@@ -1583,6 +2025,107 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
|
|
|
1583
2025
|
[storage edited:NSTextStorageEditedAttributes
|
|
1584
2026
|
range:foundRange
|
|
1585
2027
|
changeInLength:0];
|
|
2028
|
+
|
|
2029
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
2030
|
+
[self layoutAttachments];
|
|
2031
|
+
});
|
|
1586
2032
|
}
|
|
1587
2033
|
|
|
2034
|
+
// MARK: - Image/GIF Overlay Management
|
|
2035
|
+
|
|
2036
|
+
- (void)layoutAttachments {
|
|
2037
|
+
NSTextStorage *storage = textView.textStorage;
|
|
2038
|
+
NSMutableDictionary<NSValue *, UIImageView *> *activeAttachmentViews =
|
|
2039
|
+
[NSMutableDictionary dictionary];
|
|
2040
|
+
|
|
2041
|
+
// Iterate over the entire text to find ImageAttachments
|
|
2042
|
+
[storage enumerateAttribute:NSAttachmentAttributeName
|
|
2043
|
+
inRange:NSMakeRange(0, storage.length)
|
|
2044
|
+
options:0
|
|
2045
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
2046
|
+
if ([value isKindOfClass:[ImageAttachment class]]) {
|
|
2047
|
+
ImageAttachment *attachment = (ImageAttachment *)value;
|
|
2048
|
+
|
|
2049
|
+
CGRect rect = [self frameForAttachment:attachment
|
|
2050
|
+
atRange:range];
|
|
2051
|
+
|
|
2052
|
+
// Get or Create the UIImageView for this specific
|
|
2053
|
+
// attachment key
|
|
2054
|
+
NSValue *key =
|
|
2055
|
+
[NSValue valueWithNonretainedObject:attachment];
|
|
2056
|
+
UIImageView *imgView = _attachmentViews[key];
|
|
2057
|
+
|
|
2058
|
+
if (!imgView) {
|
|
2059
|
+
// It doesn't exist yet, create it
|
|
2060
|
+
imgView = [[UIImageView alloc] initWithFrame:rect];
|
|
2061
|
+
imgView.contentMode = UIViewContentModeScaleAspectFit;
|
|
2062
|
+
imgView.tintColor = [UIColor labelColor];
|
|
2063
|
+
|
|
2064
|
+
// Add it directly to the TextView
|
|
2065
|
+
[textView addSubview:imgView];
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
// Update position (in case text moved/scrolled)
|
|
2069
|
+
if (!CGRectEqualToRect(imgView.frame, rect)) {
|
|
2070
|
+
imgView.frame = rect;
|
|
2071
|
+
}
|
|
2072
|
+
UIImage *targetImage =
|
|
2073
|
+
attachment.storedAnimatedImage ?: attachment.image;
|
|
2074
|
+
|
|
2075
|
+
// Only set if different to avoid resetting the animation
|
|
2076
|
+
// loop
|
|
2077
|
+
if (imgView.image != targetImage) {
|
|
2078
|
+
imgView.image = targetImage;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
// Ensure it is visible on top
|
|
2082
|
+
imgView.hidden = NO;
|
|
2083
|
+
[textView bringSubviewToFront:imgView];
|
|
2084
|
+
|
|
2085
|
+
activeAttachmentViews[key] = imgView;
|
|
2086
|
+
// Remove from the old map so we know it has been claimed
|
|
2087
|
+
[_attachmentViews removeObjectForKey:key];
|
|
2088
|
+
}
|
|
2089
|
+
}];
|
|
2090
|
+
|
|
2091
|
+
// Everything remaining in _attachmentViews is dead or off-screen
|
|
2092
|
+
for (UIImageView *danglingView in _attachmentViews.allValues) {
|
|
2093
|
+
[danglingView removeFromSuperview];
|
|
2094
|
+
}
|
|
2095
|
+
_attachmentViews = activeAttachmentViews;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
- (CGRect)frameForAttachment:(ImageAttachment *)attachment
|
|
2099
|
+
atRange:(NSRange)range {
|
|
2100
|
+
NSLayoutManager *layoutManager = textView.layoutManager;
|
|
2101
|
+
NSTextContainer *textContainer = textView.textContainer;
|
|
2102
|
+
NSTextStorage *storage = textView.textStorage;
|
|
2103
|
+
|
|
2104
|
+
NSRange glyphRange = [layoutManager glyphRangeForCharacterRange:range
|
|
2105
|
+
actualCharacterRange:NULL];
|
|
2106
|
+
CGRect glyphRect = [layoutManager boundingRectForGlyphRange:glyphRange
|
|
2107
|
+
inTextContainer:textContainer];
|
|
2108
|
+
|
|
2109
|
+
CGRect lineRect =
|
|
2110
|
+
[layoutManager lineFragmentRectForGlyphAtIndex:glyphRange.location
|
|
2111
|
+
effectiveRange:NULL];
|
|
2112
|
+
CGSize attachmentSize = attachment.bounds.size;
|
|
2113
|
+
|
|
2114
|
+
UIFont *font = [storage attribute:NSFontAttributeName
|
|
2115
|
+
atIndex:range.location
|
|
2116
|
+
effectiveRange:NULL];
|
|
2117
|
+
if (!font) {
|
|
2118
|
+
font = [config primaryFont];
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
// Calculate (Baseline Alignment)
|
|
2122
|
+
CGFloat targetY =
|
|
2123
|
+
CGRectGetMaxY(lineRect) + font.descender - attachmentSize.height;
|
|
2124
|
+
CGRect rect =
|
|
2125
|
+
CGRectMake(glyphRect.origin.x + textView.textContainerInset.left,
|
|
2126
|
+
targetY + textView.textContainerInset.top,
|
|
2127
|
+
attachmentSize.width, attachmentSize.height);
|
|
2128
|
+
|
|
2129
|
+
return CGRectIntegral(rect);
|
|
2130
|
+
}
|
|
1588
2131
|
@end
|