feat: 「首页」支持游客模式

This commit is contained in:
AndyChen1024
2026-09-09 22:19:12 +08:00
parent 03410d7ea2
commit 0b8bcfe800
5 changed files with 93 additions and 30 deletions

View File

@@ -74,6 +74,7 @@ fun AppNavHost() {
HomeScreen(
onNavigateToCheckin = { navigateToTab(CHECKIN_ROUTE) },
onNavigateToPlan = { navigateToTab(PLAN_ROUTE) },
onNavigateToProfile = { navigateToTab(PROFILE_ROUTE) },
)
}
composable(CHECKIN_ROUTE) { CheckinScreen() }

View File

@@ -18,16 +18,34 @@ class FakeHomeRepository @Inject constructor() : HomeRepository {
emit(seedHome())
}
override fun observeGuestHome(): Flow<HomeData> = flow {
delay(250)
emit(seedGuestHome())
}
private fun seedHome() = HomeData(
greeting = "晚上好",
displayName = "张三",
encouragement = "坚持每周打卡,与小组共同进步。",
modules = listOf(
modules = modules(),
intros = intros(),
)
private fun seedGuestHome() = HomeData(
greeting = "欢迎来到明缘云道场",
displayName = "游客",
encouragement = "登录后即可打卡、提交计划",
modules = modules(),
intros = intros(),
)
private fun modules() = listOf(
HomeModule("checkin", "📋", "打卡介绍", "每日打卡记录", ModuleDestination.CHECKIN),
HomeModule("plan", "📝", "计划介绍", "周/月/年计划", ModuleDestination.PLAN),
HomeModule("about", "ℹ️", "关于我们", "了解明缘云道场", ModuleDestination.ABOUT),
),
intros = listOf(
)
private fun intros() = listOf(
IntroCard(
"📚 学习成长工具",
"明缘云道场是一款专注于个人成长的效率工具,通过每周打卡与计划管理,帮助你养成良好的学习习惯,实现持续进步。好好学习,天天向上。",
@@ -44,6 +62,5 @@ class FakeHomeRepository @Inject constructor() : HomeRepository {
"👥 小组共学",
"加入学习小组,查看组员的打卡与计划完成情况。在集体的氛围中保持学习动力,与志同道合的伙伴一起成长。",
),
),
)
}

View File

@@ -5,4 +5,6 @@ import kotlinx.coroutines.flow.Flow
interface HomeRepository {
fun observeHome(): Flow<HomeData>
fun observeGuestHome(): Flow<HomeData>
}

View File

@@ -16,9 +16,14 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
@@ -51,10 +56,12 @@ const val HOME_ROUTE = "home"
fun HomeScreen(
onNavigateToCheckin: () -> Unit,
onNavigateToPlan: () -> Unit,
onNavigateToProfile: () -> Unit,
modifier: Modifier = Modifier,
viewModel: HomeViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
var showLoginDialog by remember { mutableStateOf(false) }
when (val state = uiState) {
is HomeUiState.Loading -> HomeSkeleton(modifier)
@@ -67,15 +74,40 @@ fun HomeScreen(
is HomeUiState.Success -> HomeContent(
data = state.data,
onModuleClick = { module ->
if (state.isGuest) {
showLoginDialog = true
} else {
when (module.destination) {
ModuleDestination.CHECKIN -> onNavigateToCheckin()
ModuleDestination.PLAN -> onNavigateToPlan()
ModuleDestination.ABOUT -> Unit
}
}
},
modifier = modifier,
)
}
if (showLoginDialog) {
AlertDialog(
onDismissRequest = { showLoginDialog = false },
title = { Text("登录提示") },
text = { Text("登录后使用此功能,是否前往登录?") },
confirmButton = {
TextButton(
onClick = {
showLoginDialog = false
onNavigateToProfile()
},
) {
Text("去登录")
}
},
dismissButton = {
TextButton(onClick = { showLoginDialog = false }) { Text("取消") }
},
)
}
}
@Composable

View File

@@ -3,11 +3,13 @@ package com.mingyuan.android_client.feature.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.mingyuan.android_client.core.domain.repository.HomeRepository
import com.mingyuan.android_client.core.domain.repository.SessionRepository
import com.mingyuan.android_client.core.model.HomeData
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
@@ -15,22 +17,31 @@ import javax.inject.Inject
sealed interface HomeUiState {
data object Loading : HomeUiState
data class Success(val data: HomeData) : HomeUiState
data class Success(val data: HomeData, val isGuest: Boolean) : HomeUiState
data class Error(val message: String) : HomeUiState
}
@HiltViewModel
class HomeViewModel @Inject constructor(
homeRepository: HomeRepository,
sessionRepository: SessionRepository,
) : ViewModel() {
val uiState: StateFlow<HomeUiState> = homeRepository.observeHome()
.map<HomeData, HomeUiState>(HomeUiState::Success)
val uiState: StateFlow<HomeUiState> = sessionRepository.isLoggedIn
.flatMapLatest { loggedIn ->
val source = if (loggedIn) {
homeRepository.observeHome()
} else {
homeRepository.observeGuestHome()
}
source
.map<HomeData, HomeUiState> { HomeUiState.Success(it, isGuest = !loggedIn) }
.onStart { emit(HomeUiState.Loading) }
}
.catch { emit(HomeUiState.Error(it.message ?: "加载失败,请稍后再试")) }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
started = SharingStarted.Eagerly,
initialValue = HomeUiState.Loading,
)
}