Permalink
Browse files

TextInput: Unified support of `blurOnSubmit` prop

Summary:
Now the business logic of `blurOnSubmit` is pretty simple and lives inside `RCTTextInput`,
whereas UIKit hacks/workarounds lives inside `RCTBackedTextInputDelegateAdapter`.

Reviewed By: javache

Differential Revision: D5299397

fbshipit-source-id: 6a9d4194324ff9446c74fdb32ad5357e849e471d
  • Loading branch information...
shergin authored and facebook-github-bot committed Jul 18, 2017
1 parent da9a183 commit 8f93ce680d79fac4b58e518fde5f019fb9eb7e89
@@ -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;
@@ -73,6 +73,11 @@ - (BOOL)textField:(__unused UITextField *)textField shouldChangeCharactersInRang
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 @@ - (void)textFieldDidChange
- (void)textFieldDidEndEditingOnExit
{
[_backedTextInput.textInputDelegate textInputDidEndEditingOnExit];
[_backedTextInput.textInputDelegate textInputDidReturn];
}
#pragma mark - UIKeyboardInput (private UIKit protocol)
@@ -161,6 +166,15 @@ - (void)textViewDidEndEditing:(__unused UITextView *)textView
- (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];
}
@@ -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;
@@ -35,8 +35,6 @@ @implementation RCTTextField
- (instancetype)initWithBridge:(RCTBridge *)bridge
{
if (self = [super initWithBridge:bridge]) {
RCTAssertParam(bridge);
// `blurOnSubmit` defaults to `true` for <TextInput multiline={false}> by design.
_blurOnSubmit = YES;
@@ -189,12 +187,6 @@ - (void)textInputDidBeginEditing
- (BOOL)textInputShouldEndEditing
{
_finalText = _backedTextInput.text;
if (_submitted) {
_submitted = NO;
return _blurOnSubmit;
}
return YES;
}
@@ -221,16 +213,6 @@ - (void)textInputDidEndEditing
eventCount:_nativeEventCount];
}
- (void)textInputDidEndEditingOnExit
{
_submitted = YES;
[_eventDispatcher sendTextEventWithType:RCTTextEventTypeSubmit
reactTag:self.reactTag
text:_backedTextInput.text
key:nil
eventCount:_nativeEventCount];
}
- (void)textInputDidChangeSelection
{
[self sendSelectionEvent];
@@ -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
@@ -84,6 +84,22 @@ - (void)setSelection:(RCTTextSelection *)selection
}
}
#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
@@ -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;
@@ -41,6 +41,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
RCTAssertParam(bridge);
if (self = [super initWithBridge:bridge]) {
// `blurOnSubmit` defaults to `false` for <TextInput multiline={true}> by design.
_blurOnSubmit = NO;
_backedTextInput = [[RCTUITextView alloc] initWithFrame:self.bounds];
@@ -246,27 +247,6 @@ - (BOOL)textInputShouldChangeTextInRange:(NSRange)range replacementText:(NSStrin
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 @@ - (void)textInputDidChange
});
}
- (BOOL)textInputShouldEndEditing
{
return YES;
@@ -460,11 +439,6 @@ - (void)textInputDidEndEditing
eventCount:_nativeEventCount];
}
- (void)textInputDidEndEditingOnExit
{
// Do nothing.
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView

0 comments on commit 8f93ce6

Please sign in to comment.