fix: isolate login credentials across providers
This commit is contained in:
+23
@@ -53,6 +53,29 @@ class LoginScreenTest {
|
||||
assertEquals(2, switches)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun systemBackIsConsumedWhileSubmitting() {
|
||||
var switches = 0
|
||||
composeRule.setContent {
|
||||
ABoxTheme {
|
||||
LoginScreen(
|
||||
profile = profile,
|
||||
state = LoginUiState(isSubmitting = true),
|
||||
onUsernameChange = {},
|
||||
onPasswordChange = {},
|
||||
onRememberUsernameChange = {},
|
||||
onAutoLoginChange = {},
|
||||
onSubmit = {},
|
||||
onSwitchProvider = { switches++ },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
composeRule.activity.onBackPressedDispatcher.onBackPressed()
|
||||
composeRule.waitForIdle()
|
||||
assertEquals(0, switches)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun backControlsAreDisabledWhileSubmitting() {
|
||||
composeRule.setContent {
|
||||
|
||||
@@ -48,6 +48,10 @@ fun LoginRoute(
|
||||
) {
|
||||
LaunchedEffect(profile.id) { viewModel.loadProfile(profile) }
|
||||
val state = viewModel.uiState.collectAsStateWithLifecycle().value
|
||||
val switchProvider = {
|
||||
viewModel.clearSensitiveState()
|
||||
onSwitchProvider()
|
||||
}
|
||||
LoginScreen(
|
||||
profile = profile,
|
||||
state = state.copy(
|
||||
@@ -58,7 +62,7 @@ fun LoginRoute(
|
||||
onRememberUsernameChange = viewModel::setRememberUsername,
|
||||
onAutoLoginChange = viewModel::setAutoLogin,
|
||||
onSubmit = viewModel::submit,
|
||||
onSwitchProvider = onSwitchProvider,
|
||||
onSwitchProvider = switchProvider,
|
||||
switchingProvider = actionInProgress,
|
||||
)
|
||||
}
|
||||
@@ -77,7 +81,9 @@ fun LoginScreen(
|
||||
switchingProvider: Boolean = false,
|
||||
) {
|
||||
val navigationEnabled = !state.isSubmitting && !switchingProvider
|
||||
BackHandler(enabled = navigationEnabled, onBack = onSwitchProvider)
|
||||
BackHandler {
|
||||
if (navigationEnabled) onSwitchProvider()
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
|
||||
@@ -29,11 +29,15 @@ class LoginViewModel @Inject constructor(
|
||||
private var loadingJob: Job? = null
|
||||
|
||||
fun loadProfile(value: ProviderProfile) {
|
||||
if (profile?.id == value.id && loadingJob != null) return
|
||||
val profileChanged = profile?.id != value.id
|
||||
if (!profileChanged && loadingJob != null) return
|
||||
loadingJob?.cancel()
|
||||
profile = value
|
||||
_uiState.value = LoginUiState()
|
||||
loadingJob = viewModelScope.launch {
|
||||
val preferences = profileStore.loginPreferences(value.id)
|
||||
_uiState.value = _uiState.value.copy(
|
||||
if (profile?.id != value.id) return@launch
|
||||
_uiState.value = LoginUiState(
|
||||
username = preferences.rememberedUsername?.value.orEmpty(),
|
||||
rememberUsername = preferences.rememberUsername,
|
||||
autoLogin = preferences.autoLoginEnabled,
|
||||
@@ -41,6 +45,13 @@ class LoginViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
fun clearSensitiveState() {
|
||||
loadingJob?.cancel()
|
||||
loadingJob = null
|
||||
profile = null
|
||||
_uiState.value = LoginUiState()
|
||||
}
|
||||
|
||||
fun setUsername(value: String) {
|
||||
_uiState.value = _uiState.value.copy(username = value, errorMessage = null)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user