TextInput: update selection on native when JS calls view command

Summary:
We should have been calling this already. Trivial fix. The intent of the view command was always to update selection, I just forgot to add it. See test videos.

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D19548178

fbshipit-source-id: 14a1bdc11d84c05f2435c48c3bb96b64e8c68cb4
This commit is contained in:
Joshua Gross
2020-01-23 19:27:56 -08:00
committed by Facebook Github Bot
parent 183b1c13c4
commit 27d61388bd
2 changed files with 28 additions and 3 deletions
@@ -80,6 +80,8 @@ public class ReactEditText extends AppCompatEditText {
/** The most recent event number acked by JavaScript. Should only be updated from JS, not C++. */
protected int mMostRecentEventCount;
private static final int UNSET = -1;
private @Nullable ArrayList<TextWatcher> mListeners;
private @Nullable TextWatcherDelegator mTextWatcherDelegator;
private int mStagedInputType;
@@ -296,6 +298,24 @@ public class ReactEditText extends AppCompatEditText {
mScrollWatcher = scrollWatcher;
}
/**
* Attempt to set a selection or fail silently. Intentionally meant to handle bad inputs.
* EventCounter is the same one used as with text.
*
* @param eventCounter
* @param start
* @param end
*/
public void maybeSetSelection(int eventCounter, int start, int end) {
if (!canUpdateWithEventCount(eventCounter)) {
return;
}
if (start != UNSET && end != UNSET) {
setSelection(start, end);
}
}
@Override
public void setSelection(int start, int end) {
// Skip setting the selection if the text wasn't set because of an out of date value.
@@ -465,6 +485,10 @@ public class ReactEditText extends AppCompatEditText {
mIsSettingTextFromState = false;
}
public boolean canUpdateWithEventCount(int eventCounter) {
return eventCounter >= mNativeEventCount;
}
// VisibleForTesting from {@link TextInputEventsTestCase}.
public void maybeSetText(ReactTextUpdate reactTextUpdate) {
if (isSecureText() && TextUtils.equals(getText(), reactTextUpdate.getText())) {
@@ -473,7 +497,7 @@ public class ReactEditText extends AppCompatEditText {
// Only set the text if it is up to date.
mMostRecentEventCount = reactTextUpdate.getJsEventCounter();
if (mMostRecentEventCount < mNativeEventCount) {
if (!canUpdateWithEventCount(mMostRecentEventCount)) {
return;
}
@@ -239,6 +239,7 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
// instead of calling setText, etc directly - doing that will definitely cause bugs.
reactEditText.maybeSetTextFromJS(
getReactTextUpdate(text, mostRecentEventCount, start, end));
reactEditText.maybeSetSelection(mostRecentEventCount, start, end);
}
break;
}
@@ -281,8 +282,8 @@ public class ReactTextInputManager extends BaseViewManager<ReactEditText, Layout
TextInlineImageSpan.possiblyUpdateInlineImageSpans(spannable, view);
}
view.maybeSetTextFromState(update);
if (update.getSelectionStart() != UNSET && update.getSelectionEnd() != UNSET)
view.setSelection(update.getSelectionStart(), update.getSelectionEnd());
view.maybeSetSelection(
update.getJsEventCounter(), update.getSelectionStart(), update.getSelectionEnd());
}
}