From 18f8a53d856326e2e85cbfcc850680a60ef8b85d Mon Sep 17 00:00:00 2001 From: David Vacca Date: Thu, 7 Dec 2023 01:53:08 -0800 Subject: [PATCH] Fix lint warns and errors in ReactEditText (#41820) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/41820 Fix lint warns and errors in ReactEditText changelog: [internal] internal Reviewed By: NickGerleman Differential Revision: D51919967 fbshipit-source-id: e32d69f7d950f2577a1fcb372d501db83322d61c --- .../react/views/textinput/ReactEditText.java | 14 +- .../textinput/ReactTextInputManager.java | 159 +++++++++--------- .../react/views/textinput/ScrollWatcher.java | 2 +- .../views/textinput/SelectionWatcher.java | 2 +- 4 files changed, 86 insertions(+), 91 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index ecc6165f7244bf..1c7950e4b3c006 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -90,8 +90,8 @@ public class ReactEditText extends AppCompatEditText { // *TextChanged events should be triggered. This is less expensive than removing the text // listeners and adding them back again after the text change is completed. protected boolean mIsSettingTextFromJS; - private int mDefaultGravityHorizontal; - private int mDefaultGravityVertical; + private final int mDefaultGravityHorizontal; + private final int mDefaultGravityVertical; /** A count of events sent to JS or C++. */ protected int mNativeEventCount; @@ -120,7 +120,7 @@ public class ReactEditText extends AppCompatEditText { private boolean mDidAttachToWindow = false; private @Nullable String mPlaceholder = null; - private ReactViewBackgroundManager mReactBackgroundManager; + private final ReactViewBackgroundManager mReactBackgroundManager; private StateWrapper mStateWrapper = null; protected boolean mDisableTextDiffing = false; @@ -358,11 +358,11 @@ public void removeTextChangedListener(TextWatcher watcher) { } } - public void setContentSizeWatcher(ContentSizeWatcher contentSizeWatcher) { + public void setContentSizeWatcher(@Nullable ContentSizeWatcher contentSizeWatcher) { mContentSizeWatcher = contentSizeWatcher; } - public void setScrollWatcher(ScrollWatcher scrollWatcher) { + public void setScrollWatcher(@Nullable ScrollWatcher scrollWatcher) { mScrollWatcher = scrollWatcher; } @@ -422,7 +422,7 @@ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFoc } } - public void setSelectionWatcher(SelectionWatcher selectionWatcher) { + public void setSelectionWatcher(@Nullable SelectionWatcher selectionWatcher) { mSelectionWatcher = selectionWatcher; } @@ -470,7 +470,7 @@ public String getSubmitBehavior() { return mSubmitBehavior; } - public void setSubmitBehavior(String submitBehavior) { + public void setSubmitBehavior(@Nullable String submitBehavior) { mSubmitBehavior = submitBehavior; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 0816eeb102e4f4..376af6a81e6a10 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -25,7 +25,6 @@ import android.text.SpannableStringBuilder; import android.text.TextWatcher; import android.view.Gravity; -import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; @@ -798,9 +797,9 @@ public void setMaxLength(ReactEditText view, @Nullable Integer maxLength) { if (maxLength == null) { if (currentFilters.length > 0) { LinkedList list = new LinkedList<>(); - for (int i = 0; i < currentFilters.length; i++) { - if (!(currentFilters[i] instanceof InputFilter.LengthFilter)) { - list.add(currentFilters[i]); + for (InputFilter currentFilter : currentFilters) { + if (!(currentFilter instanceof InputFilter.LengthFilter)) { + list.add(currentFilter); } } if (!list.isEmpty()) { @@ -889,14 +888,19 @@ public void setAutoCapitalize(ReactEditText view, Dynamic autoCapitalize) { } else if (autoCapitalize.getType() == ReadableType.String) { final String autoCapitalizeStr = autoCapitalize.asString(); - if (autoCapitalizeStr.equals("none")) { - autoCapitalizeValue = 0; - } else if (autoCapitalizeStr.equals("characters")) { - autoCapitalizeValue = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS; - } else if (autoCapitalizeStr.equals("words")) { - autoCapitalizeValue = InputType.TYPE_TEXT_FLAG_CAP_WORDS; - } else if (autoCapitalizeStr.equals("sentences")) { - autoCapitalizeValue = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; + switch (autoCapitalizeStr) { + case "none": + autoCapitalizeValue = 0; + break; + case "characters": + autoCapitalizeValue = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS; + break; + case "words": + autoCapitalizeValue = InputType.TYPE_TEXT_FLAG_CAP_WORDS; + break; + case "sentences": + autoCapitalizeValue = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; + break; } } @@ -1067,7 +1071,7 @@ private final class ReactTextInputTextWatcher implements TextWatcher { private final ReactEditText mEditText; private final EventDispatcher mEventDispatcher; private final int mSurfaceId; - private String mPreviousText; + @Nullable private String mPreviousText; public ReactTextInputTextWatcher( final ReactContext reactContext, final ReactEditText editText) { @@ -1136,73 +1140,67 @@ protected void addEventEmitters( editText.setEventDispatcher(getEventDispatcher(reactContext, editText)); editText.addTextChangedListener(new ReactTextInputTextWatcher(reactContext, editText)); editText.setOnFocusChangeListener( - new View.OnFocusChangeListener() { - public void onFocusChange(View v, boolean hasFocus) { - int surfaceId = reactContext.getSurfaceId(); - EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText); - if (hasFocus) { - eventDispatcher.dispatchEvent( - new ReactTextInputFocusEvent(surfaceId, editText.getId())); - } else { - eventDispatcher.dispatchEvent( - new ReactTextInputBlurEvent(surfaceId, editText.getId())); - - eventDispatcher.dispatchEvent( - new ReactTextInputEndEditingEvent( - surfaceId, editText.getId(), editText.getText().toString())); - } + (v, hasFocus) -> { + int surfaceId = reactContext.getSurfaceId(); + EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText); + if (hasFocus) { + eventDispatcher.dispatchEvent( + new ReactTextInputFocusEvent(surfaceId, editText.getId())); + } else { + eventDispatcher.dispatchEvent(new ReactTextInputBlurEvent(surfaceId, editText.getId())); + + eventDispatcher.dispatchEvent( + new ReactTextInputEndEditingEvent( + surfaceId, editText.getId(), editText.getText().toString())); } }); editText.setOnEditorActionListener( - new TextView.OnEditorActionListener() { - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent keyEvent) { - if ((actionId & EditorInfo.IME_MASK_ACTION) != 0 || actionId == EditorInfo.IME_NULL) { - boolean isMultiline = editText.isMultiline(); - - boolean shouldSubmit = editText.shouldSubmitOnReturn(); - boolean shouldBlur = editText.shouldBlurOnReturn(); - - // Motivation: - // * shouldSubmit => Clear focus; prevent default behavior (return true); - // * shouldBlur => Submit; prevent default behavior (return true); - // * !shouldBlur && !shouldSubmit && isMultiline => Perform default behavior (return - // false); - // * !shouldBlur && !shouldSubmit && !isMultiline => Prevent default behavior (return - // true); - if (shouldSubmit) { - EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText); - eventDispatcher.dispatchEvent( - new ReactTextInputSubmitEditingEvent( - reactContext.getSurfaceId(), - editText.getId(), - editText.getText().toString())); - } - - if (shouldBlur) { - editText.clearFocus(); - } - - // Prevent default behavior except when we want it to insert a newline. - if (shouldBlur || shouldSubmit || !isMultiline) { - return true; - } - - // If we've reached this point, it means that the TextInput has 'submitBehavior' set - // nullish and 'multiline' set to true. But it's still possible to get IME_ACTION_NEXT - // and IME_ACTION_PREVIOUS here in case if 'disableFullscreenUI' is false and Android - // decides to render this EditText in the full screen mode (when a phone has the - // landscape orientation for example). The full screen EditText also renders an action - // button specified by the 'returnKeyType' prop. We have to prevent Android from - // requesting focus from the next/previous focusable view since it must only be - // controlled from JS. - return actionId == EditorInfo.IME_ACTION_NEXT - || actionId == EditorInfo.IME_ACTION_PREVIOUS; + (v, actionId, keyEvent) -> { + if ((actionId & EditorInfo.IME_MASK_ACTION) != 0 || actionId == EditorInfo.IME_NULL) { + boolean isMultiline = editText.isMultiline(); + + boolean shouldSubmit = editText.shouldSubmitOnReturn(); + boolean shouldBlur = editText.shouldBlurOnReturn(); + + // Motivation: + // * shouldSubmit => Clear focus; prevent default behavior (return true); + // * shouldBlur => Submit; prevent default behavior (return true); + // * !shouldBlur && !shouldSubmit && isMultiline => Perform default behavior (return + // false); + // * !shouldBlur && !shouldSubmit && !isMultiline => Prevent default behavior (return + // true); + if (shouldSubmit) { + EventDispatcher eventDispatcher = getEventDispatcher(reactContext, editText); + eventDispatcher.dispatchEvent( + new ReactTextInputSubmitEditingEvent( + reactContext.getSurfaceId(), + editText.getId(), + editText.getText().toString())); } - return true; + if (shouldBlur) { + editText.clearFocus(); + } + + // Prevent default behavior except when we want it to insert a newline. + if (shouldBlur || shouldSubmit || !isMultiline) { + return true; + } + + // If we've reached this point, it means that the TextInput has 'submitBehavior' set + // nullish and 'multiline' set to true. But it's still possible to get IME_ACTION_NEXT + // and IME_ACTION_PREVIOUS here in case if 'disableFullscreenUI' is false and Android + // decides to render this EditText in the full screen mode (when a phone has the + // landscape orientation for example). The full screen EditText also renders an action + // button specified by the 'returnKeyType' prop. We have to prevent Android from + // requesting focus from the next/previous focusable view since it must only be + // controlled from JS. + return actionId == EditorInfo.IME_ACTION_NEXT + || actionId == EditorInfo.IME_ACTION_PREVIOUS; } + + return true; }); } @@ -1295,7 +1293,7 @@ private static class ReactScrollWatcher implements ScrollWatcher { private final ReactEditText mReactEditText; private final EventDispatcher mEventDispatcher; private final int mSurfaceId; - private int mPreviousHoriz; + private int mPreviousHorizontal; private int mPreviousVert; public ReactScrollWatcher(ReactEditText editText) { @@ -1307,7 +1305,7 @@ public ReactScrollWatcher(ReactEditText editText) { @Override public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) { - if (mPreviousHoriz != horiz || mPreviousVert != vert) { + if (mPreviousHorizontal != horiz || mPreviousVert != vert) { ScrollEvent event = ScrollEvent.obtain( mSurfaceId, @@ -1324,14 +1322,14 @@ public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert) { mEventDispatcher.dispatchEvent(event); - mPreviousHoriz = horiz; + mPreviousHorizontal = horiz; mPreviousVert = vert; } } } @Override - public @Nullable Map getExportedViewConstants() { + public @Nullable Map getExportedViewConstants() { return MapBuilder.of( "AutoCapitalizationType", MapBuilder.of( @@ -1403,7 +1401,8 @@ public Object updateState( TextAttributeProps.getJustificationMode(props, currentJustificationMode)); } - public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, MapBuffer state) { + public @Nullable Object getReactTextUpdate( + ReactEditText view, ReactStylesDiffMap props, MapBuffer state) { // If native wants to update the state wrapper but the state data hasn't actually // changed, the MapBuffer may be empty if (state.getCount() == 0) { @@ -1412,10 +1411,6 @@ public Object getReactTextUpdate(ReactEditText view, ReactStylesDiffMap props, M MapBuffer attributedString = state.getMapBuffer(TX_STATE_KEY_ATTRIBUTED_STRING); MapBuffer paragraphAttributes = state.getMapBuffer(TX_STATE_KEY_PARAGRAPH_ATTRIBUTES); - if (attributedString == null || paragraphAttributes == null) { - throw new IllegalArgumentException( - "Invalid TextInput State (MapBuffer) was received as a parameters"); - } Spannable spanned = TextLayoutManagerMapBuffer.getOrCreateSpannableForText( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ScrollWatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ScrollWatcher.java index a45d341c885870..63cf5c2c878280 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ScrollWatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ScrollWatcher.java @@ -8,5 +8,5 @@ package com.facebook.react.views.textinput; public interface ScrollWatcher { - public void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert); + void onScrollChanged(int horiz, int vert, int oldHoriz, int oldVert); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/SelectionWatcher.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/SelectionWatcher.java index 23b47c251bed3c..1a004bde3f4cab 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/SelectionWatcher.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/SelectionWatcher.java @@ -12,5 +12,5 @@ * the ReactTextInputManager to forward events from the EditText to JS */ interface SelectionWatcher { - public void onSelectionChanged(int start, int end); + void onSelectionChanged(int start, int end); }