Skip to content

Commit

Permalink
Fix controller <TextInput> on iOS when inputting in Chinese/japanese
Browse files Browse the repository at this point in the history
Summary:
Changelog: [internal]

Solution copied over from 892212b#diff-0874427511e8753d0037472fffbe6d7ee014d831e254d4b3c12ffb1dd8ce27c9

Reviewed By: JoshuaGross

Differential Revision: D24429166

fbshipit-source-id: 3c0588ac774041a9fd6d1b6685d94c5658f754b2
  • Loading branch information
sammy-SC authored and facebook-github-bot committed Oct 20, 2020
1 parent eca9d97 commit 36b0f7d
Showing 1 changed file with 35 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,9 @@ - (void)_updateState
- (void)_setAttributedString:(NSAttributedString *)attributedString
{
UITextRange *selectedRange = [_backedTextInputView selectedTextRange];
_backedTextInputView.attributedText = attributedString;
if (![self _textOf:attributedString equals:_backedTextInputView.attributedText]) {
_backedTextInputView.attributedText = attributedString;
}
if (_lastStringStateWasUpdatedWith.length == attributedString.length) {
// Calling `[_backedTextInputView setAttributedText]` moves caret
// to the end of text input field. This cancels any selection as well
Expand All @@ -490,6 +492,38 @@ - (void)_setMultiline:(BOOL)multiline
[self addSubview:_backedTextInputView];
}

- (BOOL)_textOf:(NSAttributedString *)newText equals:(NSAttributedString *)oldText
{
// When the dictation is running we can't update the attributed text on the backed up text view
// because setting the attributed string will kill the dictation. This means that we can't impose
// the settings on a dictation.
// Similarly, when the user is in the middle of inputting some text in Japanese/Chinese, there will be styling on the
// text that we should disregard. See
// https://developer.apple.com/documentation/uikit/uitextinput/1614489-markedtextrange?language=objc for more info. If
// the user added an emoji, the system adds a font attribute for the emoji and stores the original font in
// NSOriginalFont. Lastly, when entering a password, etc., there will be additional styling on the field as the native
// text view handles showing the last character for a split second.
__block BOOL fontHasBeenUpdatedBySystem = false;
[oldText enumerateAttribute:@"NSOriginalFont"
inRange:NSMakeRange(0, oldText.length)
options:0
usingBlock:^(id value, NSRange range, BOOL *stop) {
if (value) {
fontHasBeenUpdatedBySystem = true;
}
}];

BOOL shouldFallbackToBareTextComparison =
[_backedTextInputView.textInputMode.primaryLanguage isEqualToString:@"dictation"] ||
_backedTextInputView.markedTextRange || _backedTextInputView.isSecureTextEntry || fontHasBeenUpdatedBySystem;

if (shouldFallbackToBareTextComparison) {
return ([newText.string isEqualToString:oldText.string]);
} else {
return ([newText isEqualToAttributedString:oldText]);
}
}

@end

Class<RCTComponentViewProtocol> RCTTextInputCls(void)
Expand Down

0 comments on commit 36b0f7d

Please sign in to comment.