diff --git a/Libraries/Text/RCTBackedTextInputDelegate.h b/Libraries/Text/RCTBackedTextInputDelegate.h index bb9be6938a3..d1d40c67a1e 100644 --- a/Libraries/Text/RCTBackedTextInputDelegate.h +++ b/Libraries/Text/RCTBackedTextInputDelegate.h @@ -18,7 +18,9 @@ - (BOOL)textInputShouldEndEditing; // Return `YES` to allow editing to stop and to resign first responder status. `NO` to disallow the editing session to end. - (void)textInputDidEndEditing; // May be called if forced even if `textInputShouldEndEditing` returns `NO` (e.g. view removed from window) or `[textInput endEditing:YES]` called. -- (void)textInputDidEndEditingOnExit; // May be called right before `textInputShouldEndEditing` if "Submit" button was pressed. + +- (BOOL)textInputShouldReturn; // May be called right before `textInputShouldEndEditing` if "Return" button was pressed. +- (void)textInputDidReturn; - (BOOL)textInputShouldChangeTextInRange:(NSRange)range replacementText:(NSString *)string; // Return NO to not change text. - (void)textInputDidChange; diff --git a/Libraries/Text/RCTBackedTextInputDelegateAdapter.m b/Libraries/Text/RCTBackedTextInputDelegateAdapter.m index 0533dec4c61..58cd77fa94d 100644 --- a/Libraries/Text/RCTBackedTextInputDelegateAdapter.m +++ b/Libraries/Text/RCTBackedTextInputDelegateAdapter.m @@ -73,6 +73,11 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo return [_backedTextInput.textInputDelegate textInputShouldChangeTextInRange:range replacementText:string]; } +- (BOOL)textFieldShouldReturn:(UITextField *)textField +{ + return [_backedTextInput.textInputDelegate textInputShouldReturn]; +} + #pragma mark - Key Value Observing - (void)observeValueForKeyPath:(NSString *)keyPath @@ -103,7 +108,7 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo - (void)textFieldDidEndEditingOnExit { - [_backedTextInput.textInputDelegate textInputDidEndEditingOnExit]; + [_backedTextInput.textInputDelegate textInputDidReturn]; } #pragma mark - UIKeyboardInput (private UIKit protocol) @@ -161,6 +166,15 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo - (BOOL)textView:(__unused UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text { + // Custom implementation of `textInputShouldReturn` and `textInputDidReturn` pair for `UITextView`. + if (!_backedTextInput.textWasPasted && [text isEqualToString:@"\n"]) { + if ([_backedTextInput.textInputDelegate textInputShouldReturn]) { + [_backedTextInput.textInputDelegate textInputDidReturn]; + [_backedTextInput endEditing:NO]; + return NO; + } + } + return [_backedTextInput.textInputDelegate textInputShouldChangeTextInRange:range replacementText:text]; } diff --git a/Libraries/Text/RCTTextField.h b/Libraries/Text/RCTTextField.h index 0df80898c47..1c29fd91c5b 100644 --- a/Libraries/Text/RCTTextField.h +++ b/Libraries/Text/RCTTextField.h @@ -20,7 +20,6 @@ @property (nonatomic, assign) BOOL caretHidden; @property (nonatomic, assign) BOOL selectTextOnFocus; -@property (nonatomic, assign) BOOL blurOnSubmit; @property (nonatomic, strong) NSNumber *maxLength; @property (nonatomic, copy) RCTDirectEventBlock onSelectionChange; diff --git a/Libraries/Text/RCTTextField.m b/Libraries/Text/RCTTextField.m index 9fe22eb811f..0f00e9eef7b 100644 --- a/Libraries/Text/RCTTextField.m +++ b/Libraries/Text/RCTTextField.m @@ -35,8 +35,6 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge { if (self = [super initWithBridge:bridge]) { - RCTAssertParam(bridge); - // `blurOnSubmit` defaults to `true` for by design. _blurOnSubmit = YES; @@ -189,12 +187,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) - (BOOL)textInputShouldEndEditing { _finalText = _backedTextInput.text; - - if (_submitted) { - _submitted = NO; - return _blurOnSubmit; - } - return YES; } @@ -221,16 +213,6 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)aDecoder) eventCount:_nativeEventCount]; } -- (void)textInputDidEndEditingOnExit -{ - _submitted = YES; - [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit - reactTag:self.reactTag - text:_backedTextInput.text - key:nil - eventCount:_nativeEventCount]; -} - - (void)textInputDidChangeSelection { [self sendSelectionEvent]; diff --git a/Libraries/Text/RCTTextInput.h b/Libraries/Text/RCTTextInput.h index c71210e5d2e..efcd2840323 100644 --- a/Libraries/Text/RCTTextInput.h +++ b/Libraries/Text/RCTTextInput.h @@ -23,6 +23,7 @@ UITextRange *_previousSelectionRange; NSInteger _nativeEventCount; NSInteger _mostRecentEventCount; + BOOL _blurOnSubmit; } - (instancetype)initWithBridge:(RCTBridge *)bridge NS_DESIGNATED_INITIALIZER; @@ -40,7 +41,13 @@ @property (nonatomic, copy) RCTDirectEventBlock onContentSizeChange; @property (nonatomic, assign) NSInteger mostRecentEventCount; +@property (nonatomic, assign) BOOL blurOnSubmit; - (void)invalidateContentSize; +// Temporary exposure of particial `RCTBackedTextInputDelegate` support. +// In the future all methods of the protocol should move to this class. +- (BOOL)textInputShouldReturn; +- (void)textInputDidReturn; + @end diff --git a/Libraries/Text/RCTTextInput.m b/Libraries/Text/RCTTextInput.m index 5884f0d54d1..a5dc1f8a309 100644 --- a/Libraries/Text/RCTTextInput.m +++ b/Libraries/Text/RCTTextInput.m @@ -84,6 +84,22 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame) } } +#pragma mark - RCTBackedTextInputDelegate + +- (BOOL)textInputShouldReturn +{ + return _blurOnSubmit; +} + +- (void)textInputDidReturn +{ + [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit + reactTag:self.reactTag + text:self.backedTextInputView.text + key:nil + eventCount:_nativeEventCount]; +} + #pragma mark - Content Size (in Yoga terms, without any insets) - (CGSize)contentSize diff --git a/Libraries/Text/RCTTextView.h b/Libraries/Text/RCTTextView.h index ecb37f00827..2bd86c4664d 100644 --- a/Libraries/Text/RCTTextView.h +++ b/Libraries/Text/RCTTextView.h @@ -20,7 +20,6 @@ @property (nonatomic, assign) UITextAutocorrectionType autocorrectionType; @property (nonatomic, assign) UITextSpellCheckingType spellCheckingType; -@property (nonatomic, assign) BOOL blurOnSubmit; @property (nonatomic, assign) BOOL clearTextOnFocus; @property (nonatomic, assign) BOOL selectTextOnFocus; @property (nonatomic, assign) BOOL automaticallyAdjustContentInsets; diff --git a/Libraries/Text/RCTTextView.m b/Libraries/Text/RCTTextView.m index a34d53efacd..4d930d35236 100644 --- a/Libraries/Text/RCTTextView.m +++ b/Libraries/Text/RCTTextView.m @@ -41,6 +41,7 @@ RCTAssertParam(bridge); if (self = [super initWithBridge:bridge]) { + // `blurOnSubmit` defaults to `false` for by design. _blurOnSubmit = NO; _backedTextInput = [[RCTUITextView alloc] initWithFrame:self.bounds]; @@ -246,27 +247,6 @@ static NSAttributedString *removeReactTagFromString(NSAttributedString *string) text:nil key:text eventCount:_nativeEventCount]; - - if (_blurOnSubmit && [text isEqualToString:@"\n"]) { - // TODO: the purpose of blurOnSubmit on RCTextField is to decide if the - // field should lose focus when return is pressed or not. We're cheating a - // bit here by using it on RCTextView to decide if return character should - // submit the form, or be entered into the field. - // - // The reason this is cheating is because there's no way to specify that - // you want the return key to be swallowed *and* have the field retain - // focus (which was what blurOnSubmit was originally for). For the case - // where _blurOnSubmit = YES, this is still the correct and expected - // behavior though, so we'll leave the don't-blur-or-add-newline problem - // to be solved another day. - [_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit - reactTag:self.reactTag - text:self.text - key:nil - eventCount:_nativeEventCount]; - [_backedTextInput resignFirstResponder]; - return NO; - } } // So we need to track that there is a native update in flight just in case JS manages to come back around and update @@ -433,7 +413,6 @@ static BOOL findMismatch(NSString *first, NSString *second, NSRange *firstRange, }); } - - (BOOL)textInputShouldEndEditing { return YES; @@ -460,11 +439,6 @@ static BOOL findMismatch(NSString *first, NSString *second, NSRange *firstRange, eventCount:_nativeEventCount]; } -- (void)textInputDidEndEditingOnExit -{ - // Do nothing. -} - #pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView