feat: 「计划」未登录自动跳转「我的」

This commit is contained in:
AndyChen1024
2026-09-09 22:20:01 +08:00
parent 84c4bf64b3
commit e033c18aca
3 changed files with 39 additions and 10 deletions

View File

@@ -85,6 +85,7 @@ fun AppNavHost() {
onNavigateToPlanSubmit = { type, periodKey -> onNavigateToPlanSubmit = { type, periodKey ->
navController.navigate(planSubmitRoute(type, periodKey)) navController.navigate(planSubmitRoute(type, periodKey))
}, },
onNavigateToProfile = { navigateToTab(PROFILE_ROUTE) },
) )
} }
composable( composable(

View File

@@ -22,6 +22,7 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -39,6 +40,7 @@ import com.mingyuan.android_client.core.designsystem.component.AmberProgressBar
import com.mingyuan.android_client.core.designsystem.component.Avatar import com.mingyuan.android_client.core.designsystem.component.Avatar
import com.mingyuan.android_client.core.designsystem.component.EmptyState import com.mingyuan.android_client.core.designsystem.component.EmptyState
import com.mingyuan.android_client.core.designsystem.component.ErrorState import com.mingyuan.android_client.core.designsystem.component.ErrorState
import com.mingyuan.android_client.core.designsystem.component.LoggedOutState
import com.mingyuan.android_client.core.designsystem.component.MingyuanButton import com.mingyuan.android_client.core.designsystem.component.MingyuanButton
import com.mingyuan.android_client.core.designsystem.component.SectionCard import com.mingyuan.android_client.core.designsystem.component.SectionCard
import com.mingyuan.android_client.core.designsystem.component.SegmentedControl import com.mingyuan.android_client.core.designsystem.component.SegmentedControl
@@ -66,12 +68,24 @@ const val PLAN_ROUTE = "plan"
@Composable @Composable
fun PlanScreen( fun PlanScreen(
onNavigateToPlanSubmit: (PlanType, String) -> Unit, onNavigateToPlanSubmit: (PlanType, String) -> Unit,
onNavigateToProfile: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
viewModel: PlanViewModel = hiltViewModel(), viewModel: PlanViewModel = hiltViewModel(),
) { ) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val selectedType by viewModel.selectedType.collectAsStateWithLifecycle() val selectedType by viewModel.selectedType.collectAsStateWithLifecycle()
LaunchedEffect(uiState) {
if (uiState is PlanUiState.LoggedOut) {
onNavigateToProfile()
}
}
if (uiState is PlanUiState.LoggedOut) {
LoggedOutState(modifier = modifier.fillMaxSize().background(PlanBackground))
return
}
Column(modifier = modifier.fillMaxSize().background(PlanBackground)) { Column(modifier = modifier.fillMaxSize().background(PlanBackground)) {
Box(Modifier.fillMaxWidth().padding(16.dp)) { Box(Modifier.fillMaxWidth().padding(16.dp)) {
SegmentedControl( SegmentedControl(
@@ -94,6 +108,8 @@ fun PlanScreen(
selectedType = selectedType, selectedType = selectedType,
onNavigateToPlanSubmit = onNavigateToPlanSubmit, onNavigateToPlanSubmit = onNavigateToPlanSubmit,
) )
is PlanUiState.LoggedOut -> Unit // handled above
} }
} }
} }

View File

@@ -3,6 +3,7 @@ package com.mingyuan.android_client.feature.plan
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.mingyuan.android_client.core.domain.repository.PlanRepository import com.mingyuan.android_client.core.domain.repository.PlanRepository
import com.mingyuan.android_client.core.domain.repository.SessionRepository
import com.mingyuan.android_client.core.model.PlanRecord import com.mingyuan.android_client.core.model.PlanRecord
import com.mingyuan.android_client.core.model.PlanType import com.mingyuan.android_client.core.model.PlanType
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@@ -11,7 +12,9 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
@@ -20,27 +23,36 @@ import javax.inject.Inject
sealed interface PlanUiState { sealed interface PlanUiState {
data object Loading : PlanUiState data object Loading : PlanUiState
data class Success(val record: PlanRecord) : PlanUiState data class Success(val record: PlanRecord) : PlanUiState
data object LoggedOut : PlanUiState
data class Error(val message: String) : PlanUiState data class Error(val message: String) : PlanUiState
} }
@HiltViewModel @HiltViewModel
class PlanViewModel @Inject constructor( class PlanViewModel @Inject constructor(
private val planRepository: PlanRepository, private val planRepository: PlanRepository,
private val sessionRepository: SessionRepository,
) : ViewModel() { ) : ViewModel() {
private val _selectedType = MutableStateFlow(PlanType.WEEKLY) private val _selectedType = MutableStateFlow(PlanType.WEEKLY)
val selectedType: StateFlow<PlanType> = _selectedType.asStateFlow() val selectedType: StateFlow<PlanType> = _selectedType.asStateFlow()
val uiState: StateFlow<PlanUiState> = _selectedType val uiState: StateFlow<PlanUiState> =
.flatMapLatest { type -> planRepository.observePlan(type) } combine(sessionRepository.isLoggedIn, _selectedType) { loggedIn, type -> loggedIn to type }
.map<PlanRecord, PlanUiState>(PlanUiState::Success) .flatMapLatest { (loggedIn, type) ->
.onStart { emit(PlanUiState.Loading) } if (loggedIn) {
.catch { emit(PlanUiState.Error(it.message ?: "加载失败,请稍后再试")) } planRepository.observePlan(type)
.stateIn( .map<PlanRecord, PlanUiState>(PlanUiState::Success)
scope = viewModelScope, .onStart { emit(PlanUiState.Loading) }
started = SharingStarted.WhileSubscribed(5_000), } else {
initialValue = PlanUiState.Loading, flowOf(PlanUiState.LoggedOut)
) }
}
.catch { emit(PlanUiState.Error(it.message ?: "加载失败,请稍后再试")) }
.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = PlanUiState.Loading,
)
fun selectType(type: PlanType) { fun selectType(type: PlanType) {
_selectedType.value = type _selectedType.value = type