Add dialog state to LoginWithDevice state (#883)

This commit is contained in:
David Perez
2024-01-30 19:55:49 -06:00
committed by Álison Fernandes
parent cf8f2ff7fa
commit d0dfe3ca2f
4 changed files with 126 additions and 95 deletions

View File

@@ -1,7 +1,6 @@
package com.x8bit.bitwarden.ui.auth.feature.loginwithdevice
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
@@ -39,10 +38,10 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
import com.x8bit.bitwarden.ui.platform.base.util.asText
import com.x8bit.bitwarden.ui.platform.components.BasicDialogState
import com.x8bit.bitwarden.ui.platform.components.BitwardenBasicDialog
import com.x8bit.bitwarden.ui.platform.components.BitwardenClickableText
import com.x8bit.bitwarden.ui.platform.components.BitwardenLoadingContent
import com.x8bit.bitwarden.ui.platform.components.BitwardenScaffold
import com.x8bit.bitwarden.ui.platform.components.BitwardenTopAppBar
import com.x8bit.bitwarden.ui.platform.theme.LocalNonMaterialColors
@@ -69,6 +68,13 @@ fun LoginWithDeviceScreen(
}
}
LoginWithDeviceDialogs(
state = state.dialogState,
onDismissDialog = remember(viewModel) {
{ viewModel.trySendAction(LoginWithDeviceAction.DismissDialog) }
},
)
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
BitwardenScaffold(
modifier = Modifier
@@ -93,9 +99,6 @@ fun LoginWithDeviceScreen(
is LoginWithDeviceState.ViewState.Content -> {
LoginWithDeviceScreenContent(
state = viewState,
onErrorDialogDismiss = remember(viewModel) {
{ viewModel.trySendAction(LoginWithDeviceAction.ErrorDialogDismiss) }
},
onResendNotificationClick = remember(viewModel) {
{ viewModel.trySendAction(LoginWithDeviceAction.ResendNotificationClick) }
},
@@ -106,16 +109,9 @@ fun LoginWithDeviceScreen(
)
}
LoginWithDeviceState.ViewState.Loading -> {
Column(
modifier = modifier,
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
CircularProgressIndicator()
Spacer(modifier = Modifier.navigationBarsPadding())
}
}
LoginWithDeviceState.ViewState.Loading -> BitwardenLoadingContent(
modifier = modifier,
)
}
}
}
@@ -125,23 +121,10 @@ fun LoginWithDeviceScreen(
@Composable
private fun LoginWithDeviceScreenContent(
state: LoginWithDeviceState.ViewState.Content,
onErrorDialogDismiss: () -> Unit,
onResendNotificationClick: () -> Unit,
onViewAllLogInOptionsClick: () -> Unit,
modifier: Modifier = Modifier,
) {
BitwardenBasicDialog(
visibilityState = if (state.shouldShowErrorDialog) {
BasicDialogState.Shown(
title = R.string.an_error_has_occurred.asText(),
message = R.string.generic_error_message.asText(),
)
} else {
BasicDialogState.Hidden
},
onDismissRequest = onErrorDialogDismiss,
)
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier
@@ -260,3 +243,21 @@ private fun LoginWithDeviceScreenContent(
Spacer(modifier = Modifier.navigationBarsPadding())
}
}
@Composable
private fun LoginWithDeviceDialogs(
state: LoginWithDeviceState.DialogState?,
onDismissDialog: () -> Unit,
) {
when (state) {
is LoginWithDeviceState.DialogState.Error -> BitwardenBasicDialog(
visibilityState = BasicDialogState.Shown(
title = state.title,
message = state.message,
),
onDismissRequest = onDismissDialog,
)
null -> Unit
}
}

View File

@@ -3,9 +3,12 @@ package com.x8bit.bitwarden.ui.auth.feature.loginwithdevice
import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.auth.repository.AuthRepository
import com.x8bit.bitwarden.data.auth.repository.model.AuthRequestResult
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
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.update
import kotlinx.coroutines.launch
@@ -26,6 +29,7 @@ class LoginWithDeviceViewModel @Inject constructor(
?: LoginWithDeviceState(
emailAddress = LoginWithDeviceArgs(savedStateHandle).emailAddress,
viewState = LoginWithDeviceState.ViewState.Loading,
dialogState = null,
),
) {
init {
@@ -35,7 +39,7 @@ class LoginWithDeviceViewModel @Inject constructor(
override fun handleAction(action: LoginWithDeviceAction) {
when (action) {
LoginWithDeviceAction.CloseButtonClick -> handleCloseButtonClicked()
LoginWithDeviceAction.ErrorDialogDismiss -> handleErrorDialogDismissed()
LoginWithDeviceAction.DismissDialog -> handleErrorDialogDismissed()
LoginWithDeviceAction.ResendNotificationClick -> handleResendNotificationClicked()
LoginWithDeviceAction.ViewAllLogInOptionsClick -> handleViewAllLogInOptionsClicked()
@@ -50,7 +54,7 @@ class LoginWithDeviceViewModel @Inject constructor(
}
private fun handleErrorDialogDismissed() {
updateContent { it.copy(shouldShowErrorDialog = false) }
mutableStateFlow.update { it.copy(dialogState = null) }
}
private fun handleResendNotificationClicked() {
@@ -71,8 +75,8 @@ class LoginWithDeviceViewModel @Inject constructor(
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = action.result.authRequest.fingerprint,
isResendNotificationLoading = false,
shouldShowErrorDialog = false,
),
dialogState = null,
)
}
}
@@ -83,7 +87,10 @@ class LoginWithDeviceViewModel @Inject constructor(
viewState = LoginWithDeviceState.ViewState.Content(
fingerprintPhrase = "",
isResendNotificationLoading = false,
shouldShowErrorDialog = true,
),
dialogState = LoginWithDeviceState.DialogState.Error(
title = R.string.an_error_has_occurred.asText(),
message = R.string.generic_error_message.asText(),
),
)
}
@@ -128,6 +135,7 @@ class LoginWithDeviceViewModel @Inject constructor(
data class LoginWithDeviceState(
val emailAddress: String,
val viewState: ViewState,
val dialogState: DialogState?,
) : Parcelable {
/**
* Represents the specific view states for the [LoginWithDeviceScreen].
@@ -150,9 +158,22 @@ data class LoginWithDeviceState(
data class Content(
val fingerprintPhrase: String,
val isResendNotificationLoading: Boolean,
val shouldShowErrorDialog: Boolean,
) : ViewState()
}
/**
* Represents the current state of any dialogs on the screen.
*/
sealed class DialogState : Parcelable {
/**
* Displays an error dialog to the user.
*/
@Parcelize
data class Error(
val title: Text?,
val message: Text,
) : DialogState()
}
}
/**
@@ -182,9 +203,9 @@ sealed class LoginWithDeviceAction {
data object CloseButtonClick : LoginWithDeviceAction()
/**
* Indicates that the error dialog was dismissed.
* Indicates that the dialog should be dismissed.
*/
data object ErrorDialogDismiss : LoginWithDeviceAction()
data object DismissDialog : LoginWithDeviceAction()
/**
* Indicates that the "Resend notification" text has been clicked.