mirror of
https://github.com/bitwarden/android.git
synced 2024-11-26 19:36:18 +03:00
Minor clean up of the TwoFactorLoginScreen (#1022)
This commit is contained in:
parent
6ac7e0430f
commit
b74427dd88
4 changed files with 67 additions and 53 deletions
|
@ -43,9 +43,9 @@ import com.x8bit.bitwarden.ui.platform.components.BitwardenFilledTonalButton
|
|||
import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenOverflowActionItem
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenSwitch
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenTextField
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
|
||||
import com.x8bit.bitwarden.ui.platform.components.BitwardenWideSwitch
|
||||
import com.x8bit.bitwarden.ui.platform.components.LoadingDialogState
|
||||
import com.x8bit.bitwarden.ui.platform.components.OverflowMenuItemData
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
|
@ -83,29 +83,12 @@ fun TwoFactorLoginScreen(
|
|||
}
|
||||
}
|
||||
|
||||
when (val dialog = state.dialogState) {
|
||||
is TwoFactorLoginState.DialogState.Error -> {
|
||||
BitwardenBasicDialog(
|
||||
visibilityState = BasicDialogState.Shown(
|
||||
title = dialog.title ?: R.string.an_error_has_occurred.asText(),
|
||||
message = dialog.message,
|
||||
),
|
||||
onDismissRequest = remember(viewModel) {
|
||||
{ viewModel.trySendAction(TwoFactorLoginAction.DialogDismiss) }
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
is TwoFactorLoginState.DialogState.Loading -> {
|
||||
BitwardenLoadingDialog(
|
||||
visibilityState = LoadingDialogState.Shown(
|
||||
text = dialog.message,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
null -> Unit
|
||||
}
|
||||
TwoFactorLoginDialogs(
|
||||
dialogState = state.dialogState,
|
||||
onDismissRequest = remember(viewModel) {
|
||||
{ viewModel.trySendAction(TwoFactorLoginAction.DialogDismiss) }
|
||||
},
|
||||
)
|
||||
|
||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||
BitwardenScaffold(
|
||||
|
@ -164,7 +147,28 @@ fun TwoFactorLoginScreen(
|
|||
}
|
||||
|
||||
@Composable
|
||||
@Suppress("LongMethod")
|
||||
private fun TwoFactorLoginDialogs(
|
||||
dialogState: TwoFactorLoginState.DialogState?,
|
||||
onDismissRequest: () -> Unit,
|
||||
) {
|
||||
when (dialogState) {
|
||||
is TwoFactorLoginState.DialogState.Error -> BitwardenBasicDialog(
|
||||
visibilityState = BasicDialogState.Shown(
|
||||
title = dialogState.title ?: R.string.an_error_has_occurred.asText(),
|
||||
message = dialogState.message,
|
||||
),
|
||||
onDismissRequest = onDismissRequest,
|
||||
)
|
||||
|
||||
is TwoFactorLoginState.DialogState.Loading -> BitwardenLoadingDialog(
|
||||
visibilityState = LoadingDialogState.Shown(text = dialogState.message),
|
||||
)
|
||||
|
||||
null -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TwoFactorLoginScreenContent(
|
||||
state: TwoFactorLoginState,
|
||||
onCodeInputChange: (String) -> Unit,
|
||||
|
@ -203,7 +207,7 @@ private fun TwoFactorLoginScreenContent(
|
|||
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
|
||||
BitwardenSwitch(
|
||||
BitwardenWideSwitch(
|
||||
label = stringResource(id = R.string.remember_me),
|
||||
isChecked = state.isRememberMeEnabled,
|
||||
onCheckedChange = onRememberMeToggle,
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.x8bit.bitwarden.ui.platform.base.util.Text
|
|||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -60,13 +61,8 @@ class TwoFactorLoginViewModel @Inject constructor(
|
|||
// Automatically attempt to login again if a captcha token is received.
|
||||
authRepository
|
||||
.captchaTokenResultFlow
|
||||
.onEach {
|
||||
sendAction(
|
||||
TwoFactorLoginAction.Internal.ReceiveCaptchaToken(
|
||||
tokenResult = it,
|
||||
),
|
||||
)
|
||||
}
|
||||
.map { TwoFactorLoginAction.Internal.ReceiveCaptchaToken(tokenResult = it) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
|
@ -79,20 +75,27 @@ class TwoFactorLoginViewModel @Inject constructor(
|
|||
is TwoFactorLoginAction.RememberMeToggle -> handleRememberMeToggle(action)
|
||||
TwoFactorLoginAction.ResendEmailClick -> handleResendEmailClick()
|
||||
is TwoFactorLoginAction.SelectAuthMethod -> handleSelectAuthMethod(action)
|
||||
is TwoFactorLoginAction.Internal -> handleInternalAction(action)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleInternalAction(action: TwoFactorLoginAction.Internal) {
|
||||
when (action) {
|
||||
is TwoFactorLoginAction.Internal.ReceiveLoginResult -> handleReceiveLoginResult(action)
|
||||
is TwoFactorLoginAction.Internal.ReceiveCaptchaToken -> {
|
||||
handleCaptchaTokenReceived(action.tokenResult)
|
||||
handleCaptchaTokenReceived(action)
|
||||
}
|
||||
|
||||
is TwoFactorLoginAction.Internal.ReceiveLoginResult -> handleReceiveLoginResult(action)
|
||||
is TwoFactorLoginAction.Internal.ReceiveResendEmailResult -> {
|
||||
handleReceiveResendEmailResult(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleCaptchaTokenReceived(tokenResult: CaptchaCallbackTokenResult) {
|
||||
when (tokenResult) {
|
||||
private fun handleCaptchaTokenReceived(
|
||||
action: TwoFactorLoginAction.Internal.ReceiveCaptchaToken,
|
||||
) {
|
||||
when (val tokenResult = action.tokenResult) {
|
||||
CaptchaCallbackTokenResult.MissingToken -> {
|
||||
mutableStateFlow.update {
|
||||
it.copy(
|
||||
|
@ -138,26 +141,31 @@ class TwoFactorLoginViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
// If the user is manually entering a code, remove any white spaces, just in case.
|
||||
val code = mutableStateFlow.value.codeInput.let { rawCode ->
|
||||
if (mutableStateFlow.value.authMethod == TwoFactorAuthMethod.AUTHENTICATOR_APP ||
|
||||
mutableStateFlow.value.authMethod == TwoFactorAuthMethod.EMAIL
|
||||
) {
|
||||
rawCode.replace(" ", "")
|
||||
} else {
|
||||
rawCode
|
||||
}
|
||||
val code = when (state.authMethod) {
|
||||
TwoFactorAuthMethod.AUTHENTICATOR_APP,
|
||||
TwoFactorAuthMethod.EMAIL,
|
||||
-> state.codeInput.replace(" ", "")
|
||||
|
||||
TwoFactorAuthMethod.YUBI_KEY,
|
||||
TwoFactorAuthMethod.DUO,
|
||||
TwoFactorAuthMethod.U2F,
|
||||
TwoFactorAuthMethod.REMEMBER,
|
||||
TwoFactorAuthMethod.DUO_ORGANIZATION,
|
||||
TwoFactorAuthMethod.FIDO_2_WEB_APP,
|
||||
TwoFactorAuthMethod.RECOVERY_CODE,
|
||||
-> state.codeInput
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
val result = authRepository.login(
|
||||
email = mutableStateFlow.value.email,
|
||||
password = mutableStateFlow.value.password,
|
||||
email = state.email,
|
||||
password = state.password,
|
||||
twoFactorData = TwoFactorDataModel(
|
||||
code = code,
|
||||
method = mutableStateFlow.value.authMethod.value.toString(),
|
||||
remember = mutableStateFlow.value.isRememberMeEnabled,
|
||||
method = state.authMethod.value.toString(),
|
||||
remember = state.isRememberMeEnabled,
|
||||
),
|
||||
captchaToken = mutableStateFlow.value.captchaToken,
|
||||
captchaToken = state.captchaToken,
|
||||
)
|
||||
sendAction(
|
||||
TwoFactorLoginAction.Internal.ReceiveLoginResult(
|
||||
|
@ -267,7 +275,7 @@ class TwoFactorLoginViewModel @Inject constructor(
|
|||
*/
|
||||
private fun handleResendEmailClick() {
|
||||
// Ensure that the user is in fact verifying with email.
|
||||
if (mutableStateFlow.value.authMethod != TwoFactorAuthMethod.EMAIL) {
|
||||
if (state.authMethod != TwoFactorAuthMethod.EMAIL) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ val TwoFactorAuthMethod.title: Text
|
|||
TwoFactorAuthMethod.AUTHENTICATOR_APP -> R.string.authenticator_app_title.asText()
|
||||
TwoFactorAuthMethod.EMAIL -> R.string.email.asText()
|
||||
TwoFactorAuthMethod.RECOVERY_CODE -> R.string.recovery_code_title.asText()
|
||||
TwoFactorAuthMethod.YUBI_KEY -> R.string.yubi_key_title.asText()
|
||||
else -> "".asText()
|
||||
}
|
||||
|
||||
|
@ -22,5 +23,6 @@ val TwoFactorAuthMethod.title: Text
|
|||
fun TwoFactorAuthMethod.description(email: String): Text = when (this) {
|
||||
TwoFactorAuthMethod.AUTHENTICATOR_APP -> R.string.enter_verification_code_app.asText()
|
||||
TwoFactorAuthMethod.EMAIL -> R.string.enter_verification_code_email.asText(email)
|
||||
TwoFactorAuthMethod.YUBI_KEY -> R.string.yubi_key_instruction.asText()
|
||||
else -> "".asText()
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class TwoFactorAuthMethodExtensionTest {
|
|||
TwoFactorAuthMethod.AUTHENTICATOR_APP to R.string.authenticator_app_title.asText(),
|
||||
TwoFactorAuthMethod.EMAIL to R.string.email.asText(),
|
||||
TwoFactorAuthMethod.DUO to "".asText(),
|
||||
TwoFactorAuthMethod.YUBI_KEY to "".asText(),
|
||||
TwoFactorAuthMethod.YUBI_KEY to R.string.yubi_key_title.asText(),
|
||||
TwoFactorAuthMethod.U2F to "".asText(),
|
||||
TwoFactorAuthMethod.REMEMBER to "".asText(),
|
||||
TwoFactorAuthMethod.DUO_ORGANIZATION to "".asText(),
|
||||
|
@ -36,7 +36,7 @@ class TwoFactorAuthMethodExtensionTest {
|
|||
TwoFactorAuthMethod.EMAIL to
|
||||
R.string.enter_verification_code_email.asText("ex***@email.com"),
|
||||
TwoFactorAuthMethod.DUO to "".asText(),
|
||||
TwoFactorAuthMethod.YUBI_KEY to "".asText(),
|
||||
TwoFactorAuthMethod.YUBI_KEY to R.string.yubi_key_instruction.asText(),
|
||||
TwoFactorAuthMethod.U2F to "".asText(),
|
||||
TwoFactorAuthMethod.REMEMBER to "".asText(),
|
||||
TwoFactorAuthMethod.DUO_ORGANIZATION to "".asText(),
|
||||
|
|
Loading…
Reference in a new issue