fix: serialize login submission state

This commit is contained in:
2026-08-24 00:49:42 +08:00
parent 1c5caf5a6b
commit 547146792f
3 changed files with 68 additions and 18 deletions
@@ -28,12 +28,15 @@ class LoginViewModel @Inject constructor(
val uiState: StateFlow<LoginUiState> = _uiState.asStateFlow()
private var profile: ProviderProfile? = null
private var loadingJob: Job? = null
private var submitJob: Job? = null
private var usernameEdited = false
private var rememberUsernameEdited = false
private var autoLoginEdited = false
fun loadProfile(value: ProviderProfile) {
if (profile?.id == value.id && loadingJob?.isActive == true) return
if (profile?.id == value.id &&
(loadingJob?.isActive == true || submitJob?.isActive == true)
) return
loadingJob?.cancel()
profile = value
usernameEdited = false
@@ -80,6 +83,14 @@ class LoginViewModel @Inject constructor(
fun clearSensitiveState() {
loadingJob?.cancel()
loadingJob = null
if (submitJob?.isActive == true) {
_uiState.value = _uiState.value.copy(
password = "",
errorMessage = null,
isSubmitting = true,
)
return
}
profile = null
usernameEdited = false
rememberUsernameEdited = false
@@ -107,6 +118,7 @@ class LoginViewModel @Inject constructor(
}
fun submit() {
if (submitJob?.isActive == true) return
val activeProfile = profile ?: return
val state = _uiState.value
if (state.username.isBlank() ||
@@ -117,19 +129,23 @@ class LoginViewModel @Inject constructor(
_uiState.value = state.copy(errorMessage = "Username and password are required")
return
}
viewModelScope.launch {
_uiState.value = state.copy(isSubmitting = true, errorMessage = null)
val result = coordinator.login(
activeProfile.id,
LoginCredentials(Username(state.username.trim()), Password(state.password)),
rememberUsername = state.rememberUsername,
autoLogin = state.autoLogin,
)
_uiState.value = _uiState.value.copy(
password = "",
isSubmitting = false,
errorMessage = (result as? DomainResult.Failure)?.error?.toUiMessage(),
)
submitJob = viewModelScope.launch {
try {
_uiState.value = state.copy(isSubmitting = true, errorMessage = null)
val result = coordinator.login(
activeProfile.id,
LoginCredentials(Username(state.username.trim()), Password(state.password)),
rememberUsername = state.rememberUsername,
autoLogin = state.autoLogin,
)
_uiState.value = _uiState.value.copy(
password = "",
isSubmitting = false,
errorMessage = (result as? DomainResult.Failure)?.error?.toUiMessage(),
)
} finally {
submitJob = null
}
}
}