fix: scope session errors to active screen
This commit is contained in:
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
@@ -26,11 +27,14 @@ fun ABoxManagerApp(
|
||||
sessionActionsViewModel: SessionActionsViewModel = hiltViewModel(),
|
||||
) {
|
||||
val actionState = sessionActionsViewModel.uiState.collectAsStateWithLifecycle().value
|
||||
val sessionState = appSessionViewModel.uiState.collectAsStateWithLifecycle().value
|
||||
val screenKey = sessionState.screenKey()
|
||||
LaunchedEffect(screenKey) {
|
||||
sessionActionsViewModel.dismissError()
|
||||
}
|
||||
ABoxTheme {
|
||||
ABoxSurface(modifier = Modifier.fillMaxSize()) {
|
||||
when (
|
||||
val state = appSessionViewModel.uiState.collectAsStateWithLifecycle().value
|
||||
) {
|
||||
when (val state = sessionState) {
|
||||
AppSessionUiState.Loading -> Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
@@ -58,3 +62,10 @@ fun ABoxManagerApp(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun AppSessionUiState.screenKey(): String = when (this) {
|
||||
AppSessionUiState.Loading -> "loading"
|
||||
AppSessionUiState.ProviderSelection -> "providers"
|
||||
is AppSessionUiState.Login -> "login:${profile.id.value}"
|
||||
is AppSessionUiState.Authenticated -> "authenticated:${profile.id.value}"
|
||||
}
|
||||
|
||||
+29
-6
@@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.flagship.abox.manager.domain.DomainResult
|
||||
import com.flagship.abox.manager.domain.ProviderProfile
|
||||
import com.flagship.abox.manager.domain.ProviderProfileId
|
||||
import com.flagship.abox.manager.domain.ProviderProfileStore
|
||||
import com.flagship.abox.manager.domain.Session
|
||||
import com.flagship.abox.manager.domain.SessionCoordinator
|
||||
@@ -24,15 +25,19 @@ class AppSessionViewModel @Inject constructor(
|
||||
private val profileStore: ProviderProfileStore,
|
||||
private val availability: ProviderAvailability,
|
||||
) : ViewModel() {
|
||||
private val bootstrapResult = MutableStateFlow<DomainResult<Session?>?>(null)
|
||||
private val bootstrapResult = MutableStateFlow<ProviderBootstrapResult?>(null)
|
||||
|
||||
val uiState: StateFlow<AppSessionUiState> = combine(
|
||||
bootstrapResult,
|
||||
profileStore.observeActiveProfile(),
|
||||
coordinator.observeActiveSession(),
|
||||
) { result, profile, session ->
|
||||
if (result == null) AppSessionUiState.Loading
|
||||
else stateFor(profile, session, (result as? DomainResult.Failure)?.error?.detail)
|
||||
) { bootstrap, profile, session ->
|
||||
if (bootstrap == null) AppSessionUiState.Loading
|
||||
else stateFor(
|
||||
profile = profile,
|
||||
session = session,
|
||||
bootstrapError = bootstrap.errorFor(profile?.id),
|
||||
)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(5_000),
|
||||
@@ -44,9 +49,15 @@ class AppSessionViewModel @Inject constructor(
|
||||
val activeProfile = profileStore.activeProfile()
|
||||
if (activeProfile != null && availability.forType(activeProfile.type) is Availability.Disabled) {
|
||||
coordinator.switchProvider()
|
||||
bootstrapResult.value = DomainResult.Success(null)
|
||||
bootstrapResult.value = ProviderBootstrapResult(
|
||||
profileId = null,
|
||||
result = DomainResult.Success(null),
|
||||
)
|
||||
} else {
|
||||
bootstrapResult.value = coordinator.bootstrap()
|
||||
bootstrapResult.value = ProviderBootstrapResult(
|
||||
profileId = activeProfile?.id,
|
||||
result = coordinator.bootstrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,6 +74,18 @@ class AppSessionViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private data class ProviderBootstrapResult(
|
||||
val profileId: ProviderProfileId?,
|
||||
val result: DomainResult<Session?>,
|
||||
) {
|
||||
fun errorFor(currentProfileId: ProviderProfileId?): String? =
|
||||
if (profileId == currentProfileId) {
|
||||
(result as? DomainResult.Failure)?.error?.detail
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface AppSessionUiState {
|
||||
data object Loading : AppSessionUiState
|
||||
data object ProviderSelection : AppSessionUiState
|
||||
|
||||
Reference in New Issue
Block a user