diff --git a/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt b/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt index b20540e..9a9dd2f 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/MainActivity.kt @@ -5,36 +5,59 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountBox -import androidx.compose.material.icons.filled.Favorite -import androidx.compose.material.icons.filled.Home -import androidx.compose.material3.Icon -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewScreenSizes +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.view.WindowCompat +import androidx.core.view.WindowInsetsControllerCompat +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController +import android.view.WindowManager import com.huaga.life_echo.navigation.AppNavigation import com.huaga.life_echo.navigation.Screen +import com.huaga.life_echo.ui.icons.AppIcons import com.huaga.life_echo.ui.theme.LifeechoTheme +import com.huaga.life_echo.ui.theme.LightPurple class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // 启用边缘到边缘显示 enableEdgeToEdge() + // 设置系统栏透明 + WindowCompat.setDecorFitsSystemWindows(window, false) + + // 设置状态栏完全透明 + window.statusBarColor = android.graphics.Color.TRANSPARENT + window.navigationBarColor = android.graphics.Color.TRANSPARENT + + // 设置状态栏控制器,让内容可以延伸到状态栏下方 + val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) + windowInsetsController.isAppearanceLightStatusBars = !com.huaga.life_echo.ui.settings.AppSettings.darkMode + setContent { - LifeechoTheme { + val darkMode = com.huaga.life_echo.ui.settings.AppSettings.darkMode + LifeechoTheme(darkTheme = darkMode) { + // 根据主题更新状态栏图标颜色 + androidx.compose.runtime.LaunchedEffect(darkMode) { + val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) + windowInsetsController.isAppearanceLightStatusBars = !darkMode + } LifeechoApp() } } @@ -46,45 +69,104 @@ class MainActivity : ComponentActivity() { @Composable fun LifeechoApp() { val navController = rememberNavController() - var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) } + var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.CHAT) } + + // 获取当前路由,判断是否显示底部导航栏 + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentRoute = navBackStackEntry?.destination?.route + val shouldShowBottomBar = currentRoute != null && !currentRoute.startsWith("create_memory") - NavigationSuiteScaffold( - navigationSuiteItems = { - AppDestinations.entries.forEach { - item( - icon = { - Icon( - it.icon, - contentDescription = it.label + Scaffold( + modifier = Modifier.fillMaxSize(), + bottomBar = { + // 底部导航栏 - 只在非聊天详情页显示 + if (shouldShowBottomBar) { + Surface( + modifier = Modifier + .fillMaxWidth() + .windowInsetsPadding(WindowInsets.navigationBars) + .padding(bottom = 8.dp), + color = MaterialTheme.colorScheme.surface, + shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), + shadowElevation = 8.dp + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + horizontalArrangement = Arrangement.SpaceEvenly, + verticalAlignment = Alignment.CenterVertically + ) { + AppDestinations.entries.forEach { destination -> + BottomNavItem( + destination = destination, + isSelected = currentDestination == destination, + onClick = { + currentDestination = destination + when (destination) { + AppDestinations.CHAT -> navController.navigate(Screen.ConversationList.route) { + popUpTo(Screen.ConversationList.route) { inclusive = true } + } + AppDestinations.MEMOIR -> navController.navigate(Screen.MyMemoir.route) { + popUpTo(Screen.ConversationList.route) { inclusive = false } + } + AppDestinations.PROFILE -> navController.navigate(Screen.Profile.route) { + popUpTo(Screen.ConversationList.route) { inclusive = false } + } + } + } ) - }, - label = { Text(it.label) }, - selected = it == currentDestination, - onClick = { - currentDestination = it - when (it) { - AppDestinations.HOME -> navController.navigate(Screen.CreateMemory.route) - AppDestinations.FAVORITES -> navController.navigate(Screen.MyMemoir.route) - AppDestinations.PROFILE -> navController.navigate(Screen.Profile.route) - } } - ) + } + } } } - ) { - Scaffold(modifier = Modifier.fillMaxSize()) { + ) { paddingValues -> + Box(modifier = Modifier.padding(paddingValues)) { AppNavigation(navController = navController) } } } +@Composable +fun BottomNavItem( + destination: AppDestinations, + isSelected: Boolean, + onClick: () -> Unit +) { + val iconColor = if (isSelected) LightPurple else MaterialTheme.colorScheme.onSurfaceVariant + val textColor = if (isSelected) LightPurple else MaterialTheme.colorScheme.onSurfaceVariant + + Column( + modifier = Modifier + .clickable { onClick() } + .padding(horizontal = 16.dp, vertical = 4.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Icon( + imageVector = destination.icon, + contentDescription = destination.label, + tint = iconColor, + modifier = Modifier.size(24.dp) + ) + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = destination.label, + fontSize = 12.sp, + color = textColor, + fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal + ) + } +} + enum class AppDestinations( val label: String, val icon: ImageVector, ) { - HOME("Home", Icons.Default.Home), - FAVORITES("Favorites", Icons.Default.Favorite), - PROFILE("Profile", Icons.Default.AccountBox), + CHAT("聊天", AppIcons.Chat), + MEMOIR("回忆录", AppIcons.Memoir), + PROFILE("我的", AppIcons.Profile), } @Composable diff --git a/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/ViewModelFactory.kt b/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/ViewModelFactory.kt index f0a9fc8..2bf59a6 100644 --- a/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/ViewModelFactory.kt +++ b/app-android/app/src/main/java/com/huaga/life_echo/ui/viewmodel/ViewModelFactory.kt @@ -33,6 +33,11 @@ class ViewModelFactory(private val context: Context) : ViewModelProvider.Factory chapterRepository = chapterRepository ) as T } + modelClass.isAssignableFrom(ConversationListViewModel::class.java) -> { + ConversationListViewModel( + conversationRepository = conversationRepository + ) as T + } modelClass.isAssignableFrom(MyMemoirViewModel::class.java) -> { MyMemoirViewModel( chapterRepository = chapterRepository,