From 3809a0e9d1764e92206ce0d9b79815aa37f214fb Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Wed, 17 Apr 2024 11:27:55 +0200 Subject: [PATCH 1/4] Fix style update with emojis on iOS --- ios/MarkdownTextInputDecoratorView.mm | 9 ++++-- ios/RCTBaseTextInputView+Markdown.h | 2 ++ ios/RCTBaseTextInputView+Markdown.m | 19 ++++++++++++ ios/RCTTextInputComponentView+Markdown.h | 4 ++- ios/RCTTextInputComponentView+Markdown.mm | 35 +++++++++++++++++++---- 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/ios/MarkdownTextInputDecoratorView.mm b/ios/MarkdownTextInputDecoratorView.mm index 0cec2191..28237b3a 100644 --- a/ios/MarkdownTextInputDecoratorView.mm +++ b/ios/MarkdownTextInputDecoratorView.mm @@ -100,11 +100,14 @@ - (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle { _markdownStyle = markdownStyle; [_markdownUtils setMarkdownStyle:markdownStyle]; + + // apply new styles + NSAttributedString *attributedText = _textView.attributedText; #ifdef RCT_NEW_ARCH_ENABLED - [_textInput textInputDidChange]; // apply new styles + [_textInput _setAttributedString:attributedText]; #else - [_textInput setAttributedText:_textInput.attributedText]; // apply new styles -#endif + [_textInput setAttributedText:attributedText]; +#endif /* RCT_NEW_ARCH_ENABLED */ } @end diff --git a/ios/RCTBaseTextInputView+Markdown.h b/ios/RCTBaseTextInputView+Markdown.h index 982a41fa..3d37adb2 100644 --- a/ios/RCTBaseTextInputView+Markdown.h +++ b/ios/RCTBaseTextInputView+Markdown.h @@ -9,6 +9,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)markdown_setAttributedText:(NSAttributedString *)attributedText; +- (BOOL)markdown_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText; + - (void)markdown_updateLocalData; @end diff --git a/ios/RCTBaseTextInputView+Markdown.m b/ios/RCTBaseTextInputView+Markdown.m index e5d5bacc..209dc6bb 100644 --- a/ios/RCTBaseTextInputView+Markdown.m +++ b/ios/RCTBaseTextInputView+Markdown.m @@ -23,6 +23,16 @@ - (void)markdown_setAttributedText:(NSAttributedString *)attributedText [self markdown_setAttributedText:attributedText]; } +- (BOOL)markdown_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText +{ + RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils]; + if (markdownUtils != nil) { + return [newText isEqualToAttributedString:oldText]; + } + + return [self markdown_textOf:newText equals:oldText]; +} + - (void)markdown_updateLocalData { RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils]; @@ -69,6 +79,15 @@ + (void)load Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); method_exchangeImplementations(originalMethod, swizzledMethod); } + + { + // swizzle textOf + SEL originalSelector = @selector(textOf:equals:); + SEL swizzledSelector = @selector(markdown_textOf:equals:); + Method originalMethod = class_getInstanceMethod(cls, originalSelector); + Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); + } }); } diff --git a/ios/RCTTextInputComponentView+Markdown.h b/ios/RCTTextInputComponentView+Markdown.h index 32f8d237..346bc711 100644 --- a/ios/RCTTextInputComponentView+Markdown.h +++ b/ios/RCTTextInputComponentView+Markdown.h @@ -12,7 +12,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)markdown__setAttributedString:(NSAttributedString *)attributedString; -- (void)textInputDidChange; +- (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText; + +- (void)_setAttributedString:(NSAttributedString *)attributedString; @end diff --git a/ios/RCTTextInputComponentView+Markdown.mm b/ios/RCTTextInputComponentView+Markdown.mm index 7c79cfed..1a4581f3 100644 --- a/ios/RCTTextInputComponentView+Markdown.mm +++ b/ios/RCTTextInputComponentView+Markdown.mm @@ -47,16 +47,39 @@ - (void)markdown__setAttributedString:(NSAttributedString *)attributedString [self markdown__setAttributedString:attributedString]; } +- (BOOL)markdown__textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText +{ + RCTMarkdownUtils *markdownUtils = [self getMarkdownUtils]; + if (markdownUtils != nil) { + return [newText isEqualToAttributedString:oldText]; + } + + return [self markdown__textOf:newText equals:oldText]; +} + + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - Class cls = [self class]; - SEL originalSelector = @selector(_setAttributedString:); - SEL swizzledSelector = @selector(markdown__setAttributedString:); - Method originalMethod = class_getInstanceMethod(cls, originalSelector); - Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); - method_exchangeImplementations(originalMethod, swizzledMethod); + { + // swizzle _setAttributedString + Class cls = [self class]; + SEL originalSelector = @selector(_setAttributedString:); + SEL swizzledSelector = @selector(markdown__setAttributedString:); + Method originalMethod = class_getInstanceMethod(cls, originalSelector); + Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); + } + + { + // swizzle _textOf + Class cls = [self class]; + SEL originalSelector = @selector(_textOf:equals:); + SEL swizzledSelector = @selector(markdown__textOf:equals:); + Method originalMethod = class_getInstanceMethod(cls, originalSelector); + Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); + method_exchangeImplementations(originalMethod, swizzledMethod); + } }); } From fad4a4fc4df59f2d59f63b8cd3fb287acbac1f92 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Wed, 17 Apr 2024 11:41:30 +0200 Subject: [PATCH 2/4] Directly access attributed text --- ios/MarkdownTextInputDecoratorView.mm | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ios/MarkdownTextInputDecoratorView.mm b/ios/MarkdownTextInputDecoratorView.mm index 28237b3a..d72c019f 100644 --- a/ios/MarkdownTextInputDecoratorView.mm +++ b/ios/MarkdownTextInputDecoratorView.mm @@ -102,11 +102,10 @@ - (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle [_markdownUtils setMarkdownStyle:markdownStyle]; // apply new styles - NSAttributedString *attributedText = _textView.attributedText; #ifdef RCT_NEW_ARCH_ENABLED - [_textInput _setAttributedString:attributedText]; + [_textInput _setAttributedString:_textView.attributedText]; #else - [_textInput setAttributedText:attributedText]; + [_textInput setAttributedText:_textView.attributedText]; #endif /* RCT_NEW_ARCH_ENABLED */ } From 8720e3e795262789a5685283bab5cc863f4586aa Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Tue, 21 May 2024 09:54:22 +0200 Subject: [PATCH 3/4] Use `_textInput` instead of `_textView` --- ios/MarkdownTextInputDecoratorView.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/MarkdownTextInputDecoratorView.mm b/ios/MarkdownTextInputDecoratorView.mm index d72c019f..e451e8db 100644 --- a/ios/MarkdownTextInputDecoratorView.mm +++ b/ios/MarkdownTextInputDecoratorView.mm @@ -103,9 +103,9 @@ - (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle // apply new styles #ifdef RCT_NEW_ARCH_ENABLED - [_textInput _setAttributedString:_textView.attributedText]; + [_textInput _setAttributedString:_textInput.attributedText]; #else - [_textInput setAttributedText:_textView.attributedText]; + [_textInput setAttributedText:_textInput.attributedText]; #endif /* RCT_NEW_ARCH_ENABLED */ } From 548bdca1ce36478914b3b0a63a97820509ad76dc Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Tue, 21 May 2024 10:42:12 +0200 Subject: [PATCH 4/4] Fix singleline on Fabric iOS --- ios/MarkdownTextInputDecoratorView.mm | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ios/MarkdownTextInputDecoratorView.mm b/ios/MarkdownTextInputDecoratorView.mm index e451e8db..eaa8a59b 100644 --- a/ios/MarkdownTextInputDecoratorView.mm +++ b/ios/MarkdownTextInputDecoratorView.mm @@ -22,6 +22,7 @@ @implementation MarkdownTextInputDecoratorView { #else __weak RCTBaseTextInputView *_textInput; #endif /* RCT_NEW_ARCH_ENABLED */ + __weak UIView *_backedTextInputView; __weak RCTBackedTextFieldDelegateAdapter *_adapter; __weak RCTUITextView *_textView; } @@ -51,11 +52,11 @@ - (void)didMoveToWindow { #ifdef RCT_NEW_ARCH_ENABLED react_native_assert([view isKindOfClass:[RCTTextInputComponentView class]] && "Previous sibling component is not an instance of RCTTextInputComponentView."); _textInput = (RCTTextInputComponentView *)view; - UIView *backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"]; + _backedTextInputView = [_textInput valueForKey:@"_backedTextInputView"]; #else react_native_assert([view isKindOfClass:[RCTBaseTextInputView class]] && "Previous sibling component is not an instance of RCTBaseTextInputView."); _textInput = (RCTBaseTextInputView *)view; - UIView *backedTextInputView = _textInput.backedTextInputView; + _backedTextInputView = _textInput.backedTextInputView; #endif /* RCT_NEW_ARCH_ENABLED */ _markdownUtils = [[RCTMarkdownUtils alloc] init]; @@ -63,12 +64,12 @@ - (void)didMoveToWindow { [_markdownUtils setMarkdownStyle:_markdownStyle]; [_textInput setMarkdownUtils:_markdownUtils]; - if ([backedTextInputView isKindOfClass:[RCTUITextField class]]) { - RCTUITextField *textField = (RCTUITextField *)backedTextInputView; + if ([_backedTextInputView isKindOfClass:[RCTUITextField class]]) { + RCTUITextField *textField = (RCTUITextField *)_backedTextInputView; _adapter = [textField valueForKey:@"textInputDelegateAdapter"]; [_adapter setMarkdownUtils:_markdownUtils]; - } else if ([backedTextInputView isKindOfClass:[RCTUITextView class]]) { - _textView = (RCTUITextView *)backedTextInputView; + } else if ([_backedTextInputView isKindOfClass:[RCTUITextView class]]) { + _textView = (RCTUITextView *)_backedTextInputView; [_textView setMarkdownUtils:_markdownUtils]; NSLayoutManager *layoutManager = _textView.layoutManager; // switching to TextKit 1 compatibility mode layoutManager.allowsNonContiguousLayout = NO; // workaround for onScroll issue @@ -103,7 +104,7 @@ - (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle // apply new styles #ifdef RCT_NEW_ARCH_ENABLED - [_textInput _setAttributedString:_textInput.attributedText]; + [_textInput _setAttributedString:_backedTextInputView.attributedText]; #else [_textInput setAttributedText:_textInput.attributedText]; #endif /* RCT_NEW_ARCH_ENABLED */