Skip to content

Commit 36b0f7d

Browse files
sammy-SCfacebook-github-bot
authored andcommitted
Fix controller <TextInput> on iOS when inputting in Chinese/japanese
Summary: Changelog: [internal] Solution copied over from 892212b#diff-0874427511e8753d0037472fffbe6d7ee014d831e254d4b3c12ffb1dd8ce27c9 Reviewed By: JoshuaGross Differential Revision: D24429166 fbshipit-source-id: 3c0588ac774041a9fd6d1b6685d94c5658f754b2
1 parent eca9d97 commit 36b0f7d

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,9 @@ - (void)_updateState
468468
- (void)_setAttributedString:(NSAttributedString *)attributedString
469469
{
470470
UITextRange *selectedRange = [_backedTextInputView selectedTextRange];
471-
_backedTextInputView.attributedText = attributedString;
471+
if (![self _textOf:attributedString equals:_backedTextInputView.attributedText]) {
472+
_backedTextInputView.attributedText = attributedString;
473+
}
472474
if (_lastStringStateWasUpdatedWith.length == attributedString.length) {
473475
// Calling `[_backedTextInputView setAttributedText]` moves caret
474476
// to the end of text input field. This cancels any selection as well
@@ -490,6 +492,38 @@ - (void)_setMultiline:(BOOL)multiline
490492
[self addSubview:_backedTextInputView];
491493
}
492494

495+
- (BOOL)_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText
496+
{
497+
// When the dictation is running we can't update the attributed text on the backed up text view
498+
// because setting the attributed string will kill the dictation. This means that we can't impose
499+
// the settings on a dictation.
500+
// Similarly, when the user is in the middle of inputting some text in Japanese/Chinese, there will be styling on the
501+
// text that we should disregard. See
502+
// https://developer.apple.com/documentation/uikit/uitextinput/1614489-markedtextrange?language=objc for more info. If
503+
// the user added an emoji, the system adds a font attribute for the emoji and stores the original font in
504+
// NSOriginalFont. Lastly, when entering a password, etc., there will be additional styling on the field as the native
505+
// text view handles showing the last character for a split second.
506+
__block BOOL fontHasBeenUpdatedBySystem = false;
507+
[oldText enumerateAttribute:@"NSOriginalFont"
508+
inRange:NSMakeRange(0, oldText.length)
509+
options:0
510+
usingBlock:^(id value, NSRange range, BOOL *stop) {
511+
if (value) {
512+
fontHasBeenUpdatedBySystem = true;
513+
}
514+
}];
515+
516+
BOOL shouldFallbackToBareTextComparison =
517+
[_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] ||
518+
_backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem;
519+
520+
if (shouldFallbackToBareTextComparison) {
521+
return ([newText.string isEqualToString:oldText.string]);
522+
} else {
523+
return ([newText isEqualToAttributedString:oldText]);
524+
}
525+
}
526+
493527
@end
494528

495529
Class<RCTComponentViewProtocol> RCTTextInputCls(void)

0 commit comments

Comments
 (0)