From 1e3cc80a913263c9b9ffd4e4f33d36057c3b617a Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Wed, 16 Mar 2022 12:26:09 +0800 Subject: [PATCH 01/33] reapply diff from https://github.com/facebook/react-native/compare/main...fabriziobertoglio1987:text-input-errors --- Libraries/Components/TextInput/TextInput.js | 8 +++++++ .../facebook/react/uimanager/ViewProps.java | 1 + .../react/views/textinput/ReactEditText.java | 8 +++++++ .../textinput/ReactTextInputManager.java | 5 +++++ .../TextInput/TextInputSharedExamples.js | 21 +++++++++++++++++++ 5 files changed, 43 insertions(+) diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index 4e781fb66b..bc3efcec4f 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -402,6 +402,14 @@ type AndroidProps = $ReadOnly<{| */ disableFullscreenUI?: ?boolean, + /** + * String to be read by screenreaders to indicate an error state. If this value is + * not null, an error will be announced. You can use onChangeText or onBlur to + * detect an error and set this prop. Once the error is gone, set this to null + * to clear the error + */ + android_errorMessage?: ?Stringish, + importantForAutofill?: ?( | 'auto' | 'no' diff --git a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java index 661c3466dd..c020abdde3 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java +++ b/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewProps.java @@ -84,6 +84,7 @@ public class ViewProps { public static final String BACKGROUND_COLOR = "backgroundColor"; public static final String FOREGROUND_COLOR = "foregroundColor"; public static final String COLOR = "color"; + public static final String ERROR_MESSAGE = "errorMessage"; public static final String FONT_SIZE = "fontSize"; public static final String FONT_WEIGHT = "fontWeight"; public static final String FONT_STYLE = "fontStyle"; diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 360de688d5..8b83e4bb80 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -122,6 +122,7 @@ public class ReactEditText extends AppCompatEditText private static final KeyListener sKeyListener = QwertyKeyListener.getInstanceForFullKeyboard(); private @Nullable EventDispatcher mEventDispatcher; + private @Nullable String mErrorMessage = null; public ReactEditText(Context context) { super(context); @@ -885,6 +886,7 @@ public void onAttachedToWindow() { if (mAutoFocus && !mDidAttachToWindow) { requestFocusInternal(); } + setError(mErrorMessage); mDidAttachToWindow = true; } @@ -1068,6 +1070,12 @@ void setEventDispatcher(@Nullable EventDispatcher eventDispatcher) { mEventDispatcher = eventDispatcher; } + public void setErrorMessage(String error) { + mErrorMessage = error; + setError(mErrorMessage); + invalidate(); + } + /** * This class will redirect *TextChanged calls to the listeners only in the case where the text is * changed by the user, and not explicitly set by JS. diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java index 9f64b841f1..5a0507a330 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java @@ -372,6 +372,11 @@ public void updateExtraData(ReactEditText view, Object extraData) { } } + @ReactProp(name = ViewProps.ERROR_MESSAGE) + public void setAndroidErrorMessage(ReactEditText view, String error) { + view.setErrorMessage(error); + } + @ReactProp(name = ViewProps.FONT_SIZE, defaultFloat = ViewDefaults.FONT_SIZE_SP) public void setFontSize(ReactEditText view, float fontSize) { view.setFontSize(fontSize); diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index 19e758f2a7..e06ba8806d 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -473,7 +473,28 @@ class SelectionExample extends React.Component< } } +function ErrorExample(): React.Node { + const [text, setText] = React.useState(''); + const [error, setError] = React.useState(null); + return ( + { + setText(newText); + setError(newText === 'error' ? 'this input is invalid' : null); + }} + value={text} + /> + ); +} + module.exports = ([ + { + title: 'Error Message', + render: function (): React.Node { + return ; + }, + }, { title: 'Auto-focus', render: function (): React.Node { From a3b9dc2dd38b572222338bc267da5d1233dc13a6 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 18 Mar 2022 10:51:13 +0800 Subject: [PATCH 02/33] testing solution from https://github.com/facebook/react-native/pull/29070 --- .../com/facebook/react/views/textinput/ReactEditText.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 8b83e4bb80..0859417b3e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -565,7 +565,10 @@ public void maybeSetText(ReactTextUpdate reactTextUpdate) { // When we update text, we trigger onChangeText code that will // try to update state if the wrapper is available. Temporarily disable // to prevent an infinite loop. - getText().replace(0, length(), spannableStringBuilder); + int startPosition = getSelectionStart(); + int endPosition = getSelectionEnd(); + setText(spannableStringBuilder); + maybeSetSelection(mNativeEventCount, startPosition, endPosition); } mDisableTextDiffing = false; From 98e4284442b45e841a4df0a582bb3b029c21d305 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 18 Mar 2022 10:56:07 +0800 Subject: [PATCH 03/33] removing setError call in onAttachedToWindow callback --- .../java/com/facebook/react/views/textinput/ReactEditText.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java index 0859417b3e..0d6406fdae 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java @@ -889,7 +889,6 @@ public void onAttachedToWindow() { if (mAutoFocus && !mDidAttachToWindow) { requestFocusInternal(); } - setError(mErrorMessage); mDidAttachToWindow = true; } From d04869a9ae28fba524755a68fa0afa2daa6ec674 Mon Sep 17 00:00:00 2001 From: fabriziobertoglio1987 Date: Fri, 18 Mar 2022 11:10:34 +0800 Subject: [PATCH 04/33] restore original example --- .../TextInput/TextInputSharedExamples.js | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js index e06ba8806d..498f79d424 100644 --- a/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js +++ b/packages/rn-tester/js/examples/TextInput/TextInputSharedExamples.js @@ -476,15 +476,30 @@ class SelectionExample extends React.Component< function ErrorExample(): React.Node { const [text, setText] = React.useState(''); const [error, setError] = React.useState(null); + const textinput = React.useRef(null); + /* + React.useEffect(() => { + console.log('useEffect text: ' + text); + if (!!textinput && text.length > 7) { + setError(text); + console.log('setError() with text: ' + text); + } + }); + */ return ( - { - setText(newText); - setError(newText === 'error' ? 'this input is invalid' : null); - }} - value={text} - /> + <> +