diff --git a/Libraries/Components/TextInput/TextInput.js b/Libraries/Components/TextInput/TextInput.js index b0227ca0eb554e..e25e30114466b7 100644 --- a/Libraries/Components/TextInput/TextInput.js +++ b/Libraries/Components/TextInput/TextInput.js @@ -332,18 +332,42 @@ type AndroidProps = $ReadOnly<{| * @platform android */ autoCompleteType?: ?( + | 'birthdate-day' + | 'birthdate-full' + | 'birthdate-month' + | 'birthdate-year' | 'cc-csc' | 'cc-exp' + | 'cc-exp-day' | 'cc-exp-month' | 'cc-exp-year' | 'cc-number' | 'email' + | 'gender' | 'name' + | 'name-family' + | 'name-given' + | 'name-middle' + | 'name-middle-initial' + | 'name-prefix' + | 'name-suffix' | 'password' + | 'password-new' + | 'postal-address' + | 'postal-address-country' + | 'postal-address-extended' + | 'postal-address-extended-postal-code' + | 'postal-address-locality' + | 'postal-address-region' | 'postal-code' | 'street-address' + | 'sms-otp' | 'tel' + | 'tel-country-code' + | 'tel-national' + | 'tel-device' | 'username' + | 'username-new' | 'off' ), diff --git a/ReactAndroid/build.gradle b/ReactAndroid/build.gradle index 6d5dd73ee27c38..edadad219f3b40 100644 --- a/ReactAndroid/build.gradle +++ b/ReactAndroid/build.gradle @@ -500,6 +500,7 @@ dependencies { api("com.facebook.yoga:proguard-annotations:1.19.0") api("javax.inject:javax.inject:1") api("androidx.appcompat:appcompat:1.0.2") + api("androidx.autofill:autofill:1.1.0") api("androidx.swiperefreshlayout:swiperefreshlayout:1.0.0") api("com.facebook.fresco:fresco:${FRESCO_VERSION}") api("com.facebook.fresco:imagepipeline-okhttp3:${FRESCO_VERSION}") diff --git a/ReactAndroid/src/main/java/com/facebook/react/BUCK b/ReactAndroid/src/main/java/com/facebook/react/BUCK index 00b0aec2eceebd..b550756ae1baa2 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/BUCK @@ -13,6 +13,7 @@ rn_android_library( react_native_dep("third-party/android/androidx:fragment"), react_native_dep("third-party/android/androidx:legacy-support-core-ui"), react_native_dep("third-party/android/androidx:legacy-support-core-utils"), + react_native_dep("third-party/android/androidx:autofill"), ], visibility = [ "PUBLIC", diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK index ae5cec1338544f..b8de4f2fe89496 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK +++ b/ReactAndroid/src/main/java/com/facebook/react/views/textinput/BUCK @@ -15,6 +15,7 @@ rn_android_library( react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"), react_native_dep("third-party/java/infer-annotations:infer-annotations"), react_native_dep("third-party/java/jsr-305:jsr-305"), + react_native_dep("third-party/android/androidx:autofill"), react_native_target("java/com/facebook/react/bridge:bridge"), react_native_target("java/com/facebook/react/common:common"), react_native_target("java/com/facebook/react/module/annotations:annotations"), 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 90a3b22a67558f..52d0b3b7640822 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 @@ -30,6 +30,7 @@ import android.widget.EditText; import android.widget.TextView; import androidx.annotation.Nullable; +import androidx.autofill.HintConstants; import androidx.core.content.ContextCompat; import com.facebook.common.logging.FLog; import com.facebook.infer.annotation.Assertions; @@ -72,6 +73,7 @@ import com.facebook.react.views.text.TextTransform; import com.facebook.yoga.YogaConstants; import java.lang.reflect.Field; +import java.util.HashMap; import java.util.LinkedList; import java.util.Map; @@ -84,6 +86,51 @@ public class ReactTextInputManager extends BaseViewManager REACT_PROPS_AUTOFILL_HINTS_MAP = + new HashMap() { + { + put("birthdate-day", HintConstants.AUTOFILL_HINT_BIRTH_DATE_DAY); + put("birthdate-full", HintConstants.AUTOFILL_HINT_BIRTH_DATE_FULL); + put("birthdate-month", HintConstants.AUTOFILL_HINT_BIRTH_DATE_MONTH); + put("birthdate-year", HintConstants.AUTOFILL_HINT_BIRTH_DATE_YEAR); + put("cc-csc", HintConstants.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE); + put("cc-exp", HintConstants.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE); + put("cc-exp-day", HintConstants.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY); + put("cc-exp-month", HintConstants.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH); + put("cc-exp-year", HintConstants.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR); + put("cc-number", HintConstants.AUTOFILL_HINT_CREDIT_CARD_NUMBER); + put("email", HintConstants.AUTOFILL_HINT_EMAIL_ADDRESS); + put("gender", HintConstants.AUTOFILL_HINT_GENDER); + put("name", HintConstants.AUTOFILL_HINT_PERSON_NAME); + put("name-family", HintConstants.AUTOFILL_HINT_PERSON_NAME_FAMILY); + put("name-given", HintConstants.AUTOFILL_HINT_PERSON_NAME_GIVEN); + put("name-middle", HintConstants.AUTOFILL_HINT_PERSON_NAME_MIDDLE); + put("name-middle-initial", HintConstants.AUTOFILL_HINT_PERSON_NAME_MIDDLE_INITIAL); + put("name-prefix", HintConstants.AUTOFILL_HINT_PERSON_NAME_PREFIX); + put("name-suffix", HintConstants.AUTOFILL_HINT_PERSON_NAME_SUFFIX); + put("password", HintConstants.AUTOFILL_HINT_PASSWORD); + put("password-new", HintConstants.AUTOFILL_HINT_NEW_PASSWORD); + put("postal-address", HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS); + put("postal-address-country", HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_COUNTRY); + put( + "postal-address-extended", + HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_ADDRESS); + put( + "postal-address-extended-postal-code", + HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_POSTAL_CODE); + put("postal-address-locality", HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_LOCALITY); + put("postal-address-region", HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_REGION); + put("postal-code", HintConstants.AUTOFILL_HINT_POSTAL_CODE); + put("street-address", HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_STREET_ADDRESS); + put("sms-otp", HintConstants.AUTOFILL_HINT_SMS_OTP); + put("tel", HintConstants.AUTOFILL_HINT_PHONE_NUMBER); + put("tel-country-code", HintConstants.AUTOFILL_HINT_PHONE_COUNTRY_CODE); + put("tel-national", HintConstants.AUTOFILL_HINT_PHONE_NATIONAL); + put("tel-device", HintConstants.AUTOFILL_HINT_PHONE_NUMBER_DEVICE); + put("username", HintConstants.AUTOFILL_HINT_USERNAME); + put("username-new", HintConstants.AUTOFILL_HINT_NEW_USERNAME); + } + }; private static final int FOCUS_TEXT_INPUT = 1; private static final int BLUR_TEXT_INPUT = 2; @@ -659,32 +706,10 @@ public void setMaxLength(ReactEditText view, @Nullable Integer maxLength) { public void setTextContentType(ReactEditText view, @Nullable String autoCompleteType) { if (autoCompleteType == null) { setImportantForAutofill(view, View.IMPORTANT_FOR_AUTOFILL_NO); - } else if ("username".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_USERNAME); - } else if ("password".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_PASSWORD); - } else if ("email".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_EMAIL_ADDRESS); - } else if ("name".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_NAME); - } else if ("tel".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_PHONE); - } else if ("street-address".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_POSTAL_ADDRESS); - } else if ("postal-code".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_POSTAL_CODE); - } else if ("cc-number".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_CREDIT_CARD_NUMBER); - } else if ("cc-csc".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE); - } else if ("cc-exp".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE); - } else if ("cc-exp-month".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH); - } else if ("cc-exp-year".equals(autoCompleteType)) { - setAutofillHints(view, View.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR); } else if ("off".equals(autoCompleteType)) { setImportantForAutofill(view, View.IMPORTANT_FOR_AUTOFILL_NO); + } else if (REACT_PROPS_AUTOFILL_HINTS_MAP.containsKey(autoCompleteType)) { + setAutofillHints(view, REACT_PROPS_AUTOFILL_HINTS_MAP.get(autoCompleteType)); } else { throw new JSApplicationIllegalArgumentException( "Invalid autoCompleteType: " + autoCompleteType); diff --git a/ReactAndroid/src/main/third-party/android/androidx/BUCK b/ReactAndroid/src/main/third-party/android/androidx/BUCK index 2eec208a3e473f..d8dc38c7e5afba 100644 --- a/ReactAndroid/src/main/third-party/android/androidx/BUCK +++ b/ReactAndroid/src/main/third-party/android/androidx/BUCK @@ -32,6 +32,15 @@ fb_native.android_library( ], ) +fb_native.android_library( + name = "autofill", + visibility = ["PUBLIC"], + exported_deps = [ + ":autofill-binary", + ":core", + ], +) + fb_native.android_library( name = "collection", visibility = ["PUBLIC"], @@ -342,6 +351,11 @@ fb_native.android_prebuilt_aar( aar = ":asynclayoutinflater-binary-aar", ) +fb_native.android_prebuilt_aar( + name = "autofill-binary", + aar = ":autofill-binary-aar", +) + fb_native.prebuilt_jar( name = "collection-binary", binary_jar = ":collection-binary.jar", @@ -501,6 +515,12 @@ fb_native.remote_file( url = "mvn:androidx.asynclayoutinflater:asynclayoutinflater:aar:1.0.0", ) +fb_native.remote_file( + name = "autofill-binary-aar", + sha1 = "d9cdaa22b9c373ba75a35dcc33ee8871543164e5", + url = "mvn:androidx.autofill:autofill:aar:1.1.0", +) + fb_native.remote_file( name = "collection-binary.jar", sha1 = "42858b26cafdaa69b6149f45dfc2894007bc2c7a",