@expensify/react-native-live-markdown 0.1.245 → 0.1.247

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.
@@ -1,17 +1,29 @@
1
+ #import <react/debug/react_native_assert.h>
1
2
  #import <react/renderer/components/RNLiveMarkdownSpec/Props.h>
3
+ #import <React/RCTFabricComponentsPlugins.h>
4
+ #import <React/RCTUITextField.h>
2
5
 
6
+ #import <RNLiveMarkdown/MarkdownLayoutManager.h>
7
+ #import <RNLiveMarkdown/MarkdownShadowFamilyRegistry.h>
3
8
  #import <RNLiveMarkdown/MarkdownTextInputDecoratorComponentView.h>
4
- #import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
9
+ #import <RNLiveMarkdown/MarkdownTextInputDecoratorViewComponentDescriptor.h>
10
+ #import <RNLiveMarkdown/RCTBackedTextFieldDelegateAdapter+Markdown.h>
5
11
  #import <RNLiveMarkdown/RCTMarkdownStyle.h>
12
+ #import <RNLiveMarkdown/RCTTextInputComponentView+Markdown.h>
13
+ #import <RNLiveMarkdown/RCTUITextView+Markdown.h>
6
14
 
7
- #import <RNLiveMarkdown/MarkdownTextInputDecoratorViewComponentDescriptor.h>
8
- #import "MarkdownShadowFamilyRegistry.h"
9
- #import "RCTFabricComponentsPlugins.h"
15
+ #import <objc/runtime.h>
10
16
 
11
17
  using namespace facebook::react;
12
18
 
13
19
  @implementation MarkdownTextInputDecoratorComponentView {
14
- MarkdownTextInputDecoratorView *_view;
20
+ RCTMarkdownUtils *_markdownUtils;
21
+ RCTMarkdownStyle *_markdownStyle;
22
+ NSNumber *_parserId;
23
+ __weak RCTTextInputComponentView *_textInput;
24
+ __weak UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
25
+ __weak RCTBackedTextFieldDelegateAdapter *_adapter;
26
+ __weak RCTUITextView *_textView;
15
27
  ShadowNodeFamily::Shared _decoratorFamily;
16
28
  }
17
29
 
@@ -31,10 +43,6 @@ using namespace facebook::react;
31
43
  if (self = [super initWithFrame:frame]) {
32
44
  static const auto defaultProps = std::make_shared<const MarkdownTextInputDecoratorViewProps>();
33
45
  _props = defaultProps;
34
-
35
- _view = [[MarkdownTextInputDecoratorView alloc] init];
36
-
37
- self.contentView = _view;
38
46
  }
39
47
 
40
48
  return self;
@@ -43,11 +51,11 @@ using namespace facebook::react;
43
51
  - (void)updateState:(const facebook::react::State::Shared &)state oldState:(const facebook::react::State::Shared &)oldState
44
52
  {
45
53
  auto data = std::static_pointer_cast<MarkdownTextInputDecoratorShadowNode::ConcreteState const>(state)->getData();
46
-
54
+
47
55
  if (_decoratorFamily != nullptr) {
48
56
  MarkdownShadowFamilyRegistry::unregisterFamilyForUpdates(_decoratorFamily);
49
57
  }
50
-
58
+
51
59
  _decoratorFamily = data.decoratorFamily;
52
60
  MarkdownShadowFamilyRegistry::registerFamilyForUpdates(_decoratorFamily);
53
61
  }
@@ -57,26 +65,103 @@ using namespace facebook::react;
57
65
  MarkdownShadowFamilyRegistry::unregisterFamilyForUpdates(_decoratorFamily);
58
66
  _decoratorFamily = nullptr;
59
67
  }
60
-
68
+
61
69
  [super willMoveToSuperview:newSuperview];
62
70
  }
63
71
 
72
+ - (void)didMoveToWindow {
73
+ if (self.superview == nil) {
74
+ return;
75
+ }
76
+
77
+ NSArray *viewsArray = self.superview.subviews;
78
+ NSUInteger currentIndex = [viewsArray indexOfObject:self];
79
+
80
+ react_native_assert(currentIndex != 0 && currentIndex != NSNotFound && "Error while finding current component.");
81
+ UIView *view = [viewsArray objectAtIndex:currentIndex - 1];
82
+
83
+ react_native_assert([view isKindOfClass:[RCTTextInputComponentView class]] && "Previous sibling component is not an instance of RCTTextInputComponentView.");
84
+ _textInput = (RCTTextInputComponentView *)view;
85
+ _backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"];
86
+
87
+ _markdownUtils = [[RCTMarkdownUtils alloc] init];
88
+ react_native_assert(_markdownStyle != nil);
89
+ [_markdownUtils setMarkdownStyle:_markdownStyle];
90
+ [_markdownUtils setParserId:_parserId];
91
+
92
+ [_textInput setMarkdownUtils:_markdownUtils];
93
+ if ([_backedTextInputView isKindOfClass:[RCTUITextField class]]) {
94
+ RCTUITextField *textField = (RCTUITextField *)_backedTextInputView;
95
+ _adapter = [textField valueForKey:@"textInputDelegateAdapter"];
96
+ [_adapter setMarkdownUtils:_markdownUtils];
97
+ } else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) {
98
+ _textView = (RCTUITextView *)_backedTextInputView;
99
+ [_textView setMarkdownUtils:_markdownUtils];
100
+ NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode
101
+
102
+ // Correct content height in TextKit 1 compatibility mode. (See https://github.com/Expensify/App/issues/41567)
103
+ // Consider removing this fix if it is no longer needed after migrating to TextKit 2.
104
+ CGSize contentSize = _textView.contentSize;
105
+ CGRect textBounds = [layoutManager usedRectForTextContainer:_textView.textContainer];
106
+ contentSize.height = textBounds.size.height + _textView.textContainerInset.top + _textView.textContainerInset.bottom;
107
+ [_textView setContentSize:contentSize];
108
+
109
+ layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
110
+ object_setClass(layoutManager, [MarkdownLayoutManager class]);
111
+ [layoutManager setValue:_markdownUtils forKey:@"markdownUtils"];
112
+ } else {
113
+ react_native_assert(false && "Cannot enable Markdown for this type of TextInput.");
114
+ }
115
+ }
116
+
117
+ - (void)willMoveToWindow:(UIWindow *)newWindow
118
+ {
119
+ if (_textInput != nil) {
120
+ [_textInput setMarkdownUtils:nil];
121
+ }
122
+ if (_adapter != nil) {
123
+ [_adapter setMarkdownUtils:nil];
124
+ }
125
+ if (_textView != nil) {
126
+ [_textView setMarkdownUtils:nil];
127
+ if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
128
+ [_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
129
+ object_setClass(_textView.layoutManager, [NSLayoutManager class]);
130
+ }
131
+ }
132
+ }
133
+
64
134
  - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
65
135
  {
66
136
  const auto &oldViewProps = *std::static_pointer_cast<MarkdownTextInputDecoratorViewProps const>(_props);
67
137
  const auto &newViewProps = *std::static_pointer_cast<MarkdownTextInputDecoratorViewProps const>(props);
68
138
 
69
139
  if (oldViewProps.parserId != newViewProps.parserId) {
70
- [_view setParserId:@(newViewProps.parserId)];
140
+ _parserId = @(newViewProps.parserId);
141
+ [_markdownUtils setParserId:_parserId];
71
142
  }
72
143
 
73
144
  // TODO: if (oldViewProps.markdownStyle != newViewProps.markdownStyle)
74
- RCTMarkdownStyle *markdownStyle = [[RCTMarkdownStyle alloc] initWithStruct:newViewProps.markdownStyle];
75
- [_view setMarkdownStyle:markdownStyle];
145
+ _markdownStyle = [[RCTMarkdownStyle alloc] initWithStruct:newViewProps.markdownStyle];
146
+ [_markdownUtils setMarkdownStyle:_markdownStyle];
147
+
148
+ // TODO: call applyNewStyles only if needed
149
+ [self applyNewStyles];
76
150
 
77
151
  [super updateProps:props oldProps:oldProps];
78
152
  }
79
153
 
154
+ - (void)applyNewStyles
155
+ {
156
+ if (_textView != nil) {
157
+ // We want to use `textStorage` for applying markdown when possible. Currently it's only available for UITextView
158
+ [_textView textDidChange];
159
+ } else {
160
+ // apply new styles
161
+ [_textInput _setAttributedString:_backedTextInputView.attributedText];
162
+ }
163
+ }
164
+
80
165
  Class<RCTComponentViewProtocol> MarkdownTextInputDecoratorViewCls(void)
81
166
  {
82
167
  return MarkdownTextInputDecoratorComponentView.class;
@@ -1,23 +1,11 @@
1
1
  #import <RNLiveMarkdown/MarkdownTextInputDecoratorViewManager.h>
2
- #import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
3
2
 
4
3
  @implementation MarkdownTextInputDecoratorViewManager
5
4
 
6
5
  RCT_EXPORT_MODULE(MarkdownTextInputDecoratorView)
7
6
 
8
- - (UIView *)view
9
- {
10
- return [[MarkdownTextInputDecoratorView alloc] init];
11
- }
7
+ RCT_EXPORT_VIEW_PROPERTY(markdownStyle, NSDictionary)
12
8
 
13
- RCT_CUSTOM_VIEW_PROPERTY(markdownStyle, NSDictionary, MarkdownTextInputDecoratorView)
14
- {
15
- // implemented in MarkdownTextInputDecoratorView updateProps:
16
- }
17
-
18
- RCT_CUSTOM_VIEW_PROPERTY(parserId, NSNumber, MarkdownTextInputDecoratorView)
19
- {
20
- // implemented in MarkdownTextInputDecoratorView updateProps:
21
- }
9
+ RCT_EXPORT_VIEW_PROPERTY(parserId, NSNumber)
22
10
 
23
11
  @end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expensify/react-native-live-markdown",
3
- "version": "0.1.245",
3
+ "version": "0.1.247",
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",
@@ -1,14 +0,0 @@
1
- #import <UIKit/UIKit.h>
2
- #import <RNLiveMarkdown/RCTMarkdownStyle.h>
3
-
4
- NS_ASSUME_NONNULL_BEGIN
5
-
6
- @interface MarkdownTextInputDecoratorView : UIView
7
-
8
- - (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle;
9
-
10
- - (void)setParserId:(NSNumber *)parserId;
11
-
12
- @end
13
-
14
- NS_ASSUME_NONNULL_END
@@ -1,110 +0,0 @@
1
- #import <React/RCTUITextField.h>
2
- #import "react_native_assert.h"
3
-
4
- #import <RNLiveMarkdown/MarkdownLayoutManager.h>
5
- #import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
6
- #import <RNLiveMarkdown/RCTBackedTextFieldDelegateAdapter+Markdown.h>
7
- #import <RNLiveMarkdown/RCTUITextView+Markdown.h>
8
-
9
- #import <RNLiveMarkdown/RCTTextInputComponentView+Markdown.h>
10
-
11
- #import <objc/runtime.h>
12
-
13
- @implementation MarkdownTextInputDecoratorView {
14
- RCTMarkdownUtils *_markdownUtils;
15
- RCTMarkdownStyle *_markdownStyle;
16
- NSNumber *_parserId;
17
- __weak RCTTextInputComponentView *_textInput;
18
- __weak UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
19
- __weak RCTBackedTextFieldDelegateAdapter *_adapter;
20
- __weak RCTUITextView *_textView;
21
- }
22
-
23
- - (void)didMoveToWindow {
24
- if (self.superview.superview == nil) {
25
- return;
26
- }
27
-
28
- NSArray *viewsArray = self.superview.superview.subviews;
29
- NSUInteger currentIndex = [viewsArray indexOfObject:self.superview];
30
-
31
- react_native_assert(currentIndex != 0 && currentIndex != NSNotFound && "Error while finding current component.");
32
- UIView *view = [viewsArray objectAtIndex:currentIndex - 1];
33
-
34
- react_native_assert([view isKindOfClass:[RCTTextInputComponentView class]] && "Previous sibling component is not an instance of RCTTextInputComponentView.");
35
- _textInput = (RCTTextInputComponentView *)view;
36
- _backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"];
37
-
38
- _markdownUtils = [[RCTMarkdownUtils alloc] init];
39
- react_native_assert(_markdownStyle != nil);
40
- [_markdownUtils setMarkdownStyle:_markdownStyle];
41
- [_markdownUtils setParserId:_parserId];
42
-
43
- [_textInput setMarkdownUtils:_markdownUtils];
44
- if ([_backedTextInputView isKindOfClass:[RCTUITextField class]]) {
45
- RCTUITextField *textField = (RCTUITextField *)_backedTextInputView;
46
- _adapter = [textField valueForKey:@"textInputDelegateAdapter"];
47
- [_adapter setMarkdownUtils:_markdownUtils];
48
- } else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) {
49
- _textView = (RCTUITextView *)_backedTextInputView;
50
- [_textView setMarkdownUtils:_markdownUtils];
51
- NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode
52
-
53
- // Correct content height in TextKit 1 compatibility mode. (See https://github.com/Expensify/App/issues/41567)
54
- // Consider removing this fix if it is no longer needed after migrating to TextKit 2.
55
- CGSize contentSize = _textView.contentSize;
56
- CGRect textBounds = [layoutManager usedRectForTextContainer:_textView.textContainer];
57
- contentSize.height = textBounds.size.height + _textView.textContainerInset.top + _textView.textContainerInset.bottom;
58
- [_textView setContentSize:contentSize];
59
-
60
- layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
61
- object_setClass(layoutManager, [MarkdownLayoutManager class]);
62
- [layoutManager setValue:_markdownUtils forKey:@"markdownUtils"];
63
- } else {
64
- react_native_assert(false && "Cannot enable Markdown for this type of TextInput.");
65
- }
66
- }
67
-
68
- - (void)willMoveToWindow:(UIWindow *)newWindow
69
- {
70
- if (_textInput != nil) {
71
- [_textInput setMarkdownUtils:nil];
72
- }
73
- if (_adapter != nil) {
74
- [_adapter setMarkdownUtils:nil];
75
- }
76
- if (_textView != nil) {
77
- [_textView setMarkdownUtils:nil];
78
- if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
79
- [_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
80
- object_setClass(_textView.layoutManager, [NSLayoutManager class]);
81
- }
82
- }
83
- }
84
-
85
- - (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle
86
- {
87
- _markdownStyle = markdownStyle;
88
- [_markdownUtils setMarkdownStyle:markdownStyle];
89
- [self applyNewStyles];
90
- }
91
-
92
- - (void)setParserId:(NSNumber *)parserId
93
- {
94
- _parserId = parserId;
95
- [_markdownUtils setParserId:parserId];
96
- [self applyNewStyles];
97
- }
98
-
99
- - (void)applyNewStyles
100
- {
101
- if (_textView != nil) {
102
- // We want to use `textStorage` for applying markdown when possible. Currently it's only available for UITextView
103
- [_textView textDidChange];
104
- } else {
105
- // apply new styles
106
- [_textInput _setAttributedString:_backedTextInputView.attributedText];
107
- }
108
- }
109
-
110
- @end