Skip to content

Commit ac598af

Browse files
radko93meta-codesync[bot]
authored andcommitted
Android autofill: bump to 1.3.0 and add extended hints (facebook#56105)
Summary: This change expands Android `TextInput` autofill support by aligning React Native with newer AndroidX autofill APIs and exposing additional `autoComplete` values backed by official `androidx.autofill.HintConstants`. What changed: - Bumped AndroidX Autofill dependency from `1.1.0` to `1.3.0`. - Added Android native mappings in `ReactTextInputManager` for: - `2fa-app-otp` - `email-otp` - `wifi-password` - `upi-vpa` - `postal-address-unit` - `postal-address-dependent-locality` - `promo-code` - `flight-number` - `flight-confirmation-code` - `gift-card-number` - `gift-card-pin` - `loyalty-account-number` - Updated public `TextInput` type/docs surfaces (`Flow`, `TypeScript`, and Android native component props) to include the new Android values. - Added Android unit test coverage for the extended hint mappings. - Added RNTester Android examples for the new `autoComplete` values. ## Changelog: [ANDROID] [ADDED] - Add extended Android `TextInput` `autoComplete` autofill hint support and bump `androidx.autofill` to `1.3.0`. Pull Request resolved: facebook#56105 Test Plan: Ran Android unit tests locally: ```bash ./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests com.facebook.react.views.textinput.ReactTextInputPropertyTest ``` Run `rn-tester` <img width="473" height="864" alt="image" src="https://github.com/user-attachments/assets/21b779d9-b485-47e9-809b-d9917e12b472" /> Reviewed By: cortinico, javache Differential Revision: D96952637 Pulled By: NickGerleman fbshipit-source-id: e01c99bfa4411219a73fb586b873b1f86ea28122
1 parent b1e2e5a commit ac598af

8 files changed

Lines changed: 176 additions & 4 deletions

File tree

packages/react-native/Libraries/Components/TextInput/AndroidTextInputNativeComponent.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,15 @@ export type AndroidTextInputNativeProps = Readonly<{
9090
* - `cc-exp-month`
9191
* - `cc-exp-year`
9292
* - `cc-number`
93+
* - `2fa-app-otp`
9394
* - `email`
95+
* - `email-otp`
96+
* - `flight-confirmation-code`
97+
* - `flight-number`
9498
* - `gender`
99+
* - `gift-card-number`
100+
* - `gift-card-pin`
101+
* - `loyalty-account-number`
95102
* - `name`
96103
* - `name-family`
97104
* - `name-given`
@@ -103,24 +110,30 @@ export type AndroidTextInputNativeProps = Readonly<{
103110
* - `password-new`
104111
* - `postal-address`
105112
* - `postal-address-country`
113+
* - `postal-address-dependent-locality`
106114
* - `postal-address-extended`
107115
* - `postal-address-extended-postal-code`
108116
* - `postal-address-locality`
109117
* - `postal-address-region`
118+
* - `postal-address-unit`
110119
* - `postal-code`
120+
* - `promo-code`
111121
* - `street-address`
112122
* - `sms-otp`
113123
* - `tel`
114124
* - `tel-country-code`
115125
* - `tel-national`
116126
* - `tel-device`
127+
* - `upi-vpa`
128+
* - `wifi-password`
117129
* - `username`
118130
* - `username-new`
119131
* - `off`
120132
*
121133
* @platform android
122134
*/
123135
autoComplete?: WithDefault<
136+
| '2fa-app-otp'
124137
| 'birthdate-day'
125138
| 'birthdate-full'
126139
| 'birthdate-month'
@@ -132,7 +145,13 @@ export type AndroidTextInputNativeProps = Readonly<{
132145
| 'cc-exp-year'
133146
| 'cc-number'
134147
| 'email'
148+
| 'email-otp'
149+
| 'flight-confirmation-code'
150+
| 'flight-number'
135151
| 'gender'
152+
| 'gift-card-number'
153+
| 'gift-card-pin'
154+
| 'loyalty-account-number'
136155
| 'name'
137156
| 'name-family'
138157
| 'name-given'
@@ -144,17 +163,22 @@ export type AndroidTextInputNativeProps = Readonly<{
144163
| 'password-new'
145164
| 'postal-address'
146165
| 'postal-address-country'
166+
| 'postal-address-dependent-locality'
147167
| 'postal-address-extended'
148168
| 'postal-address-extended-postal-code'
149169
| 'postal-address-locality'
150170
| 'postal-address-region'
171+
| 'postal-address-unit'
151172
| 'postal-code'
173+
| 'promo-code'
152174
| 'street-address'
153175
| 'sms-otp'
154176
| 'tel'
155177
| 'tel-country-code'
156178
| 'tel-national'
157179
| 'tel-device'
180+
| 'upi-vpa'
181+
| 'wifi-password'
158182
| 'username'
159183
| 'username-new'
160184
| 'off',

packages/react-native/Libraries/Components/TextInput/TextInput.d.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,14 @@ export interface TextInputProps
632632
* - `cc-exp-day`
633633
* - `cc-exp-month`
634634
* - `cc-exp-year`
635+
* - `2fa-app-otp`
636+
* - `email-otp`
637+
* - `flight-confirmation-code`
638+
* - `flight-number`
635639
* - `gender`
640+
* - `gift-card-number`
641+
* - `gift-card-pin`
642+
* - `loyalty-account-number`
636643
* - `name-family`
637644
* - `name-given`
638645
* - `name-middle`
@@ -643,17 +650,23 @@ export interface TextInputProps
643650
* - `password-new`
644651
* - `postal-address`
645652
* - `postal-address-country`
653+
* - `postal-address-dependent-locality`
646654
* - `postal-address-extended`
647655
* - `postal-address-extended-postal-code`
648656
* - `postal-address-locality`
649657
* - `postal-address-region`
658+
* - `postal-address-unit`
659+
* - `promo-code`
650660
* - `sms-otp`
651661
* - `tel-country-code`
652662
* - `tel-national`
653663
* - `tel-device`
664+
* - `upi-vpa`
665+
* - `wifi-password`
654666
* - `username-new`
655667
*/
656668
autoComplete?:
669+
| '2fa-app-otp'
657670
| 'additional-name'
658671
| 'address-line1'
659672
| 'address-line2'
@@ -675,11 +688,17 @@ export interface TextInputProps
675688
| 'country'
676689
| 'current-password'
677690
| 'email'
691+
| 'email-otp'
692+
| 'flight-confirmation-code'
693+
| 'flight-number'
678694
| 'family-name'
679695
| 'gender'
696+
| 'gift-card-number'
697+
| 'gift-card-pin'
680698
| 'given-name'
681699
| 'honorific-prefix'
682700
| 'honorific-suffix'
701+
| 'loyalty-account-number'
683702
| 'name'
684703
| 'name-family'
685704
| 'name-given'
@@ -696,18 +715,23 @@ export interface TextInputProps
696715
| 'password-new'
697716
| 'postal-address'
698717
| 'postal-address-country'
718+
| 'postal-address-dependent-locality'
699719
| 'postal-address-extended'
700720
| 'postal-address-extended-postal-code'
701721
| 'postal-address-locality'
702722
| 'postal-address-region'
723+
| 'postal-address-unit'
703724
| 'postal-code'
725+
| 'promo-code'
704726
| 'street-address'
705727
| 'sms-otp'
706728
| 'tel'
707729
| 'tel-country-code'
708730
| 'tel-national'
709731
| 'tel-device'
732+
| 'upi-vpa'
710733
| 'url'
734+
| 'wifi-password'
711735
| 'username'
712736
| 'username-new'
713737
| 'off'

packages/react-native/Libraries/Components/TextInput/TextInput.flow.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,14 @@ type TextInputBaseProps = Readonly<{
594594
*
595595
* The following values work on Android only:
596596
*
597+
* - `2fa-app-otp`
598+
* - `email-otp`
599+
* - `flight-confirmation-code`
600+
* - `flight-number`
597601
* - `gender`
602+
* - `gift-card-number`
603+
* - `gift-card-pin`
604+
* - `loyalty-account-number`
598605
* - `name-family`
599606
* - `name-given`
600607
* - `name-middle`
@@ -605,17 +612,23 @@ type TextInputBaseProps = Readonly<{
605612
* - `password-new`
606613
* - `postal-address`
607614
* - `postal-address-country`
615+
* - `postal-address-dependent-locality`
608616
* - `postal-address-extended`
609617
* - `postal-address-extended-postal-code`
610618
* - `postal-address-locality`
611619
* - `postal-address-region`
620+
* - `postal-address-unit`
621+
* - `promo-code`
612622
* - `sms-otp`
613623
* - `tel-country-code`
614624
* - `tel-national`
615625
* - `tel-device`
626+
* - `upi-vpa`
627+
* - `wifi-password`
616628
* - `username-new`
617629
*/
618630
autoComplete?: ?(
631+
| '2fa-app-otp'
619632
| 'additional-name'
620633
| 'address-line1'
621634
| 'address-line2'
@@ -637,11 +650,17 @@ type TextInputBaseProps = Readonly<{
637650
| 'country'
638651
| 'current-password'
639652
| 'email'
653+
| 'email-otp'
654+
| 'flight-confirmation-code'
655+
| 'flight-number'
640656
| 'family-name'
641657
| 'gender'
658+
| 'gift-card-number'
659+
| 'gift-card-pin'
642660
| 'given-name'
643661
| 'honorific-prefix'
644662
| 'honorific-suffix'
663+
| 'loyalty-account-number'
645664
| 'name'
646665
| 'name-family'
647666
| 'name-given'
@@ -658,18 +677,23 @@ type TextInputBaseProps = Readonly<{
658677
| 'password-new'
659678
| 'postal-address'
660679
| 'postal-address-country'
680+
| 'postal-address-dependent-locality'
661681
| 'postal-address-extended'
662682
| 'postal-address-extended-postal-code'
663683
| 'postal-address-locality'
664684
| 'postal-address-region'
685+
| 'postal-address-unit'
665686
| 'postal-code'
687+
| 'promo-code'
666688
| 'street-address'
667689
| 'sms-otp'
668690
| 'tel'
669691
| 'tel-country-code'
670692
| 'tel-national'
671693
| 'tel-device'
694+
| 'upi-vpa'
672695
| 'url'
696+
| 'wifi-password'
673697
| 'username'
674698
| 'username-new'
675699
| 'off'

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,7 @@ public open class ReactTextInputManager public constructor() :
10561056

10571057
private val REACT_PROPS_AUTOFILL_HINTS_MAP: Map<String, String> =
10581058
mapOf(
1059+
"2fa-app-otp" to HintConstants.AUTOFILL_HINT_2FA_APP_OTP,
10591060
"birthdate-day" to HintConstants.AUTOFILL_HINT_BIRTH_DATE_DAY,
10601061
"birthdate-full" to HintConstants.AUTOFILL_HINT_BIRTH_DATE_FULL,
10611062
"birthdate-month" to HintConstants.AUTOFILL_HINT_BIRTH_DATE_MONTH,
@@ -1067,7 +1068,13 @@ public open class ReactTextInputManager public constructor() :
10671068
"cc-exp-year" to HintConstants.AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR,
10681069
"cc-number" to HintConstants.AUTOFILL_HINT_CREDIT_CARD_NUMBER,
10691070
"email" to HintConstants.AUTOFILL_HINT_EMAIL_ADDRESS,
1071+
"email-otp" to HintConstants.AUTOFILL_HINT_EMAIL_OTP,
1072+
"flight-confirmation-code" to HintConstants.AUTOFILL_HINT_FLIGHT_CONFIRMATION_CODE,
1073+
"flight-number" to HintConstants.AUTOFILL_HINT_FLIGHT_NUMBER,
10701074
"gender" to HintConstants.AUTOFILL_HINT_GENDER,
1075+
"gift-card-number" to HintConstants.AUTOFILL_HINT_GIFT_CARD_NUMBER,
1076+
"gift-card-pin" to HintConstants.AUTOFILL_HINT_GIFT_CARD_PIN,
1077+
"loyalty-account-number" to HintConstants.AUTOFILL_HINT_LOYALTY_ACCOUNT_NUMBER,
10711078
"name" to HintConstants.AUTOFILL_HINT_PERSON_NAME,
10721079
"name-family" to HintConstants.AUTOFILL_HINT_PERSON_NAME_FAMILY,
10731080
"name-given" to HintConstants.AUTOFILL_HINT_PERSON_NAME_GIVEN,
@@ -1079,19 +1086,25 @@ public open class ReactTextInputManager public constructor() :
10791086
"password-new" to HintConstants.AUTOFILL_HINT_NEW_PASSWORD,
10801087
"postal-address" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS,
10811088
"postal-address-country" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_COUNTRY,
1089+
"postal-address-dependent-locality" to
1090+
HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_DEPENDENT_LOCALITY,
10821091
"postal-address-extended" to
10831092
HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_ADDRESS,
10841093
"postal-address-extended-postal-code" to
10851094
HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_EXTENDED_POSTAL_CODE,
10861095
"postal-address-locality" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_LOCALITY,
10871096
"postal-address-region" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_REGION,
1097+
"postal-address-unit" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_APT_NUMBER,
10881098
"postal-code" to HintConstants.AUTOFILL_HINT_POSTAL_CODE,
1099+
"promo-code" to HintConstants.AUTOFILL_HINT_PROMO_CODE,
10891100
"street-address" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_STREET_ADDRESS,
10901101
"sms-otp" to HintConstants.AUTOFILL_HINT_SMS_OTP,
10911102
"tel" to HintConstants.AUTOFILL_HINT_PHONE_NUMBER,
10921103
"tel-country-code" to HintConstants.AUTOFILL_HINT_PHONE_COUNTRY_CODE,
10931104
"tel-national" to HintConstants.AUTOFILL_HINT_PHONE_NATIONAL,
10941105
"tel-device" to HintConstants.AUTOFILL_HINT_PHONE_NUMBER_DEVICE,
1106+
"upi-vpa" to HintConstants.AUTOFILL_HINT_UPI_VPA,
1107+
"wifi-password" to HintConstants.AUTOFILL_HINT_WIFI_PASSWORD,
10951108
"username" to HintConstants.AUTOFILL_HINT_USERNAME,
10961109
"username-new" to HintConstants.AUTOFILL_HINT_NEW_USERNAME,
10971110
)

packages/react-native/ReactAndroid/src/test/java/com/facebook/react/views/textinput/ReactTextInputPropertyTest.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import android.text.InputType
1919
import android.text.Layout
2020
import android.util.DisplayMetrics
2121
import android.view.Gravity
22+
import android.view.View
2223
import android.view.inputmethod.EditorInfo
24+
import androidx.autofill.HintConstants
2325
import androidx.core.content.res.ResourcesCompat.ID_NULL
2426
import com.facebook.react.bridge.BridgeReactContext
2527
import com.facebook.react.bridge.CatalystInstance
@@ -214,6 +216,37 @@ class ReactTextInputPropertyTest {
214216
assertThat(view.isEnabled).isTrue
215217
}
216218

219+
@Test
220+
fun testAutoCompleteExtendedHints() {
221+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
222+
return
223+
}
224+
225+
val expectedHints =
226+
listOf(
227+
"2fa-app-otp" to HintConstants.AUTOFILL_HINT_2FA_APP_OTP,
228+
"email-otp" to HintConstants.AUTOFILL_HINT_EMAIL_OTP,
229+
"flight-confirmation-code" to HintConstants.AUTOFILL_HINT_FLIGHT_CONFIRMATION_CODE,
230+
"flight-number" to HintConstants.AUTOFILL_HINT_FLIGHT_NUMBER,
231+
"gift-card-number" to HintConstants.AUTOFILL_HINT_GIFT_CARD_NUMBER,
232+
"gift-card-pin" to HintConstants.AUTOFILL_HINT_GIFT_CARD_PIN,
233+
"loyalty-account-number" to HintConstants.AUTOFILL_HINT_LOYALTY_ACCOUNT_NUMBER,
234+
"postal-address-dependent-locality" to
235+
HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_DEPENDENT_LOCALITY,
236+
"postal-address-unit" to HintConstants.AUTOFILL_HINT_POSTAL_ADDRESS_APT_NUMBER,
237+
"promo-code" to HintConstants.AUTOFILL_HINT_PROMO_CODE,
238+
"upi-vpa" to HintConstants.AUTOFILL_HINT_UPI_VPA,
239+
"wifi-password" to HintConstants.AUTOFILL_HINT_WIFI_PASSWORD,
240+
)
241+
242+
expectedHints.forEach { (autoComplete, expectedHint) ->
243+
manager.updateProperties(view, buildStyles("autoComplete", autoComplete))
244+
245+
assertThat(view.importantForAutofill).isEqualTo(View.IMPORTANT_FOR_AUTOFILL_YES)
246+
assertThat(view.autofillHints?.toList()).containsExactly(expectedHint)
247+
}
248+
}
249+
217250
@Test
218251
fun testPlaceholderTextColor() {
219252
val defaultPlaceholderColorStateList = getDefaultTextColorHint(view.context)

0 commit comments

Comments
 (0)