Skip to content

Commit

Permalink
TextInput: Avoid firing onSubmitEditing twice on Android
Browse files Browse the repository at this point in the history
Summary:
For returnKeyType 'go', 'search' and 'send' Android will call
onEditorAction twice, once with IME_NULL and another time with the respective IME_ACTION.
This change makes sure to only fire one onSubmitEditing by always returning true in onEditorAction, which causes no subsequent events to be fired by android.

Fixes facebook#10443

**Test plan**

1. Create view with TextInput having 'go', 'search' or 'send as `returnKeyType`
```javascript
<View>
           <TextInput
                returnKeyType='search'
                onSubmitEditing={event => console.log('submit search')}></TextInput>

           <TextInput
                returnKeyType='go'
                onSubmitEditing={event => console.log('submit go')}></TextInput>

         <TextInput
              returnKeyType='send'
              onSubmitEditing={event => console.log('submit send')}></TextInput>
</View>
```

2. Input some text and click submit button in soft keyboard
3. See event fired only once instead of two times
Closes facebook#11006

Differential Revision: D4439110

Pulled By: hramos

fbshipit-source-id: 5573b7f15f862b432600ddd3d61a0852ce51b2b3
  • Loading branch information
reneweb authored and nicktate committed Feb 9, 2017
1 parent 727f015 commit 1920e7b
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,26 @@
import android.graphics.Color;
import android.text.style.ForegroundColorSpan;
import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;

import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.testing.ReactAppInstrumentationTestCase;
import com.facebook.react.testing.ReactInstanceSpecForTest;
import com.facebook.react.testing.StringRecordingModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.UIManagerModule;
import com.facebook.react.uimanager.events.EventDispatcher;
import com.facebook.react.views.textinput.ReactEditText;
import com.facebook.react.views.textinput.ReactTextChangedEvent;
import com.facebook.react.views.textinput.ReactTextInputEvent;

/**
* Test to verify that TextInput renders correctly
*/
public class TextInputTestCase extends ReactAppInstrumentationTestCase {

private final StringRecordingModule mRecordingModule = new StringRecordingModule();

private interface TextInputTestModule extends JavaScriptModule {
void setValueRef(String ref, String value);
}
Expand Down Expand Up @@ -99,6 +100,46 @@ public void testTextInputColors() throws Throwable {
}
}

public void testOnSubmitEditing() throws Throwable {
String testId = "onSubmitTextInput";
ReactEditText reactEditText = getViewByTestId(testId);

fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_GO);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_DONE);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_NEXT);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_PREVIOUS);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_SEARCH);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_SEND);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_UNSPECIFIED);
fireEditorActionAndCheckRecording(reactEditText, EditorInfo.IME_ACTION_NONE);
}

private void fireEditorActionAndCheckRecording(final ReactEditText reactEditText,
final int actionId) throws Throwable {
fireEditorActionAndCheckRecording(reactEditText, actionId, true);
fireEditorActionAndCheckRecording(reactEditText, actionId, false);
}

private void fireEditorActionAndCheckRecording(final ReactEditText reactEditText,
final int actionId,
final boolean blurOnSubmit) throws Throwable {
mRecordingModule.reset();

runTestOnUiThread(
new Runnable() {
@Override
public void run() {
reactEditText.requestFocusFromJS();
reactEditText.setBlurOnSubmit(blurOnSubmit);
reactEditText.onEditorAction(actionId);
}
});
waitForBridgeAndUIIdle();

assertEquals(1, mRecordingModule.getCalls().size());
assertEquals(!blurOnSubmit, reactEditText.isFocused());
}

/**
* Test that the mentions input has colors displayed correctly.
* Removed for being flaky in open source, December 2016
Expand Down Expand Up @@ -207,7 +248,8 @@ public void testMetionsInputColors() throws Throwable {
@Override
protected ReactInstanceSpecForTest createReactInstanceSpecForTest() {
return super.createReactInstanceSpecForTest()
.addJSModule(TextInputTestModule.class);
.addJSModule(TextInputTestModule.class)
.addNativeModule(mRecordingModule);
}

@Override
Expand Down
12 changes: 12 additions & 0 deletions ReactAndroid/src/androidTest/js/TextInputTestModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ var Text = require('Text');
var TextInput = require('TextInput');
var View = require('View');

var Recording = require('NativeModules').Recording;

var app;

class TokenizedTextExample extends React.Component {
Expand Down Expand Up @@ -81,6 +83,10 @@ class TextInputTestApp extends React.Component {
app = this;
}

handleOnSubmitEditing = (record) => {
Recording.record(record);
};

render() {
return (
<View style={styles.container}>
Expand Down Expand Up @@ -128,6 +134,12 @@ class TextInputTestApp extends React.Component {
defaultValue="Text"
testID="textInput6"
/>
<TextInput
ref="onSubmitTextInput"
onSubmitEditing={this.handleOnSubmitEditing.bind(this, 'onSubmit')}
defaultValue=""
testID="onSubmitTextInput"
/>
<TokenizedTextExample />
</View>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,14 +688,12 @@ public boolean onEditorAction(TextView v, int actionId, KeyEvent keyEvent) {
editText.getId(),
editText.getText().toString()));
}
if (actionId == EditorInfo.IME_ACTION_NEXT ||
actionId == EditorInfo.IME_ACTION_PREVIOUS) {
if (editText.getBlurOnSubmit()) {
editText.clearFocus();
}
return true;

if (editText.getBlurOnSubmit()) {
editText.clearFocus();
}
return !editText.getBlurOnSubmit();

return true;
}
});
}
Expand Down

0 comments on commit 1920e7b

Please sign in to comment.