mirror of
https://github.com/bitwarden/android.git
synced 2026-05-11 02:15:43 -05:00
Force LTR text direction for passwords and TOTP codes
Adds TextStyle extension to force left-to-right text direction with locale-aware alignment for sensitive alphanumeric content. This ensures passwords and TOTP codes read correctly in RTL locales while maintaining proper alignment. - Add TextStyle.withForcedLtr() extension in TypographyExtensions.kt - Refactor BitwardenPasswordField to use extension - Refactor VerificationCodeItem (app) to use extension - Refactor VaultVerificationCodeItem (authenticator) to use extension
This commit is contained in:
@@ -24,6 +24,7 @@ import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.util.withForcedLtr
|
||||
|
||||
/**
|
||||
* The verification code item displayed to the user.
|
||||
@@ -107,7 +108,7 @@ fun VaultVerificationCodeItem(
|
||||
if (!hideAuthCode) {
|
||||
Text(
|
||||
text = authCode.chunked(3).joinToString(" "),
|
||||
style = BitwardenTheme.typography.sensitiveInfoSmall,
|
||||
style = BitwardenTheme.typography.sensitiveInfoSmall.withForcedLtr(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
)
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.util.withForcedLtr
|
||||
|
||||
/**
|
||||
* The verification code item displayed to the user.
|
||||
@@ -155,7 +156,7 @@ fun VaultVerificationCodeItem(
|
||||
Text(
|
||||
modifier = Modifier.testTag(tag = "AuthCode"),
|
||||
text = authCode.chunked(size = 3).joinToString(separator = " "),
|
||||
style = BitwardenTheme.typography.sensitiveInfoSmall,
|
||||
style = BitwardenTheme.typography.sensitiveInfoSmall.withForcedLtr(),
|
||||
color = BitwardenTheme.colorScheme.text.primary,
|
||||
)
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ import com.bitwarden.ui.platform.components.util.nonLetterColorVisualTransformat
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
import com.bitwarden.ui.platform.resource.BitwardenString
|
||||
import com.bitwarden.ui.platform.theme.BitwardenTheme
|
||||
import com.bitwarden.ui.platform.util.withForcedLtr
|
||||
|
||||
/**
|
||||
* Represents a Bitwarden-styled password field that hoists show/hide password state to the caller.
|
||||
@@ -155,7 +156,7 @@ fun BitwardenPasswordField(
|
||||
var focused by remember { mutableStateOf(value = false) }
|
||||
TextField(
|
||||
colors = bitwardenTextFieldColors(),
|
||||
textStyle = BitwardenTheme.typography.sensitiveInfoSmall,
|
||||
textStyle = BitwardenTheme.typography.sensitiveInfoSmall.withForcedLtr(),
|
||||
label = label?.let {
|
||||
{
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.bitwarden.ui.platform.util
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDirection
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import com.bitwarden.annotation.OmitFromCoverage
|
||||
|
||||
/**
|
||||
* Returns a [TextStyle] that forces left-to-right text direction while maintaining
|
||||
* locale-aware alignment.
|
||||
*
|
||||
* This extension is designed for sensitive alphanumeric content (passwords, TOTP codes)
|
||||
* that must always read left-to-right regardless of system locale, but should align
|
||||
* according to the layout direction (right-aligned in RTL locales, left-aligned in LTR).
|
||||
*
|
||||
* **Implementation:**
|
||||
* - Sets `textDirection = TextDirection.Ltr` to force LTR reading order
|
||||
* - Sets `textAlign` conditionally:
|
||||
* - `TextAlign.End` in RTL layouts (aligns to right side)
|
||||
* - `TextAlign.Start` in LTR layouts (aligns to left side)
|
||||
*
|
||||
* **Use cases:**
|
||||
* - Password fields that should read "Pass123!" not "!321ssaP" in RTL locales
|
||||
* - TOTP verification codes that should read "123 456" not "654 321"
|
||||
* - Any alphanumeric content requiring LTR reading with locale-aware positioning
|
||||
*
|
||||
* @return A merged [TextStyle] with forced LTR direction and locale-aware alignment.
|
||||
*/
|
||||
@OmitFromCoverage
|
||||
@Composable
|
||||
fun TextStyle.withForcedLtr(): TextStyle {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
return merge(
|
||||
TextStyle(
|
||||
textDirection = TextDirection.Ltr,
|
||||
textAlign = when (layoutDirection) {
|
||||
LayoutDirection.Rtl -> TextAlign.End
|
||||
LayoutDirection.Ltr -> TextAlign.Start
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user