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( HomeScreen(
onNavigateToCheckin = { navigateToTab(CHECKIN_ROUTE) }, onNavigateToCheckin = { navigateToTab(CHECKIN_ROUTE) },
onNavigateToPlan = { navigateToTab(PLAN_ROUTE) }, onNavigateToPlan = { navigateToTab(PLAN_ROUTE) },
onNavigateToProfile = { navigateToTab(PROFILE_ROUTE) },
) )
} }
composable(CHECKIN_ROUTE) { CheckinScreen() } composable(CHECKIN_ROUTE) { CheckinScreen() }

View File

@@ -18,32 +18,49 @@ class FakeHomeRepository @Inject constructor() : HomeRepository {
emit(seedHome()) emit(seedHome())
} }
override fun observeGuestHome(): Flow<HomeData> = flow {
delay(250)
emit(seedGuestHome())
}
private fun seedHome() = HomeData( private fun seedHome() = HomeData(
greeting = "晚上好", greeting = "晚上好",
displayName = "张三", displayName = "张三",
encouragement = "坚持每周打卡,与小组共同进步。", encouragement = "坚持每周打卡,与小组共同进步。",
modules = listOf( modules = modules(),
HomeModule("checkin", "📋", "打卡介绍", "每日打卡记录", ModuleDestination.CHECKIN), intros = intros(),
HomeModule("plan", "📝", "计划介绍", "周/月/年计划", ModuleDestination.PLAN), )
HomeModule("about", "ℹ️", "关于我们", "了解明缘云道场", ModuleDestination.ABOUT),
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),
)
private fun intros() = listOf(
IntroCard(
"📚 学习成长工具",
"明缘云道场是一款专注于个人成长的效率工具,通过每周打卡与计划管理,帮助你养成良好的学习习惯,实现持续进步。好好学习,天天向上。",
), ),
intros = listOf( IntroCard(
IntroCard( "✅ 周打卡",
"📚 学习成长工具", "每周打卡,支持多种状态记录(正常、迟到、请假、早退、不参加讨论等)。查看小组打卡情况,与同学们互相监督、共同进步。",
"明缘云道场是一款专注于个人成长的效率工具,通过每周打卡与计划管理,帮助你养成良好的学习习惯,实现持续进步。好好学习,天天向上。", ),
), IntroCard(
IntroCard( "📝 计划管理",
"✅ 周打卡", "提供周计划、月计划、年计划三级管理,支持文字与图片上传。清晰追踪每个周期的目标完成情况,让成长有迹可循。",
"每周打卡,支持多种状态记录(正常、迟到、请假、早退、不参加讨论等)。查看小组打卡情况,与同学们互相监督、共同进步。", ),
), IntroCard(
IntroCard( "👥 小组共学",
"📝 计划管理", "加入学习小组,查看组员的打卡与计划完成情况。在集体的氛围中保持学习动力,与志同道合的伙伴一起成长。",
"提供周计划、月计划、年计划三级管理,支持文字与图片上传。清晰追踪每个周期的目标完成情况,让成长有迹可循。",
),
IntroCard(
"👥 小组共学",
"加入学习小组,查看组员的打卡与计划完成情况。在集体的氛围中保持学习动力,与志同道合的伙伴一起成长。",
),
), ),
) )
} }

View File

@@ -5,4 +5,6 @@ import kotlinx.coroutines.flow.Flow
interface HomeRepository { interface HomeRepository {
fun observeHome(): Flow<HomeData> 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.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow import androidx.compose.ui.draw.shadow
@@ -51,10 +56,12 @@ const val HOME_ROUTE = "home"
fun HomeScreen( fun HomeScreen(
onNavigateToCheckin: () -> Unit, onNavigateToCheckin: () -> Unit,
onNavigateToPlan: () -> Unit, onNavigateToPlan: () -> Unit,
onNavigateToProfile: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
viewModel: HomeViewModel = hiltViewModel(), viewModel: HomeViewModel = hiltViewModel(),
) { ) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle() val uiState by viewModel.uiState.collectAsStateWithLifecycle()
var showLoginDialog by remember { mutableStateOf(false) }
when (val state = uiState) { when (val state = uiState) {
is HomeUiState.Loading -> HomeSkeleton(modifier) is HomeUiState.Loading -> HomeSkeleton(modifier)
@@ -67,15 +74,40 @@ fun HomeScreen(
is HomeUiState.Success -> HomeContent( is HomeUiState.Success -> HomeContent(
data = state.data, data = state.data,
onModuleClick = { module -> onModuleClick = { module ->
when (module.destination) { if (state.isGuest) {
ModuleDestination.CHECKIN -> onNavigateToCheckin() showLoginDialog = true
ModuleDestination.PLAN -> onNavigateToPlan() } else {
ModuleDestination.ABOUT -> Unit when (module.destination) {
ModuleDestination.CHECKIN -> onNavigateToCheckin()
ModuleDestination.PLAN -> onNavigateToPlan()
ModuleDestination.ABOUT -> Unit
}
} }
}, },
modifier = modifier, 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 @Composable

View File

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