react-native-enriched 0.3.0 → 0.4.1
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 +6 -4
- package/android/build.gradle +3 -3
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +1 -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/{ios/generated/RNEnrichedTextInputViewSpec → android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec}/EventEmitters.cpp +31 -29
- package/{ios/generated/RNEnrichedTextInputViewSpec → android/generated/jni/react/renderer/components/ReactNativeEnrichedSpec}/EventEmitters.h +22 -25
- package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +57 -0
- package/android/gradle.properties +5 -5
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewPackage.kt → ReactNativeEnrichedPackage.kt} +3 -2
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/AsyncDrawable.kt +40 -8
- package/android/src/main/java/com/swmansion/enriched/common/CheckboxDrawable.kt +81 -0
- package/android/src/main/java/com/swmansion/enriched/{utils → common}/EnrichedConstants.kt +1 -1
- 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 +1 -1
- 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 +126 -99
- package/android/src/main/java/com/swmansion/enriched/common/parser/EnrichedSpanFactory.kt +79 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedBlockQuoteSpan.kt +9 -13
- 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 +8 -12
- 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 +43 -38
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedInlineCodeSpan.kt +7 -11
- package/android/src/main/java/com/swmansion/enriched/common/spans/EnrichedItalicSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedLinkSpan.kt +7 -11
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedMentionSpan.kt +6 -10
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/EnrichedOrderedListSpan.kt +12 -21
- 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 +9 -13
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedBlockSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedHeadingSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/common/spans/interfaces/EnrichedInlineSpan.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/{spans → common/spans}/interfaces/EnrichedParagraphSpan.kt +1 -1
- 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 +1 -1
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputConnectionWrapper.kt → textinput/EnrichedTextInputConnectionWrapper.kt} +2 -2
- 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} +87 -51
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewLayoutManager.kt → textinput/EnrichedTextInputViewLayoutManager.kt} +1 -1
- package/android/src/main/java/com/swmansion/enriched/{EnrichedTextInputViewManager.kt → textinput/EnrichedTextInputViewManager.kt} +24 -17
- package/android/src/main/java/com/swmansion/enriched/{MeasurementStore.kt → textinput/MeasurementStore.kt} +5 -4
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/MentionHandler.kt +2 -2
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeHtmlEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeSelectionEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeStateEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnChangeTextEvent.kt +2 -2
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputBlurEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputFocusEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnInputKeyPressEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnLinkDetectedEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionDetectedEvent.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/{events → textinput/events}/OnMentionEvent.kt +1 -1
- 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 +1 -1
- 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/{spans → textinput/spans}/EnrichedSpans.kt +39 -30
- 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 +58 -43
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/InlineStyles.kt +4 -4
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ListStyles.kt +77 -26
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParagraphStyles.kt +30 -25
- package/android/src/main/java/com/swmansion/enriched/{styles → textinput/styles}/ParametrizedStyles.kt +19 -19
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedEditableFactory.kt +2 -2
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSelection.kt +15 -14
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpanState.kt +15 -50
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpannable.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/{utils → textinput/utils}/EnrichedSpannableStringBuilder.kt +2 -1
- 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 +10 -10
- package/android/src/main/java/com/swmansion/enriched/{watchers → textinput/watchers}/EnrichedTextWatcher.kt +3 -3
- package/android/src/main/new_arch/CMakeLists.txt +1 -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/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/conversions.h +1 -1
- package/ios/EnrichedTextInputView.h +1 -0
- package/ios/EnrichedTextInputView.mm +274 -55
- package/ios/config/InputConfig.h +10 -0
- package/ios/config/InputConfig.mm +119 -0
- package/ios/extensions/ImageExtension.h +35 -0
- package/ios/extensions/ImageExtension.mm +156 -0
- package/ios/extensions/LayoutManagerExtension.mm +115 -95
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.cpp +1 -1
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/ComponentDescriptors.h +1 -1
- package/{android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec → ios/generated/ReactNativeEnrichedSpec}/EventEmitters.cpp +31 -29
- package/{android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec → ios/generated/ReactNativeEnrichedSpec}/EventEmitters.h +22 -25
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.h +57 -0
- package/ios/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/RCTComponentViewHelpers.h +21 -0
- package/ios/inputParser/InputParser.mm +135 -8
- package/ios/inputTextView/InputTextView.mm +118 -0
- package/ios/interfaces/ImageAttachment.h +1 -0
- package/ios/interfaces/ImageAttachment.mm +43 -4
- package/ios/interfaces/StyleHeaders.h +13 -2
- package/ios/interfaces/StyleTypeEnum.h +1 -0
- package/ios/internals/EnrichedTextInputViewState.cpp +6 -6
- package/ios/styles/CheckboxListStyle.mm +321 -0
- 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 +3 -0
- package/ios/styles/H5Style.mm +3 -0
- package/ios/styles/H6Style.mm +3 -0
- package/ios/styles/HeadingStyleBase.mm +150 -78
- package/ios/utils/CheckboxHitTestUtils.h +10 -0
- package/ios/utils/CheckboxHitTestUtils.mm +123 -0
- package/ios/utils/ParagraphAttributesUtils.mm +83 -53
- 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 +36 -11
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +40 -9
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/utils/normalizeHtmlStyle.js +6 -0
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -1
- package/lib/module/utils/nullthrows.js +9 -0
- package/lib/module/utils/nullthrows.js.map +1 -0
- package/lib/typescript/src/EnrichedTextInput.d.ts +9 -49
- 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} +33 -8
- 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 +2 -2
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -1
- 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 +1 -1
- package/lib/typescript/src/utils/regexParser.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/EnrichedTextInput.tsx +49 -62
- package/src/index.tsx +3 -1
- package/src/{EnrichedTextInputNativeComponent.ts → spec/EnrichedTextInputNativeComponent.ts} +40 -9
- package/src/types.ts +59 -0
- package/src/utils/normalizeHtmlStyle.ts +8 -5
- package/src/utils/nullthrows.ts +7 -0
- package/src/utils/regexParser.ts +1 -1
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +0 -21
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +0 -17
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +0 -24
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +0 -16
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +0 -15
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +0 -15
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +0 -3
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +0 -9
- package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -21
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +0 -22
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +0 -26
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +0 -1
- /package/android/generated/jni/react/renderer/components/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +0 -0
- /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/generated/{RNEnrichedTextInputViewSpec → ReactNativeEnrichedSpec}/Props.cpp +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
|
@@ -528,6 +528,57 @@ static inline folly::dynamic toDynamic(const EnrichedTextInputViewHtmlStyleUlStr
|
|
|
528
528
|
}
|
|
529
529
|
#endif
|
|
530
530
|
|
|
531
|
+
struct EnrichedTextInputViewHtmlStyleUlCheckboxStruct {
|
|
532
|
+
Float gapWidth{0.0};
|
|
533
|
+
Float boxSize{0.0};
|
|
534
|
+
Float marginLeft{0.0};
|
|
535
|
+
SharedColor boxColor{};
|
|
536
|
+
|
|
537
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
538
|
+
bool operator==(const EnrichedTextInputViewHtmlStyleUlCheckboxStruct&) const = default;
|
|
539
|
+
|
|
540
|
+
folly::dynamic toDynamic() const {
|
|
541
|
+
folly::dynamic result = folly::dynamic::object();
|
|
542
|
+
result["gapWidth"] = gapWidth;
|
|
543
|
+
result["boxSize"] = boxSize;
|
|
544
|
+
result["marginLeft"] = marginLeft;
|
|
545
|
+
result["boxColor"] = ::facebook::react::toDynamic(boxColor);
|
|
546
|
+
return result;
|
|
547
|
+
}
|
|
548
|
+
#endif
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
static inline void fromRawValue(const PropsParserContext& context, const RawValue &value, EnrichedTextInputViewHtmlStyleUlCheckboxStruct &result) {
|
|
552
|
+
auto map = (std::unordered_map<std::string, RawValue>)value;
|
|
553
|
+
|
|
554
|
+
auto tmp_gapWidth = map.find("gapWidth");
|
|
555
|
+
if (tmp_gapWidth != map.end()) {
|
|
556
|
+
fromRawValue(context, tmp_gapWidth->second, result.gapWidth);
|
|
557
|
+
}
|
|
558
|
+
auto tmp_boxSize = map.find("boxSize");
|
|
559
|
+
if (tmp_boxSize != map.end()) {
|
|
560
|
+
fromRawValue(context, tmp_boxSize->second, result.boxSize);
|
|
561
|
+
}
|
|
562
|
+
auto tmp_marginLeft = map.find("marginLeft");
|
|
563
|
+
if (tmp_marginLeft != map.end()) {
|
|
564
|
+
fromRawValue(context, tmp_marginLeft->second, result.marginLeft);
|
|
565
|
+
}
|
|
566
|
+
auto tmp_boxColor = map.find("boxColor");
|
|
567
|
+
if (tmp_boxColor != map.end()) {
|
|
568
|
+
fromRawValue(context, tmp_boxColor->second, result.boxColor);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
static inline std::string toString(const EnrichedTextInputViewHtmlStyleUlCheckboxStruct &value) {
|
|
573
|
+
return "[Object EnrichedTextInputViewHtmlStyleUlCheckboxStruct]";
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
#ifdef RN_SERIALIZABLE_STATE
|
|
577
|
+
static inline folly::dynamic toDynamic(const EnrichedTextInputViewHtmlStyleUlCheckboxStruct &value) {
|
|
578
|
+
return value.toDynamic();
|
|
579
|
+
}
|
|
580
|
+
#endif
|
|
581
|
+
|
|
531
582
|
struct EnrichedTextInputViewHtmlStyleStruct {
|
|
532
583
|
EnrichedTextInputViewHtmlStyleH1Struct h1{};
|
|
533
584
|
EnrichedTextInputViewHtmlStyleH2Struct h2{};
|
|
@@ -542,6 +593,7 @@ struct EnrichedTextInputViewHtmlStyleStruct {
|
|
|
542
593
|
folly::dynamic mention{};
|
|
543
594
|
EnrichedTextInputViewHtmlStyleOlStruct ol{};
|
|
544
595
|
EnrichedTextInputViewHtmlStyleUlStruct ul{};
|
|
596
|
+
EnrichedTextInputViewHtmlStyleUlCheckboxStruct ulCheckbox{};
|
|
545
597
|
|
|
546
598
|
#ifdef RN_SERIALIZABLE_STATE
|
|
547
599
|
bool operator==(const EnrichedTextInputViewHtmlStyleStruct&) const = default;
|
|
@@ -561,6 +613,7 @@ struct EnrichedTextInputViewHtmlStyleStruct {
|
|
|
561
613
|
result["mention"] = mention;
|
|
562
614
|
result["ol"] = ::facebook::react::toDynamic(ol);
|
|
563
615
|
result["ul"] = ::facebook::react::toDynamic(ul);
|
|
616
|
+
result["ulCheckbox"] = ::facebook::react::toDynamic(ulCheckbox);
|
|
564
617
|
return result;
|
|
565
618
|
}
|
|
566
619
|
#endif
|
|
@@ -621,6 +674,10 @@ static inline void fromRawValue(const PropsParserContext& context, const RawValu
|
|
|
621
674
|
if (tmp_ul != map.end()) {
|
|
622
675
|
fromRawValue(context, tmp_ul->second, result.ul);
|
|
623
676
|
}
|
|
677
|
+
auto tmp_ulCheckbox = map.find("ulCheckbox");
|
|
678
|
+
if (tmp_ulCheckbox != map.end()) {
|
|
679
|
+
fromRawValue(context, tmp_ulCheckbox->second, result.ulCheckbox);
|
|
680
|
+
}
|
|
624
681
|
}
|
|
625
682
|
|
|
626
683
|
static inline std::string toString(const EnrichedTextInputViewHtmlStyleStruct &value) {
|
|
@@ -33,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
33
33
|
- (void)toggleBlockQuote;
|
|
34
34
|
- (void)toggleOrderedList;
|
|
35
35
|
- (void)toggleUnorderedList;
|
|
36
|
+
- (void)toggleCheckboxList:(BOOL)checked;
|
|
36
37
|
- (void)addLink:(NSInteger)start end:(NSInteger)end text:(NSString *)text url:(NSString *)url;
|
|
37
38
|
- (void)addImage:(NSString *)uri width:(float)width height:(float)height;
|
|
38
39
|
- (void)startMention:(NSString *)indicator;
|
|
@@ -331,6 +332,26 @@ if ([commandName isEqualToString:@"toggleUnorderedList"]) {
|
|
|
331
332
|
return;
|
|
332
333
|
}
|
|
333
334
|
|
|
335
|
+
if ([commandName isEqualToString:@"toggleCheckboxList"]) {
|
|
336
|
+
#if RCT_DEBUG
|
|
337
|
+
if ([args count] != 1) {
|
|
338
|
+
RCTLogError(@"%@ command %@ received %d arguments, expected %d.", @"EnrichedTextInputView", commandName, (int)[args count], 1);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
#endif
|
|
342
|
+
|
|
343
|
+
NSObject *arg0 = args[0];
|
|
344
|
+
#if RCT_DEBUG
|
|
345
|
+
if (!RCTValidateTypeOfViewCommandArgument(arg0, [NSNumber class], @"boolean", @"EnrichedTextInputView", commandName, @"1st")) {
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
#endif
|
|
349
|
+
BOOL checked = [(NSNumber *)arg0 boolValue];
|
|
350
|
+
|
|
351
|
+
[componentView toggleCheckboxList:checked];
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
334
355
|
if ([commandName isEqualToString:@"addLink"]) {
|
|
335
356
|
#if RCT_DEBUG
|
|
336
357
|
if ([args count] != 4) {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
BOOL inOrderedList = NO;
|
|
34
34
|
BOOL inBlockQuote = NO;
|
|
35
35
|
BOOL inCodeBlock = NO;
|
|
36
|
+
BOOL inCheckboxList = NO;
|
|
36
37
|
unichar lastCharacter = 0;
|
|
37
38
|
|
|
38
39
|
for (int i = 0; i < text.length; i++) {
|
|
@@ -107,6 +108,21 @@
|
|
|
107
108
|
[result appendString:@"\n</codeblock>\n<br>"];
|
|
108
109
|
inCodeBlock = NO;
|
|
109
110
|
}
|
|
111
|
+
} else if (inCheckboxList) {
|
|
112
|
+
CheckboxListStyle *cbLStyle = _input->stylesDict[@(CheckboxList)];
|
|
113
|
+
BOOL detected =
|
|
114
|
+
[cbLStyle detectStyle:NSMakeRange(currentRange.location, 0)];
|
|
115
|
+
if (detected) {
|
|
116
|
+
BOOL checked = [cbLStyle getCheckboxStateAt:currentRange.location];
|
|
117
|
+
if (checked) {
|
|
118
|
+
[result appendString:@"\n<li checked></li>"];
|
|
119
|
+
} else {
|
|
120
|
+
[result appendString:@"\n<li></li>"];
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
[result appendString:@"\n</ul>\n<br>"];
|
|
124
|
+
inCheckboxList = NO;
|
|
125
|
+
}
|
|
110
126
|
} else {
|
|
111
127
|
[result appendString:@"\n<br>"];
|
|
112
128
|
}
|
|
@@ -145,7 +161,9 @@
|
|
|
145
161
|
[previousActiveStyles
|
|
146
162
|
containsObject:@([BlockQuoteStyle getStyleType])] ||
|
|
147
163
|
[previousActiveStyles
|
|
148
|
-
containsObject:@([CodeBlockStyle getStyleType])]
|
|
164
|
+
containsObject:@([CodeBlockStyle getStyleType])] ||
|
|
165
|
+
[previousActiveStyles
|
|
166
|
+
containsObject:@([CheckboxListStyle getStyleType])]) {
|
|
149
167
|
// do nothing, proper closing paragraph tags have been already
|
|
150
168
|
// appended
|
|
151
169
|
} else {
|
|
@@ -191,6 +209,13 @@
|
|
|
191
209
|
inCodeBlock = NO;
|
|
192
210
|
[result appendString:@"\n</codeblock>"];
|
|
193
211
|
}
|
|
212
|
+
// handle ending checkbox list
|
|
213
|
+
if (inCheckboxList &&
|
|
214
|
+
![currentActiveStyles
|
|
215
|
+
containsObject:@([CheckboxListStyle getStyleType])]) {
|
|
216
|
+
inCheckboxList = NO;
|
|
217
|
+
[result appendString:@"\n</ul>"];
|
|
218
|
+
}
|
|
194
219
|
|
|
195
220
|
// handle starting unordered list
|
|
196
221
|
if (!inUnorderedList &&
|
|
@@ -220,6 +245,13 @@
|
|
|
220
245
|
inCodeBlock = YES;
|
|
221
246
|
[result appendString:@"\n<codeblock>"];
|
|
222
247
|
}
|
|
248
|
+
// handle starting checkbox list
|
|
249
|
+
if (!inCheckboxList &&
|
|
250
|
+
[currentActiveStyles
|
|
251
|
+
containsObject:@([CheckboxListStyle getStyleType])]) {
|
|
252
|
+
inCheckboxList = YES;
|
|
253
|
+
[result appendString:@"\n<ul data-type=\"checkbox\">"];
|
|
254
|
+
}
|
|
223
255
|
|
|
224
256
|
// don't add the <p> tag if some paragraph styles are present
|
|
225
257
|
if ([currentActiveStyles
|
|
@@ -235,7 +267,9 @@
|
|
|
235
267
|
[currentActiveStyles
|
|
236
268
|
containsObject:@([BlockQuoteStyle getStyleType])] ||
|
|
237
269
|
[currentActiveStyles
|
|
238
|
-
containsObject:@([CodeBlockStyle getStyleType])]
|
|
270
|
+
containsObject:@([CodeBlockStyle getStyleType])] ||
|
|
271
|
+
[currentActiveStyles
|
|
272
|
+
containsObject:@([CheckboxListStyle getStyleType])]) {
|
|
239
273
|
[result appendString:@"\n"];
|
|
240
274
|
} else {
|
|
241
275
|
[result appendString:@"\n<p>"];
|
|
@@ -381,6 +415,9 @@
|
|
|
381
415
|
} else if ([previousActiveStyles
|
|
382
416
|
containsObject:@([CodeBlockStyle getStyleType])]) {
|
|
383
417
|
[result appendString:@"\n</codeblock>"];
|
|
418
|
+
} else if ([previousActiveStyles
|
|
419
|
+
containsObject:@([CheckboxListStyle getStyleType])]) {
|
|
420
|
+
[result appendString:@"\n</ul>"];
|
|
384
421
|
} else if ([previousActiveStyles
|
|
385
422
|
containsObject:@([H1Style getStyleType])] ||
|
|
386
423
|
[previousActiveStyles
|
|
@@ -415,6 +452,10 @@
|
|
|
415
452
|
inCodeBlock = NO;
|
|
416
453
|
[result appendString:@"\n</codeblock>"];
|
|
417
454
|
}
|
|
455
|
+
if (inCheckboxList) {
|
|
456
|
+
inCheckboxList = NO;
|
|
457
|
+
[result appendString:@"\n</ul>"];
|
|
458
|
+
}
|
|
418
459
|
}
|
|
419
460
|
|
|
420
461
|
[result appendString:@"\n</html>"];
|
|
@@ -536,6 +577,20 @@
|
|
|
536
577
|
} else if ([style isEqualToNumber:@([UnorderedListStyle getStyleType])] ||
|
|
537
578
|
[style isEqualToNumber:@([OrderedListStyle getStyleType])]) {
|
|
538
579
|
return @"li";
|
|
580
|
+
} else if ([style isEqualToNumber:@([CheckboxListStyle getStyleType])]) {
|
|
581
|
+
if (openingTag) {
|
|
582
|
+
CheckboxListStyle *checkboxListStyleClass =
|
|
583
|
+
(CheckboxListStyle *)
|
|
584
|
+
_input->stylesDict[@([CheckboxListStyle getStyleType])];
|
|
585
|
+
BOOL checked = [checkboxListStyleClass getCheckboxStateAt:location];
|
|
586
|
+
|
|
587
|
+
if (checked) {
|
|
588
|
+
return @"li checked";
|
|
589
|
+
}
|
|
590
|
+
return @"li";
|
|
591
|
+
} else {
|
|
592
|
+
return @"li";
|
|
593
|
+
}
|
|
539
594
|
} else if ([style isEqualToNumber:@([BlockQuoteStyle getStyleType])] ||
|
|
540
595
|
[style isEqualToNumber:@([CodeBlockStyle getStyleType])]) {
|
|
541
596
|
// blockquotes and codeblock use <p> tags the same way lists use <li>
|
|
@@ -634,6 +689,28 @@
|
|
|
634
689
|
[((ImageStyle *)baseStyle) addImageAtRange:styleRange
|
|
635
690
|
imageData:imgData
|
|
636
691
|
withSelection:NO];
|
|
692
|
+
} else if ([styleType
|
|
693
|
+
isEqualToNumber:@([CheckboxListStyle getStyleType])]) {
|
|
694
|
+
NSDictionary *checkboxStates = (NSDictionary *)stylePair.styleValue;
|
|
695
|
+
CheckboxListStyle *cbLStyle = (CheckboxListStyle *)baseStyle;
|
|
696
|
+
|
|
697
|
+
// First apply the checkbox list style to the entire range with
|
|
698
|
+
// unchecked value
|
|
699
|
+
BOOL shouldAddTypingAttr =
|
|
700
|
+
styleRange.location + styleRange.length == plainTextLength;
|
|
701
|
+
[cbLStyle addAttributes:styleRange withTypingAttr:shouldAddTypingAttr];
|
|
702
|
+
|
|
703
|
+
if (!checkboxStates && checkboxStates.count == 0) {
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
// Then toggle checked checkboxes
|
|
707
|
+
for (NSNumber *key in checkboxStates) {
|
|
708
|
+
NSUInteger checkboxPosition = offset + [key unsignedIntegerValue];
|
|
709
|
+
BOOL isChecked = [checkboxStates[key] boolValue];
|
|
710
|
+
if (isChecked) {
|
|
711
|
+
[cbLStyle toggleCheckedAt:checkboxPosition];
|
|
712
|
+
}
|
|
713
|
+
}
|
|
637
714
|
} else {
|
|
638
715
|
BOOL shouldAddTypingAttr =
|
|
639
716
|
styleRange.location + styleRange.length == plainTextLength;
|
|
@@ -752,6 +829,10 @@
|
|
|
752
829
|
inString:fixedHtml
|
|
753
830
|
leading:YES
|
|
754
831
|
trailing:NO];
|
|
832
|
+
fixedHtml = [self stringByAddingNewlinesToTag:@"<li checked>"
|
|
833
|
+
inString:fixedHtml
|
|
834
|
+
leading:YES
|
|
835
|
+
trailing:NO];
|
|
755
836
|
fixedHtml = [self stringByAddingNewlinesToTag:@"<h1>"
|
|
756
837
|
inString:fixedHtml
|
|
757
838
|
leading:YES
|
|
@@ -983,6 +1064,8 @@
|
|
|
983
1064
|
NSMutableString *plainText = [[NSMutableString alloc] initWithString:@""];
|
|
984
1065
|
NSMutableDictionary *ongoingTags = [[NSMutableDictionary alloc] init];
|
|
985
1066
|
NSMutableArray *initiallyProcessedTags = [[NSMutableArray alloc] init];
|
|
1067
|
+
NSMutableDictionary *checkboxStates = [[NSMutableDictionary alloc] init];
|
|
1068
|
+
BOOL insideCheckboxList = NO;
|
|
986
1069
|
_precedingImageCount = 0;
|
|
987
1070
|
BOOL insideTag = NO;
|
|
988
1071
|
BOOL gettingTagName = NO;
|
|
@@ -1023,9 +1106,14 @@
|
|
|
1023
1106
|
}
|
|
1024
1107
|
|
|
1025
1108
|
if ([currentTagName isEqualToString:@"p"] ||
|
|
1026
|
-
[currentTagName isEqualToString:@"br"]
|
|
1027
|
-
[currentTagName isEqualToString:@"li"]) {
|
|
1109
|
+
[currentTagName isEqualToString:@"br"]) {
|
|
1028
1110
|
// do nothing, we don't include these tags in styles
|
|
1111
|
+
} else if ([currentTagName isEqualToString:@"li"]) {
|
|
1112
|
+
// Only track checkbox state if we're inside a checkbox list
|
|
1113
|
+
if (insideCheckboxList && !closingTag) {
|
|
1114
|
+
BOOL isChecked = [currentTagParams containsString:@"checked"];
|
|
1115
|
+
checkboxStates[@(plainText.length)] = @(isChecked);
|
|
1116
|
+
}
|
|
1029
1117
|
} else if (!closingTag) {
|
|
1030
1118
|
// we finish opening tag - get its location and optionally params and
|
|
1031
1119
|
// put them under tag name key in ongoingTags
|
|
@@ -1036,6 +1124,12 @@
|
|
|
1036
1124
|
}
|
|
1037
1125
|
ongoingTags[currentTagName] = tagArr;
|
|
1038
1126
|
|
|
1127
|
+
// Check if this is a checkbox list
|
|
1128
|
+
if ([currentTagName isEqualToString:@"ul"] &&
|
|
1129
|
+
[self isUlCheckboxList:currentTagParams]) {
|
|
1130
|
+
insideCheckboxList = YES;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1039
1133
|
// skip one newline after opening tags that are in separate lines
|
|
1040
1134
|
// intentionally
|
|
1041
1135
|
if ([currentTagName isEqualToString:@"ul"] ||
|
|
@@ -1055,6 +1149,12 @@
|
|
|
1055
1149
|
// we finish closing tags - pack tag name, tag range and optionally tag
|
|
1056
1150
|
// params into an entry that goes inside initiallyProcessedTags
|
|
1057
1151
|
|
|
1152
|
+
// Check if we're closing a checkbox list by looking at the params
|
|
1153
|
+
if ([currentTagName isEqualToString:@"ul"] &&
|
|
1154
|
+
[self isUlCheckboxList:currentTagParams]) {
|
|
1155
|
+
insideCheckboxList = NO;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1058
1158
|
// skip one newline that was added before some closing tags that are in
|
|
1059
1159
|
// separate lines
|
|
1060
1160
|
if ([currentTagName isEqualToString:@"ul"] ||
|
|
@@ -1215,7 +1315,7 @@
|
|
|
1215
1315
|
[styleArr addObject:@([MentionStyle getStyleType])];
|
|
1216
1316
|
// extract html expression into dict using some regex
|
|
1217
1317
|
NSMutableDictionary *paramsDict = [[NSMutableDictionary alloc] init];
|
|
1218
|
-
NSString *pattern = @"(\\w+)
|
|
1318
|
+
NSString *pattern = @"(\\w+)=(['\"])(.*?)\\2";
|
|
1219
1319
|
NSRegularExpression *regex =
|
|
1220
1320
|
[NSRegularExpression regularExpressionWithPattern:pattern
|
|
1221
1321
|
options:0
|
|
@@ -1227,11 +1327,11 @@
|
|
|
1227
1327
|
usingBlock:^(NSTextCheckingResult *_Nullable result,
|
|
1228
1328
|
NSMatchingFlags flags,
|
|
1229
1329
|
BOOL *_Nonnull stop) {
|
|
1230
|
-
if (result.numberOfRanges ==
|
|
1330
|
+
if (result.numberOfRanges == 4) {
|
|
1231
1331
|
NSString *key = [params
|
|
1232
1332
|
substringWithRange:[result rangeAtIndex:1]];
|
|
1233
1333
|
NSString *value = [params
|
|
1234
|
-
substringWithRange:[result rangeAtIndex:
|
|
1334
|
+
substringWithRange:[result rangeAtIndex:3]];
|
|
1235
1335
|
paramsDict[key] = value;
|
|
1236
1336
|
}
|
|
1237
1337
|
}];
|
|
@@ -1267,7 +1367,14 @@
|
|
|
1267
1367
|
[styleArr addObject:@([H6Style getStyleType])];
|
|
1268
1368
|
}
|
|
1269
1369
|
} else if ([tagName isEqualToString:@"ul"]) {
|
|
1270
|
-
|
|
1370
|
+
if ([self isUlCheckboxList:params]) {
|
|
1371
|
+
[styleArr addObject:@([CheckboxListStyle getStyleType])];
|
|
1372
|
+
stylePair.styleValue =
|
|
1373
|
+
[self prepareCheckboxListStyleValue:tagRangeValue
|
|
1374
|
+
checkboxStates:checkboxStates];
|
|
1375
|
+
} else {
|
|
1376
|
+
[styleArr addObject:@([UnorderedListStyle getStyleType])];
|
|
1377
|
+
}
|
|
1271
1378
|
} else if ([tagName isEqualToString:@"ol"]) {
|
|
1272
1379
|
[styleArr addObject:@([OrderedListStyle getStyleType])];
|
|
1273
1380
|
} else if ([tagName isEqualToString:@"blockquote"]) {
|
|
@@ -1288,4 +1395,24 @@
|
|
|
1288
1395
|
return @[ plainText, processedStyles ];
|
|
1289
1396
|
}
|
|
1290
1397
|
|
|
1398
|
+
- (BOOL)isUlCheckboxList:(NSString *)params {
|
|
1399
|
+
return ([params containsString:@"data-type=\"checkbox\""] ||
|
|
1400
|
+
[params containsString:@"data-type='checkbox'"]);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
- (NSDictionary *)prepareCheckboxListStyleValue:(NSValue *)rangeValue
|
|
1404
|
+
checkboxStates:(NSDictionary *)checkboxStates {
|
|
1405
|
+
NSRange range = [rangeValue rangeValue];
|
|
1406
|
+
NSMutableDictionary *statesInRange = [[NSMutableDictionary alloc] init];
|
|
1407
|
+
|
|
1408
|
+
for (NSNumber *key in checkboxStates) {
|
|
1409
|
+
NSUInteger pos = [key unsignedIntegerValue];
|
|
1410
|
+
if (pos >= range.location && pos < range.location + range.length) {
|
|
1411
|
+
[statesInRange setObject:checkboxStates[key] forKey:key];
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
return statesInRange;
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1291
1418
|
@end
|
|
@@ -55,6 +55,67 @@
|
|
|
55
55
|
NSArray<NSString *> *pasteboardTypes = pasteboard.pasteboardTypes;
|
|
56
56
|
NSRange currentRange = typedInput->textView.selectedRange;
|
|
57
57
|
|
|
58
|
+
// Check the pasteboard for supported image formats. If found, save them to
|
|
59
|
+
// temporary storage then emit the 'onPasteImages' event and stop processing
|
|
60
|
+
// further (ignoring any HTML/Text).
|
|
61
|
+
NSMutableArray<NSDictionary *> *foundImages = [NSMutableArray new];
|
|
62
|
+
|
|
63
|
+
for (NSDictionary<NSString *, id> *item in pasteboard.items) {
|
|
64
|
+
NSData *imageData = nil;
|
|
65
|
+
BOOL added = NO;
|
|
66
|
+
NSString *ext = nil;
|
|
67
|
+
NSString *mimeType = nil;
|
|
68
|
+
|
|
69
|
+
for (int j = 0; j < item.allKeys.count; j++) {
|
|
70
|
+
if (added) {
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
NSString *type = item.allKeys[j];
|
|
75
|
+
if ([type isEqual:UTTypeJPEG.identifier] ||
|
|
76
|
+
[type isEqual:UTTypePNG.identifier] ||
|
|
77
|
+
[type isEqual:UTTypeWebP.identifier] ||
|
|
78
|
+
[type isEqual:UTTypeHEIC.identifier] ||
|
|
79
|
+
[type isEqual:UTTypeTIFF.identifier]) {
|
|
80
|
+
imageData = [self getDataForImageItem:item[type] type:type];
|
|
81
|
+
} else if ([type isEqual:UTTypeGIF.identifier]) {
|
|
82
|
+
// gifs
|
|
83
|
+
imageData = [pasteboard dataForPasteboardType:type];
|
|
84
|
+
}
|
|
85
|
+
if (!imageData) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
NSDictionary *info = [self detectImageFormat:type];
|
|
90
|
+
if (!info) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
ext = info[@"ext"];
|
|
94
|
+
mimeType = info[@"mime"];
|
|
95
|
+
|
|
96
|
+
UIImage *imageInfo = [UIImage imageWithData:imageData];
|
|
97
|
+
|
|
98
|
+
if (imageInfo) {
|
|
99
|
+
NSString *path = [self saveToTempFile:imageData extension:ext];
|
|
100
|
+
|
|
101
|
+
if (path) {
|
|
102
|
+
added = YES;
|
|
103
|
+
[foundImages addObject:@{
|
|
104
|
+
@"uri" : path,
|
|
105
|
+
@"type" : mimeType,
|
|
106
|
+
@"width" : @(imageInfo.size.width),
|
|
107
|
+
@"height" : @(imageInfo.size.height)
|
|
108
|
+
}];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (foundImages.count > 0) {
|
|
115
|
+
[typedInput emitOnPasteImagesEvent:foundImages];
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
58
119
|
if ([pasteboardTypes containsObject:UTTypeHTML.identifier]) {
|
|
59
120
|
// we try processing the html contents
|
|
60
121
|
|
|
@@ -94,6 +155,52 @@
|
|
|
94
155
|
[typedInput anyTextMayHaveBeenModified];
|
|
95
156
|
}
|
|
96
157
|
|
|
158
|
+
- (NSDictionary *)detectImageFormat:(NSString *)type {
|
|
159
|
+
if ([type isEqual:UTTypeJPEG.identifier]) {
|
|
160
|
+
return @{@"ext" : @"jpg", @"mime" : @"image/jpeg"};
|
|
161
|
+
} else if ([type isEqual:UTTypePNG.identifier]) {
|
|
162
|
+
return @{@"ext" : @"png", @"mime" : @"image/png"};
|
|
163
|
+
} else if ([type isEqual:UTTypeGIF.identifier]) {
|
|
164
|
+
return @{@"ext" : @"gif", @"mime" : @"image/gif"};
|
|
165
|
+
} else if ([type isEqual:UTTypeHEIC.identifier]) {
|
|
166
|
+
return @{@"ext" : @"heic", @"mime" : @"image/heic"};
|
|
167
|
+
} else if ([type isEqual:UTTypeWebP.identifier]) {
|
|
168
|
+
return @{@"ext" : @"webp", @"mime" : @"image/webp"};
|
|
169
|
+
} else if ([type isEqual:UTTypeTIFF.identifier]) {
|
|
170
|
+
return @{@"ext" : @"tiff", @"mime" : @"image/tiff"};
|
|
171
|
+
} else {
|
|
172
|
+
return nil;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
- (NSData *)getDataForImageItem:(NSData *)imageData type:(NSString *)type {
|
|
177
|
+
UIImage *image = (UIImage *)imageData;
|
|
178
|
+
|
|
179
|
+
if ([type isEqual:UTTypePNG.identifier]) {
|
|
180
|
+
return UIImagePNGRepresentation(image);
|
|
181
|
+
} else if ([type isEqual:UTTypeHEIC.identifier]) {
|
|
182
|
+
return UIImageHEICRepresentation(image);
|
|
183
|
+
} else {
|
|
184
|
+
return UIImageJPEGRepresentation(image, 1.0);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
- (NSString *)saveToTempFile:(NSData *)data extension:(NSString *)ext {
|
|
189
|
+
if (!data)
|
|
190
|
+
return nil;
|
|
191
|
+
NSString *fileName =
|
|
192
|
+
[NSString stringWithFormat:@"%@.%@", [NSUUID UUID].UUIDString, ext];
|
|
193
|
+
|
|
194
|
+
NSString *filePath =
|
|
195
|
+
[NSTemporaryDirectory() stringByAppendingPathComponent:fileName];
|
|
196
|
+
|
|
197
|
+
if ([data writeToFile:filePath atomically:YES]) {
|
|
198
|
+
return [NSURL fileURLWithPath:filePath].absoluteString;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return nil;
|
|
202
|
+
}
|
|
203
|
+
|
|
97
204
|
- (void)tryHandlingPlainTextItemsIn:(UIPasteboard *)pasteboard
|
|
98
205
|
range:(NSRange)range
|
|
99
206
|
input:(EnrichedTextInputView *)input {
|
|
@@ -153,4 +260,15 @@
|
|
|
153
260
|
[typedInput anyTextMayHaveBeenModified];
|
|
154
261
|
}
|
|
155
262
|
|
|
263
|
+
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
|
|
264
|
+
if (action == @selector(paste:)) {
|
|
265
|
+
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
|
|
266
|
+
// Enable Paste if clipboard has Text OR Images
|
|
267
|
+
if (pasteboard.hasStrings || pasteboard.hasImages) {
|
|
268
|
+
return YES;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return [super canPerformAction:action withSender:sender];
|
|
272
|
+
}
|
|
273
|
+
|
|
156
274
|
@end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import "ImageAttachment.h"
|
|
2
|
+
#import "ImageExtension.h"
|
|
2
3
|
|
|
3
4
|
@implementation ImageAttachment
|
|
4
5
|
|
|
@@ -8,26 +9,64 @@
|
|
|
8
9
|
return nil;
|
|
9
10
|
|
|
10
11
|
_imageData = data;
|
|
12
|
+
|
|
13
|
+
// Assign an empty image to reserve layout space within the text system.
|
|
14
|
+
// The actual image is not drawn here; it is rendered and overlaid by a
|
|
15
|
+
// separate ImageView.
|
|
11
16
|
self.image = [UIImage new];
|
|
12
17
|
|
|
13
18
|
[self loadAsync];
|
|
14
19
|
return self;
|
|
15
20
|
}
|
|
16
21
|
|
|
22
|
+
- (CGRect)attachmentBoundsForTextContainer:(NSTextContainer *)textContainer
|
|
23
|
+
proposedLineFragment:(CGRect)lineFrag
|
|
24
|
+
glyphPosition:(CGPoint)position
|
|
25
|
+
characterIndex:(NSUInteger)charIndex {
|
|
26
|
+
CGRect baseBounds = self.bounds;
|
|
27
|
+
|
|
28
|
+
if (!textContainer.layoutManager.textStorage ||
|
|
29
|
+
charIndex >= textContainer.layoutManager.textStorage.length) {
|
|
30
|
+
return baseBounds;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
UIFont *font =
|
|
34
|
+
[textContainer.layoutManager.textStorage attribute:NSFontAttributeName
|
|
35
|
+
atIndex:charIndex
|
|
36
|
+
effectiveRange:NULL];
|
|
37
|
+
if (!font) {
|
|
38
|
+
return baseBounds;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Extend the layout bounds below the baseline by the font's descender.
|
|
42
|
+
// Without this, a line containing only the attachment has no descender space
|
|
43
|
+
// below the baseline, but adding a text character introduces it — causing
|
|
44
|
+
// the line height to jump. By reserving descender space upfront the line
|
|
45
|
+
// height stays consistent regardless of whether text is present.
|
|
46
|
+
CGFloat descender = font.descender;
|
|
47
|
+
return CGRectMake(baseBounds.origin.x, descender, baseBounds.size.width,
|
|
48
|
+
baseBounds.size.height - descender);
|
|
49
|
+
}
|
|
50
|
+
|
|
17
51
|
- (void)loadAsync {
|
|
18
52
|
NSURL *url = [NSURL URLWithString:self.uri];
|
|
19
53
|
if (!url) {
|
|
20
|
-
self.
|
|
54
|
+
self.storedAnimatedImage = [UIImage systemImageNamed:@"photo"];
|
|
21
55
|
return;
|
|
22
56
|
}
|
|
23
57
|
|
|
24
58
|
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
|
|
25
59
|
NSData *bytes = [NSData dataWithContentsOfURL:url];
|
|
26
|
-
|
|
27
|
-
|
|
60
|
+
|
|
61
|
+
// We pass all image data (including static formats like PNG or JPEG)
|
|
62
|
+
// through the GIF parser. It safely acts as a universal parser, returning
|
|
63
|
+
// a single-frame UIImage for static formats and an animated UIImage for
|
|
64
|
+
// GIFs.
|
|
65
|
+
UIImage *img = bytes ? [UIImage animatedImageWithAnimatedGIFData:bytes]
|
|
66
|
+
: [UIImage systemImageNamed:@"photo"];
|
|
28
67
|
|
|
29
68
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
30
|
-
self.
|
|
69
|
+
self.storedAnimatedImage = img;
|
|
31
70
|
[self notifyUpdate];
|
|
32
71
|
});
|
|
33
72
|
});
|
|
@@ -55,10 +55,10 @@
|
|
|
55
55
|
id input;
|
|
56
56
|
}
|
|
57
57
|
- (CGFloat)getHeadingFontSize;
|
|
58
|
+
- (NSString *)getHeadingLevelString;
|
|
58
59
|
- (BOOL)isHeadingBold;
|
|
59
60
|
- (BOOL)handleNewlinesInRange:(NSRange)range replacementText:(NSString *)text;
|
|
60
|
-
- (
|
|
61
|
-
@property(nonatomic, assign) CGFloat lastAppliedFontSize;
|
|
61
|
+
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
62
62
|
@end
|
|
63
63
|
|
|
64
64
|
@interface H1Style : HeadingStyleBase
|
|
@@ -91,6 +91,17 @@
|
|
|
91
91
|
replacementText:(NSString *)text;
|
|
92
92
|
@end
|
|
93
93
|
|
|
94
|
+
@interface CheckboxListStyle : NSObject <BaseStyleProtocol>
|
|
95
|
+
- (void)applyStyleWithCheckedValue:(BOOL)checked inRange:(NSRange)range;
|
|
96
|
+
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
97
|
+
- (BOOL)getCheckboxStateAt:(NSUInteger)location;
|
|
98
|
+
- (void)toggleCheckedAt:(NSUInteger)location;
|
|
99
|
+
- (BOOL)handleNewlinesInRange:(NSRange)range replacementText:(NSString *)text;
|
|
100
|
+
- (void)addAttributesWithCheckedValue:(BOOL)checked
|
|
101
|
+
inRange:(NSRange)range
|
|
102
|
+
withTypingAttr:(BOOL)withTypingAttr;
|
|
103
|
+
@end
|
|
104
|
+
|
|
94
105
|
@interface BlockQuoteStyle : NSObject <BaseStyleProtocol>
|
|
95
106
|
- (BOOL)handleBackspaceInRange:(NSRange)range replacementText:(NSString *)text;
|
|
96
107
|
- (void)manageBlockquoteColor;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#include "EnrichedTextInputViewState.h"
|
|
2
2
|
|
|
3
3
|
namespace facebook::react {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
int EnrichedTextInputViewState::getForceHeightRecalculationCounter() const {
|
|
5
|
+
return forceHeightRecalculationCounter_;
|
|
6
|
+
}
|
|
7
|
+
std::shared_ptr<void> EnrichedTextInputViewState::getComponentViewRef() const {
|
|
8
|
+
return componentViewRef_;
|
|
9
|
+
}
|
|
10
10
|
} // namespace facebook::react
|