@expensify/react-native-live-markdown 0.1.73 → 0.1.75

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
 
@@ -14,24 +14,54 @@
14
14
  @implementation RCTLiveMarkdownModule {
15
15
  BOOL installed_;
16
16
  std::shared_ptr<livemarkdown::MarkdownCommitHook> commitHook_;
17
+ __weak RCTSurfacePresenter *surfacePresenter_;
17
18
  }
18
19
 
19
20
  RCT_EXPORT_MODULE(@"LiveMarkdownModule")
20
21
 
21
22
  - (NSNumber *)install {
22
- if (!installed_) {
23
- installed_ = YES;
24
-
25
- RCTBridge *bridge = self.bridge;
26
- RCTSurfacePresenter *surfacePresenter = bridge.surfacePresenter;
27
- RCTScheduler *scheduler = [surfacePresenter scheduler];
23
+ if (!installed_ && surfacePresenter_ != nil) {
24
+ RCTScheduler *scheduler = [surfacePresenter_ scheduler];
28
25
 
29
26
  commitHook_ =
30
- std::make_shared<livemarkdown::MarkdownCommitHook>(scheduler.uiManager);
27
+ std::make_shared<livemarkdown::MarkdownCommitHook>(scheduler.uiManager);
28
+ installed_ = YES;
31
29
  }
32
30
  return @1;
33
31
  }
34
32
 
33
+ - (void)handleJavaScriptDidLoadNotification:(NSNotification *)notification
34
+ {
35
+ surfacePresenter_ = self.bridge.surfacePresenter;
36
+ [self install];
37
+ }
38
+
39
+ - (void)setBridge:(RCTBridge *)bridge
40
+ {
41
+ [super setBridge:bridge];
42
+
43
+ [[NSNotificationCenter defaultCenter] addObserver:self
44
+ selector:@selector(handleJavaScriptDidLoadNotification:)
45
+ name:RCTJavaScriptDidLoadNotification
46
+ object:nil];
47
+
48
+ // only within the first loading `self.bridge.surfacePresenter` exists
49
+ // during the reload `self.bridge.surfacePresenter` is null
50
+ if (self.bridge.surfacePresenter) {
51
+ surfacePresenter_ = self.bridge.surfacePresenter;
52
+ }
53
+ }
54
+
55
+ /*
56
+ * Taken from RCTNativeAnimatedTurboModule:
57
+ * This selector is invoked via BridgelessTurboModuleSetup.
58
+ */
59
+ - (void)setSurfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter
60
+ {
61
+ surfacePresenter_ = surfacePresenter;
62
+ }
63
+
64
+
35
65
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
36
66
  (const facebook::react::ObjCTurboModule::InitParams &)params {
37
67
  return std::make_shared<facebook::react::NativeLiveMarkdownModuleSpecJSI>(
@@ -40,6 +70,7 @@ RCT_EXPORT_MODULE(@"LiveMarkdownModule")
40
70
 
41
71
  - (void)invalidate {
42
72
  MarkdownShadowFamilyRegistry::reset();
73
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
43
74
  [super invalidate];
44
75
  }
45
76
 
@@ -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.73",
3
+ "version": "0.1.75",
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",