react-native-enriched 0.2.0 → 0.2.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.
Files changed (107) hide show
  1. package/README.md +1 -5
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +3 -0
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +1 -0
  4. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +10 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +7 -0
  6. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +92 -0
  7. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +6 -0
  8. package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +1 -1
  9. package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +33 -0
  10. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +6 -0
  11. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +6 -0
  12. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +6 -0
  13. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +6 -0
  14. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +6 -0
  15. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +6 -0
  16. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +5 -0
  17. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +6 -0
  18. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +5 -0
  19. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +6 -0
  20. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +6 -0
  21. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +6 -0
  22. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +9 -3
  23. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +5 -0
  24. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +5 -0
  25. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +6 -0
  26. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +4 -0
  27. package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +78 -0
  28. package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +80 -4
  29. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +8 -0
  30. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
  31. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
  32. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
  33. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
  34. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
  35. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
  36. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
  37. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
  38. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
  39. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +12 -13
  40. package/ios/EnrichedTextInputView.h +25 -13
  41. package/ios/EnrichedTextInputView.mm +872 -581
  42. package/ios/attachments/ImageAttachment.h +10 -0
  43. package/ios/attachments/ImageAttachment.mm +34 -0
  44. package/ios/attachments/MediaAttachment.h +23 -0
  45. package/ios/attachments/MediaAttachment.mm +31 -0
  46. package/ios/config/InputConfig.h +6 -6
  47. package/ios/config/InputConfig.mm +39 -33
  48. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +10 -0
  49. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +7 -0
  50. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +21 -0
  51. package/ios/inputParser/InputParser.h +5 -5
  52. package/ios/inputParser/InputParser.mm +789 -378
  53. package/ios/inputTextView/InputTextView.h +1 -1
  54. package/ios/inputTextView/InputTextView.mm +100 -59
  55. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
  56. package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
  57. package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
  58. package/ios/internals/EnrichedTextInputViewState.h +3 -1
  59. package/ios/styles/BlockQuoteStyle.mm +189 -118
  60. package/ios/styles/BoldStyle.mm +95 -63
  61. package/ios/styles/CodeBlockStyle.mm +204 -128
  62. package/ios/styles/H1Style.mm +10 -4
  63. package/ios/styles/H2Style.mm +10 -4
  64. package/ios/styles/H3Style.mm +10 -4
  65. package/ios/styles/HeadingStyleBase.mm +129 -84
  66. package/ios/styles/ImageStyle.mm +75 -73
  67. package/ios/styles/InlineCodeStyle.mm +148 -85
  68. package/ios/styles/ItalicStyle.mm +76 -52
  69. package/ios/styles/LinkStyle.mm +348 -227
  70. package/ios/styles/MentionStyle.mm +363 -246
  71. package/ios/styles/OrderedListStyle.mm +171 -106
  72. package/ios/styles/StrikethroughStyle.mm +52 -35
  73. package/ios/styles/UnderlineStyle.mm +68 -46
  74. package/ios/styles/UnorderedListStyle.mm +169 -106
  75. package/ios/utils/BaseStyleProtocol.h +2 -2
  76. package/ios/utils/ColorExtension.mm +7 -5
  77. package/ios/utils/FontExtension.mm +42 -27
  78. package/ios/utils/LayoutManagerExtension.h +1 -1
  79. package/ios/utils/LayoutManagerExtension.mm +280 -170
  80. package/ios/utils/MentionParams.h +0 -1
  81. package/ios/utils/MentionStyleProps.h +1 -1
  82. package/ios/utils/MentionStyleProps.mm +27 -20
  83. package/ios/utils/OccurenceUtils.h +42 -42
  84. package/ios/utils/OccurenceUtils.mm +142 -119
  85. package/ios/utils/ParagraphAttributesUtils.h +6 -2
  86. package/ios/utils/ParagraphAttributesUtils.mm +115 -71
  87. package/ios/utils/ParagraphsUtils.h +2 -1
  88. package/ios/utils/ParagraphsUtils.mm +40 -26
  89. package/ios/utils/StringExtension.h +1 -1
  90. package/ios/utils/StringExtension.mm +19 -16
  91. package/ios/utils/StyleHeaders.h +27 -15
  92. package/ios/utils/TextInsertionUtils.h +13 -2
  93. package/ios/utils/TextInsertionUtils.mm +38 -20
  94. package/ios/utils/WordsUtils.h +2 -1
  95. package/ios/utils/WordsUtils.mm +32 -22
  96. package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
  97. package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
  98. package/lib/module/EnrichedTextInput.js +39 -1
  99. package/lib/module/EnrichedTextInput.js.map +1 -1
  100. package/lib/module/EnrichedTextInputNativeComponent.ts +11 -0
  101. package/lib/typescript/src/EnrichedTextInput.d.ts +1 -0
  102. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  103. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +6 -0
  104. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  105. package/package.json +8 -1
  106. package/src/EnrichedTextInput.tsx +45 -0
  107. package/src/EnrichedTextInputNativeComponent.ts +11 -0
@@ -1,24 +1,25 @@
1
1
  #import "EnrichedTextInputView.h"
2
+ #import "CoreText/CoreText.h"
3
+ #import "LayoutManagerExtension.h"
4
+ #import "ParagraphAttributesUtils.h"
2
5
  #import "RCTFabricComponentsPlugins.h"
6
+ #import "StringExtension.h"
7
+ #import "StyleHeaders.h"
8
+ #import "UIView+React.h"
9
+ #import "WordsUtils.h"
10
+ #import "ZeroWidthSpaceUtils.h"
11
+ #import <React/RCTConversions.h>
3
12
  #import <ReactNativeEnriched/EnrichedTextInputViewComponentDescriptor.h>
4
13
  #import <ReactNativeEnriched/EventEmitters.h>
5
14
  #import <ReactNativeEnriched/Props.h>
6
15
  #import <ReactNativeEnriched/RCTComponentViewHelpers.h>
7
- #import <react/utils/ManagedObjectWrapper.h>
8
16
  #import <folly/dynamic.h>
9
- #import "UIView+React.h"
10
- #import "StringExtension.h"
11
- #import "CoreText/CoreText.h"
12
- #import <React/RCTConversions.h>
13
- #import "StyleHeaders.h"
14
- #import "WordsUtils.h"
15
- #import "LayoutManagerExtension.h"
16
- #import "ZeroWidthSpaceUtils.h"
17
- #import "ParagraphAttributesUtils.h"
17
+ #import <react/utils/ManagedObjectWrapper.h>
18
18
 
19
19
  using namespace facebook::react;
20
20
 
21
- @interface EnrichedTextInputView () <RCTEnrichedTextInputViewViewProtocol, UITextViewDelegate, NSObject>
21
+ @interface EnrichedTextInputView () <RCTEnrichedTextInputViewViewProtocol,
22
+ UITextViewDelegate, NSObject>
22
23
 
23
24
  @end
24
25
 
@@ -28,7 +29,7 @@ using namespace facebook::react;
28
29
  NSMutableSet<NSNumber *> *_activeStyles;
29
30
  LinkData *_recentlyActiveLinkData;
30
31
  NSRange _recentlyActiveLinkRange;
31
- NSString *_recentlyEmittedString;
32
+ NSString *_recentInputString;
32
33
  MentionParams *_recentlyActiveMentionParams;
33
34
  NSRange _recentlyActiveMentionRange;
34
35
  NSString *_recentlyEmittedHtml;
@@ -41,7 +42,8 @@ using namespace facebook::react;
41
42
  // MARK: - Component utils
42
43
 
43
44
  + (ComponentDescriptorProvider)componentDescriptorProvider {
44
- return concreteComponentDescriptorProvider<EnrichedTextInputViewComponentDescriptor>();
45
+ return concreteComponentDescriptorProvider<
46
+ EnrichedTextInputViewComponentDescriptor>();
45
47
  }
46
48
 
47
49
  Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
@@ -56,7 +58,8 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
56
58
 
57
59
  - (instancetype)initWithFrame:(CGRect)frame {
58
60
  if (self = [super initWithFrame:frame]) {
59
- static const auto defaultProps = std::make_shared<const EnrichedTextInputViewProps>();
61
+ static const auto defaultProps =
62
+ std::make_shared<const EnrichedTextInputViewProps>();
60
63
  _props = defaultProps;
61
64
  [self setDefaults];
62
65
  [self setupTextView];
@@ -72,69 +75,118 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
72
75
  _recentlyActiveLinkRange = NSMakeRange(0, 0);
73
76
  _recentlyActiveMentionRange = NSMakeRange(0, 0);
74
77
  recentlyChangedRange = NSMakeRange(0, 0);
75
- _recentlyEmittedString = @"";
78
+ _recentInputString = @"";
76
79
  _recentlyEmittedHtml = @"<html>\n<p></p>\n</html>";
77
80
  _emitHtml = NO;
78
81
  blockEmitting = NO;
79
82
  _emitFocusBlur = YES;
80
-
81
- defaultTypingAttributes = [[NSMutableDictionary<NSAttributedStringKey, id> alloc] init];
82
-
83
+
84
+ defaultTypingAttributes =
85
+ [[NSMutableDictionary<NSAttributedStringKey, id> alloc] init];
86
+
83
87
  stylesDict = @{
84
88
  @([BoldStyle getStyleType]) : [[BoldStyle alloc] initWithInput:self],
85
- @([ItalicStyle getStyleType]): [[ItalicStyle alloc] initWithInput:self],
86
- @([UnderlineStyle getStyleType]): [[UnderlineStyle alloc] initWithInput:self],
87
- @([StrikethroughStyle getStyleType]): [[StrikethroughStyle alloc] initWithInput:self],
88
- @([InlineCodeStyle getStyleType]): [[InlineCodeStyle alloc] initWithInput:self],
89
- @([LinkStyle getStyleType]): [[LinkStyle alloc] initWithInput:self],
90
- @([MentionStyle getStyleType]): [[MentionStyle alloc] initWithInput:self],
91
- @([H1Style getStyleType]): [[H1Style alloc] initWithInput:self],
92
- @([H2Style getStyleType]): [[H2Style alloc] initWithInput:self],
93
- @([H3Style getStyleType]): [[H3Style alloc] initWithInput:self],
94
- @([UnorderedListStyle getStyleType]): [[UnorderedListStyle alloc] initWithInput:self],
95
- @([OrderedListStyle getStyleType]): [[OrderedListStyle alloc] initWithInput:self],
96
- @([BlockQuoteStyle getStyleType]): [[BlockQuoteStyle alloc] initWithInput:self],
97
- @([CodeBlockStyle getStyleType]): [[CodeBlockStyle alloc] initWithInput:self],
98
- @([ImageStyle getStyleType]): [[ImageStyle alloc] initWithInput:self]
89
+ @([ItalicStyle getStyleType]) : [[ItalicStyle alloc] initWithInput:self],
90
+ @([UnderlineStyle getStyleType]) :
91
+ [[UnderlineStyle alloc] initWithInput:self],
92
+ @([StrikethroughStyle getStyleType]) :
93
+ [[StrikethroughStyle alloc] initWithInput:self],
94
+ @([InlineCodeStyle getStyleType]) :
95
+ [[InlineCodeStyle alloc] initWithInput:self],
96
+ @([LinkStyle getStyleType]) : [[LinkStyle alloc] initWithInput:self],
97
+ @([MentionStyle getStyleType]) : [[MentionStyle alloc] initWithInput:self],
98
+ @([H1Style getStyleType]) : [[H1Style alloc] initWithInput:self],
99
+ @([H2Style getStyleType]) : [[H2Style alloc] initWithInput:self],
100
+ @([H3Style getStyleType]) : [[H3Style alloc] initWithInput:self],
101
+ @([UnorderedListStyle getStyleType]) :
102
+ [[UnorderedListStyle alloc] initWithInput:self],
103
+ @([OrderedListStyle getStyleType]) :
104
+ [[OrderedListStyle alloc] initWithInput:self],
105
+ @([BlockQuoteStyle getStyleType]) :
106
+ [[BlockQuoteStyle alloc] initWithInput:self],
107
+ @([CodeBlockStyle getStyleType]) :
108
+ [[CodeBlockStyle alloc] initWithInput:self],
109
+ @([ImageStyle getStyleType]) : [[ImageStyle alloc] initWithInput:self]
99
110
  };
100
-
111
+
101
112
  conflictingStyles = @{
102
113
  @([BoldStyle getStyleType]) : @[],
103
114
  @([ItalicStyle getStyleType]) : @[],
104
115
  @([UnderlineStyle getStyleType]) : @[],
105
116
  @([StrikethroughStyle getStyleType]) : @[],
106
- @([InlineCodeStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
107
- @([LinkStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]), @([MentionStyle getStyleType])],
108
- @([MentionStyle getStyleType]): @[@([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType])],
109
- @([H1Style getStyleType]): @[@([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])],
110
- @([H2Style getStyleType]): @[@([H1Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])],
111
- @([H3Style getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])],
112
- @([UnorderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])],
113
- @([OrderedListStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])],
114
- @([BlockQuoteStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([CodeBlockStyle getStyleType])],
115
- @([CodeBlockStyle getStyleType]): @[@([H1Style getStyleType]), @([H2Style getStyleType]), @([H3Style getStyleType]),
116
- @([BoldStyle getStyleType]), @([ItalicStyle getStyleType]), @([UnderlineStyle getStyleType]), @([StrikethroughStyle getStyleType]), @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]), @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]), @([MentionStyle getStyleType]), @([LinkStyle getStyleType])],
117
- @([ImageStyle getStyleType]) : @[@([LinkStyle getStyleType]), @([MentionStyle getStyleType])]
117
+ @([InlineCodeStyle getStyleType]) :
118
+ @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ],
119
+ @([LinkStyle getStyleType]) : @[
120
+ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]),
121
+ @([MentionStyle getStyleType])
122
+ ],
123
+ @([MentionStyle getStyleType]) :
124
+ @[ @([InlineCodeStyle getStyleType]), @([LinkStyle getStyleType]) ],
125
+ @([H1Style getStyleType]) : @[
126
+ @([H2Style getStyleType]), @([H3Style getStyleType]),
127
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
128
+ @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
129
+ ],
130
+ @([H2Style getStyleType]) : @[
131
+ @([H1Style getStyleType]), @([H3Style getStyleType]),
132
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
133
+ @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
134
+ ],
135
+ @([H3Style getStyleType]) : @[
136
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
137
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
138
+ @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
139
+ ],
140
+ @([UnorderedListStyle getStyleType]) : @[
141
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
142
+ @([H3Style getStyleType]), @([OrderedListStyle getStyleType]),
143
+ @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
144
+ ],
145
+ @([OrderedListStyle getStyleType]) : @[
146
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
147
+ @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]),
148
+ @([BlockQuoteStyle getStyleType]), @([CodeBlockStyle getStyleType])
149
+ ],
150
+ @([BlockQuoteStyle getStyleType]) : @[
151
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
152
+ @([H3Style getStyleType]), @([UnorderedListStyle getStyleType]),
153
+ @([OrderedListStyle getStyleType]), @([CodeBlockStyle getStyleType])
154
+ ],
155
+ @([CodeBlockStyle getStyleType]) : @[
156
+ @([H1Style getStyleType]), @([H2Style getStyleType]),
157
+ @([H3Style getStyleType]), @([BoldStyle getStyleType]),
158
+ @([ItalicStyle getStyleType]), @([UnderlineStyle getStyleType]),
159
+ @([StrikethroughStyle getStyleType]),
160
+ @([UnorderedListStyle getStyleType]), @([OrderedListStyle getStyleType]),
161
+ @([BlockQuoteStyle getStyleType]), @([InlineCodeStyle getStyleType]),
162
+ @([MentionStyle getStyleType]), @([LinkStyle getStyleType])
163
+ ],
164
+ @([ImageStyle getStyleType]) :
165
+ @[ @([LinkStyle getStyleType]), @([MentionStyle getStyleType]) ]
118
166
  };
119
-
167
+
120
168
  blockingStyles = @{
121
- @([BoldStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
122
- @([ItalicStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
123
- @([UnderlineStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
124
- @([StrikethroughStyle getStyleType]) : @[@([CodeBlockStyle getStyleType])],
125
- @([InlineCodeStyle getStyleType]) : @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
126
- @([LinkStyle getStyleType]): @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
127
- @([MentionStyle getStyleType]): @[@([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType])],
128
- @([H1Style getStyleType]): @[],
129
- @([H2Style getStyleType]): @[],
130
- @([H3Style getStyleType]): @[],
131
- @([UnorderedListStyle getStyleType]): @[],
132
- @([OrderedListStyle getStyleType]): @[],
133
- @([BlockQuoteStyle getStyleType]): @[],
134
- @([CodeBlockStyle getStyleType]): @[],
135
- @([ImageStyle getStyleType]) : @[@([InlineCodeStyle getStyleType])]
169
+ @([BoldStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
170
+ @([ItalicStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
171
+ @([UnderlineStyle getStyleType]) : @[ @([CodeBlockStyle getStyleType]) ],
172
+ @([StrikethroughStyle getStyleType]) :
173
+ @[ @([CodeBlockStyle getStyleType]) ],
174
+ @([InlineCodeStyle getStyleType]) :
175
+ @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
176
+ @([LinkStyle getStyleType]) :
177
+ @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
178
+ @([MentionStyle getStyleType]) :
179
+ @[ @([CodeBlockStyle getStyleType]), @([ImageStyle getStyleType]) ],
180
+ @([H1Style getStyleType]) : @[],
181
+ @([H2Style getStyleType]) : @[],
182
+ @([H3Style getStyleType]) : @[],
183
+ @([UnorderedListStyle getStyleType]) : @[],
184
+ @([OrderedListStyle getStyleType]) : @[],
185
+ @([BlockQuoteStyle getStyleType]) : @[],
186
+ @([CodeBlockStyle getStyleType]) : @[],
187
+ @([ImageStyle getStyleType]) : @[ @([InlineCodeStyle getStyleType]) ]
136
188
  };
137
-
189
+
138
190
  parser = [[InputParser alloc] initWithInput:self];
139
191
  }
140
192
 
@@ -152,11 +204,14 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
152
204
  _placeholderLabel = [[UILabel alloc] initWithFrame:CGRectZero];
153
205
  _placeholderLabel.translatesAutoresizingMaskIntoConstraints = NO;
154
206
  [textView addSubview:_placeholderLabel];
155
- [NSLayoutConstraint activateConstraints: @[
156
- [_placeholderLabel.leadingAnchor constraintEqualToAnchor:textView.leadingAnchor],
157
- [_placeholderLabel.widthAnchor constraintEqualToAnchor:textView.widthAnchor],
207
+ [NSLayoutConstraint activateConstraints:@[
208
+ [_placeholderLabel.leadingAnchor
209
+ constraintEqualToAnchor:textView.leadingAnchor],
210
+ [_placeholderLabel.widthAnchor
211
+ constraintEqualToAnchor:textView.widthAnchor],
158
212
  [_placeholderLabel.topAnchor constraintEqualToAnchor:textView.topAnchor],
159
- [_placeholderLabel.bottomAnchor constraintEqualToAnchor:textView.bottomAnchor]
213
+ [_placeholderLabel.bottomAnchor
214
+ constraintEqualToAnchor:textView.bottomAnchor]
160
215
  ]];
161
216
  _placeholderLabel.lineBreakMode = NSLineBreakByTruncatingTail;
162
217
  _placeholderLabel.text = @"";
@@ -165,25 +220,28 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
165
220
 
166
221
  // MARK: - Props
167
222
 
168
- - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps {
169
- const auto &oldViewProps = *std::static_pointer_cast<EnrichedTextInputViewProps const>(_props);
170
- const auto &newViewProps = *std::static_pointer_cast<EnrichedTextInputViewProps const>(props);
223
+ - (void)updateProps:(Props::Shared const &)props
224
+ oldProps:(Props::Shared const &)oldProps {
225
+ const auto &oldViewProps =
226
+ *std::static_pointer_cast<EnrichedTextInputViewProps const>(_props);
227
+ const auto &newViewProps =
228
+ *std::static_pointer_cast<EnrichedTextInputViewProps const>(props);
171
229
  BOOL isFirstMount = NO;
172
230
  BOOL stylePropChanged = NO;
173
-
231
+
174
232
  // initial config
175
- if(config == nullptr) {
233
+ if (config == nullptr) {
176
234
  isFirstMount = YES;
177
235
  config = [[InputConfig alloc] init];
178
236
  }
179
-
237
+
180
238
  // any style prop changes:
181
239
  // firstly we create the new config for the changes
182
-
240
+
183
241
  InputConfig *newConfig = [config copy];
184
-
185
- if(newViewProps.color != oldViewProps.color) {
186
- if(isColorMeaningful(newViewProps.color)) {
242
+
243
+ if (newViewProps.color != oldViewProps.color) {
244
+ if (isColorMeaningful(newViewProps.color)) {
187
245
  UIColor *uiColor = RCTUIColorFromSharedColor(newViewProps.color);
188
246
  [newConfig setPrimaryColor:uiColor];
189
247
  } else {
@@ -191,272 +249,342 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
191
249
  }
192
250
  stylePropChanged = YES;
193
251
  }
194
-
195
- if(newViewProps.fontSize != oldViewProps.fontSize) {
196
- if(newViewProps.fontSize) {
197
- NSNumber* fontSize = @(newViewProps.fontSize);
252
+
253
+ if (newViewProps.fontSize != oldViewProps.fontSize) {
254
+ if (newViewProps.fontSize) {
255
+ NSNumber *fontSize = @(newViewProps.fontSize);
198
256
  [newConfig setPrimaryFontSize:fontSize];
199
257
  } else {
200
258
  [newConfig setPrimaryFontSize:nullptr];
201
259
  }
202
260
  stylePropChanged = YES;
203
261
  }
204
-
205
- if(newViewProps.fontWeight != oldViewProps.fontWeight) {
206
- if(!newViewProps.fontWeight.empty()) {
207
- [newConfig setPrimaryFontWeight:[NSString fromCppString:newViewProps.fontWeight]];
262
+
263
+ if (newViewProps.fontWeight != oldViewProps.fontWeight) {
264
+ if (!newViewProps.fontWeight.empty()) {
265
+ [newConfig
266
+ setPrimaryFontWeight:[NSString
267
+ fromCppString:newViewProps.fontWeight]];
208
268
  } else {
209
269
  [newConfig setPrimaryFontWeight:nullptr];
210
270
  }
211
271
  stylePropChanged = YES;
212
272
  }
213
-
214
- if(newViewProps.fontFamily != oldViewProps.fontFamily) {
215
- if(!newViewProps.fontFamily.empty()) {
216
- [newConfig setPrimaryFontFamily:[NSString fromCppString:newViewProps.fontFamily]];
273
+
274
+ if (newViewProps.fontFamily != oldViewProps.fontFamily) {
275
+ if (!newViewProps.fontFamily.empty()) {
276
+ [newConfig
277
+ setPrimaryFontFamily:[NSString
278
+ fromCppString:newViewProps.fontFamily]];
217
279
  } else {
218
280
  [newConfig setPrimaryFontFamily:nullptr];
219
281
  }
220
282
  stylePropChanged = YES;
221
283
  }
222
-
284
+
223
285
  // rich text style
224
-
225
- if(newViewProps.htmlStyle.h1.fontSize != oldViewProps.htmlStyle.h1.fontSize) {
286
+
287
+ if (newViewProps.htmlStyle.h1.fontSize !=
288
+ oldViewProps.htmlStyle.h1.fontSize) {
226
289
  [newConfig setH1FontSize:newViewProps.htmlStyle.h1.fontSize];
227
290
  stylePropChanged = YES;
228
291
  }
229
-
230
- if(newViewProps.htmlStyle.h1.bold != oldViewProps.htmlStyle.h1.bold) {
292
+
293
+ if (newViewProps.htmlStyle.h1.bold != oldViewProps.htmlStyle.h1.bold) {
231
294
  [newConfig setH1Bold:newViewProps.htmlStyle.h1.bold];
232
295
  stylePropChanged = YES;
233
296
  }
234
-
235
- if(newViewProps.htmlStyle.h2.fontSize != oldViewProps.htmlStyle.h2.fontSize) {
297
+
298
+ if (newViewProps.htmlStyle.h2.fontSize !=
299
+ oldViewProps.htmlStyle.h2.fontSize) {
236
300
  [newConfig setH2FontSize:newViewProps.htmlStyle.h2.fontSize];
237
301
  stylePropChanged = YES;
238
302
  }
239
-
240
- if(newViewProps.htmlStyle.h2.bold != oldViewProps.htmlStyle.h2.bold) {
303
+
304
+ if (newViewProps.htmlStyle.h2.bold != oldViewProps.htmlStyle.h2.bold) {
241
305
  [newConfig setH2Bold:newViewProps.htmlStyle.h2.bold];
242
306
  stylePropChanged = YES;
243
307
  }
244
-
245
- if(newViewProps.htmlStyle.h3.fontSize != oldViewProps.htmlStyle.h3.fontSize) {
308
+
309
+ if (newViewProps.htmlStyle.h3.fontSize !=
310
+ oldViewProps.htmlStyle.h3.fontSize) {
246
311
  [newConfig setH3FontSize:newViewProps.htmlStyle.h3.fontSize];
247
312
  stylePropChanged = YES;
248
313
  }
249
-
250
- if(newViewProps.htmlStyle.h3.bold != oldViewProps.htmlStyle.h3.bold) {
314
+
315
+ if (newViewProps.htmlStyle.h3.bold != oldViewProps.htmlStyle.h3.bold) {
251
316
  [newConfig setH3Bold:newViewProps.htmlStyle.h3.bold];
252
317
  stylePropChanged = YES;
253
318
  }
254
-
255
- if(newViewProps.htmlStyle.blockquote.borderColor != oldViewProps.htmlStyle.blockquote.borderColor) {
256
- if(isColorMeaningful(newViewProps.htmlStyle.blockquote.borderColor)) {
257
- [newConfig setBlockquoteBorderColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.blockquote.borderColor)];
319
+
320
+ if (newViewProps.htmlStyle.blockquote.borderColor !=
321
+ oldViewProps.htmlStyle.blockquote.borderColor) {
322
+ if (isColorMeaningful(newViewProps.htmlStyle.blockquote.borderColor)) {
323
+ [newConfig setBlockquoteBorderColor:RCTUIColorFromSharedColor(
324
+ newViewProps.htmlStyle.blockquote
325
+ .borderColor)];
258
326
  stylePropChanged = YES;
259
327
  }
260
328
  }
261
-
262
- if(newViewProps.htmlStyle.blockquote.borderWidth != oldViewProps.htmlStyle.blockquote.borderWidth) {
263
- [newConfig setBlockquoteBorderWidth:newViewProps.htmlStyle.blockquote.borderWidth];
329
+
330
+ if (newViewProps.htmlStyle.blockquote.borderWidth !=
331
+ oldViewProps.htmlStyle.blockquote.borderWidth) {
332
+ [newConfig
333
+ setBlockquoteBorderWidth:newViewProps.htmlStyle.blockquote.borderWidth];
264
334
  stylePropChanged = YES;
265
335
  }
266
-
267
- if(newViewProps.htmlStyle.blockquote.gapWidth != oldViewProps.htmlStyle.blockquote.gapWidth) {
268
- [newConfig setBlockquoteGapWidth:newViewProps.htmlStyle.blockquote.gapWidth];
336
+
337
+ if (newViewProps.htmlStyle.blockquote.gapWidth !=
338
+ oldViewProps.htmlStyle.blockquote.gapWidth) {
339
+ [newConfig
340
+ setBlockquoteGapWidth:newViewProps.htmlStyle.blockquote.gapWidth];
269
341
  stylePropChanged = YES;
270
342
  }
271
-
272
- // since this prop defaults to undefined on JS side, we need to force set the value on first mount
273
- if(newViewProps.htmlStyle.blockquote.color != oldViewProps.htmlStyle.blockquote.color || isFirstMount) {
274
- if(isColorMeaningful(newViewProps.htmlStyle.blockquote.color)) {
275
- [newConfig setBlockquoteColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.blockquote.color)];
343
+
344
+ // since this prop defaults to undefined on JS side, we need to force set the
345
+ // value on first mount
346
+ if (newViewProps.htmlStyle.blockquote.color !=
347
+ oldViewProps.htmlStyle.blockquote.color ||
348
+ isFirstMount) {
349
+ if (isColorMeaningful(newViewProps.htmlStyle.blockquote.color)) {
350
+ [newConfig
351
+ setBlockquoteColor:RCTUIColorFromSharedColor(
352
+ newViewProps.htmlStyle.blockquote.color)];
276
353
  } else {
277
354
  [newConfig setBlockquoteColor:[newConfig primaryColor]];
278
355
  }
279
356
  stylePropChanged = YES;
280
357
  }
281
-
282
- if(newViewProps.htmlStyle.code.color != oldViewProps.htmlStyle.code.color) {
283
- if(isColorMeaningful(newViewProps.htmlStyle.code.color)) {
284
- [newConfig setInlineCodeFgColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.code.color)];
358
+
359
+ if (newViewProps.htmlStyle.code.color != oldViewProps.htmlStyle.code.color) {
360
+ if (isColorMeaningful(newViewProps.htmlStyle.code.color)) {
361
+ [newConfig setInlineCodeFgColor:RCTUIColorFromSharedColor(
362
+ newViewProps.htmlStyle.code.color)];
285
363
  stylePropChanged = YES;
286
364
  }
287
365
  }
288
-
289
- if(newViewProps.htmlStyle.code.backgroundColor != oldViewProps.htmlStyle.code.backgroundColor) {
290
- if(isColorMeaningful(newViewProps.htmlStyle.code.backgroundColor)) {
291
- [newConfig setInlineCodeBgColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.code.backgroundColor)];
366
+
367
+ if (newViewProps.htmlStyle.code.backgroundColor !=
368
+ oldViewProps.htmlStyle.code.backgroundColor) {
369
+ if (isColorMeaningful(newViewProps.htmlStyle.code.backgroundColor)) {
370
+ [newConfig setInlineCodeBgColor:RCTUIColorFromSharedColor(
371
+ newViewProps.htmlStyle.code
372
+ .backgroundColor)];
292
373
  stylePropChanged = YES;
293
374
  }
294
375
  }
295
-
296
- if(newViewProps.htmlStyle.ol.gapWidth != oldViewProps.htmlStyle.ol.gapWidth) {
376
+
377
+ if (newViewProps.htmlStyle.ol.gapWidth !=
378
+ oldViewProps.htmlStyle.ol.gapWidth) {
297
379
  [newConfig setOrderedListGapWidth:newViewProps.htmlStyle.ol.gapWidth];
298
380
  stylePropChanged = YES;
299
381
  }
300
-
301
- if(newViewProps.htmlStyle.ol.marginLeft != oldViewProps.htmlStyle.ol.marginLeft) {
382
+
383
+ if (newViewProps.htmlStyle.ol.marginLeft !=
384
+ oldViewProps.htmlStyle.ol.marginLeft) {
302
385
  [newConfig setOrderedListMarginLeft:newViewProps.htmlStyle.ol.marginLeft];
303
386
  stylePropChanged = YES;
304
387
  }
305
-
306
- // since this prop defaults to undefined on JS side, we need to force set the value on first mount
307
- if(newViewProps.htmlStyle.ol.markerFontWeight != oldViewProps.htmlStyle.ol.markerFontWeight || isFirstMount) {
308
- if(!newViewProps.htmlStyle.ol.markerFontWeight.empty()) {
309
- [newConfig setOrderedListMarkerFontWeight:[NSString fromCppString: newViewProps.htmlStyle.ol.markerFontWeight]];
388
+
389
+ // since this prop defaults to undefined on JS side, we need to force set the
390
+ // value on first mount
391
+ if (newViewProps.htmlStyle.ol.markerFontWeight !=
392
+ oldViewProps.htmlStyle.ol.markerFontWeight ||
393
+ isFirstMount) {
394
+ if (!newViewProps.htmlStyle.ol.markerFontWeight.empty()) {
395
+ [newConfig
396
+ setOrderedListMarkerFontWeight:
397
+ [NSString
398
+ fromCppString:newViewProps.htmlStyle.ol.markerFontWeight]];
310
399
  } else {
311
400
  [newConfig setOrderedListMarkerFontWeight:[newConfig primaryFontWeight]];
312
401
  }
313
402
  stylePropChanged = YES;
314
403
  }
315
-
316
- // since this prop defaults to undefined on JS side, we need to force set the value on first mount
317
- if(newViewProps.htmlStyle.ol.markerColor != oldViewProps.htmlStyle.ol.markerColor || isFirstMount) {
318
- if(isColorMeaningful(newViewProps.htmlStyle.ol.markerColor)) {
319
- [newConfig setOrderedListMarkerColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.ol.markerColor)];
404
+
405
+ // since this prop defaults to undefined on JS side, we need to force set the
406
+ // value on first mount
407
+ if (newViewProps.htmlStyle.ol.markerColor !=
408
+ oldViewProps.htmlStyle.ol.markerColor ||
409
+ isFirstMount) {
410
+ if (isColorMeaningful(newViewProps.htmlStyle.ol.markerColor)) {
411
+ [newConfig
412
+ setOrderedListMarkerColor:RCTUIColorFromSharedColor(
413
+ newViewProps.htmlStyle.ol.markerColor)];
320
414
  } else {
321
415
  [newConfig setOrderedListMarkerColor:[newConfig primaryColor]];
322
416
  }
323
417
  stylePropChanged = YES;
324
418
  }
325
-
326
- if(newViewProps.htmlStyle.ul.bulletColor != oldViewProps.htmlStyle.ul.bulletColor) {
327
- if(isColorMeaningful(newViewProps.htmlStyle.ul.bulletColor)) {
328
- [newConfig setUnorderedListBulletColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.ul.bulletColor)];
419
+
420
+ if (newViewProps.htmlStyle.ul.bulletColor !=
421
+ oldViewProps.htmlStyle.ul.bulletColor) {
422
+ if (isColorMeaningful(newViewProps.htmlStyle.ul.bulletColor)) {
423
+ [newConfig setUnorderedListBulletColor:RCTUIColorFromSharedColor(
424
+ newViewProps.htmlStyle.ul
425
+ .bulletColor)];
329
426
  stylePropChanged = YES;
330
427
  }
331
428
  }
332
-
333
- if(newViewProps.htmlStyle.ul.bulletSize != oldViewProps.htmlStyle.ul.bulletSize) {
429
+
430
+ if (newViewProps.htmlStyle.ul.bulletSize !=
431
+ oldViewProps.htmlStyle.ul.bulletSize) {
334
432
  [newConfig setUnorderedListBulletSize:newViewProps.htmlStyle.ul.bulletSize];
335
433
  stylePropChanged = YES;
336
434
  }
337
-
338
- if(newViewProps.htmlStyle.ul.gapWidth != oldViewProps.htmlStyle.ul.gapWidth) {
435
+
436
+ if (newViewProps.htmlStyle.ul.gapWidth !=
437
+ oldViewProps.htmlStyle.ul.gapWidth) {
339
438
  [newConfig setUnorderedListGapWidth:newViewProps.htmlStyle.ul.gapWidth];
340
439
  stylePropChanged = YES;
341
440
  }
342
-
343
- if(newViewProps.htmlStyle.ul.marginLeft != oldViewProps.htmlStyle.ul.marginLeft) {
441
+
442
+ if (newViewProps.htmlStyle.ul.marginLeft !=
443
+ oldViewProps.htmlStyle.ul.marginLeft) {
344
444
  [newConfig setUnorderedListMarginLeft:newViewProps.htmlStyle.ul.marginLeft];
345
445
  stylePropChanged = YES;
346
446
  }
347
-
348
- if(newViewProps.htmlStyle.a.color != oldViewProps.htmlStyle.a.color) {
349
- if(isColorMeaningful(newViewProps.htmlStyle.a.color)) {
350
- [newConfig setLinkColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.a.color)];
447
+
448
+ if (newViewProps.htmlStyle.a.color != oldViewProps.htmlStyle.a.color) {
449
+ if (isColorMeaningful(newViewProps.htmlStyle.a.color)) {
450
+ [newConfig setLinkColor:RCTUIColorFromSharedColor(
451
+ newViewProps.htmlStyle.a.color)];
351
452
  stylePropChanged = YES;
352
453
  }
353
454
  }
354
-
355
- if(newViewProps.htmlStyle.codeblock.color != oldViewProps.htmlStyle.codeblock.color) {
356
- if(isColorMeaningful(newViewProps.htmlStyle.codeblock.color)) {
357
- [newConfig setCodeBlockFgColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.codeblock.color)];
455
+
456
+ if (newViewProps.htmlStyle.codeblock.color !=
457
+ oldViewProps.htmlStyle.codeblock.color) {
458
+ if (isColorMeaningful(newViewProps.htmlStyle.codeblock.color)) {
459
+ [newConfig
460
+ setCodeBlockFgColor:RCTUIColorFromSharedColor(
461
+ newViewProps.htmlStyle.codeblock.color)];
358
462
  stylePropChanged = YES;
359
463
  }
360
464
  }
361
-
362
- if(newViewProps.htmlStyle.codeblock.backgroundColor != oldViewProps.htmlStyle.codeblock.backgroundColor) {
363
- if(isColorMeaningful(newViewProps.htmlStyle.codeblock.backgroundColor)) {
364
- [newConfig setCodeBlockBgColor:RCTUIColorFromSharedColor(newViewProps.htmlStyle.codeblock.backgroundColor)];
465
+
466
+ if (newViewProps.htmlStyle.codeblock.backgroundColor !=
467
+ oldViewProps.htmlStyle.codeblock.backgroundColor) {
468
+ if (isColorMeaningful(newViewProps.htmlStyle.codeblock.backgroundColor)) {
469
+ [newConfig setCodeBlockBgColor:RCTUIColorFromSharedColor(
470
+ newViewProps.htmlStyle.codeblock
471
+ .backgroundColor)];
365
472
  stylePropChanged = YES;
366
473
  }
367
474
  }
368
-
369
- if(newViewProps.htmlStyle.codeblock.borderRadius != oldViewProps.htmlStyle.codeblock.borderRadius) {
370
- [newConfig setCodeBlockBorderRadius:newViewProps.htmlStyle.codeblock.borderRadius];
475
+
476
+ if (newViewProps.htmlStyle.codeblock.borderRadius !=
477
+ oldViewProps.htmlStyle.codeblock.borderRadius) {
478
+ [newConfig
479
+ setCodeBlockBorderRadius:newViewProps.htmlStyle.codeblock.borderRadius];
371
480
  stylePropChanged = YES;
372
481
  }
373
-
374
- if(newViewProps.htmlStyle.a.textDecorationLine != oldViewProps.htmlStyle.a.textDecorationLine) {
375
- NSString *objcString = [NSString fromCppString:newViewProps.htmlStyle.a.textDecorationLine];
376
- if([objcString isEqualToString:DecorationUnderline]) {
482
+
483
+ if (newViewProps.htmlStyle.a.textDecorationLine !=
484
+ oldViewProps.htmlStyle.a.textDecorationLine) {
485
+ NSString *objcString =
486
+ [NSString fromCppString:newViewProps.htmlStyle.a.textDecorationLine];
487
+ if ([objcString isEqualToString:DecorationUnderline]) {
377
488
  [newConfig setLinkDecorationLine:DecorationUnderline];
378
489
  } else {
379
- // both DecorationNone and a different, wrong value gets a DecorationNone here
490
+ // both DecorationNone and a different, wrong value gets a DecorationNone
491
+ // here
380
492
  [newConfig setLinkDecorationLine:DecorationNone];
381
493
  }
382
494
  stylePropChanged = YES;
383
495
  }
384
-
385
- if(newViewProps.scrollEnabled != oldViewProps.scrollEnabled || textView.scrollEnabled != newViewProps.scrollEnabled) {
496
+
497
+ if (newViewProps.scrollEnabled != oldViewProps.scrollEnabled ||
498
+ textView.scrollEnabled != newViewProps.scrollEnabled) {
386
499
  [textView setScrollEnabled:newViewProps.scrollEnabled];
387
500
  }
388
-
501
+
389
502
  folly::dynamic oldMentionStyle = oldViewProps.htmlStyle.mention;
390
503
  folly::dynamic newMentionStyle = newViewProps.htmlStyle.mention;
391
- if(oldMentionStyle != newMentionStyle) {
504
+ if (oldMentionStyle != newMentionStyle) {
392
505
  bool newSingleProps = NO;
393
-
394
- for(const auto& obj : newMentionStyle.items()) {
395
- if(obj.second.isInt() || obj.second.isString()) {
506
+
507
+ for (const auto &obj : newMentionStyle.items()) {
508
+ if (obj.second.isInt() || obj.second.isString()) {
396
509
  // we are in just a single MentionStyleProps object
397
510
  newSingleProps = YES;
398
511
  break;
399
- } else if(obj.second.isObject()) {
512
+ } else if (obj.second.isObject()) {
400
513
  // we are in map of indicators to MentionStyleProps
401
514
  newSingleProps = NO;
402
515
  break;
403
516
  }
404
517
  }
405
-
406
- if(newSingleProps) {
407
- [newConfig setMentionStyleProps:[MentionStyleProps getSinglePropsFromFollyDynamic:newMentionStyle]];
518
+
519
+ if (newSingleProps) {
520
+ [newConfig setMentionStyleProps:
521
+ [MentionStyleProps
522
+ getSinglePropsFromFollyDynamic:newMentionStyle]];
408
523
  } else {
409
- [newConfig setMentionStyleProps:[MentionStyleProps getComplexPropsFromFollyDynamic:newMentionStyle]];
524
+ [newConfig setMentionStyleProps:
525
+ [MentionStyleProps
526
+ getComplexPropsFromFollyDynamic:newMentionStyle]];
410
527
  }
411
-
528
+
412
529
  stylePropChanged = YES;
413
530
  }
414
-
415
- if(stylePropChanged) {
531
+
532
+ if (stylePropChanged) {
416
533
  // all the text needs to be rebuilt
417
- // we get the current html using old config, then switch to new config and replace text using the html
418
- // this way, the newest config attributes are being used!
419
-
534
+ // we get the current html using old config, then switch to new config and
535
+ // replace text using the html this way, the newest config attributes are
536
+ // being used!
537
+
420
538
  // the html needs to be generated using the old config
421
- NSString *currentHtml = [parser parseToHtmlFromRange:NSMakeRange(0, textView.textStorage.string.length)];
422
-
539
+ NSString *currentHtml = [parser
540
+ parseToHtmlFromRange:NSMakeRange(0,
541
+ textView.textStorage.string.length)];
542
+
423
543
  // now set the new config
424
544
  config = newConfig;
425
-
545
+
426
546
  // no emitting during styles reload
427
547
  blockEmitting = YES;
428
-
548
+
429
549
  // make sure everything is sound in the html
430
- NSString *initiallyProcessedHtml = [parser initiallyProcessHtml:currentHtml];
431
- if(initiallyProcessedHtml != nullptr) {
550
+ NSString *initiallyProcessedHtml =
551
+ [parser initiallyProcessHtml:currentHtml];
552
+ if (initiallyProcessedHtml != nullptr) {
432
553
  [parser replaceWholeFromHtml:initiallyProcessedHtml];
433
554
  }
434
-
555
+
435
556
  blockEmitting = NO;
436
-
557
+
437
558
  // fill the typing attributes with style props
438
- defaultTypingAttributes[NSForegroundColorAttributeName] = [config primaryColor];
559
+ defaultTypingAttributes[NSForegroundColorAttributeName] =
560
+ [config primaryColor];
439
561
  defaultTypingAttributes[NSFontAttributeName] = [config primaryFont];
440
- defaultTypingAttributes[NSUnderlineColorAttributeName] = [config primaryColor];
441
- defaultTypingAttributes[NSStrikethroughColorAttributeName] = [config primaryColor];
442
- defaultTypingAttributes[NSParagraphStyleAttributeName] = [[NSParagraphStyle alloc] init];
562
+ defaultTypingAttributes[NSUnderlineColorAttributeName] =
563
+ [config primaryColor];
564
+ defaultTypingAttributes[NSStrikethroughColorAttributeName] =
565
+ [config primaryColor];
566
+ defaultTypingAttributes[NSParagraphStyleAttributeName] =
567
+ [[NSParagraphStyle alloc] init];
443
568
  textView.typingAttributes = defaultTypingAttributes;
444
-
569
+
445
570
  // update the placeholder as well
446
571
  [self refreshPlaceholderLabelStyles];
447
572
  }
448
-
573
+
449
574
  // editable
450
- if(newViewProps.editable != textView.editable) {
575
+ if (newViewProps.editable != textView.editable) {
451
576
  textView.editable = newViewProps.editable;
452
577
  }
453
-
454
- // default value - must be set before placeholder to make sure it correctly shows on first mount
455
- if(newViewProps.defaultValue != oldViewProps.defaultValue) {
456
- NSString *newDefaultValue = [NSString fromCppString:newViewProps.defaultValue];
457
-
458
- NSString *initiallyProcessedHtml = [parser initiallyProcessHtml:newDefaultValue];
459
- if(initiallyProcessedHtml == nullptr) {
578
+
579
+ // default value - must be set before placeholder to make sure it correctly
580
+ // shows on first mount
581
+ if (newViewProps.defaultValue != oldViewProps.defaultValue) {
582
+ NSString *newDefaultValue =
583
+ [NSString fromCppString:newViewProps.defaultValue];
584
+
585
+ NSString *initiallyProcessedHtml =
586
+ [parser initiallyProcessHtml:newDefaultValue];
587
+ if (initiallyProcessedHtml == nullptr) {
460
588
  // just plain text
461
589
  textView.text = newDefaultValue;
462
590
  } else {
@@ -464,89 +592,94 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
464
592
  [parser replaceWholeFromHtml:initiallyProcessedHtml];
465
593
  }
466
594
  }
467
-
595
+
468
596
  // placeholderTextColor
469
- if(newViewProps.placeholderTextColor != oldViewProps.placeholderTextColor) {
597
+ if (newViewProps.placeholderTextColor != oldViewProps.placeholderTextColor) {
470
598
  // some real color
471
- if(isColorMeaningful(newViewProps.placeholderTextColor)) {
472
- _placeholderColor = RCTUIColorFromSharedColor(newViewProps.placeholderTextColor);
599
+ if (isColorMeaningful(newViewProps.placeholderTextColor)) {
600
+ _placeholderColor =
601
+ RCTUIColorFromSharedColor(newViewProps.placeholderTextColor);
473
602
  } else {
474
603
  _placeholderColor = nullptr;
475
604
  }
476
605
  [self refreshPlaceholderLabelStyles];
477
606
  }
478
-
607
+
479
608
  // placeholder
480
- if(newViewProps.placeholder != oldViewProps.placeholder) {
609
+ if (newViewProps.placeholder != oldViewProps.placeholder) {
481
610
  _placeholderLabel.text = [NSString fromCppString:newViewProps.placeholder];
482
611
  [self refreshPlaceholderLabelStyles];
483
612
  // additionally show placeholder on first mount if it should be there
484
- if(isFirstMount && textView.text.length == 0) {
613
+ if (isFirstMount && textView.text.length == 0) {
485
614
  [self setPlaceholderLabelShown:YES];
486
615
  }
487
616
  }
488
-
617
+
489
618
  // mention indicators
490
- auto mismatchPair = std::mismatch(
491
- newViewProps.mentionIndicators.begin(), newViewProps.mentionIndicators.end(),
492
- oldViewProps.mentionIndicators.begin(), oldViewProps.mentionIndicators.end()
493
- );
494
- if(mismatchPair.first != newViewProps.mentionIndicators.end() || mismatchPair.second != oldViewProps.mentionIndicators.end()) {
619
+ auto mismatchPair = std::mismatch(newViewProps.mentionIndicators.begin(),
620
+ newViewProps.mentionIndicators.end(),
621
+ oldViewProps.mentionIndicators.begin(),
622
+ oldViewProps.mentionIndicators.end());
623
+ if (mismatchPair.first != newViewProps.mentionIndicators.end() ||
624
+ mismatchPair.second != oldViewProps.mentionIndicators.end()) {
495
625
  NSMutableSet<NSNumber *> *newIndicators = [[NSMutableSet alloc] init];
496
- for(const std::string &item : newViewProps.mentionIndicators) {
497
- if(item.length() == 1) {
626
+ for (const std::string &item : newViewProps.mentionIndicators) {
627
+ if (item.length() == 1) {
498
628
  [newIndicators addObject:@(item[0])];
499
629
  }
500
630
  }
501
631
  [config setMentionIndicators:newIndicators];
502
632
  }
503
-
633
+
504
634
  // selection color sets both selection and cursor on iOS (just as in RN)
505
- if(newViewProps.selectionColor != oldViewProps.selectionColor) {
506
- if(isColorMeaningful(newViewProps.selectionColor)) {
507
- textView.tintColor = RCTUIColorFromSharedColor(newViewProps.selectionColor);
635
+ if (newViewProps.selectionColor != oldViewProps.selectionColor) {
636
+ if (isColorMeaningful(newViewProps.selectionColor)) {
637
+ textView.tintColor =
638
+ RCTUIColorFromSharedColor(newViewProps.selectionColor);
508
639
  } else {
509
640
  textView.tintColor = nullptr;
510
641
  }
511
642
  }
512
-
643
+
513
644
  // autoCapitalize
514
- if(newViewProps.autoCapitalize != oldViewProps.autoCapitalize) {
645
+ if (newViewProps.autoCapitalize != oldViewProps.autoCapitalize) {
515
646
  NSString *str = [NSString fromCppString:newViewProps.autoCapitalize];
516
- if([str isEqualToString: @"none"]) {
647
+ if ([str isEqualToString:@"none"]) {
517
648
  textView.autocapitalizationType = UITextAutocapitalizationTypeNone;
518
- } else if([str isEqualToString: @"sentences"]) {
649
+ } else if ([str isEqualToString:@"sentences"]) {
519
650
  textView.autocapitalizationType = UITextAutocapitalizationTypeSentences;
520
- } else if([str isEqualToString: @"words"]) {
651
+ } else if ([str isEqualToString:@"words"]) {
521
652
  textView.autocapitalizationType = UITextAutocapitalizationTypeWords;
522
- } else if([str isEqualToString: @"characters"]) {
523
- textView.autocapitalizationType = UITextAutocapitalizationTypeAllCharacters;
653
+ } else if ([str isEqualToString:@"characters"]) {
654
+ textView.autocapitalizationType =
655
+ UITextAutocapitalizationTypeAllCharacters;
524
656
  }
525
-
526
- // textView needs to be refocused on autocapitalization type change and we don't want to emit these events
527
- if([textView isFirstResponder]) {
657
+
658
+ // textView needs to be refocused on autocapitalization type change and we
659
+ // don't want to emit these events
660
+ if ([textView isFirstResponder]) {
528
661
  _emitFocusBlur = NO;
529
662
  [textView reactBlur];
530
663
  [textView reactFocus];
531
664
  _emitFocusBlur = YES;
532
665
  }
533
666
  }
534
-
667
+
535
668
  // isOnChangeHtmlSet
536
669
  _emitHtml = newViewProps.isOnChangeHtmlSet;
537
-
670
+
538
671
  [super updateProps:props oldProps:oldProps];
539
672
  // run the changes callback
540
673
  [self anyTextMayHaveBeenModified];
541
-
674
+
542
675
  // autofocus - needs to be done at the very end
543
- if(isFirstMount && newViewProps.autoFocus) {
676
+ if (isFirstMount && newViewProps.autoFocus) {
544
677
  [textView reactFocus];
545
678
  }
546
679
  }
547
680
 
548
681
  - (void)setPlaceholderLabelShown:(BOOL)shown {
549
- if(shown) {
682
+ if (shown) {
550
683
  [self refreshPlaceholderLabelStyles];
551
684
  _placeholderLabel.hidden = NO;
552
685
  } else {
@@ -556,10 +689,12 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
556
689
 
557
690
  - (void)refreshPlaceholderLabelStyles {
558
691
  NSMutableDictionary *newAttrs = [defaultTypingAttributes mutableCopy];
559
- if(_placeholderColor != nullptr) {
692
+ if (_placeholderColor != nullptr) {
560
693
  newAttrs[NSForegroundColorAttributeName] = _placeholderColor;
561
694
  }
562
- NSAttributedString *newAttrStr = [[NSAttributedString alloc] initWithString:_placeholderLabel.text attributes: newAttrs];
695
+ NSAttributedString *newAttrStr =
696
+ [[NSAttributedString alloc] initWithString:_placeholderLabel.text
697
+ attributes:newAttrs];
563
698
  _placeholderLabel.attributedText = newAttrStr;
564
699
  }
565
700
 
@@ -567,183 +702,220 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
567
702
 
568
703
  - (CGSize)measureSize:(CGFloat)maxWidth {
569
704
  // copy the the whole attributed string
570
- NSMutableAttributedString *currentStr = [[NSMutableAttributedString alloc] initWithAttributedString:textView.textStorage];
571
-
572
- // edge case: empty input should still be of a height of a single line, so we add a mock "I" character
573
- if([currentStr length] == 0 ) {
574
- [currentStr appendAttributedString:
575
- [[NSAttributedString alloc] initWithString:@"I" attributes:textView.typingAttributes]
576
- ];
577
- }
578
-
579
- // edge case: input with only a zero width space should still be of a height of a single line, so we add a mock "I" character
580
- if([currentStr length] == 1 && [[currentStr.string substringWithRange:NSMakeRange(0, 1)] isEqualToString:@"\u200B"]) {
581
- [currentStr appendAttributedString:
582
- [[NSAttributedString alloc] initWithString:@"I" attributes:textView.typingAttributes]
583
- ];
584
- }
585
-
586
- // edge case: trailing newlines aren't counted towards height calculations, so we add a mock "I" character
587
- if(currentStr.length > 0) {
588
- unichar lastChar = [currentStr.string characterAtIndex:currentStr.length-1];
589
- if([[NSCharacterSet newlineCharacterSet] characterIsMember:lastChar]) {
590
- [currentStr appendAttributedString:
591
- [[NSAttributedString alloc] initWithString:@"I" attributes:defaultTypingAttributes]
592
- ];
705
+ NSMutableAttributedString *currentStr = [[NSMutableAttributedString alloc]
706
+ initWithAttributedString:textView.textStorage];
707
+
708
+ // edge case: empty input should still be of a height of a single line, so we
709
+ // add a mock "I" character
710
+ if ([currentStr length] == 0) {
711
+ [currentStr
712
+ appendAttributedString:[[NSAttributedString alloc]
713
+ initWithString:@"I"
714
+ attributes:textView.typingAttributes]];
715
+ }
716
+
717
+ // edge case: input with only a zero width space should still be of a height
718
+ // of a single line, so we add a mock "I" character
719
+ if ([currentStr length] == 1 &&
720
+ [[currentStr.string substringWithRange:NSMakeRange(0, 1)]
721
+ isEqualToString:@"\u200B"]) {
722
+ [currentStr
723
+ appendAttributedString:[[NSAttributedString alloc]
724
+ initWithString:@"I"
725
+ attributes:textView.typingAttributes]];
726
+ }
727
+
728
+ // edge case: trailing newlines aren't counted towards height calculations, so
729
+ // we add a mock "I" character
730
+ if (currentStr.length > 0) {
731
+ unichar lastChar =
732
+ [currentStr.string characterAtIndex:currentStr.length - 1];
733
+ if ([[NSCharacterSet newlineCharacterSet] characterIsMember:lastChar]) {
734
+ [currentStr
735
+ appendAttributedString:[[NSAttributedString alloc]
736
+ initWithString:@"I"
737
+ attributes:defaultTypingAttributes]];
593
738
  }
594
739
  }
595
-
596
- CGRect boundingBox = [currentStr boundingRectWithSize:
597
- CGSizeMake(maxWidth, CGFLOAT_MAX)
598
- options: NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
599
- context: nullptr
600
- ];
740
+
741
+ CGRect boundingBox =
742
+ [currentStr boundingRectWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
743
+ options:NSStringDrawingUsesLineFragmentOrigin |
744
+ NSStringDrawingUsesFontLeading
745
+ context:nullptr];
601
746
 
602
747
  return CGSizeMake(maxWidth, ceil(boundingBox.size.height));
603
748
  }
604
749
 
605
750
  // make sure the newest state is kept in _state property
606
- - (void)updateState:(State::Shared const &)state oldState:(State::Shared const &)oldState {
607
- _state = std::static_pointer_cast<const EnrichedTextInputViewShadowNode::ConcreteState>(state);
608
-
609
- // first render with all the needed stuff already defined (state and componentView)
610
- // so we need to run a single height calculation for any initial values
611
- if(oldState == nullptr) {
751
+ - (void)updateState:(State::Shared const &)state
752
+ oldState:(State::Shared const &)oldState {
753
+ _state = std::static_pointer_cast<
754
+ const EnrichedTextInputViewShadowNode::ConcreteState>(state);
755
+
756
+ // first render with all the needed stuff already defined (state and
757
+ // componentView) so we need to run a single height calculation for any
758
+ // initial values
759
+ if (oldState == nullptr) {
612
760
  [self tryUpdatingHeight];
613
761
  }
614
762
  }
615
763
 
616
764
  - (void)tryUpdatingHeight {
617
- if(_state == nullptr) {
765
+ if (_state == nullptr) {
618
766
  return;
619
767
  }
620
768
  _componentViewHeightUpdateCounter++;
621
769
  auto selfRef = wrapManagedObjectWeakly(self);
622
- _state->updateState(EnrichedTextInputViewState(_componentViewHeightUpdateCounter, selfRef));
770
+ _state->updateState(
771
+ EnrichedTextInputViewState(_componentViewHeightUpdateCounter, selfRef));
623
772
  }
624
773
 
625
774
  // MARK: - Active styles
626
775
 
627
776
  - (void)tryUpdatingActiveStyles {
628
- // style updates are emitted only if something differs from the previously active styles
777
+ // style updates are emitted only if something differs from the previously
778
+ // active styles
629
779
  BOOL updateNeeded = NO;
630
-
631
- // active styles are kept in a separate set until we're sure they can be emitted
780
+
781
+ // active styles are kept in a separate set until we're sure they can be
782
+ // emitted
632
783
  NSMutableSet *newActiveStyles = [_activeStyles mutableCopy];
633
-
784
+
634
785
  // data for onLinkDetected event
635
786
  LinkData *detectedLinkData;
636
787
  NSRange detectedLinkRange = NSMakeRange(0, 0);
637
-
788
+
638
789
  // data for onMentionDetected event
639
790
  MentionParams *detectedMentionParams;
640
791
  NSRange detectedMentionRange = NSMakeRange(0, 0);
641
792
 
642
- for (NSNumber* type in stylesDict) {
793
+ for (NSNumber *type in stylesDict) {
643
794
  id<BaseStyleProtocol> style = stylesDict[type];
644
- BOOL wasActive = [newActiveStyles containsObject: type];
795
+ BOOL wasActive = [newActiveStyles containsObject:type];
645
796
  BOOL isActive = [style detectStyle:textView.selectedRange];
646
- if(wasActive != isActive) {
797
+ if (wasActive != isActive) {
647
798
  updateNeeded = YES;
648
- if(isActive) {
799
+ if (isActive) {
649
800
  [newActiveStyles addObject:type];
650
801
  } else {
651
802
  [newActiveStyles removeObject:type];
652
803
  }
653
804
  }
654
-
805
+
655
806
  // onLinkDetected event
656
- if(isActive && [type intValue] == [LinkStyle getStyleType]) {
807
+ if (isActive && [type intValue] == [LinkStyle getStyleType]) {
657
808
  // get the link data
658
809
  LinkData *candidateLinkData;
659
810
  NSRange candidateLinkRange = NSMakeRange(0, 0);
660
- LinkStyle *linkStyleClass = (LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
661
- if(linkStyleClass != nullptr) {
662
- candidateLinkData = [linkStyleClass getLinkDataAt:textView.selectedRange.location];
663
- candidateLinkRange = [linkStyleClass getFullLinkRangeAt:textView.selectedRange.location];
811
+ LinkStyle *linkStyleClass =
812
+ (LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
813
+ if (linkStyleClass != nullptr) {
814
+ candidateLinkData =
815
+ [linkStyleClass getLinkDataAt:textView.selectedRange.location];
816
+ candidateLinkRange =
817
+ [linkStyleClass getFullLinkRangeAt:textView.selectedRange.location];
664
818
  }
665
-
666
- if(wasActive == NO) {
819
+
820
+ if (wasActive == NO) {
667
821
  // we changed selection from non-link to a link
668
822
  detectedLinkData = candidateLinkData;
669
823
  detectedLinkRange = candidateLinkRange;
670
- } else if(
671
- ![_recentlyActiveLinkData.url isEqualToString:candidateLinkData.url] ||
672
- ![_recentlyActiveLinkData.text isEqualToString:candidateLinkData.text] ||
673
- !NSEqualRanges(_recentlyActiveLinkRange, candidateLinkRange)
674
- ) {
675
- // we changed selection from one link to the other or modified current link's text
824
+ } else if (![_recentlyActiveLinkData.url
825
+ isEqualToString:candidateLinkData.url] ||
826
+ ![_recentlyActiveLinkData.text
827
+ isEqualToString:candidateLinkData.text] ||
828
+ !NSEqualRanges(_recentlyActiveLinkRange, candidateLinkRange)) {
829
+ // we changed selection from one link to the other or modified current
830
+ // link's text
676
831
  detectedLinkData = candidateLinkData;
677
832
  detectedLinkRange = candidateLinkRange;
678
833
  }
679
834
  }
680
-
835
+
681
836
  // onMentionDetected event
682
- if(isActive && [type intValue] == [MentionStyle getStyleType]) {
837
+ if (isActive && [type intValue] == [MentionStyle getStyleType]) {
683
838
  // get mention data
684
839
  MentionParams *candidateMentionParams;
685
840
  NSRange candidateMentionRange = NSMakeRange(0, 0);
686
- MentionStyle *mentionStyleClass = (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
687
- if(mentionStyleClass != nullptr) {
688
- candidateMentionParams = [mentionStyleClass getMentionParamsAt:textView.selectedRange.location];
689
- candidateMentionRange = [mentionStyleClass getFullMentionRangeAt:textView.selectedRange.location];
841
+ MentionStyle *mentionStyleClass =
842
+ (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
843
+ if (mentionStyleClass != nullptr) {
844
+ candidateMentionParams = [mentionStyleClass
845
+ getMentionParamsAt:textView.selectedRange.location];
846
+ candidateMentionRange = [mentionStyleClass
847
+ getFullMentionRangeAt:textView.selectedRange.location];
690
848
  }
691
-
692
- if(wasActive == NO) {
849
+
850
+ if (wasActive == NO) {
693
851
  // selection was changed from a non-mention to a mention
694
852
  detectedMentionParams = candidateMentionParams;
695
853
  detectedMentionRange = candidateMentionRange;
696
- } else if(
697
- ![_recentlyActiveMentionParams.text isEqualToString:candidateMentionParams.text] ||
698
- ![_recentlyActiveMentionParams.attributes isEqualToString:candidateMentionParams.attributes] ||
699
- !NSEqualRanges(_recentlyActiveMentionRange, candidateMentionRange)
700
- ) {
854
+ } else if (![_recentlyActiveMentionParams.text
855
+ isEqualToString:candidateMentionParams.text] ||
856
+ ![_recentlyActiveMentionParams.attributes
857
+ isEqualToString:candidateMentionParams.attributes] ||
858
+ !NSEqualRanges(_recentlyActiveMentionRange,
859
+ candidateMentionRange)) {
701
860
  // selection changed from one mention to another
702
861
  detectedMentionParams = candidateMentionParams;
703
862
  detectedMentionRange = candidateMentionRange;
704
863
  }
705
864
  }
706
865
  }
707
-
708
- if(updateNeeded) {
866
+
867
+ if (updateNeeded) {
709
868
  auto emitter = [self getEventEmitter];
710
- if(emitter != nullptr) {
869
+ if (emitter != nullptr) {
711
870
  // update activeStyles only if emitter is available
712
871
  _activeStyles = newActiveStyles;
713
-
872
+
714
873
  emitter->onChangeState({
715
- .isBold = [_activeStyles containsObject: @([BoldStyle getStyleType])],
716
- .isItalic = [_activeStyles containsObject: @([ItalicStyle getStyleType])],
717
- .isUnderline = [_activeStyles containsObject: @([UnderlineStyle getStyleType])],
718
- .isStrikeThrough = [_activeStyles containsObject: @([StrikethroughStyle getStyleType])],
719
- .isInlineCode = [_activeStyles containsObject: @([InlineCodeStyle getStyleType])],
720
- .isLink = [_activeStyles containsObject: @([LinkStyle getStyleType])],
721
- .isMention = [_activeStyles containsObject: @([MentionStyle getStyleType])],
722
- .isH1 = [_activeStyles containsObject: @([H1Style getStyleType])],
723
- .isH2 = [_activeStyles containsObject: @([H2Style getStyleType])],
724
- .isH3 = [_activeStyles containsObject: @([H3Style getStyleType])],
725
- .isUnorderedList = [_activeStyles containsObject: @([UnorderedListStyle getStyleType])],
726
- .isOrderedList = [_activeStyles containsObject: @([OrderedListStyle getStyleType])],
727
- .isBlockQuote = [_activeStyles containsObject: @([BlockQuoteStyle getStyleType])],
728
- .isCodeBlock = [_activeStyles containsObject: @([CodeBlockStyle getStyleType])],
729
- .isImage = [_activeStyles containsObject: @([ImageStyle getStyleType])],
874
+ .isBold = [_activeStyles containsObject:@([BoldStyle getStyleType])],
875
+ .isItalic =
876
+ [_activeStyles containsObject:@([ItalicStyle getStyleType])],
877
+ .isUnderline =
878
+ [_activeStyles containsObject:@([UnderlineStyle getStyleType])],
879
+ .isStrikeThrough =
880
+ [_activeStyles containsObject:@([StrikethroughStyle getStyleType])],
881
+ .isInlineCode =
882
+ [_activeStyles containsObject:@([InlineCodeStyle getStyleType])],
883
+ .isLink = [_activeStyles containsObject:@([LinkStyle getStyleType])],
884
+ .isMention =
885
+ [_activeStyles containsObject:@([MentionStyle getStyleType])],
886
+ .isH1 = [_activeStyles containsObject:@([H1Style getStyleType])],
887
+ .isH2 = [_activeStyles containsObject:@([H2Style getStyleType])],
888
+ .isH3 = [_activeStyles containsObject:@([H3Style getStyleType])],
889
+ .isUnorderedList =
890
+ [_activeStyles containsObject:@([UnorderedListStyle getStyleType])],
891
+ .isOrderedList =
892
+ [_activeStyles containsObject:@([OrderedListStyle getStyleType])],
893
+ .isBlockQuote =
894
+ [_activeStyles containsObject:@([BlockQuoteStyle getStyleType])],
895
+ .isCodeBlock =
896
+ [_activeStyles containsObject:@([CodeBlockStyle getStyleType])],
897
+ .isImage = [_activeStyles containsObject:@([ImageStyle getStyleType])],
730
898
  });
731
899
  }
732
900
  }
733
-
734
- if(detectedLinkData != nullptr) {
901
+
902
+ if (detectedLinkData != nullptr) {
735
903
  // emit onLinkeDetected event
736
- [self emitOnLinkDetectedEvent:detectedLinkData.text url:detectedLinkData.url range:detectedLinkRange];
904
+ [self emitOnLinkDetectedEvent:detectedLinkData.text
905
+ url:detectedLinkData.url
906
+ range:detectedLinkRange];
737
907
  }
738
-
739
- if(detectedMentionParams != nullptr) {
908
+
909
+ if (detectedMentionParams != nullptr) {
740
910
  // emit onMentionDetected event
741
- [self emitOnMentionDetectedEvent:detectedMentionParams.text indicator:detectedMentionParams.indicator attributes:detectedMentionParams.attributes];
742
-
911
+ [self emitOnMentionDetectedEvent:detectedMentionParams.text
912
+ indicator:detectedMentionParams.indicator
913
+ attributes:detectedMentionParams.attributes];
914
+
743
915
  _recentlyActiveMentionParams = detectedMentionParams;
744
916
  _recentlyActiveMentionRange = detectedMentionRange;
745
917
  }
746
-
918
+
747
919
  // emit onChangeHtml event if needed
748
920
  [self tryEmittingOnChangeHtmlEvent];
749
921
  }
@@ -751,63 +923,67 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
751
923
  // MARK: - Native commands and events
752
924
 
753
925
  - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
754
- if([commandName isEqualToString:@"focus"]) {
926
+ if ([commandName isEqualToString:@"focus"]) {
755
927
  [self focus];
756
- } else if([commandName isEqualToString:@"blur"]) {
928
+ } else if ([commandName isEqualToString:@"blur"]) {
757
929
  [self blur];
758
- } else if([commandName isEqualToString:@"setValue"]) {
930
+ } else if ([commandName isEqualToString:@"setValue"]) {
759
931
  NSString *value = (NSString *)args[0];
760
932
  [self setValue:value];
761
- } else if([commandName isEqualToString:@"toggleBold"]) {
762
- [self toggleRegularStyle: [BoldStyle getStyleType]];
763
- } else if([commandName isEqualToString:@"toggleItalic"]) {
764
- [self toggleRegularStyle: [ItalicStyle getStyleType]];
765
- } else if([commandName isEqualToString:@"toggleUnderline"]) {
766
- [self toggleRegularStyle: [UnderlineStyle getStyleType]];
767
- } else if([commandName isEqualToString:@"toggleStrikeThrough"]) {
768
- [self toggleRegularStyle: [StrikethroughStyle getStyleType]];
769
- } else if([commandName isEqualToString:@"toggleInlineCode"]) {
770
- [self toggleRegularStyle: [InlineCodeStyle getStyleType]];
771
- } else if([commandName isEqualToString:@"addLink"]) {
772
- NSInteger start = [((NSNumber*)args[0]) integerValue];
773
- NSInteger end = [((NSNumber*)args[1]) integerValue];
933
+ } else if ([commandName isEqualToString:@"toggleBold"]) {
934
+ [self toggleRegularStyle:[BoldStyle getStyleType]];
935
+ } else if ([commandName isEqualToString:@"toggleItalic"]) {
936
+ [self toggleRegularStyle:[ItalicStyle getStyleType]];
937
+ } else if ([commandName isEqualToString:@"toggleUnderline"]) {
938
+ [self toggleRegularStyle:[UnderlineStyle getStyleType]];
939
+ } else if ([commandName isEqualToString:@"toggleStrikeThrough"]) {
940
+ [self toggleRegularStyle:[StrikethroughStyle getStyleType]];
941
+ } else if ([commandName isEqualToString:@"toggleInlineCode"]) {
942
+ [self toggleRegularStyle:[InlineCodeStyle getStyleType]];
943
+ } else if ([commandName isEqualToString:@"addLink"]) {
944
+ NSInteger start = [((NSNumber *)args[0]) integerValue];
945
+ NSInteger end = [((NSNumber *)args[1]) integerValue];
774
946
  NSString *text = (NSString *)args[2];
775
947
  NSString *url = (NSString *)args[3];
776
948
  [self addLinkAt:start end:end text:text url:url];
777
- } else if([commandName isEqualToString:@"addMention"]) {
949
+ } else if ([commandName isEqualToString:@"addMention"]) {
778
950
  NSString *indicator = (NSString *)args[0];
779
951
  NSString *text = (NSString *)args[1];
780
952
  NSString *attributes = (NSString *)args[2];
781
953
  [self addMention:indicator text:text attributes:attributes];
782
- } else if([commandName isEqualToString:@"startMention"]) {
954
+ } else if ([commandName isEqualToString:@"startMention"]) {
783
955
  NSString *indicator = (NSString *)args[0];
784
956
  [self startMentionWithIndicator:indicator];
785
- } else if([commandName isEqualToString:@"toggleH1"]) {
957
+ } else if ([commandName isEqualToString:@"toggleH1"]) {
786
958
  [self toggleParagraphStyle:[H1Style getStyleType]];
787
- } else if([commandName isEqualToString:@"toggleH2"]) {
959
+ } else if ([commandName isEqualToString:@"toggleH2"]) {
788
960
  [self toggleParagraphStyle:[H2Style getStyleType]];
789
- } else if([commandName isEqualToString:@"toggleH3"]) {
961
+ } else if ([commandName isEqualToString:@"toggleH3"]) {
790
962
  [self toggleParagraphStyle:[H3Style getStyleType]];
791
- } else if([commandName isEqualToString:@"toggleUnorderedList"]) {
963
+ } else if ([commandName isEqualToString:@"toggleUnorderedList"]) {
792
964
  [self toggleParagraphStyle:[UnorderedListStyle getStyleType]];
793
- } else if([commandName isEqualToString:@"toggleOrderedList"]) {
965
+ } else if ([commandName isEqualToString:@"toggleOrderedList"]) {
794
966
  [self toggleParagraphStyle:[OrderedListStyle getStyleType]];
795
- } else if([commandName isEqualToString:@"toggleBlockQuote"]) {
967
+ } else if ([commandName isEqualToString:@"toggleBlockQuote"]) {
796
968
  [self toggleParagraphStyle:[BlockQuoteStyle getStyleType]];
797
- } else if([commandName isEqualToString:@"toggleCodeBlock"]) {
969
+ } else if ([commandName isEqualToString:@"toggleCodeBlock"]) {
798
970
  [self toggleParagraphStyle:[CodeBlockStyle getStyleType]];
799
- } else if([commandName isEqualToString:@"addImage"]) {
971
+ } else if ([commandName isEqualToString:@"addImage"]) {
800
972
  NSString *uri = (NSString *)args[0];
801
- CGFloat imgWidth = [(NSNumber*)args[1] floatValue];
802
- CGFloat imgHeight = [(NSNumber*)args[2] floatValue];
803
-
973
+ CGFloat imgWidth = [(NSNumber *)args[1] floatValue];
974
+ CGFloat imgHeight = [(NSNumber *)args[2] floatValue];
975
+
804
976
  [self addImage:uri width:imgWidth height:imgHeight];
977
+ } else if ([commandName isEqualToString:@"requestHTML"]) {
978
+ NSInteger requestId = [((NSNumber *)args[0]) integerValue];
979
+ [self requestHTML:requestId];
805
980
  }
806
981
  }
807
982
 
808
983
  - (std::shared_ptr<EnrichedTextInputViewEventEmitter>)getEventEmitter {
809
- if(_eventEmitter != nullptr && !blockEmitting) {
810
- auto emitter = static_cast<const EnrichedTextInputViewEventEmitter &>(*_eventEmitter);
984
+ if (_eventEmitter != nullptr && !blockEmitting) {
985
+ auto emitter =
986
+ static_cast<const EnrichedTextInputViewEventEmitter &>(*_eventEmitter);
811
987
  return std::make_shared<EnrichedTextInputViewEventEmitter>(emitter);
812
988
  } else {
813
989
  return nullptr;
@@ -824,81 +1000,93 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
824
1000
 
825
1001
  - (void)setValue:(NSString *)value {
826
1002
  NSString *initiallyProcessedHtml = [parser initiallyProcessHtml:value];
827
- if(initiallyProcessedHtml == nullptr) {
1003
+ if (initiallyProcessedHtml == nullptr) {
828
1004
  // just plain text
829
1005
  textView.text = value;
830
1006
  } else {
831
1007
  // we've got some seemingly proper html
832
1008
  [parser replaceWholeFromHtml:initiallyProcessedHtml];
833
1009
  }
834
-
1010
+
835
1011
  // set recentlyChangedRange and check for changes
836
1012
  recentlyChangedRange = NSMakeRange(0, textView.textStorage.string.length);
837
1013
  [self anyTextMayHaveBeenModified];
838
1014
  }
839
1015
 
840
- - (void)emitOnLinkDetectedEvent:(NSString *)text url:(NSString *)url range:(NSRange)range {
1016
+ - (void)emitOnLinkDetectedEvent:(NSString *)text
1017
+ url:(NSString *)url
1018
+ range:(NSRange)range {
841
1019
  auto emitter = [self getEventEmitter];
842
- if(emitter != nullptr) {
1020
+ if (emitter != nullptr) {
843
1021
  // update recently active link info
844
1022
  LinkData *newLinkData = [[LinkData alloc] init];
845
1023
  newLinkData.text = text;
846
1024
  newLinkData.url = url;
847
1025
  _recentlyActiveLinkData = newLinkData;
848
1026
  _recentlyActiveLinkRange = range;
849
-
1027
+
850
1028
  emitter->onLinkDetected({
851
- .text = [text toCppString],
852
- .url = [url toCppString],
853
- .start = static_cast<int>(range.location),
854
- .end = static_cast<int>(range.location + range.length),
1029
+ .text = [text toCppString],
1030
+ .url = [url toCppString],
1031
+ .start = static_cast<int>(range.location),
1032
+ .end = static_cast<int>(range.location + range.length),
855
1033
  });
856
1034
  }
857
1035
  }
858
1036
 
859
- - (void)emitOnMentionDetectedEvent:(NSString *)text indicator:(NSString *)indicator attributes:(NSString *)attributes {
1037
+ - (void)emitOnMentionDetectedEvent:(NSString *)text
1038
+ indicator:(NSString *)indicator
1039
+ attributes:(NSString *)attributes {
860
1040
  auto emitter = [self getEventEmitter];
861
- if(emitter != nullptr) {
862
- emitter->onMentionDetected({
863
- .text = [text toCppString],
864
- .indicator = [indicator toCppString],
865
- .payload = [attributes toCppString]
866
- });
1041
+ if (emitter != nullptr) {
1042
+ emitter->onMentionDetected({.text = [text toCppString],
1043
+ .indicator = [indicator toCppString],
1044
+ .payload = [attributes toCppString]});
867
1045
  }
868
1046
  }
869
1047
 
870
1048
  - (void)emitOnMentionEvent:(NSString *)indicator text:(NSString *)text {
871
1049
  auto emitter = [self getEventEmitter];
872
- if(emitter != nullptr) {
873
- if(text != nullptr) {
1050
+ if (emitter != nullptr) {
1051
+ if (text != nullptr) {
874
1052
  folly::dynamic fdStr = [text toCppString];
875
- emitter->onMention({
876
- .indicator = [indicator toCppString],
877
- .text = fdStr
878
- });
1053
+ emitter->onMention({.indicator = [indicator toCppString], .text = fdStr});
879
1054
  } else {
880
1055
  folly::dynamic nul = nullptr;
881
- emitter->onMention({
882
- .indicator = [indicator toCppString],
883
- .text = nul
884
- });
1056
+ emitter->onMention({.indicator = [indicator toCppString], .text = nul});
885
1057
  }
886
1058
  }
887
1059
  }
888
1060
 
889
1061
  - (void)tryEmittingOnChangeHtmlEvent {
890
- if(!_emitHtml || textView.markedTextRange != nullptr) {
1062
+ if (!_emitHtml || textView.markedTextRange != nullptr) {
891
1063
  return;
892
1064
  }
893
1065
  auto emitter = [self getEventEmitter];
894
- if(emitter != nullptr) {
895
- NSString *htmlOutput = [parser parseToHtmlFromRange:NSMakeRange(0, textView.textStorage.string.length)];
1066
+ if (emitter != nullptr) {
1067
+ NSString *htmlOutput = [parser
1068
+ parseToHtmlFromRange:NSMakeRange(0,
1069
+ textView.textStorage.string.length)];
896
1070
  // make sure html really changed
897
- if(![htmlOutput isEqualToString:_recentlyEmittedHtml]) {
1071
+ if (![htmlOutput isEqualToString:_recentlyEmittedHtml]) {
898
1072
  _recentlyEmittedHtml = htmlOutput;
899
- emitter->onChangeHtml({
900
- .value = [htmlOutput toCppString]
901
- });
1073
+ emitter->onChangeHtml({.value = [htmlOutput toCppString]});
1074
+ }
1075
+ }
1076
+ }
1077
+
1078
+ - (void)requestHTML:(NSInteger)requestId {
1079
+ auto emitter = [self getEventEmitter];
1080
+ if (emitter != nullptr) {
1081
+ @try {
1082
+ NSString *htmlOutput = [parser
1083
+ parseToHtmlFromRange:NSMakeRange(0,
1084
+ textView.textStorage.string.length)];
1085
+ emitter->onRequestHtmlResult({.requestId = static_cast<int>(requestId),
1086
+ .html = [htmlOutput toCppString]});
1087
+ } @catch (NSException *exception) {
1088
+ emitter->onRequestHtmlResult({.requestId = static_cast<int>(requestId),
1089
+ .html = folly::dynamic(nullptr)});
902
1090
  }
903
1091
  }
904
1092
  }
@@ -907,8 +1095,8 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
907
1095
 
908
1096
  - (void)toggleRegularStyle:(StyleType)type {
909
1097
  id<BaseStyleProtocol> styleClass = stylesDict[@(type)];
910
-
911
- if([self handleStyleBlocksAndConflicts:type range:textView.selectedRange]) {
1098
+
1099
+ if ([self handleStyleBlocksAndConflicts:type range:textView.selectedRange]) {
912
1100
  [styleClass applyStyle:textView.selectedRange];
913
1101
  [self anyTextMayHaveBeenModified];
914
1102
  }
@@ -917,53 +1105,82 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
917
1105
  - (void)toggleParagraphStyle:(StyleType)type {
918
1106
  id<BaseStyleProtocol> styleClass = stylesDict[@(type)];
919
1107
  // we always pass whole paragraph/s range to these styles
920
- NSRange paragraphRange = [textView.textStorage.string paragraphRangeForRange:textView.selectedRange];
921
-
922
- if([self handleStyleBlocksAndConflicts:type range:paragraphRange]) {
1108
+ NSRange paragraphRange = [textView.textStorage.string
1109
+ paragraphRangeForRange:textView.selectedRange];
1110
+
1111
+ if ([self handleStyleBlocksAndConflicts:type range:paragraphRange]) {
923
1112
  [styleClass applyStyle:paragraphRange];
924
1113
  [self anyTextMayHaveBeenModified];
925
1114
  }
926
1115
  }
927
1116
 
928
- - (void)addLinkAt:(NSInteger)start end:(NSInteger)end text:(NSString *)text url:(NSString *)url {
929
- LinkStyle *linkStyleClass = (LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
930
- if(linkStyleClass == nullptr) { return; }
931
-
1117
+ - (void)addLinkAt:(NSInteger)start
1118
+ end:(NSInteger)end
1119
+ text:(NSString *)text
1120
+ url:(NSString *)url {
1121
+ LinkStyle *linkStyleClass =
1122
+ (LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
1123
+ if (linkStyleClass == nullptr) {
1124
+ return;
1125
+ }
1126
+
932
1127
  // translate the output start-end notation to range
933
1128
  NSRange linkRange = NSMakeRange(start, end - start);
934
- if([self handleStyleBlocksAndConflicts:[LinkStyle getStyleType] range:linkRange]) {
935
- [linkStyleClass addLink:text url:url range:linkRange manual:YES];
1129
+ if ([self handleStyleBlocksAndConflicts:[LinkStyle getStyleType]
1130
+ range:linkRange]) {
1131
+ [linkStyleClass addLink:text
1132
+ url:url
1133
+ range:linkRange
1134
+ manual:YES
1135
+ withSelection:YES];
936
1136
  [self anyTextMayHaveBeenModified];
937
1137
  }
938
1138
  }
939
1139
 
940
- - (void)addMention:(NSString *)indicator text:(NSString *)text attributes:(NSString *)attributes {
941
- MentionStyle *mentionStyleClass = (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
942
- if(mentionStyleClass == nullptr) { return; }
943
- if([mentionStyleClass getActiveMentionRange] == nullptr) { return; }
944
-
945
- if([self handleStyleBlocksAndConflicts:[MentionStyle getStyleType] range:[[mentionStyleClass getActiveMentionRange] rangeValue]]) {
1140
+ - (void)addMention:(NSString *)indicator
1141
+ text:(NSString *)text
1142
+ attributes:(NSString *)attributes {
1143
+ MentionStyle *mentionStyleClass =
1144
+ (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
1145
+ if (mentionStyleClass == nullptr) {
1146
+ return;
1147
+ }
1148
+ if ([mentionStyleClass getActiveMentionRange] == nullptr) {
1149
+ return;
1150
+ }
1151
+
1152
+ if ([self handleStyleBlocksAndConflicts:[MentionStyle getStyleType]
1153
+ range:[[mentionStyleClass
1154
+ getActiveMentionRange]
1155
+ rangeValue]]) {
946
1156
  [mentionStyleClass addMention:indicator text:text attributes:attributes];
947
1157
  [self anyTextMayHaveBeenModified];
948
1158
  }
949
1159
  }
950
1160
 
951
- - (void)addImage:(NSString *)uri width:(float)width height:(float)height
952
- {
953
- ImageStyle *imageStyleClass = (ImageStyle *)stylesDict[@([ImageStyle getStyleType])];
954
- if(imageStyleClass == nullptr) { return; }
955
-
956
- if([self handleStyleBlocksAndConflicts:[ImageStyle getStyleType] range:textView.selectedRange]) {
1161
+ - (void)addImage:(NSString *)uri width:(float)width height:(float)height {
1162
+ ImageStyle *imageStyleClass =
1163
+ (ImageStyle *)stylesDict[@([ImageStyle getStyleType])];
1164
+ if (imageStyleClass == nullptr) {
1165
+ return;
1166
+ }
1167
+
1168
+ if ([self handleStyleBlocksAndConflicts:[ImageStyle getStyleType]
1169
+ range:textView.selectedRange]) {
957
1170
  [imageStyleClass addImage:uri width:width height:height];
958
1171
  [self anyTextMayHaveBeenModified];
959
1172
  }
960
1173
  }
961
1174
 
962
1175
  - (void)startMentionWithIndicator:(NSString *)indicator {
963
- MentionStyle *mentionStyleClass = (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
964
- if(mentionStyleClass == nullptr) { return; }
965
-
966
- if([self handleStyleBlocksAndConflicts:[MentionStyle getStyleType] range:textView.selectedRange]) {
1176
+ MentionStyle *mentionStyleClass =
1177
+ (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
1178
+ if (mentionStyleClass == nullptr) {
1179
+ return;
1180
+ }
1181
+
1182
+ if ([self handleStyleBlocksAndConflicts:[MentionStyle getStyleType]
1183
+ range:textView.selectedRange]) {
967
1184
  [mentionStyleClass startMentionWithIndicator:indicator];
968
1185
  [self anyTextMayHaveBeenModified];
969
1186
  }
@@ -972,26 +1189,30 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
972
1189
  // returns false when style shouldn't be applied and true when it can be
973
1190
  - (BOOL)handleStyleBlocksAndConflicts:(StyleType)type range:(NSRange)range {
974
1191
  // handle blocking styles: if any is present we do not apply the toggled style
975
- NSArray<NSNumber *> *blocking = [self getPresentStyleTypesFrom: blockingStyles[@(type)] range:range];
976
- if(blocking.count != 0) {
1192
+ NSArray<NSNumber *> *blocking =
1193
+ [self getPresentStyleTypesFrom:blockingStyles[@(type)] range:range];
1194
+ if (blocking.count != 0) {
977
1195
  return NO;
978
1196
  }
979
-
1197
+
980
1198
  // handle conflicting styles: all of their occurences have to be removed
981
- NSArray<NSNumber *> *conflicting = [self getPresentStyleTypesFrom: conflictingStyles[@(type)] range:range];
982
- if(conflicting.count != 0) {
983
- for(NSNumber *style in conflicting) {
1199
+ NSArray<NSNumber *> *conflicting =
1200
+ [self getPresentStyleTypesFrom:conflictingStyles[@(type)] range:range];
1201
+ if (conflicting.count != 0) {
1202
+ for (NSNumber *style in conflicting) {
984
1203
  id<BaseStyleProtocol> styleClass = stylesDict[style];
985
-
986
- if(range.length >= 1) {
1204
+
1205
+ if (range.length >= 1) {
987
1206
  // for ranges, we need to remove each occurence
988
- NSArray<StylePair *> *allOccurences = [styleClass findAllOccurences:range];
989
-
990
- for(StylePair* pair in allOccurences) {
991
- [styleClass removeAttributes: [pair.rangeValue rangeValue]];
1207
+ NSArray<StylePair *> *allOccurences =
1208
+ [styleClass findAllOccurences:range];
1209
+
1210
+ for (StylePair *pair in allOccurences) {
1211
+ [styleClass removeAttributes:[pair.rangeValue rangeValue]];
992
1212
  }
993
1213
  } else {
994
- // with in-place selection, we just remove the adequate typing attributes
1214
+ // with in-place selection, we just remove the adequate typing
1215
+ // attributes
995
1216
  [styleClass removeTypingAttributes];
996
1217
  }
997
1218
  }
@@ -999,17 +1220,19 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
999
1220
  return YES;
1000
1221
  }
1001
1222
 
1002
- - (NSArray<NSNumber *> *)getPresentStyleTypesFrom:(NSArray<NSNumber *> *)types range:(NSRange)range {
1003
- NSMutableArray<NSNumber *> *resultArray = [[NSMutableArray<NSNumber *> alloc] init];
1004
- for(NSNumber *type in types) {
1223
+ - (NSArray<NSNumber *> *)getPresentStyleTypesFrom:(NSArray<NSNumber *> *)types
1224
+ range:(NSRange)range {
1225
+ NSMutableArray<NSNumber *> *resultArray =
1226
+ [[NSMutableArray<NSNumber *> alloc] init];
1227
+ for (NSNumber *type in types) {
1005
1228
  id<BaseStyleProtocol> styleClass = stylesDict[type];
1006
-
1007
- if(range.length >= 1) {
1008
- if([styleClass anyOccurence:range]) {
1229
+
1230
+ if (range.length >= 1) {
1231
+ if ([styleClass anyOccurence:range]) {
1009
1232
  [resultArray addObject:type];
1010
1233
  }
1011
1234
  } else {
1012
- if([styleClass detectStyle:range]) {
1235
+ if ([styleClass detectStyle:range]) {
1013
1236
  [resultArray addObject:type];
1014
1237
  }
1015
1238
  }
@@ -1019,49 +1242,58 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1019
1242
 
1020
1243
  - (void)manageSelectionBasedChanges {
1021
1244
  // link typing attributes fix
1022
- LinkStyle *linkStyleClass = (LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
1023
- if(linkStyleClass != nullptr) {
1245
+ LinkStyle *linkStyleClass =
1246
+ (LinkStyle *)stylesDict[@([LinkStyle getStyleType])];
1247
+ if (linkStyleClass != nullptr) {
1024
1248
  [linkStyleClass manageLinkTypingAttributes];
1025
1249
  }
1026
-
1250
+
1027
1251
  // mention typing attribtues fix and active editing
1028
- MentionStyle *mentionStyleClass = (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
1029
- if(mentionStyleClass != nullptr) {
1252
+ MentionStyle *mentionStyleClass =
1253
+ (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
1254
+ if (mentionStyleClass != nullptr) {
1030
1255
  [mentionStyleClass manageMentionTypingAttributes];
1031
-
1256
+
1032
1257
  // mention editing runs if only a selection was done (no text change)
1033
- // otherwise we would double-emit with a second call in the anyTextMayHaveBeenModified method
1034
- if([_recentlyEmittedString isEqualToString:[textView.textStorage.string copy]]) {
1258
+ // otherwise we would double-emit with a second call in the
1259
+ // anyTextMayHaveBeenModified method
1260
+ if ([_recentInputString
1261
+ isEqualToString:[textView.textStorage.string copy]]) {
1035
1262
  [mentionStyleClass manageMentionEditing];
1036
1263
  }
1037
1264
  }
1038
-
1265
+
1039
1266
  // typing attributes for empty lines selection reset
1040
1267
  NSString *currentString = [textView.textStorage.string copy];
1041
- if(textView.selectedRange.length == 0 && [_recentlyEmittedString isEqualToString:currentString]) {
1268
+ if (textView.selectedRange.length == 0 &&
1269
+ [_recentInputString isEqualToString:currentString]) {
1042
1270
  // no string change means only a selection changed with no character changes
1043
- NSRange paragraphRange = [textView.textStorage.string paragraphRangeForRange:textView.selectedRange];
1044
- if(
1045
- paragraphRange.length == 0 ||
1046
- (paragraphRange.length == 1 &&
1047
- [[NSCharacterSet newlineCharacterSet] characterIsMember:[textView.textStorage.string characterAtIndex:paragraphRange.location]])
1048
- ) {
1271
+ NSRange paragraphRange = [textView.textStorage.string
1272
+ paragraphRangeForRange:textView.selectedRange];
1273
+ if (paragraphRange.length == 0 ||
1274
+ (paragraphRange.length == 1 &&
1275
+ [[NSCharacterSet newlineCharacterSet]
1276
+ characterIsMember:[textView.textStorage.string
1277
+ characterAtIndex:paragraphRange
1278
+ .location]])) {
1049
1279
  // user changed selection to an empty line (or empty line with a newline)
1050
1280
  // typing attributes need to be reset
1051
1281
  textView.typingAttributes = defaultTypingAttributes;
1052
1282
  }
1053
1283
  }
1054
-
1284
+
1055
1285
  // update active styles as well
1056
1286
  [self tryUpdatingActiveStyles];
1057
1287
  }
1058
1288
 
1059
- - (void)handleWordModificationBasedChanges:(NSString*)word inRange:(NSRange)range {
1289
+ - (void)handleWordModificationBasedChanges:(NSString *)word
1290
+ inRange:(NSRange)range {
1060
1291
  // manual links refreshing and automatic links detection handling
1061
- LinkStyle* linkStyle = [stylesDict objectForKey:@([LinkStyle getStyleType])];
1062
-
1063
- if(linkStyle != nullptr) {
1064
- // manual links need to be handled first because they can block automatic links after being refreshed
1292
+ LinkStyle *linkStyle = [stylesDict objectForKey:@([LinkStyle getStyleType])];
1293
+
1294
+ if (linkStyle != nullptr) {
1295
+ // manual links need to be handled first because they can block automatic
1296
+ // links after being refreshed
1065
1297
  [linkStyle handleManualLinks:word inRange:range];
1066
1298
  [linkStyle handleAutomaticLinks:word inRange:range];
1067
1299
  }
@@ -1069,92 +1301,98 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1069
1301
 
1070
1302
  - (void)anyTextMayHaveBeenModified {
1071
1303
  // we don't do no text changes when working with iOS marked text
1072
- if(textView.markedTextRange != nullptr) {
1304
+ if (textView.markedTextRange != nullptr) {
1073
1305
  return;
1074
1306
  }
1075
-
1307
+
1076
1308
  // zero width space adding or removal
1077
1309
  [ZeroWidthSpaceUtils handleZeroWidthSpacesInInput:self];
1078
-
1310
+
1079
1311
  // emptying input typing attributes management
1080
- if(textView.textStorage.string.length == 0 && _recentlyEmittedString.length > 0) {
1312
+ if (textView.textStorage.string.length == 0 &&
1313
+ _recentInputString.length > 0) {
1081
1314
  // reset typing attribtues
1082
1315
  textView.typingAttributes = defaultTypingAttributes;
1083
1316
  }
1084
-
1317
+
1085
1318
  // inline code on newlines fix
1086
1319
  InlineCodeStyle *codeStyle = stylesDict[@([InlineCodeStyle getStyleType])];
1087
- if(codeStyle != nullptr) {
1320
+ if (codeStyle != nullptr) {
1088
1321
  [codeStyle handleNewlines];
1089
1322
  }
1090
-
1323
+
1091
1324
  // blockquote colors management
1092
1325
  BlockQuoteStyle *bqStyle = stylesDict[@([BlockQuoteStyle getStyleType])];
1093
- if(bqStyle != nullptr) {
1326
+ if (bqStyle != nullptr) {
1094
1327
  [bqStyle manageBlockquoteColor];
1095
1328
  }
1096
-
1329
+
1097
1330
  // codeblock font and color management
1098
1331
  CodeBlockStyle *codeBlockStyle = stylesDict[@([CodeBlockStyle getStyleType])];
1099
- if(codeBlockStyle != nullptr) {
1332
+ if (codeBlockStyle != nullptr) {
1100
1333
  [codeBlockStyle manageCodeBlockFontAndColor];
1101
1334
  }
1102
-
1335
+
1103
1336
  // improper headings fix
1104
1337
  H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
1105
1338
  H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
1106
1339
  H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
1107
- if(h1Style != nullptr && h2Style != nullptr && h3Style != nullptr) {
1340
+ if (h1Style != nullptr && h2Style != nullptr && h3Style != nullptr) {
1108
1341
  [h1Style handleImproperHeadings];
1109
1342
  [h2Style handleImproperHeadings];
1110
1343
  [h3Style handleImproperHeadings];
1111
1344
  }
1112
-
1345
+
1113
1346
  // mentions management: removal and editing
1114
- MentionStyle *mentionStyleClass = (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
1115
- if(mentionStyleClass != nullptr) {
1347
+ MentionStyle *mentionStyleClass =
1348
+ (MentionStyle *)stylesDict[@([MentionStyle getStyleType])];
1349
+ if (mentionStyleClass != nullptr) {
1116
1350
  [mentionStyleClass handleExistingMentions];
1117
1351
  [mentionStyleClass manageMentionEditing];
1118
1352
  }
1119
-
1353
+
1120
1354
  // placholder management
1121
- if(!_placeholderLabel.hidden && textView.textStorage.string.length > 0) {
1355
+ if (!_placeholderLabel.hidden && textView.textStorage.string.length > 0) {
1122
1356
  [self setPlaceholderLabelShown:NO];
1123
- } else if(textView.textStorage.string.length == 0 && _placeholderLabel.hidden) {
1357
+ } else if (textView.textStorage.string.length == 0 &&
1358
+ _placeholderLabel.hidden) {
1124
1359
  [self setPlaceholderLabelShown:YES];
1125
1360
  }
1126
-
1127
- if(![textView.textStorage.string isEqualToString:_recentlyEmittedString]) {
1361
+
1362
+ if (![textView.textStorage.string isEqualToString:_recentInputString]) {
1128
1363
  // modified words handling
1129
- NSArray *modifiedWords = [WordsUtils getAffectedWordsFromText:textView.textStorage.string modificationRange:recentlyChangedRange];
1130
- if(modifiedWords != nullptr) {
1131
- for(NSDictionary *wordDict in modifiedWords) {
1364
+ NSArray *modifiedWords =
1365
+ [WordsUtils getAffectedWordsFromText:textView.textStorage.string
1366
+ modificationRange:recentlyChangedRange];
1367
+ if (modifiedWords != nullptr) {
1368
+ for (NSDictionary *wordDict in modifiedWords) {
1132
1369
  NSString *wordText = (NSString *)[wordDict objectForKey:@"word"];
1133
1370
  NSValue *wordRange = (NSValue *)[wordDict objectForKey:@"range"];
1134
-
1135
- if(wordText == nullptr || wordRange == nullptr) {
1371
+
1372
+ if (wordText == nullptr || wordRange == nullptr) {
1136
1373
  continue;
1137
1374
  }
1138
-
1139
- [self handleWordModificationBasedChanges:wordText inRange:[wordRange rangeValue]];
1375
+
1376
+ [self handleWordModificationBasedChanges:wordText
1377
+ inRange:[wordRange rangeValue]];
1140
1378
  }
1141
1379
  }
1142
-
1143
- // emit string without zero width spaces
1144
- NSString *stringToBeEmitted = [[textView.textStorage.string stringByReplacingOccurrencesOfString:@"\u200B" withString:@""] copy];
1145
-
1380
+
1146
1381
  // emit onChangeText event
1147
1382
  auto emitter = [self getEventEmitter];
1148
- if(emitter != nullptr) {
1149
- // set the recently emitted string only if the emitter is defined
1150
- _recentlyEmittedString = stringToBeEmitted;
1151
-
1152
- emitter->onChangeText({
1153
- .value = [stringToBeEmitted toCppString]
1154
- });
1383
+ if (emitter != nullptr) {
1384
+ // set the recent input string only if the emitter is defined
1385
+ _recentInputString = [textView.textStorage.string copy];
1386
+
1387
+ // emit string without zero width spaces
1388
+ NSString *stringToBeEmitted = [[textView.textStorage.string
1389
+ stringByReplacingOccurrencesOfString:@"\u200B"
1390
+ withString:@""] copy];
1391
+
1392
+ emitter->onChangeText({.value = [stringToBeEmitted toCppString]});
1155
1393
  }
1156
1394
  }
1157
-
1395
+
1158
1396
  // update height on each character change
1159
1397
  [self tryUpdatingHeight];
1160
1398
  // update active styles as well
@@ -1163,29 +1401,39 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1163
1401
  [self scheduleRelayoutIfNeeded];
1164
1402
  }
1165
1403
 
1166
- // Debounced relayout helper - coalesces multiple requests into one per runloop tick
1167
- - (void)scheduleRelayoutIfNeeded
1168
- {
1404
+ // Debounced relayout helper - coalesces multiple requests into one per runloop
1405
+ // tick
1406
+ - (void)scheduleRelayoutIfNeeded {
1169
1407
  // Cancel any previously scheduled invocation to debounce
1170
- [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_performRelayout) object:nil];
1408
+ [NSObject cancelPreviousPerformRequestsWithTarget:self
1409
+ selector:@selector(_performRelayout)
1410
+ object:nil];
1171
1411
  // Schedule on next runloop cycle
1172
- [self performSelector:@selector(_performRelayout) withObject:nil afterDelay:0];
1412
+ [self performSelector:@selector(_performRelayout)
1413
+ withObject:nil
1414
+ afterDelay:0];
1173
1415
  }
1174
1416
 
1175
- - (void)_performRelayout
1176
- {
1177
- if (!textView) { return; }
1417
+ - (void)_performRelayout {
1418
+ if (!textView) {
1419
+ return;
1420
+ }
1178
1421
 
1179
1422
  dispatch_async(dispatch_get_main_queue(), ^{
1180
- NSRange wholeRange = NSMakeRange(0, self->textView.textStorage.string.length);
1423
+ NSRange wholeRange =
1424
+ NSMakeRange(0, self->textView.textStorage.string.length);
1181
1425
  NSRange actualRange = NSMakeRange(0, 0);
1182
- [self->textView.layoutManager invalidateLayoutForCharacterRange:wholeRange actualCharacterRange:&actualRange];
1426
+ [self->textView.layoutManager
1427
+ invalidateLayoutForCharacterRange:wholeRange
1428
+ actualCharacterRange:&actualRange];
1183
1429
  [self->textView.layoutManager ensureLayoutForCharacterRange:actualRange];
1184
- [self->textView.layoutManager invalidateDisplayForCharacterRange:wholeRange];
1185
-
1430
+ [self->textView.layoutManager
1431
+ invalidateDisplayForCharacterRange:wholeRange];
1432
+
1186
1433
  // We have to explicitly set contentSize
1187
1434
  // That way textView knows if content overflows and if should be scrollable
1188
- // We recall measureSize here because value returned from previous measureSize may not be up-to date at that point
1435
+ // We recall measureSize here because value returned from previous
1436
+ // measureSize may not be up-to date at that point
1189
1437
  CGSize measuredSize = [self measureSize:self->textView.frame.size.width];
1190
1438
  self->textView.contentSize = measuredSize;
1191
1439
  });
@@ -1201,34 +1449,39 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1201
1449
 
1202
1450
  - (void)textViewDidBeginEditing:(UITextView *)textView {
1203
1451
  auto emitter = [self getEventEmitter];
1204
- if(emitter != nullptr) {
1205
- //send onFocus event if allowed
1206
- if(_emitFocusBlur) {
1452
+ if (emitter != nullptr) {
1453
+ // send onFocus event if allowed
1454
+ if (_emitFocusBlur) {
1207
1455
  emitter->onInputFocus({});
1208
1456
  }
1209
-
1210
- NSString *textAtSelection = [[[NSMutableString alloc] initWithString:textView.textStorage.string] substringWithRange: textView.selectedRange];
1211
- emitter->onChangeSelection({
1212
- .start = static_cast<int>(textView.selectedRange.location),
1213
- .end = static_cast<int>(textView.selectedRange.location + textView.selectedRange.length),
1214
- .text = [textAtSelection toCppString]
1215
- });
1216
- }
1217
- // manage selection changes since textViewDidChangeSelection sometimes doesn't run on focus
1457
+
1458
+ NSString *textAtSelection =
1459
+ [[[NSMutableString alloc] initWithString:textView.textStorage.string]
1460
+ substringWithRange:textView.selectedRange];
1461
+ emitter->onChangeSelection(
1462
+ {.start = static_cast<int>(textView.selectedRange.location),
1463
+ .end = static_cast<int>(textView.selectedRange.location +
1464
+ textView.selectedRange.length),
1465
+ .text = [textAtSelection toCppString]});
1466
+ }
1467
+ // manage selection changes since textViewDidChangeSelection sometimes doesn't
1468
+ // run on focus
1218
1469
  [self manageSelectionBasedChanges];
1219
1470
  }
1220
1471
 
1221
1472
  - (void)textViewDidEndEditing:(UITextView *)textView {
1222
1473
  auto emitter = [self getEventEmitter];
1223
- if(emitter != nullptr && _emitFocusBlur) {
1224
- //send onBlur event
1474
+ if (emitter != nullptr && _emitFocusBlur) {
1475
+ // send onBlur event
1225
1476
  emitter->onInputBlur({});
1226
1477
  }
1227
1478
  }
1228
1479
 
1229
- - (bool)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
1480
+ - (bool)textView:(UITextView *)textView
1481
+ shouldChangeTextInRange:(NSRange)range
1482
+ replacementText:(NSString *)text {
1230
1483
  recentlyChangedRange = NSMakeRange(range.location, text.length);
1231
-
1484
+
1232
1485
  UnorderedListStyle *uStyle = stylesDict[@([UnorderedListStyle getStyleType])];
1233
1486
  OrderedListStyle *oStyle = stylesDict[@([OrderedListStyle getStyleType])];
1234
1487
  BlockQuoteStyle *bqStyle = stylesDict[@([BlockQuoteStyle getStyleType])];
@@ -1238,30 +1491,37 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1238
1491
  H1Style *h1Style = stylesDict[@([H1Style getStyleType])];
1239
1492
  H2Style *h2Style = stylesDict[@([H2Style getStyleType])];
1240
1493
  H3Style *h3Style = stylesDict[@([H3Style getStyleType])];
1241
-
1242
- // some of the changes these checks do could interfere with later checks and cause a crash
1243
- // so here I rely on short circuiting evaluation of the logical expression
1244
- // either way it's not possible to have two of them come off at the same time
1245
- if(
1246
- [uStyle handleBackspaceInRange:range replacementText:text] ||
1247
- [uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
1248
- [oStyle handleBackspaceInRange:range replacementText:text] ||
1249
- [oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
1250
- [bqStyle handleBackspaceInRange:range replacementText:text] ||
1251
- [cbStyle handleBackspaceInRange:range replacementText:text] ||
1252
- [linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
1253
- [mentionStyle handleLeadingMentionReplacement:range replacementText:text] ||
1254
- [h1Style handleNewlinesInRange:range replacementText:text] ||
1255
- [h2Style handleNewlinesInRange:range replacementText:text] ||
1256
- [h3Style handleNewlinesInRange:range replacementText:text] ||
1257
- [ZeroWidthSpaceUtils handleBackspaceInRange:range replacementText:text input:self] ||
1258
- [ParagraphAttributesUtils handleBackspaceInRange:range replacementText:text input:self] ||
1259
- // CRITICAL: This callback HAS TO be always evaluated last.
1260
- //
1261
- // This function is the "Generic Fallback": if no specific style claims the backspace action
1262
- // to change its state, only then do we proceed to physically delete the newline and merge paragraphs.
1263
- [ParagraphAttributesUtils handleNewlineBackspaceInRange:range replacementText:text input:self]
1264
- ) {
1494
+
1495
+ // some of the changes these checks do could interfere with later checks and
1496
+ // cause a crash so here I rely on short circuiting evaluation of the logical
1497
+ // expression either way it's not possible to have two of them come off at the
1498
+ // same time
1499
+ if ([uStyle handleBackspaceInRange:range replacementText:text] ||
1500
+ [uStyle tryHandlingListShorcutInRange:range replacementText:text] ||
1501
+ [oStyle handleBackspaceInRange:range replacementText:text] ||
1502
+ [oStyle tryHandlingListShorcutInRange:range replacementText:text] ||
1503
+ [bqStyle handleBackspaceInRange:range replacementText:text] ||
1504
+ [cbStyle handleBackspaceInRange:range replacementText:text] ||
1505
+ [linkStyle handleLeadingLinkReplacement:range replacementText:text] ||
1506
+ [mentionStyle handleLeadingMentionReplacement:range
1507
+ replacementText:text] ||
1508
+ [h1Style handleNewlinesInRange:range replacementText:text] ||
1509
+ [h2Style handleNewlinesInRange:range replacementText:text] ||
1510
+ [h3Style handleNewlinesInRange:range replacementText:text] ||
1511
+ [ZeroWidthSpaceUtils handleBackspaceInRange:range
1512
+ replacementText:text
1513
+ input:self] ||
1514
+ [ParagraphAttributesUtils handleBackspaceInRange:range
1515
+ replacementText:text
1516
+ input:self] ||
1517
+ // CRITICAL: This callback HAS TO be always evaluated last.
1518
+ //
1519
+ // This function is the "Generic Fallback": if no specific style claims
1520
+ // the backspace action to change its state, only then do we proceed to
1521
+ // physically delete the newline and merge paragraphs.
1522
+ [ParagraphAttributesUtils handleParagraphStylesMergeOnBackspace:range
1523
+ replacementText:text
1524
+ input:self]) {
1265
1525
  [self anyTextMayHaveBeenModified];
1266
1526
  return NO;
1267
1527
  }
@@ -1271,27 +1531,58 @@ Class<RCTComponentViewProtocol> EnrichedTextInputViewCls(void) {
1271
1531
 
1272
1532
  - (void)textViewDidChangeSelection:(UITextView *)textView {
1273
1533
  // emit the event
1274
- NSString *textAtSelection = [[[NSMutableString alloc] initWithString:textView.textStorage.string] substringWithRange: textView.selectedRange];
1275
-
1534
+ NSString *textAtSelection =
1535
+ [[[NSMutableString alloc] initWithString:textView.textStorage.string]
1536
+ substringWithRange:textView.selectedRange];
1537
+
1276
1538
  auto emitter = [self getEventEmitter];
1277
- if(emitter != nullptr) {
1539
+ if (emitter != nullptr) {
1278
1540
  // iOS range works differently because it specifies location and length
1279
- // here, start is the location, but end is the first index BEHIND the end. So a 0 length range will have equal start and end
1280
- emitter->onChangeSelection({
1281
- .start = static_cast<int>(textView.selectedRange.location),
1282
- .end = static_cast<int>(textView.selectedRange.location + textView.selectedRange.length),
1283
- .text = [textAtSelection toCppString]
1284
- });
1541
+ // here, start is the location, but end is the first index BEHIND the end.
1542
+ // So a 0 length range will have equal start and end
1543
+ emitter->onChangeSelection(
1544
+ {.start = static_cast<int>(textView.selectedRange.location),
1545
+ .end = static_cast<int>(textView.selectedRange.location +
1546
+ textView.selectedRange.length),
1547
+ .text = [textAtSelection toCppString]});
1285
1548
  }
1286
-
1549
+
1287
1550
  // manage selection changes
1288
1551
  [self manageSelectionBasedChanges];
1289
1552
  }
1290
1553
 
1291
- // this function isn't called always when some text changes (for example setting link or starting mention with indicator doesn't fire it)
1292
- // so all the logic is in anyTextMayHaveBeenModified
1554
+ // this function isn't called always when some text changes (for example setting
1555
+ // link or starting mention with indicator doesn't fire it) so all the logic is
1556
+ // in anyTextMayHaveBeenModified
1293
1557
  - (void)textViewDidChange:(UITextView *)textView {
1294
1558
  [self anyTextMayHaveBeenModified];
1295
1559
  }
1296
1560
 
1561
+ // MARK: - Media attachments delegate
1562
+
1563
+ - (void)mediaAttachmentDidUpdate:(NSTextAttachment *)attachment {
1564
+ NSTextStorage *storage = textView.textStorage;
1565
+ NSRange fullRange = NSMakeRange(0, storage.length);
1566
+
1567
+ __block NSRange foundRange = NSMakeRange(NSNotFound, 0);
1568
+
1569
+ [storage enumerateAttribute:NSAttachmentAttributeName
1570
+ inRange:fullRange
1571
+ options:0
1572
+ usingBlock:^(id value, NSRange range, BOOL *stop) {
1573
+ if (value == attachment) {
1574
+ foundRange = range;
1575
+ *stop = YES;
1576
+ }
1577
+ }];
1578
+
1579
+ if (foundRange.location == NSNotFound) {
1580
+ return;
1581
+ }
1582
+
1583
+ [storage edited:NSTextStorageEditedAttributes
1584
+ range:foundRange
1585
+ changeInLength:0];
1586
+ }
1587
+
1297
1588
  @end