feat: separate session and credential actions

This commit is contained in:
2026-08-26 12:57:44 +08:00
parent 283f56a3b6
commit c1c21551fb
6 changed files with 397 additions and 13 deletions
@@ -52,6 +52,7 @@ fun ABoxManagerApp(
val actionState = sessionActionsViewModel.uiState.collectAsStateWithLifecycle().value
val sessionState = appSessionViewModel.uiState.collectAsStateWithLifecycle().value
val settingsState = settingsViewModel.uiState.collectAsStateWithLifecycle().value
val actionError = actionState.errorMessage?.asString()
val screenKey = sessionState.screenKey()
LaunchedEffect(screenKey) {
sessionActionsViewModel.dismissError()
@@ -74,7 +75,7 @@ fun ABoxManagerApp(
is AppSessionUiState.Login -> LoginRoute(
profile = state.profile,
bootstrapError = state.bootstrapError,
actionError = actionState.errorMessage,
actionError = actionError,
actionInProgress = actionState.inProgress,
onSwitchProvider = sessionActionsViewModel::switchProvider,
viewModel = loginViewModel,
@@ -83,7 +84,7 @@ fun ABoxManagerApp(
username = state.username,
profile = state.profile,
actionInProgress = actionState.inProgress,
errorMessage = actionState.errorMessage,
errorMessage = actionError,
onLogout = sessionActionsViewModel::logout,
)
}
@@ -13,13 +13,6 @@ object DomainErrorMapper {
is DomainError.InvalidRequest -> UiText.StringResource(R.string.error_invalid_request)
is DomainError.OperationFailed -> UiText.StringResource(R.string.error_operation_failed)
is DomainError.NoData -> UiText.StringResource(R.string.error_no_data)
is DomainError.Unknown -> {
val detail = error.detail
if (!detail.isNullOrBlank()) {
UiText.DynamicString(detail)
} else {
UiText.StringResource(R.string.error_unknown)
}
}
is DomainError.Unknown -> UiText.StringResource(R.string.error_unknown)
}
}
@@ -4,6 +4,9 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.flagship.abox.manager.domain.DomainResult
import com.flagship.abox.manager.domain.SessionCoordinator
import com.flagship.abox.manager.domain.SessionValidity
import com.flagship.abox.manager.ui.common.DomainErrorMapper
import com.flagship.abox.manager.ui.common.UiText
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
@@ -18,9 +21,21 @@ class SessionActionsViewModel @Inject constructor(
private val _uiState = MutableStateFlow(SessionActionsUiState())
val uiState: StateFlow<SessionActionsUiState> = _uiState.asStateFlow()
fun onAction(action: SessionUiAction) {
when (action) {
SessionUiAction.EndSession -> runAction(coordinator::endActiveSession)
SessionUiAction.ForgetSavedCredentials -> runAction(coordinator::forgetSavedCredentials)
SessionUiAction.SwitchProvider -> runAction(coordinator::switchProvider)
SessionUiAction.ValidateConnection -> runValidation()
SessionUiAction.DismissError -> dismissError()
}
}
fun dispatch(action: SessionUiAction) = onAction(action)
fun logout() = runAction(coordinator::logout)
fun switchProvider() = runAction(coordinator::switchProvider)
fun switchProvider() = onAction(SessionUiAction.SwitchProvider)
fun dismissError() {
_uiState.value = _uiState.value.copy(errorMessage = null)
@@ -32,7 +47,19 @@ class SessionActionsViewModel @Inject constructor(
_uiState.value = SessionActionsUiState(inProgress = true)
val result = action()
_uiState.value = SessionActionsUiState(
errorMessage = (result as? DomainResult.Failure)?.error?.detail,
errorMessage = (result as? DomainResult.Failure)?.error?.let(DomainErrorMapper::map),
)
}
}
private fun runValidation() {
if (_uiState.value.inProgress) return
viewModelScope.launch {
_uiState.value = SessionActionsUiState(inProgress = true)
val result = coordinator.validateActiveSession()
_uiState.value = SessionActionsUiState(
validity = (result as? DomainResult.Success)?.value,
errorMessage = (result as? DomainResult.Failure)?.error?.let(DomainErrorMapper::map),
)
}
}
@@ -40,5 +67,14 @@ class SessionActionsViewModel @Inject constructor(
data class SessionActionsUiState(
val inProgress: Boolean = false,
val errorMessage: String? = null,
val validity: SessionValidity? = null,
val errorMessage: UiText? = null,
)
sealed interface SessionUiAction {
data object EndSession : SessionUiAction
data object ForgetSavedCredentials : SessionUiAction
data object SwitchProvider : SessionUiAction
data object ValidateConnection : SessionUiAction
data object DismissError : SessionUiAction
}