@expensify/react-native-live-markdown 0.1.251 → 0.1.253

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.
@@ -0,0 +1,12 @@
1
+ #import <React/RCTBackedTextInputDelegate.h>
2
+ #import <React/RCTUITextView.h>
3
+
4
+ NS_ASSUME_NONNULL_BEGIN
5
+
6
+ @interface MarkdownBackedTextInputDelegate : NSObject <RCTBackedTextInputDelegate>
7
+
8
+ - (instancetype)initWithTextView:(RCTUITextView *)textView;
9
+
10
+ @end
11
+
12
+ NS_ASSUME_NONNULL_END
@@ -0,0 +1,92 @@
1
+ #import "MarkdownBackedTextInputDelegate.h"
2
+
3
+ @implementation MarkdownBackedTextInputDelegate {
4
+ __weak RCTUITextView *_textView;
5
+ id<RCTBackedTextInputDelegate> _originalTextInputDelegate;
6
+ }
7
+
8
+ - (instancetype)initWithTextView:(RCTUITextView *)textView
9
+ {
10
+ if (self = [super init]) {
11
+ _textView = textView;
12
+ _originalTextInputDelegate = _textView.textInputDelegate;
13
+ _textView.textInputDelegate = self;
14
+ }
15
+ return self;
16
+ }
17
+
18
+ - (void)dealloc
19
+ {
20
+ // Restore original text input delegate
21
+ _textView.textInputDelegate = _originalTextInputDelegate;
22
+ }
23
+
24
+ - (void)textInputDidChangeSelection
25
+ {
26
+ // Delegate the call to the original text input delegate
27
+ [_originalTextInputDelegate textInputDidChangeSelection];
28
+
29
+ // After adding a newline at the end of the blockquote, the typing attributes in the next line still contain
30
+ // NSParagraphStyle with non-zero firstLineHeadIndent and headIntent added by `_updateTypingAttributes` call.
31
+ // This causes the cursor to be shifted to the right instead of being located at the beginning of the line.
32
+ // The following code resets firstLineHeadIndent and headIndent in NSParagraphStyle in typing attributes
33
+ // in order to fix the position of the cursor.
34
+ NSDictionary<NSAttributedStringKey, id> *typingAttributes = _textView.typingAttributes;
35
+ if (typingAttributes[NSParagraphStyleAttributeName] != nil) {
36
+ NSMutableDictionary *mutableTypingAttributes = [typingAttributes mutableCopy];
37
+ NSMutableParagraphStyle *mutableParagraphStyle = [typingAttributes[NSParagraphStyleAttributeName] mutableCopy];
38
+ mutableParagraphStyle.firstLineHeadIndent = 0;
39
+ mutableParagraphStyle.headIndent = 0;
40
+ mutableTypingAttributes[NSParagraphStyleAttributeName] = mutableParagraphStyle;
41
+ _textView.typingAttributes = mutableTypingAttributes;
42
+ }
43
+ }
44
+
45
+ // Delegate all remaining calls to the original text input delegate
46
+
47
+ - (void)textInputDidChange
48
+ {
49
+ [_originalTextInputDelegate textInputDidChange];
50
+ }
51
+
52
+ - (void)textInputDidBeginEditing
53
+ {
54
+ [_originalTextInputDelegate textInputDidBeginEditing];
55
+ }
56
+
57
+ - (void)textInputDidEndEditing
58
+ {
59
+ [_originalTextInputDelegate textInputDidEndEditing];
60
+ }
61
+
62
+ - (void)textInputDidReturn
63
+ {
64
+ [_originalTextInputDelegate textInputDidReturn];
65
+ }
66
+
67
+ - (BOOL)textInputShouldBeginEditing
68
+ {
69
+ return [_originalTextInputDelegate textInputShouldBeginEditing];
70
+ }
71
+
72
+ - (nonnull NSString *)textInputShouldChangeText:(nonnull NSString *)text inRange:(NSRange)range
73
+ {
74
+ return [_originalTextInputDelegate textInputShouldChangeText:text inRange:range];
75
+ }
76
+
77
+ - (BOOL)textInputShouldEndEditing
78
+ {
79
+ return [_originalTextInputDelegate textInputShouldEndEditing];
80
+ }
81
+
82
+ - (BOOL)textInputShouldReturn
83
+ {
84
+ return [_originalTextInputDelegate textInputShouldReturn];
85
+ }
86
+
87
+ - (BOOL)textInputShouldSubmitOnReturn
88
+ {
89
+ return [_originalTextInputDelegate textInputShouldSubmitOnReturn];
90
+ }
91
+
92
+ @end
@@ -3,6 +3,7 @@
3
3
  #import <React/RCTFabricComponentsPlugins.h>
4
4
  #import <React/RCTUITextField.h>
5
5
 
6
+ #import <RNLiveMarkdown/MarkdownBackedTextInputDelegate.h>
6
7
  #import <RNLiveMarkdown/MarkdownLayoutManager.h>
7
8
  #import <RNLiveMarkdown/MarkdownShadowFamilyRegistry.h>
8
9
  #import <RNLiveMarkdown/MarkdownTextInputDecoratorComponentView.h>
@@ -20,6 +21,7 @@ using namespace facebook::react;
20
21
  RCTMarkdownUtils *_markdownUtils;
21
22
  RCTMarkdownStyle *_markdownStyle;
22
23
  NSNumber *_parserId;
24
+ MarkdownBackedTextInputDelegate *_markdownBackedTextInputDelegate;
23
25
  __weak RCTTextInputComponentView *_textInput;
24
26
  __weak UIView<RCTBackedTextInputViewProtocol> *_backedTextInputView;
25
27
  __weak RCTBackedTextFieldDelegateAdapter *_adapter;
@@ -109,6 +111,9 @@ using namespace facebook::react;
109
111
  layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue
110
112
  object_setClass(layoutManager, [MarkdownLayoutManager class]);
111
113
  [layoutManager setValue:_markdownUtils forKey:@"markdownUtils"];
114
+
115
+ // register delegate for fixing cursor position after blockquote
116
+ _markdownBackedTextInputDelegate = [[MarkdownBackedTextInputDelegate alloc] initWithTextView:_textView];
112
117
  } else {
113
118
  react_native_assert(false && "Cannot enable Markdown for this type of TextInput.");
114
119
  }
@@ -123,6 +128,7 @@ using namespace facebook::react;
123
128
  [_adapter setMarkdownUtils:nil];
124
129
  }
125
130
  if (_textView != nil) {
131
+ _markdownBackedTextInputDelegate = nil;
126
132
  [_textView setMarkdownUtils:nil];
127
133
  if (_textView.layoutManager != nil && [object_getClass(_textView.layoutManager) isEqual:[MarkdownLayoutManager class]]) {
128
134
  [_textView.layoutManager setValue:nil forKey:@"markdownUtils"];
@@ -44,6 +44,23 @@ using namespace expensify::livemarkdown;
44
44
 
45
45
  // Call the original method
46
46
  [self markdown__setAttributedString:attributedString];
47
+
48
+ if (markdownUtils != nil && backedTextInputView != nil) {
49
+ // After adding a newline at the end of the blockquote, the typing attributes in the next line still contain
50
+ // NSParagraphStyle with non-zero firstLineHeadIndent and headIntent added by `_updateTypingAttributes` call.
51
+ // This causes the cursor to be shifted to the right instead of being located at the beginning of the line.
52
+ // The following code resets firstLineHeadIndent and headIndent in NSParagraphStyle in typing attributes
53
+ // in order to fix the position of the cursor.
54
+ NSDictionary<NSAttributedStringKey, id> *typingAttributes = backedTextInputView.typingAttributes;
55
+ if (typingAttributes[NSParagraphStyleAttributeName] != nil) {
56
+ NSMutableDictionary *mutableTypingAttributes = [typingAttributes mutableCopy];
57
+ NSMutableParagraphStyle *mutableParagraphStyle = [typingAttributes[NSParagraphStyleAttributeName] mutableCopy];
58
+ mutableParagraphStyle.firstLineHeadIndent = 0;
59
+ mutableParagraphStyle.headIndent = 0;
60
+ mutableTypingAttributes[NSParagraphStyleAttributeName] = mutableParagraphStyle;
61
+ backedTextInputView.typingAttributes = mutableTypingAttributes;
62
+ }
63
+ }
47
64
  }
48
65
 
49
66
  - (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText
@@ -19,7 +19,6 @@
19
19
  UITextRange *range = self.selectedTextRange;
20
20
  super.attributedText = [markdownUtils parseMarkdown:self.attributedText withDefaultTextAttributes:self.defaultTextAttributes];
21
21
  [super setSelectedTextRange:range]; // prevents cursor from jumping at the end when typing in the middle of the text
22
- self.typingAttributes = self.defaultTextAttributes; // removes indent in new line when typing after blockquote
23
22
  }
24
23
 
25
24
  // Call the original method
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@expensify/react-native-live-markdown",
3
- "version": "0.1.251",
3
+ "version": "0.1.253",
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",