diff --git a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt index a4e704bf26..192d29cd7c 100644 --- a/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt +++ b/authenticator/src/main/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreen.kt @@ -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, diff --git a/authenticator/src/test/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreenTest.kt b/authenticator/src/test/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreenTest.kt index 7a805a3617..be1e36c667 100644 --- a/authenticator/src/test/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreenTest.kt +++ b/authenticator/src/test/kotlin/com/bitwarden/authenticator/ui/platform/feature/settings/SettingsScreenTest.kt @@ -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