@expensify/react-native-live-markdown 0.1.74 → 0.1.76

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.
@@ -22,6 +22,7 @@
22
22
  #else
23
23
  __weak RCTBaseTextInputView *_textInput;
24
24
  #endif /* RCT_NEW_ARCH_ENABLED */
25
+ __weak UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
25
26
  __weak RCTBackedTextFieldDelegateAdapter *_adapter;
26
27
  __weak RCTUITextView *_textView;
27
28
  }
@@ -51,11 +52,11 @@
51
52
  #ifdef RCT_NEW_ARCH_ENABLED
52
53
  react_native_assert([view isKindOfClass:[RCTTextInputComponentView class]] && "Previous sibling component is not an instance of RCTTextInputComponentView.");
53
54
  _textInput = (RCTTextInputComponentView *)view;
54
- UIView<RCTBackedTextInputViewProtocol> *backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"];
55
+ _backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"];
55
56
  #else
56
57
  react_native_assert([view isKindOfClass:[RCTBaseTextInputView class]] && "Previous sibling component is not an instance of RCTBaseTextInputView.");
57
58
  _textInput = (RCTBaseTextInputView *)view;
58
- UIView<RCTBackedTextInputViewProtocol> *backedTextInputView = _textInput.backedTextInputView;
59
+ _backedTextInputView = _textInput.backedTextInputView;
59
60
  #endif /* RCT_NEW_ARCH_ENABLED */
60
61
 
61
62
  _markdownUtils = [[RCTMarkdownUtils alloc] init];
@@ -63,12 +64,12 @@
63
64
  [_markdownUtils setMarkdownStyle:_markdownStyle];
64
65
 
65
66
  [_textInput setMarkdownUtils:_markdownUtils];
66
- if ([backedTextInputView isKindOfClass:[RCTUITextField class]]) {
67
- RCTUITextField *textField = (RCTUITextField *)backedTextInputView;
67
+ if ([_backedTextInputView isKindOfClass:[RCTUITextField class]]) {
68
+ RCTUITextField *textField = (RCTUITextField *)_backedTextInputView;
68
69
  _adapter = [textField valueForKey:@"textInputDelegateAdapter"];
69
70
  [_adapter setMarkdownUtils:_markdownUtils];
70
- } else if ([backedTextInputView isKindOfClass:[RCTUITextView class]]) {
71
- _textView = (RCTUITextView *)backedTextInputView;
71
+ } else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) {
72
+ _textView = (RCTUITextView *)_backedTextInputView;
72
73
  [_textView setMarkdownUtils:_markdownUtils];
73
74
  NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode
74
75
  layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
@@ -100,11 +101,13 @@
100
101
  {
101
102
  _markdownStyle = markdownStyle;
102
103
  [_markdownUtils setMarkdownStyle:markdownStyle];
104
+
105
+ // apply new styles
103
106
  #ifdef RCT_NEW_ARCH_ENABLED
104
- [_textInput textInputDidChange]; // apply new styles
107
+ [_textInput _setAttributedString:_backedTextInputView.attributedText];
105
108
  #else
106
- [_textInput setAttributedText:_textInput.attributedText]; // apply new styles
107
- #endif
109
+ [_textInput setAttributedText:_textInput.attributedText];
110
+ #endif /* RCT_NEW_ARCH_ENABLED */
108
111
  }
109
112
 
110
113
  @end
@@ -9,6 +9,8 @@ NS_ASSUME_NONNULL_BEGIN
9
9
 
10
10
  - (void)markdown_setAttributedText:(NSAttributedString *)attributedText;
11
11
 
12
+ - (BOOL)markdown_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText;
13
+
12
14
  - (void)markdown_updateLocalData;
13
15
 
14
16
  @end
@@ -23,6 +23,16 @@
23
23
  [self markdown_setAttributedText:attributedText];
24
24
  }
25
25
 
26
+ - (BOOL)markdown_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText
27
+ {
28
+ RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils];
29
+ if (markdownUtils != nil) {
30
+ return [newText isEqualToAttributedString:oldText];
31
+ }
32
+
33
+ return [self markdown_textOf:newText equals:oldText];
34
+ }
35
+
26
36
  - (void)markdown_updateLocalData
27
37
  {
28
38
  RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils];
@@ -69,6 +79,15 @@
69
79
  Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
70
80
  method_exchangeImplementations(originalMethod, swizzledMethod);
71
81
  }
82
+
83
+ {
84
+ // swizzle textOf
85
+ SEL originalSelector = @selector(textOf:equals:);
86
+ SEL swizzledSelector = @selector(markdown_textOf:equals:);
87
+ Method originalMethod = class_getInstanceMethod(cls, originalSelector);
88
+ Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
89
+ method_exchangeImplementations(originalMethod, swizzledMethod);
90
+ }
72
91
  });
73
92
  }
74
93
 
@@ -136,6 +136,8 @@
136
136
  }
137
137
  }];
138
138
 
139
+ RCTApplyBaselineOffset(attributedString);
140
+
139
141
  [attributedString endEditing];
140
142
 
141
143
  _prevInputString = inputString;
@@ -148,4 +150,47 @@
148
150
  }
149
151
  }
150
152
 
153
+ static void RCTApplyBaselineOffset(NSMutableAttributedString *attributedText)
154
+ {
155
+ __block CGFloat maximumLineHeight = 0;
156
+
157
+ [attributedText enumerateAttribute:NSParagraphStyleAttributeName
158
+ inRange:NSMakeRange(0, attributedText.length)
159
+ options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
160
+ usingBlock:^(NSParagraphStyle *paragraphStyle, __unused NSRange range, __unused BOOL *stop) {
161
+ if (!paragraphStyle) {
162
+ return;
163
+ }
164
+
165
+ maximumLineHeight = MAX(paragraphStyle.maximumLineHeight, maximumLineHeight);
166
+ }];
167
+
168
+ if (maximumLineHeight == 0) {
169
+ // `lineHeight` was not specified, nothing to do.
170
+ return;
171
+ }
172
+
173
+ __block CGFloat maximumFontLineHeight = 0;
174
+
175
+ [attributedText enumerateAttribute:NSFontAttributeName
176
+ inRange:NSMakeRange(0, attributedText.length)
177
+ options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
178
+ usingBlock:^(UIFont *font, NSRange range, __unused BOOL *stop) {
179
+ if (!font) {
180
+ return;
181
+ }
182
+
183
+ maximumFontLineHeight = MAX(font.lineHeight, maximumFontLineHeight);
184
+ }];
185
+
186
+ if (maximumLineHeight < maximumFontLineHeight) {
187
+ return;
188
+ }
189
+
190
+ CGFloat baseLineOffset = (maximumLineHeight - maximumFontLineHeight) / 2.0;
191
+ [attributedText addAttribute:NSBaselineOffsetAttributeName
192
+ value:@(baseLineOffset)
193
+ range:NSMakeRange(0, attributedText.length)];
194
+ }
195
+
151
196
  @end
@@ -12,7 +12,9 @@ NS_ASSUME_NONNULL_BEGIN
12
12
 
13
13
  - (void)markdown__setAttributedString:(NSAttributedString *)attributedString;
14
14
 
15
- - (void)textInputDidChange;
15
+ - (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText;
16
+
17
+ - (void)_setAttributedString:(NSAttributedString *)attributedString;
16
18
 
17
19
  @end
18
20
 
@@ -47,16 +47,39 @@
47
47
  [self markdown__setAttributedString:attributedString];
48
48
  }
49
49
 
50
+ - (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText
51
+ {
52
+ RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils];
53
+ if (markdownUtils != nil) {
54
+ return [newText isEqualToAttributedString:oldText];
55
+ }
56
+
57
+ return [self markdown__textOf:newText equals:oldText];
58
+ }
59
+
50
60
  + (void)load
51
61
  {
52
62
  static dispatch_once_t onceToken;
53
63
  dispatch_once(&onceToken, ^{
54
- Class cls = [self class];
55
- SEL originalSelector = @selector(_setAttributedString:);
56
- SEL swizzledSelector = @selector(markdown__setAttributedString:);
57
- Method originalMethod = class_getInstanceMethod(cls, originalSelector);
58
- Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
59
- method_exchangeImplementations(originalMethod, swizzledMethod);
64
+ {
65
+ // swizzle _setAttributedString
66
+ Class cls = [self class];
67
+ SEL originalSelector = @selector(_setAttributedString:);
68
+ SEL swizzledSelector = @selector(markdown__setAttributedString:);
69
+ Method originalMethod = class_getInstanceMethod(cls, originalSelector);
70
+ Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
71
+ method_exchangeImplementations(originalMethod, swizzledMethod);
72
+ }
73
+
74
+ {
75
+ // swizzle _textOf
76
+ Class cls = [self class];
77
+ SEL originalSelector = @selector(_textOf:equals:);
78
+ SEL swizzledSelector = @selector(markdown__textOf:equals:);
79
+ Method originalMethod = class_getInstanceMethod(cls, originalSelector);
80
+ Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
81
+ method_exchangeImplementations(originalMethod, swizzledMethod);
82
+ }
60
83
  });
61
84
  }
62
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expensify/react-native-live-markdown",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "description": "Drop-in replacement for React Native's TextInput component with Markdown formatting.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",