Skip to content

Compose Android keyboardType and secureTextEntry into one input type - #59014

Open
YevheniiKotyrlo wants to merge 2 commits into
react:mainfrom
YevheniiKotyrlo:fix/android-text-input-keyboard-composition
Open

YevheniiKotyrlo wants to merge 2 commits into
react:mainfrom
YevheniiKotyrlo:fix/android-text-input-keyboard-composition

Conversation

@YevheniiKotyrlo

Copy link
Copy Markdown
Contributor

Summary:

Depends on #59013; the first commit here is that PR.

keyboardType and secureTextEntry both write the class and variation of the staged input type, each with bit edits applied in the order the props arrive. A variation is a value within its class rather than a set of flags (0x10 is TYPE_TEXT_VARIATION_URI in the text class and TYPE_NUMBER_VARIATION_PASSWORD in the number class), so the committed input type depends on that order:

Both setters now only stage their value, and onAfterUpdateTransaction resolves the class and variation once, before reconcileAutoCapitalize reads the class, the same deferral autoCapitalize already uses. A secure field takes its class's password variation; a class without one keeps its keyboard, so phone-pad stays unmasked as before.

Changelog:

[ANDROID] [FIXED] - Fix keyboardType and secureTextEntry overwriting each other's input type

Test Plan:

Seven cases in ReactTextInputPropertyTest; the order-dependent ones apply the two setters in both orders within one transaction. With #59013 alone, six fail (first failure of each):

Test Expected Was
testSecureTextEntryFalseKeepsTheKeyboardVariationInEitherPropOrder (url, keyboard first) 0x11 0x01
testSecureTextEntryMasksEveryTextKeyboardInEitherPropOrder (email-address) 0x81 0xA1
testSecureTextEntryStaysMaskedWithWordCapitalization 0x81 0x11
testChangingTheKeyboardTypeReplacesItsVariationAndNumberFlags 0x21 0x31
testRevealingAPasswordRestoresTheKeyboardVariation 0x11 0x01
testSecureTextEntryLeavesAKeyboardWithNoPasswordVariationAsItIs 0x03 0x13

testSecureTextEntryUsesTheNumberPasswordForNumberKeyboards passes before and after; giving number keyboards the text password makes it fail alone.

  • ./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest -PenableWarningsAsErrors=true -Preact.internal.useHermesStable=true: 681 tests, 0 failures.
  • node ./scripts/format-kotlin.js --check passes.
  • The same change on 0.86.3, in an app whose inputs pass secureTextEntry={false}: on a Galaxy S23 (Android 14) the focused editor's EditorInfo reads TYPE_CLASS_TEXT with TYPE_TEXT_VARIATION_URI for keyboardType="url" and with TYPE_TEXT_VARIATION_VISIBLE_PASSWORD for keyboardType="visible-password"; without it, visible-password read TYPE_NULL with no variation.
  • Not run: the RNTester build and Android lint (build_android).

keyboardType="visible-password" sets TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
with no input class, and setKeyboardType applies its flags with
TYPE_MASK_CLASS as the mask to clear, so the field is committed with class
TYPE_NULL, which Android documents as not editable. The url arm had the
same omission until react#58505; this gives visible-password the TYPE_CLASS_TEXT
the email-address and url arms already set.

The test masked its reading with generalKeyboardTypeFlags, which excludes
TYPE_TEXT_VARIATION_PASSWORD, so it compared 0x10 and passed with the class
missing. It now asserts the class and the variation exactly.
keyboardType and secureTextEntry both write the class and variation of the
staged input type, each with bit edits applied in the order the props
arrive. A variation is a value within its class, not a set of flags: 0x10
is TYPE_TEXT_VARIATION_URI in the text class and
TYPE_NUMBER_VARIATION_PASSWORD in the number class. Depending on that
order:

- secureTextEntry={false} clears the url and visible-password variations.
- email-address with secureTextEntry commits
  TYPE_TEXT_VARIATION_WEB_EDIT_TEXT, which is not masked.
- secureTextEntry set after autoCapitalize="words" or "characters" commits
  text + URI, which is not masked, because checkPasswordType reads the
  capitalization flags as the number flags they share bits with.
- Changing keyboardType keeps the previous variation (url then
  email-address commits EMAIL_SUBJECT) and the previous number flags.
- phone-pad with secureTextEntry commits a variation the phone class does
  not define.

Both setters now only stage their value, and onAfterUpdateTransaction
resolves the class and variation once, before reconcileAutoCapitalize
reads the class, the way autoCapitalize is already deferred. A secure field
takes the password variation of its class, and a class without one keeps
its keyboard.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 12, 2026
@facebook-github-tools facebook-github-tools Bot added the Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. label Oct 12, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant