From 36507e4a3c2fa58dcfdc9bd389b37536c66006d0 Mon Sep 17 00:00:00 2001 From: Emily Janzer Date: Tue, 16 Oct 2018 19:42:13 -0700 Subject: [PATCH] Fix issue when inserting text at 0 when maxLength is set Summary: 1. The user inserts a character ('0') at index 0. Because the range matches 0, 0, predictedText is set to that character that was inserted. 2. In textInputDidChange, it discovers a mismatch between the rendered text ('1234') and predicted text ('0') 3. This triggers textInputShouldChangeTextInRange to be called again with the 'new' text that it thinks was just added ('1234') 4. It goes to insert this text, but runs into the maxLength limit, so it gets truncated and then inserted. (I'm not totally sure why only happens if maxLength is set - I need to look into that.) One fix for this is to just get rid of the range check, but that'll regress #18374. I decided to just check and see if the rendered text is empty instead of checking the range where text could be inserted, since that seems like it should properly handle both cases. Reviewed By: shergin Differential Revision: D10392176 fbshipit-source-id: 84fb3b6cac9b0aa25b3c1a127d43f9cdc5a1c6a8 --- Libraries/Text/TextInput/RCTBaseTextInputView.m | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Libraries/Text/TextInput/RCTBaseTextInputView.m b/Libraries/Text/TextInput/RCTBaseTextInputView.m index 6c8747efdba..21af4400918 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputView.m @@ -328,15 +328,10 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame) NSString *previousText = [_predictedText substringWithRange:range] ?: @""; - // After clearing the text by replacing it with an empty string, `_predictedText` - // still preserves the deleted text. - // As the first character in the TextInput always comes with the range value (0, 0), - // we should check the range value in order to avoid appending a character to the deleted string - // (which caused the issue #18374) - if (!NSEqualRanges(range, NSMakeRange(0, 0)) && _predictedText) { - _predictedText = [_predictedText stringByReplacingCharactersInRange:range withString:text]; - } else { + if (!_predictedText || backedTextInputView.attributedText.string.length == 0) { _predictedText = text; + } else { + _predictedText = [_predictedText stringByReplacingCharactersInRange:range withString:text]; } if (_onTextInput) {