PM-24277: Add language selector to Authenticator (#6120)

This commit is contained in:
David Perez 2025-11-04 13:09:20 -06:00 committed by GitHub
parent 14e833247d
commit 448ba97ae2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 57 additions and 0 deletions

View File

@ -43,6 +43,7 @@ import androidx.core.net.toUri
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bitwarden.authenticator.ui.platform.composition.LocalBiometricsManager
import com.bitwarden.authenticator.ui.platform.feature.settings.appearance.model.AppLanguage
import com.bitwarden.authenticator.ui.platform.feature.settings.data.model.DefaultSaveOption
import com.bitwarden.authenticator.ui.platform.manager.biometrics.BiometricsManager
import com.bitwarden.authenticator.ui.platform.util.displayLabel
@ -206,6 +207,9 @@ fun SettingsScreen(
Spacer(modifier = Modifier.height(16.dp))
AppearanceSettings(
state = state.appearance,
onLanguageSelection = remember(viewModel) {
{ viewModel.trySendAction(SettingsAction.AppearanceChange.LanguageChange(it)) }
},
onThemeSelection = remember(viewModel) {
{
viewModel.trySendAction(SettingsAction.AppearanceChange.ThemeChange(it))
@ -511,8 +515,10 @@ private fun ScreenCaptureRow(
@Composable
private fun ColumnScope.AppearanceSettings(
state: SettingsState.Appearance,
onLanguageSelection: (language: AppLanguage) -> Unit,
onThemeSelection: (theme: AppTheme) -> Unit,
onDynamicColorChange: (isEnabled: Boolean) -> Unit,
resources: Resources = LocalResources.current,
) {
BitwardenListHeaderText(
modifier = Modifier
@ -521,6 +527,22 @@ private fun ColumnScope.AppearanceSettings(
label = stringResource(id = BitwardenString.appearance),
)
Spacer(modifier = Modifier.height(height = 8.dp))
BitwardenMultiSelectButton(
label = stringResource(id = BitwardenString.language),
options = AppLanguage.entries.map { it.text() }.toImmutableList(),
selectedOption = state.language.text(),
onOptionSelected = { language ->
onLanguageSelection(
AppLanguage.entries.first { language == it.text.toString(resources) },
)
},
cardStyle = CardStyle.Full,
modifier = Modifier
.testTag(tag = "LanguageChooser")
.standardHorizontalMargin()
.fillMaxWidth(),
)
Spacer(modifier = Modifier.height(height = 8.dp))
ThemeSelectionRow(
currentSelection = state.theme,
onThemeSelection = onThemeSelection,

View File

@ -6,6 +6,7 @@ import androidx.compose.ui.test.filterToOne
import androidx.compose.ui.test.hasAnyAncestor
import androidx.compose.ui.test.isDialog
import androidx.compose.ui.test.onAllNodesWithText
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollTo
@ -209,6 +210,40 @@ class SettingsScreenTest : AuthenticatorComposeTest() {
.assertIsDisplayed()
}
@Test
fun `on language row click should send display language selector dialog`() {
composeTestRule.assertNoDialogExists()
composeTestRule
.onNodeWithContentDescription(label = "English. Language")
.performScrollTo()
.performClick()
composeTestRule
.onAllNodesWithText(text = "Language")
.filterToOne(hasAnyAncestor(isDialog()))
.assertIsDisplayed()
}
@Test
fun `on language selected should emit LanguageChange event`() {
composeTestRule.assertNoDialogExists()
composeTestRule
.onNodeWithContentDescription(label = "English. Language")
.performScrollTo()
.performClick()
composeTestRule
.onNodeWithText(text = "English (United Kingdom)")
.performScrollTo()
.performClick()
composeTestRule.assertNoDialogExists()
verify(exactly = 1) {
viewModel.trySendAction(
action = SettingsAction.AppearanceChange.LanguageChange(
language = AppLanguage.ENGLISH_BRITISH,
),
)
}
}
@Test
fun `on use dynamic colors row click should send DynamicColorChange event`() {
composeTestRule