diff --git a/composeApp/src/androidMain/kotlin/com/grtsinry43/activityanalyzer/MainActivity.kt b/composeApp/src/androidMain/kotlin/com/grtsinry43/activityanalyzer/MainActivity.kt index 6492e11..6926e4b 100644 --- a/composeApp/src/androidMain/kotlin/com/grtsinry43/activityanalyzer/MainActivity.kt +++ b/composeApp/src/androidMain/kotlin/com/grtsinry43/activityanalyzer/MainActivity.kt @@ -3,10 +3,12 @@ package com.grtsinry43.activityanalyzer import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.Preview class MainActivity : ComponentActivity() { + @OptIn(ExperimentalMaterial3Api::class) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -16,6 +18,7 @@ class MainActivity : ComponentActivity() { } } +@OptIn(ExperimentalMaterial3Api::class) @Preview @Composable fun AppAndroidPreview() { diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt index 951cec4..13ab8b6 100644 --- a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt @@ -1,44 +1,1352 @@ package com.grtsinry43.activityanalyzer -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.* +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import org.jetbrains.compose.resources.painterResource -import org.jetbrains.compose.ui.tooling.preview.Preview +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.launch -import activityanalyzer.composeapp.generated.resources.Res -import activityanalyzer.composeapp.generated.resources.compose_multiplatform +// --- THEMES (Reused from Desktop App) --- +// 定义颜色主题,提供更传统的桌面应用外观 +object AppThemes { + data class Colors( + val background: Color, + val surface: Color, + val onSurface: Color, + val onBackground: Color, + val accent: Color, + val accentVariant: Color, // 用于细微强调或悬停状态 + val border: Color, + val secondaryText: Color, + val onAccent: Color // 强调背景上的文本/图标颜色 + ) + val LightThemeColors = Colors( + background = Color(0xFFE0E0E0), // Light Gray // 浅灰色 + surface = Color(0xFFFFFFFF), // White // 白色 + onSurface = Color(0xFF212121), // Dark Gray // 深灰色 + onBackground = Color(0xFF212121), // Dark Gray // 深灰色 + accent = Color(0xFF0D47A1), // Dark Blue // 深蓝色 + accentVariant = Color(0xFF1565C0), // Medium Blue // 中蓝色 + border = Color(0xFFB0B0B0), // Medium Gray // 中灰色 + secondaryText = Color(0xFF757575), // Gray // 灰色 + onAccent = Color.White + ) + + val DarkThemeColors = Colors( + background = Color(0xFF212121), // Very Dark Gray // 非常深的灰色 + surface = Color(0xFF303030), // Dark Gray // 深灰色 + onSurface = Color(0xFFE0E0E0), // Light Gray // 浅灰色 + onBackground = Color(0xFFE0E0E0), // Light Gray // 浅灰色 + accent = Color(0xFF42A5F5), // Light Blue // 浅蓝色 + accentVariant = Color(0xFF64B5F6), // Lighter Blue // 更浅的蓝色 + border = Color(0xFF525252), // Medium Dark Gray // 中度深灰色 + secondaryText = Color(0xFFBDBDBD), // Light Gray // 浅灰色 + onAccent = Color.Black + ) +} + +// --- Main App Composable --- @Composable -@Preview +@ExperimentalMaterial3Api fun App() { - MaterialTheme { - var showContent by remember { mutableStateOf(false) } - var greetingText by remember { mutableStateOf("加载中...") } + var isDarkTheme by remember { mutableStateOf(false) } + val currentColors = if (isDarkTheme) AppThemes.DarkThemeColors else AppThemes.LightThemeColors - LaunchedEffect(key1 = Unit) { - greetingText = try { - Greeting().greet() - } catch (e: Exception) { - "错误:${e.message}" - } - } + // Navigation state + var selectedNavItemIndex by remember { mutableStateOf(0) } + val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) + val scope = rememberCoroutineScope() - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Button(onClick = { showContent = !showContent }) { - Text("Click me!") + val navItems = listOf( + "Home" to Icons.Default.Home, + "Analytics" to Icons.Default.BarChart, + "Reports" to Icons.Default.Assessment, + "Profile" to Icons.Default.AccountCircle, + "Settings" to Icons.Default.Settings, + "About" to Icons.Default.Info + ) + + val currentScreenTitle = navItems[selectedNavItemIndex].first + + MaterialTheme( + colorScheme = if (isDarkTheme) darkColorScheme( + primary = currentColors.accent, + secondary = currentColors.accentVariant, + background = currentColors.background, + surface = currentColors.surface, + onPrimary = currentColors.onAccent, + onSecondary = currentColors.onAccent, + onBackground = currentColors.onBackground, + onSurface = currentColors.onSurface, + ) else lightColorScheme( + primary = currentColors.accent, + secondary = currentColors.accentVariant, + background = currentColors.background, + surface = currentColors.surface, + onPrimary = currentColors.onAccent, + onSecondary = currentColors.onAccent, + onBackground = currentColors.onBackground, + onSurface = currentColors.onSurface, + ) + ) { + ModalNavigationDrawer( + drawerState = drawerState, + drawerContent = { + ModalDrawerSheet( + drawerContainerColor = currentColors.surface, + drawerContentColor = currentColors.onSurface + ) { + // Drawer Header with User Info + Column( + modifier = Modifier + .fillMaxWidth() + .background(currentColors.accent.copy(alpha = 0.1f)) + .padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Icon( + imageVector = Icons.Filled.AccountCircle, + contentDescription = "User Avatar", + tint = currentColors.accent, + modifier = Modifier + .size(64.dp) + .clip(CircleShape) + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = "grtsinry43", // Placeholder Nickname + color = currentColors.onSurface, + fontSize = 16.sp, + fontWeight = FontWeight.Medium + ) + Text( + text = "grtsinry43@outlook.com", // Placeholder Email + color = currentColors.secondaryText, + fontSize = 12.sp + ) + } + Spacer(Modifier.height(12.dp)) + // Navigation Items + navItems.forEachIndexed { index, item -> + NavigationDrawerItem( + icon = { + Icon( + item.second, + contentDescription = item.first, + tint = if (selectedNavItemIndex == index) currentColors.accent else currentColors.onSurface.copy( + alpha = 0.7f + ) + ) + }, + label = { + Text( + item.first, + color = if (selectedNavItemIndex == index) currentColors.accent else currentColors.onSurface.copy( + alpha = 0.7f + ) + ) + }, + selected = selectedNavItemIndex == index, + onClick = { + selectedNavItemIndex = index + scope.launch { drawerState.close() } + }, + modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding), + colors = NavigationDrawerItemDefaults.colors( + selectedContainerColor = currentColors.accent.copy(alpha = 0.1f), + unselectedContainerColor = Color.Transparent, + selectedTextColor = currentColors.accent, + unselectedTextColor = currentColors.onSurface.copy(alpha = 0.7f), + selectedIconColor = currentColors.accent, + unselectedIconColor = currentColors.onSurface.copy(alpha = 0.7f) + ) + ) + } + } } - AnimatedVisibility(showContent) { - Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { - Image(painterResource(Res.drawable.compose_multiplatform), null) - Text("Compose: $greetingText") + ) { + Scaffold( + containerColor = currentColors.background, + topBar = { + TopAppBar( + title = { Text(currentScreenTitle, color = currentColors.onSurface) }, + navigationIcon = { + IconButton(onClick = { scope.launch { drawerState.open() } }) { + Icon( + Icons.Filled.Menu, + contentDescription = "Open Navigation Drawer", + tint = currentColors.onSurface + ) + } + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = currentColors.surface, + titleContentColor = currentColors.onSurface + ) + ) + } + ) { paddingValues -> + Box( + modifier = Modifier.padding(paddingValues).fillMaxSize() + .background(currentColors.background) + ) { + when (selectedNavItemIndex) { + 0 -> MobileHomeScreen(colors = currentColors) + 1 -> MobileAnalyticsScreen(colors = currentColors) + 2 -> MobileReportsScreen(colors = currentColors) + 3 -> MobileProfileScreen(colors = currentColors) + 4 -> MobileSettingsScreen( + colors = currentColors, + isDarkTheme = isDarkTheme, + onThemeChange = { isDarkTheme = it } + ) + + 5 -> MobileAboutScreen(colors = currentColors) + } } } } } -} \ No newline at end of file +} + +// --- Reusable Helper Composables (Adapted from Desktop App) --- + +@Composable +fun StyledCard( + modifier: Modifier = Modifier, + colors: AppThemes.Colors, + content: @Composable ColumnScope.() -> Unit +) { + Card( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(12.dp)), // Slightly more rounded for mobile + colors = CardDefaults.cardColors( + containerColor = colors.surface + ), + elevation = CardDefaults.cardElevation(defaultElevation = 2.dp), // Slightly more elevation for mobile + border = BorderStroke(1.dp, colors.border.copy(alpha = 0.4f)), + content = content + ) +} + +@Composable +fun StyledButton( + modifier: Modifier = Modifier, + icon: ImageVector, + text: String, + onClick: () -> Unit, + colors: AppThemes.Colors, + enabled: Boolean = true +) { + Button( + onClick = onClick, + modifier = modifier.height(48.dp), // Consistent height for mobile buttons + enabled = enabled, + shape = RoundedCornerShape(10.dp), + colors = ButtonDefaults.buttonColors( + containerColor = colors.accent.copy(alpha = 0.15f), // Slightly more opaque for visibility + contentColor = colors.accent, + disabledContainerColor = colors.border.copy(alpha = 0.1f), + disabledContentColor = colors.secondaryText.copy(alpha = 0.7f) + ), + border = BorderStroke(1.dp, colors.accent.copy(alpha = 0.4f)), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 10.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon(imageVector = icon, contentDescription = null, modifier = Modifier.size(20.dp)) + Text(text = text, fontSize = 14.sp, fontWeight = FontWeight.Medium) + } + } +} + +@Composable +fun ActivityItem(title: String, time: String, icon: ImageVector, colors: AppThemes.Colors) { + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(10.dp)) + .background(colors.surface.copy(alpha = 0.5f)) + .border(1.dp, colors.border.copy(alpha = 0.3f), RoundedCornerShape(10.dp)) + .padding(horizontal = 16.dp, vertical = 12.dp), // Adjusted padding for mobile + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = colors.accent, + modifier = Modifier.size(24.dp) // Slightly larger icon for mobile list items + ) + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + fontSize = 15.sp, + color = colors.onSurface, + fontWeight = FontWeight.Normal // Adjusted weight + ) + Text( + text = time, + fontSize = 13.sp, + color = colors.secondaryText + ) + } + } +} + +@Composable +fun ReportItem( + title: String, + period: String, + icon: ImageVector, + colors: AppThemes.Colors, + onDownload: () -> Unit, + onView: () -> Unit +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(10.dp)) + .clickable { onView() } // Make the whole item clickable for viewing + .padding(vertical = 12.dp, horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = colors.accent, + modifier = Modifier.size(32.dp) // Larger icon for report items + ) + Spacer(modifier = Modifier.width(16.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + fontSize = 16.sp, // Slightly larger title + color = colors.onSurface, + fontWeight = FontWeight.Medium + ) + Text( + text = period, + fontSize = 13.sp, + color = colors.secondaryText + ) + } + Spacer(modifier = Modifier.width(8.dp)) + IconButton(onClick = onDownload, modifier = Modifier.size(40.dp)) { + Icon( + imageVector = Icons.Default.Download, + contentDescription = "Download Report", + tint = colors.accentVariant + ) + } + } +} + +@Composable +fun SettingItem( + title: String, + subtitle: String, + icon: ImageVector, + colors: AppThemes.Colors, + onClick: (() -> Unit)? = null, + showSwitch: Boolean = false, + switchChecked: Boolean = false, + onSwitchChange: ((Boolean) -> Unit)? = null +) { + val itemModifier = if (onClick != null || showSwitch) { + Modifier.clickable { + if (showSwitch && onSwitchChange != null) { + onSwitchChange(!switchChecked) + } else { + onClick?.invoke() + } + } + } else { + Modifier + } + + Row( + modifier = Modifier + .fillMaxWidth() + .then(itemModifier) // Apply clickable if needed + .padding(horizontal = 16.dp, vertical = 14.dp), // Standard padding for list items + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = colors.accentVariant, + modifier = Modifier.size(24.dp) + ) + Spacer(modifier = Modifier.width(16.dp)) + Column(modifier = Modifier.weight(1f)) { + Text( + text = title, + fontSize = 16.sp, // Standard mobile list item title size + color = colors.onSurface, + fontWeight = FontWeight.Normal + ) + if (subtitle.isNotEmpty()) { + Text( + text = subtitle, + fontSize = 13.sp, + color = colors.secondaryText + ) + } + } + Spacer(modifier = Modifier.width(8.dp)) + if (showSwitch && onSwitchChange != null) { + Switch( + checked = switchChecked, + onCheckedChange = null, // Click handled by Row + colors = SwitchDefaults.colors( + checkedThumbColor = colors.accent, + checkedTrackColor = colors.accent.copy(alpha = 0.5f), + uncheckedThumbColor = colors.secondaryText, + uncheckedTrackColor = colors.border.copy(alpha = 0.5f) + ), + modifier = Modifier.size(40.dp) + ) + } else if (onClick != null && !showSwitch) { + Icon( + imageVector = Icons.Default.ChevronRight, + contentDescription = "Go to setting", + tint = colors.secondaryText.copy(alpha = 0.7f) + ) + } + } +} + +@Composable +fun SimpleListItem( + icon: ImageVector, + text: String, + colors: AppThemes.Colors, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier.padding(vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = colors.accentVariant, + modifier = Modifier.size(22.dp) + ) + Text( + text, + style = MaterialTheme.typography.bodyLarge.copy( + color = colors.onSurface, + fontSize = 15.sp + ) + ) + } +} + +@Composable +fun InfoItem( + icon: ImageVector, + text: String, + colors: AppThemes.Colors, + isLink: Boolean = false, + linkUrl: String? = null, + onClick: (() -> Unit)? = null +) { + // val uriHandler = LocalUriHandler.current // For opening links + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(8.dp)) + .clickable(enabled = onClick != null || (isLink && linkUrl != null), onClick = { + onClick?.invoke() + // if (isLink && linkUrl != null) { uriHandler.openUri(linkUrl) } // TODO: Implement link opening + }) + .padding(vertical = 12.dp, horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = icon, + contentDescription = null, + tint = colors.accentVariant, + modifier = Modifier.size(24.dp) + ) + Spacer(modifier = Modifier.width(16.dp)) + Text( + text = text, + fontSize = 15.sp, + color = if (isLink) colors.accent else colors.onSurface, + fontWeight = FontWeight.Normal + ) + } +} + +@Composable +fun MetricCard( + title: String, + value: String, + icon: ImageVector, + colors: AppThemes.Colors, + modifier: Modifier = Modifier +) { + StyledCard(colors = colors, modifier = modifier) { + Column( + modifier = Modifier.padding(16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(6.dp) // Tighter spacing for mobile + ) { + Icon( + imageVector = icon, + contentDescription = title, + tint = colors.accent, + modifier = Modifier.size(28.dp) + ) + Text( + text = title, + style = MaterialTheme.typography.labelMedium.copy(color = colors.secondaryText), + textAlign = TextAlign.Center + ) + Text( + text = value, + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.Bold + ), + textAlign = TextAlign.Center + ) + } + } +} + +@Composable +fun ChartPlaceholder(text: String, colors: AppThemes.Colors, modifier: Modifier = Modifier) { + Box( + modifier = modifier + .background(colors.background.copy(alpha = 0.5f), RoundedCornerShape(10.dp)) + .border(1.dp, colors.border.copy(alpha = 0.7f), RoundedCornerShape(10.dp)) + .padding(16.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = text, + color = colors.secondaryText, + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center + ) + } +} + + +// --- Screen Composables (Mobile Versions) --- + +@Composable +fun MobileHomeScreen(colors: AppThemes.Colors) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(16.dp), // Standard padding for mobile screens + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + text = "Welcome Back, grtsinry43!", + style = MaterialTheme.typography.headlineSmall.copy( + color = colors.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 22.sp // Adjusted for mobile + ) + ) + + StyledCard(colors = colors) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + Text( + text = "Today's Screen Time", + style = MaterialTheme.typography.titleLarge.copy( // Larger title for emphasis + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 18.sp + ) + ) + Text( + text = "3h 45m", // Placeholder + style = MaterialTheme.typography.displayMedium.copy( // Prominent display + color = colors.accent, + fontWeight = FontWeight.Bold, + fontSize = 36.sp + ), + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + Text( + text = "You're on track with your daily goal!", // Placeholder + style = MaterialTheme.typography.bodyMedium.copy( + color = colors.secondaryText, + fontSize = 14.sp + ), + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + } + } + + StyledCard(colors = colors) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Quick Glance: Top Apps", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + ) + SimpleListItem( + icon = Icons.Filled.SmartDisplay, + text = "App A: 1h 15m", + colors = colors + ) + SimpleListItem( + icon = Icons.Filled.PhotoCamera, + text = "App B: 45m", + colors = colors + ) + SimpleListItem(icon = Icons.Filled.Chat, text = "App C: 30m", colors = colors) + } + } + + StyledCard(colors = colors) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) // Spacing for buttons + ) { + Text( + text = "Quick Actions", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + ) + StyledButton( // Full width buttons for mobile quick actions + modifier = Modifier.fillMaxWidth(), + icon = Icons.Default.HourglassTop, + text = "Start Focus Session", + onClick = { /* TODO */ }, + colors = colors + ) + StyledButton( + modifier = Modifier.fillMaxWidth(), + icon = Icons.Default.CalendarViewDay, // Changed icon + text = "View Today's Details", + onClick = { /* TODO */ }, + colors = colors + ) + } + } + + StyledCard(colors = colors) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Recent Insights", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + ) + ActivityItem( + title = "Exceeded daily goal for App X.", + time = "Today, 2:30 PM", + icon = Icons.Default.WarningAmber, + colors = colors + ) + ActivityItem( + title = "Screen time 20% higher yesterday.", + time = "Insight from yesterday", + icon = Icons.Default.TrendingUp, + colors = colors + ) + } + } + } +} + +@Composable +fun MobileAnalyticsScreen(colors: AppThemes.Colors) { + var selectedTimeRange by remember { mutableStateOf("Last 7 Days") } + val timeRanges = + listOf("Today", "Yesterday", "Last 7 Days", "Last 30 Days") // Simplified for mobile + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + "Screen Time Analytics", + style = MaterialTheme.typography.headlineSmall.copy( + color = colors.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 22.sp + ) + ) + + var expanded by remember { mutableStateOf(false) } + Box(modifier = Modifier.fillMaxWidth()) { // Make dropdown full width for better mobile UX + OutlinedButton( + onClick = { expanded = true }, + shape = RoundedCornerShape(10.dp), + modifier = Modifier.fillMaxWidth(), + contentPadding = PaddingValues(16.dp) + ) { + Text(selectedTimeRange, color = colors.accent, fontSize = 16.sp) + Spacer(Modifier.weight(1f)) + Icon( + Icons.Default.ArrowDropDown, + contentDescription = "Select time range", + tint = colors.accent + ) + } + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false }, + modifier = Modifier.fillMaxWidth(0.9f) // Adjust width as needed + ) { + timeRanges.forEach { range -> + DropdownMenuItem( + text = { Text(range, fontSize = 16.sp) }, + onClick = { + selectedTimeRange = range + expanded = false + // TODO: Update analytics data + } + ) + } + } + } + + // Key Metrics - Use a Grid for better mobile layout if more than 2, or stacked Rows + Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { + MetricCard( + title = "Total Time", + value = "25h 10m", + icon = Icons.Default.Smartphone, + colors = colors, + modifier = Modifier.weight(1f) + ) + MetricCard( + title = "Avg Daily", + value = "3h 35m", + icon = Icons.Default.AvTimer, + colors = colors, + modifier = Modifier.weight(1f) + ) + } + Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { + MetricCard( + title = "Most Used", + value = "App A", + icon = Icons.Default.StarOutline, + colors = colors, + modifier = Modifier.weight(1f) + ) + MetricCard( + title = "Pickups", + value = "75", + icon = Icons.Default.TouchApp, + colors = colors, + modifier = Modifier.weight(1f) + ) + } + + + StyledCard(colors = colors) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text( + "Usage Patterns", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + ) + ChartPlaceholder( + text = "Daily Screen Time (Bar Chart)", + colors = colors, + modifier = Modifier.fillMaxWidth().height(180.dp) + ) // Slightly smaller charts for mobile + ChartPlaceholder( + text = "App Usage (Pie Chart)", + colors = colors, + modifier = Modifier.fillMaxWidth().height(180.dp) + ) + } + } + + StyledCard(colors = colors) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + "Analysis Tools", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + ) + StyledButton( + modifier = Modifier.fillMaxWidth(), + icon = Icons.Default.PieChartOutline, + text = "App Usage Breakdown", + onClick = { /* TODO */ }, + colors = colors + ) + StyledButton( + modifier = Modifier.fillMaxWidth(), + icon = Icons.Default.AccessTime, + text = "Time of Day Analysis", + onClick = { /* TODO */ }, + colors = colors + ) + StyledButton( + modifier = Modifier.fillMaxWidth(), + icon = Icons.Default.TrackChanges, + text = "Set Usage Goals", + onClick = { /* TODO */ }, + colors = colors + ) + } + } + } +} + +@Composable +fun MobileReportsScreen(colors: AppThemes.Colors) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + "Screen Time Reports", + style = MaterialTheme.typography.headlineSmall.copy( + color = colors.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 22.sp + ) + ) + IconButton(onClick = { /* TODO: Generate new report */ }) { // Icon button for mobile + Icon( + Icons.Default.Addchart, + contentDescription = "Generate New Report", + tint = colors.accent + ) + } + } + + // Example Reports - for mobile, a simple list is often best + ReportItem( + title = "Weekly Summary - May 5-11", + period = "Generated: May 12, 2025", + icon = Icons.Default.CalendarToday, + colors = colors, + onDownload = {}, + onView = {}) + Divider(color = colors.border.copy(alpha = 0.2f), thickness = 0.5.dp) + ReportItem( + title = "Monthly App Usage - April", + period = "Generated: May 1, 2025", + icon = Icons.Default.PieChart, + colors = colors, + onDownload = {}, + onView = {}) + Divider(color = colors.border.copy(alpha = 0.2f), thickness = 0.5.dp) + ReportItem( + title = "Q1 Device Pickups", + period = "Generated: April 5, 2025", + icon = Icons.Default.TouchApp, + colors = colors, + onDownload = {}, + onView = {}) + Divider(color = colors.border.copy(alpha = 0.2f), thickness = 0.5.dp) + ReportItem( + title = "Focus Session - Project X", + period = "Generated: May 10, 2025", + icon = Icons.Default.HourglassEmpty, + colors = colors, + onDownload = {}, + onView = {}) + + // Placeholder if no reports + // Box(modifier = Modifier.fillMaxSize().padding(top = 32.dp), contentAlignment = Alignment.Center) { + // Text("No reports generated yet.", color = colors.secondaryText, style = MaterialTheme.typography.bodyLarge) + // } + } +} + +@Composable +fun MobileProfileScreen(colors: AppThemes.Colors) { + var nickname by remember { mutableStateOf("grtsinry43") } + var email by remember { mutableStateOf("grtsinry43@outlook.com") } + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(20.dp), + horizontalAlignment = Alignment.CenterHorizontally // Center content like avatar + ) { + Text( + "User Profile", + style = MaterialTheme.typography.headlineSmall.copy( + color = colors.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 22.sp + ), + modifier = Modifier.align(Alignment.Start) // Align title to start + ) + + Icon( + imageVector = Icons.Filled.AccountCircle, + contentDescription = "User Avatar", + tint = colors.accent, + modifier = Modifier.size(120.dp) // Large avatar for profile screen + ) + // TODO: Add option to change avatar (e.g., an Edit icon button) + + OutlinedTextField( + value = nickname, + onValueChange = { nickname = it }, + label = { Text("Nickname") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = colors.accent, + unfocusedBorderColor = colors.border, + focusedLabelColor = colors.accent, + cursorColor = colors.accent, + focusedTextColor = colors.onSurface, + unfocusedTextColor = colors.onSurface + ) + ) + OutlinedTextField( + value = email, + onValueChange = { email = it }, + label = { Text("Email") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = colors.accent, + unfocusedBorderColor = colors.border, + focusedLabelColor = colors.accent, + cursorColor = colors.accent, + focusedTextColor = colors.onSurface, + unfocusedTextColor = colors.onSurface + ) + ) + StyledButton( + icon = Icons.Default.Save, + text = "Save Changes", + onClick = { /* TODO: Save profile changes */ }, + colors = colors, + modifier = Modifier.fillMaxWidth().padding(top = 8.dp) + ) + + // Overall Statistics Card + StyledCard(colors = colors, modifier = Modifier.padding(top = 16.dp)) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + "Overall Statistics", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onSurface, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ) + ) + SimpleListItem( + icon = Icons.Filled.Timer, + text = "Total Time Tracked: 1250 hrs", + colors = colors + ) + SimpleListItem( + icon = Icons.Filled.CheckCircleOutline, + text = "Goals Met Streak: 15 days", + colors = colors + ) + SimpleListItem( + icon = Icons.Filled.EventAvailable, + text = "Joined: Jan 1, 2024", + colors = colors + ) + } + } + + // Account Actions + Column( + modifier = Modifier.padding(top = 16.dp).fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + "Account Actions", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.onBackground, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ), + modifier = Modifier.padding(bottom = 4.dp) + ) + StyledButton( + icon = Icons.Default.LockReset, + text = "Change Password", + onClick = { /* TODO */ }, + colors = colors, + modifier = Modifier.fillMaxWidth() + ) + Button( // Destructive action button styling + onClick = { /* TODO: Show confirmation dialog */ }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(10.dp), + colors = ButtonDefaults.buttonColors( + containerColor = Color.Red.copy(alpha = 0.1f), + contentColor = Color.Red.copy(alpha = 0.9f) + ), + border = BorderStroke(1.dp, Color.Red.copy(alpha = 0.3f)), + contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + Icons.Default.DeleteForever, + contentDescription = null, + modifier = Modifier.size(20.dp) + ) + Text("Delete Account", fontSize = 14.sp, fontWeight = FontWeight.Medium) + } + } + } + } +} + +@Composable +fun MobileSettingsScreen( + colors: AppThemes.Colors, + isDarkTheme: Boolean, + onThemeChange: (Boolean) -> Unit +) { + var autoBackupEnabled by remember { mutableStateOf(true) } + var notificationsEnabled by remember { mutableStateOf(true) } + + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(bottom = 16.dp), // Padding at the bottom for scrollable content + verticalArrangement = Arrangement.spacedBy(0.dp) // No space between items, handled by SettingItem padding and dividers + ) { + // General Group + SettingsGroupHeader(title = "General", colors = colors) + SettingItem( + title = "Dark Theme", + subtitle = if (isDarkTheme) "Enabled" else "Disabled", + icon = Icons.Default.Brightness6, + colors = colors, + showSwitch = true, + switchChecked = isDarkTheme, + onSwitchChange = onThemeChange + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Data Storage", + subtitle = "Manage storage location", // Simplified for mobile + icon = Icons.Default.FolderOpen, + colors = colors, + onClick = { /* TODO */ } + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Auto Backup", + subtitle = if (autoBackupEnabled) "Daily at 2:00 AM" else "Disabled", + icon = Icons.Default.SaveAlt, + colors = colors, + showSwitch = true, + switchChecked = autoBackupEnabled, + onSwitchChange = { autoBackupEnabled = it } + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Cloud Sync", + subtitle = "Not Connected", + icon = Icons.Default.CloudQueue, + colors = colors, + onClick = { /* TODO */ } + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Export Data", + subtitle = "Export activity data", + icon = Icons.Default.Output, + colors = colors, + onClick = { /* TODO */ } + ) + + // Tracking Group + SettingsGroupHeader(title = "Tracking", colors = colors) + SettingItem( + title = "Apps to Track", + subtitle = "All Apps", // Placeholder + icon = Icons.Default.AppBlocking, + colors = colors, + onClick = { /* TODO */ } + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Tracking Sensitivity", + subtitle = "Medium", // Placeholder + icon = Icons.Default.Tune, + colors = colors, + onClick = { /* TODO */ } + ) + + // Notifications Group + SettingsGroupHeader(title = "Notifications", colors = colors) + SettingItem( + title = "Screen Time Limits", + subtitle = "Notify when limits exceeded", + icon = Icons.Default.NotificationsActive, + colors = colors, + showSwitch = true, + switchChecked = notificationsEnabled, + onSwitchChange = { notificationsEnabled = it } + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Break Reminders", + subtitle = "Get reminded to take breaks", + icon = Icons.Default.SelfImprovement, + colors = colors, + onClick = { /* TODO */ } + ) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "Weekly Summary", + subtitle = "Notify every Monday", + icon = Icons.Default.MarkEmailRead, + colors = colors, + showSwitch = true, + switchChecked = true, // Placeholder + onSwitchChange = { /* TODO */ } + ) + } +} + +@Composable +fun SettingsGroupHeader(title: String, colors: AppThemes.Colors) { + Text( + text = title, + style = MaterialTheme.typography.titleSmall.copy( // Using titleSmall for group headers + color = colors.accent, // Use accent color for headers + fontWeight = FontWeight.SemiBold, + fontSize = 14.sp + ), + modifier = Modifier + .fillMaxWidth() + .background(colors.background) // Ensure header background matches screen + .padding(horizontal = 16.dp, vertical = 12.dp) // More padding for group headers + ) +} + + +@Composable +fun MobileAboutScreen(colors: AppThemes.Colors) { + Column( + modifier = Modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Icon( + imageVector = Icons.Filled.Analytics, // App Icon + contentDescription = "App Logo", + tint = colors.accent, + modifier = Modifier.size(72.dp) // Slightly smaller for mobile about screen + ) + Text( + "Activity Analyzer", + style = MaterialTheme.typography.headlineMedium.copy( + color = colors.onBackground, + fontWeight = FontWeight.Bold, + fontSize = 24.sp + ) + ) + Text( + "Version 1.0.0-beta", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.secondaryText, + fontSize = 16.sp + ) + ) + + Text( + "Your personal screen time companion, helping you understand and manage your digital habits across platforms.", + style = MaterialTheme.typography.bodyLarge.copy( + color = colors.onSurface, + fontSize = 15.sp + ), + textAlign = TextAlign.Center, + modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp) + ) + + // Developer Info Section + Text( + "Developer", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.accent, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ), + modifier = Modifier.align(Alignment.Start).padding(top = 8.dp) + ) + InfoItem(icon = Icons.Filled.Person, text = "grtsinry43", colors = colors, onClick = {}) + Divider(color = colors.border.copy(alpha = 0.2f)) + InfoItem( + icon = Icons.Filled.Email, + text = "grtsinry43@outlook.com", + colors = colors, + isLink = true, + linkUrl = "mailto:grtsinry43@outlook.com", + onClick = {}) + Divider(color = colors.border.copy(alpha = 0.2f)) + InfoItem( + icon = Icons.Filled.Language, + text = "blog.grtsinry43.com", + colors = colors, + isLink = true, + linkUrl = "https://blog.grtsinry43.com", + onClick = {}) + Divider(color = colors.border.copy(alpha = 0.2f)) + InfoItem( + icon = Icons.Filled.Code, + text = "github.com/grtsinry43", + colors = colors, + isLink = true, + linkUrl = "https://github.com/grtsinry43", + onClick = {}) + + + // Application Info Section + Text( + "Application Info", + style = MaterialTheme.typography.titleMedium.copy( + color = colors.accent, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp + ), + modifier = Modifier.align(Alignment.Start).padding(top = 16.dp) + ) + SettingItem( + title = "Check for Updates", + subtitle = "Last checked: Today", + icon = Icons.Default.SystemUpdateAlt, + colors = colors, + onClick = {}) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) // Use full width divider for settings like items + SettingItem( + title = "Acknowledgements", + subtitle = "Libraries and resources", + icon = Icons.Default.FavoriteBorder, + colors = colors, + onClick = {}) + Divider( + color = colors.border.copy(alpha = 0.2f), + modifier = Modifier.padding(horizontal = 16.dp) + ) + SettingItem( + title = "License Information", + subtitle = "View license", + icon = Icons.Default.Gavel, + colors = colors, + onClick = {}) + + Spacer(modifier = Modifier.weight(1f)) + Text( + "© 2025 grtsinry43. All rights reserved.", + style = MaterialTheme.typography.bodySmall.copy( + color = colors.secondaryText, + fontSize = 12.sp + ), + textAlign = TextAlign.Center, + modifier = Modifier.padding(bottom = 8.dp, top = 16.dp) + ) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt index 8719066..e9a215c 100644 --- a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt @@ -3,9 +3,8 @@ package com.grtsinry43.activityanalyzer import androidx.compose.foundation.* import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.BasicText -import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material3.* @@ -16,631 +15,1456 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import org.jetbrains.compose.ui.tooling.preview.Preview -import androidx.compose.material3.Switch -import androidx.compose.material3.SwitchDefaults -import androidx.compose.material3.TextButton +import androidx.compose.foundation.text.selection.SelectionContainer + +// Define color palettes for a more traditional desktop look +// 定义颜色主题,提供更传统的桌面应用外观 +//object AppThemes { +// data class Colors( +// val background: Color, +// val surface: Color, +// val onSurface: Color, +// val onBackground: Color, +// val accent: Color, +// val accentVariant: Color, // For subtle accents or hover states // 用于细微强调或悬停状态 +// val border: Color, +// val secondaryText: Color, +// val onAccent: Color // Text/icon color on accent background // 强调背景上的文本/图标颜色 +// ) +// +// val LightThemeColors = Colors( +// background = Color(0xFFF0F0F0), // Light Gray // 浅灰色 +// surface = Color(0xFFFFFFFF), // White // 白色 +// onSurface = Color(0xFF212121), // Dark Gray // 深灰色 +// onBackground = Color(0xFF212121), // Dark Gray // 深灰色 +// accent = Color(0xFF0D47A1), // Dark Blue // 深蓝色 +// accentVariant = Color(0xFF1565C0), // Medium Blue // 中蓝色 +// border = Color(0xFFB0B0B0), // Medium Gray // 中灰色 +// secondaryText = Color(0xFF757575), // Gray // 灰色 +// onAccent = Color.White +// ) +// +// val DarkThemeColors = Colors( +// background = Color(0xFF212121), // Very Dark Gray // 非常深的灰色 +// surface = Color(0xFF303030), // Dark Gray // 深灰色 +// onSurface = Color(0xFFE0E0E0), // Light Gray // 浅灰色 +// onBackground = Color(0xFFE0E0E0), // Light Gray // 浅灰色 +// accent = Color(0xFF42A5F5), // Light Blue // 浅蓝色 +// accentVariant = Color(0xFF64B5F6), // Lighter Blue // 更浅的蓝色 +// border = Color(0xFF525252), // Medium Dark Gray // 中度深灰色 +// secondaryText = Color(0xFFBDBDBD), // Light Gray // 浅灰色 +// onAccent = Color.Black +// ) +//} @Composable @Preview fun DesktopApp() { - var selectedItem by remember { mutableStateOf(0) } - var isDarkTheme by remember { mutableStateOf(false) } - var isSidebarCollapsed by remember { mutableStateOf(false) } // 新增状态变量 - - val backgroundColor = if (isDarkTheme) Color(0xFF1E1E1E) else Color(0xFFF5F5F5) - val surfaceColor = if (isDarkTheme) Color(0xFF2D2D2D) else Color.White - val textColor = if (isDarkTheme) Color.White else Color.Black - val accentColor = Color(0xFF007AFF) - - Box( - modifier = Modifier - .fillMaxSize() - .background(backgroundColor) - ) { - Row( - modifier = Modifier.fillMaxSize() - ) { - // Sidebar - Box( - modifier = Modifier - .width(if (isSidebarCollapsed) 60.dp else 200.dp) // 动态宽度 - .fillMaxHeight() - .background(surfaceColor) - .padding(16.dp) - ) { - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - if (!isSidebarCollapsed) { - Text( - "Activity Analyzer", - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - color = textColor - ) - Spacer(modifier = Modifier.height(32.dp)) - } - - // Navigation items - NavItem( - icon = Icons.Default.Home, - text = if (isSidebarCollapsed) "" else "Home", // 根据收缩状态显示文本 - isSelected = selectedItem == 0, - onClick = { selectedItem = 0 }, - textColor = textColor, - accentColor = accentColor, - isSidebarCollapsed = isSidebarCollapsed - ) - NavItem( - icon = Icons.Default.BarChart, - text = if (isSidebarCollapsed) "" else "Analytics", - isSelected = selectedItem == 1, - onClick = { selectedItem = 1 }, - textColor = textColor, - accentColor = accentColor, - isSidebarCollapsed = isSidebarCollapsed - ) - NavItem( - icon = Icons.Default.Dataset, - text = if (isSidebarCollapsed) "" else "Reports", - isSelected = selectedItem == 2, - onClick = { selectedItem = 2 }, - textColor = textColor, - accentColor = accentColor, - isSidebarCollapsed = isSidebarCollapsed - ) - NavItem( - icon = Icons.Default.Settings, - text = if (isSidebarCollapsed) "" else "Settings", - isSelected = selectedItem == 3, - onClick = { selectedItem = 3 }, - textColor = textColor, - accentColor = accentColor, - isSidebarCollapsed = isSidebarCollapsed - ) - - Spacer(modifier = Modifier.weight(1f)) - - // Theme switch - if (!isSidebarCollapsed) { - Row( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - .background(if (isDarkTheme) Color(0xFF3D3D3D) else Color(0xFFE8E8E8)) - .padding(8.dp), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text( - "Dark Theme", - color = textColor - ) - Switch( - checked = isDarkTheme, - onCheckedChange = { isDarkTheme = it }, - colors = SwitchDefaults.colors( - checkedThumbColor = accentColor, - checkedTrackColor = accentColor.copy(alpha = 0.5f) - ) - ) - } - } - - // Collapse/Expand button - IconButton( - onClick = { isSidebarCollapsed = !isSidebarCollapsed }, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) { - Icon( - imageVector = if (isSidebarCollapsed) Icons.Default.ChevronRight else Icons.Default.ChevronLeft, - contentDescription = "Toggle Sidebar", - tint = textColor - ) - } - } - } - - // Main content - Box( - modifier = Modifier - .fillMaxSize() - .padding(24.dp) - ) { - when (selectedItem) { - 0 -> HomeScreen(textColor = textColor, surfaceColor = surfaceColor) - 1 -> AnalyticsScreen(textColor = textColor, surfaceColor = surfaceColor) - 2 -> ReportsScreen(textColor = textColor, surfaceColor = surfaceColor) - 3 -> SettingsScreen(textColor = textColor, surfaceColor = surfaceColor) - } - } - } - } -} - -@Composable -fun NavItem( - icon: ImageVector, - text: String, - isSelected: Boolean, - onClick: () -> Unit, - textColor: Color, - accentColor: Color, - isSidebarCollapsed: Boolean -) { - Box( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(12.dp)) // 更大的圆角 - .background(if (isSelected) accentColor.copy(alpha = 0.2f) else Color.Transparent) - .padding(vertical = 12.dp, horizontal = if (isSidebarCollapsed) 8.dp else 16.dp) - .clickable( - onClick = onClick, - indication = null, - interactionSource = remember { MutableInteractionSource() } - ), - contentAlignment = Alignment.CenterStart - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = if (isSelected) accentColor else textColor, - modifier = Modifier.size(if (isSidebarCollapsed) 32.dp else 24.dp) // 动态调整图标大小 - ) - if (!isSidebarCollapsed) { - Text( - text = text, - style = MaterialTheme.typography.titleMedium.copy( - color = if (isSelected) accentColor else textColor, - fontSize = 16.sp, - fontWeight = if (isSelected) FontWeight.Bold else FontWeight.Normal - ) - ) - } - } - } -} - -@Composable -fun HomeScreen(textColor: Color, surfaceColor: Color) { - Column( - modifier = Modifier - .fillMaxSize() - .padding(16.dp), - verticalArrangement = Arrangement.spacedBy(24.dp) - ) { - SelectionContainer { - Text( - text = "Welcome Back!", - style = MaterialTheme.typography.headlineMedium, - color = MaterialTheme.colorScheme.onBackground - ) - } - - // Quick actions - Card( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .height(150.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surface - ) - ) { - Column( - modifier = Modifier.padding(16.dp), - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - SelectionContainer { - Text( - text = "Quick Actions", - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.onSurface - ) - } - Row( - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - ActionButton( - icon = Icons.Default.Add, - text = "New Activity", - onClick = {/* TODO */ } - ) - ActionButton( - icon = Icons.Default.Upload, - text = "Import Data", - onClick = {/* TODO */ } - ) - } - } - } - } - -// // Recent activities -// Card( +// var selectedItem by remember { mutableStateOf(0) } // 记住当前选中的导航项索引 +// var isDarkTheme by remember { mutableStateOf(false) } // 记住当前是否为暗色主题 +// var isSidebarCollapsed by remember { mutableStateOf(false) } // 记住侧边栏是否折叠 +// +// val currentColors = +// if (isDarkTheme) AppThemes.DarkThemeColors else AppThemes.LightThemeColors // 根据主题选择颜色 +// +// Box( // modifier = Modifier -// .fillMaxWidth() -// .clip(RoundedCornerShape(16.dp)), -// colors = CardDefaults.cardColors( -// containerColor = MaterialTheme.colorScheme.surface -// ) +// .fillMaxSize() // 填充整个可用空间 +// .background(currentColors.background) // 设置背景色 // ) { -// Column( -// modifier = Modifier.padding(16.dp), -// verticalArrangement = Arrangement.spacedBy(16.dp) +// Row( +// modifier = Modifier.fillMaxSize() // 主行布局,填充整个可用空间 // ) { -// Text( -// text = "Recent Activities", -// style = MaterialTheme.typography.titleMedium, -// color = MaterialTheme.colorScheme.onSurface -// ) -// ActivityItem( -// title = "Activity Report Generated", -// time = "2024-04-12 14:30", -// icon = Icons.Default.Description -// ) -// ActivityItem( -// title = "Data Imported", -// time = "2024-04-12 10:15", -// icon = Icons.Default.Upload -// ) +// // Sidebar +// // 侧边栏 +// Box( +// modifier = Modifier +// .width(if (isSidebarCollapsed) 70.dp else 240.dp) // 根据折叠状态调整宽度 +// .fillMaxHeight() // 填充整个高度 +// .background(currentColors.surface) // 设置侧边栏背景色 +// .padding( +// start = 8.dp, +// end = 8.dp, +// top = 16.dp, +// bottom = 16.dp +// ) // 设置内边距 +// ) { +// Column( +// modifier = Modifier.fillMaxHeight(), // 列布局,填充整个高度 +// verticalArrangement = Arrangement.spacedBy(8.dp) // 子项垂直间距 +// ) { +// if (!isSidebarCollapsed) { +// Text( +// "Activity Analyzer", // 应用标题 +// fontSize = 18.sp, // 字体大小 +// fontWeight = FontWeight.SemiBold, // 字体粗细 +// color = currentColors.onSurface, // 文本颜色 +// modifier = Modifier.padding( +// horizontal = 8.dp, +// vertical = 16.dp +// ) // 标题内边距 +// ) +// } else { +// // 折叠时显示应用Logo图标 +// Icon( +// Icons.Default.Analytics, // 应用Logo图标 (示例) +// contentDescription = "App Logo", // 内容描述 +// tint = currentColors.accent, // 图标颜色 +// modifier = Modifier +// .size(40.dp) // 图标大小 +// .align(Alignment.CenterHorizontally) // 水平居中 +// .padding(vertical = 16.dp) // 垂直内边距 +// ) +// } +// +// // Navigation items +// // 导航项列表 +// val navItems = listOf( +// "Home" to Icons.Default.Home, // 首页 +// "Analytics" to Icons.Default.BarChart, // 分析页 +// "Reports" to Icons.Default.Assessment, // 报告页 (图标已更改) +// "Profile" to Icons.Default.AccountCircle, // 个人资料页 +// "Settings" to Icons.Default.Settings, // 设置页 +// "About" to Icons.Default.Info // 关于页 +// ) +// +// navItems.forEachIndexed { index, (text, icon) -> +// NavItem( +// icon = icon, +// text = if (isSidebarCollapsed) "" else text, // 折叠时不显示文本 +// isSelected = selectedItem == index, // 判断是否选中 +// onClick = { selectedItem = index }, // 点击事件,更新选中项 +// colors = currentColors, +// isSidebarCollapsed = isSidebarCollapsed +// ) +// } +// +// Spacer(modifier = Modifier.weight(1f)) // 弹性空间,将后续内容推到底部 +// +// // User Profile Section +// // 用户资料区域 (侧边栏底部) +// if (!isSidebarCollapsed) { +// Column( +// modifier = Modifier +// .fillMaxWidth() +// .padding(horizontal = 8.dp, vertical = 8.dp), +// horizontalAlignment = Alignment.CenterHorizontally // 水平居中对齐 +// ) { +// Icon( +// imageVector = Icons.Default.AccountCircle, // 用户头像图标 +// contentDescription = "User Avatar", // 内容描述 +// tint = currentColors.accent, // 图标颜色 +// modifier = Modifier +// .size(48.dp) // 图标大小 +// .clip(CircleShape) // 圆形裁剪 +// ) +// Spacer(modifier = Modifier.height(8.dp)) // 垂直间距 +// Text( +// text = "grtsinry43", // 用户昵称 (占位符) +// color = currentColors.onSurface, // 文本颜色 +// fontSize = 14.sp, // 字体大小 +// fontWeight = FontWeight.Medium // 字体粗细 +// ) +// } +// Spacer(modifier = Modifier.height(16.dp)) // 垂直间距 +// } +// +// +// // Collapse/Expand button +// // 折叠/展开侧边栏按钮 +// IconButton( +// onClick = { isSidebarCollapsed = !isSidebarCollapsed }, // 点击切换折叠状态 +// modifier = Modifier.align(Alignment.CenterHorizontally) // 水平居中 +// .size(40.dp) // 按钮大小 +// ) { +// Icon( +// imageVector = if (isSidebarCollapsed) Icons.Default.MenuOpen else Icons.Default.Menu, // 根据状态选择图标 +// contentDescription = "Toggle Sidebar", // 内容描述 +// tint = currentColors.onSurface // 图标颜色 +// ) +// } +// } +// } +// +// // Main content +// // 主内容区域 +// Box( +// modifier = Modifier +// .fillMaxSize() // 填充整个可用空间 +// .padding(24.dp) // 内边距 +// ) { +// // 根据选中的导航项显示不同的屏幕内容 +// when (selectedItem) { +// 0 -> HomeScreen(colors = currentColors) +// 1 -> AnalyticsScreen(colors = currentColors) +// 2 -> ReportsScreen(colors = currentColors) +// 3 -> ProfileScreen(colors = currentColors) +// 4 -> SettingsScreen( +// colors = currentColors, +// isDarkTheme = isDarkTheme, +// onThemeChange = { isDarkTheme = it } // 主题切换回调 +// ) +// +// 5 -> AboutScreen(colors = currentColors) +// } +// } // } // } } -@Composable -fun ActionButton( - icon: ImageVector, - text: String, - onClick: () -> Unit -) { - Box( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(12.dp)) - .background(Color(0xFF007AFF).copy(alpha = 0.1f)) - .clickable(onClick = onClick) - .padding(16.dp), - contentAlignment = Alignment.Center - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = Color(0xFF007AFF) - ) - Text( - text = text, - color = Color(0xFF007AFF), - fontSize = 14.sp - ) - } - } -} - -@Composable -fun ActivityItem( - title: String, - time: String, - icon: ImageVector -) { - Row( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - .background(Color(0xFFF5F5F5)) - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = Color(0xFF007AFF) - ) - Column { - Text( - text = title, - fontSize = 16.sp, - color = Color.Black - ) - Text( - text = time, - fontSize = 14.sp, - color = Color.Gray - ) - } - } -} - -@Composable -fun AnalyticsScreen(textColor: Color, surfaceColor: Color) { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(24.dp) - ) { - Text( - "Analytics", - fontSize = 32.sp, - fontWeight = FontWeight.Bold, - color = textColor - ) - - // Analysis tools card - Card( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .background(surfaceColor) - .padding(24.dp) - ) { - Column( - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - Text( - "Analysis Tools", - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - color = textColor - ) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - AnalysisToolButton( - icon = Icons.Default.Info, - text = "Time Analysis", - onClick = {/* TODO */ } - ) - AnalysisToolButton( - icon = Icons.Default.Info, - text = "Distribution Analysis", - onClick = {/* TODO */ } - ) - } - } - } - } -} - -@Composable -fun AnalysisToolButton( - icon: ImageVector, - text: String, - onClick: () -> Unit -) { - Box( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(12.dp)) - .background(Color(0xFF007AFF).copy(alpha = 0.1f)) - .clickable(onClick = onClick) - .padding(16.dp), - contentAlignment = Alignment.Center - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = Color(0xFF007AFF) - ) - Text( - text = text, - color = Color(0xFF007AFF), - fontSize = 14.sp - ) - } - } -} - -@Composable -fun ReportsScreen(textColor: Color, surfaceColor: Color) { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(24.dp) - ) { - Text( - "Reports", - fontSize = 32.sp, - fontWeight = FontWeight.Bold, - color = textColor - ) - - // Report list - Card( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .background(surfaceColor) - .padding(24.dp) - ) { - Column( - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - Text( - "My Reports", - fontSize = 20.sp, - fontWeight = FontWeight.Bold, - color = textColor - ) - ReportItem( - title = "Monthly Activity Report", - period = "March 2024", - icon = Icons.Default.Info - ) - ReportItem( - title = "Weekly Activity Analysis", - period = "Week 12, 2024", - icon = Icons.Default.Info - ) - } - } - } -} - -@Composable -fun ReportItem( - title: String, - period: String, - icon: ImageVector -) { - Row( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - .background(Color(0xFFF5F5F5)) - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = Color(0xFF007AFF) - ) - Column { - Text( - text = title, - fontSize = 16.sp, - color = Color.Black - ) - Text( - text = period, - fontSize = 14.sp, - color = Color.Gray - ) - } - } - IconButton(onClick = { /* TODO */ }) { - Icon( - imageVector = Icons.Default.Info, - contentDescription = "Download", - tint = Color(0xFF007AFF) - ) - } - } -} - -@Composable -fun SettingsScreen(textColor: Color, surfaceColor: Color) { - Column( - modifier = Modifier.fillMaxSize(), - verticalArrangement = Arrangement.spacedBy(24.dp) - ) { - Text( - "Settings", - fontSize = 32.sp, - fontWeight = FontWeight.Bold, - color = textColor - ) - - // Settings options - Card( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(16.dp)) - .background(surfaceColor) - .padding(24.dp) - ) { - Column( - verticalArrangement = Arrangement.spacedBy(16.dp) - ) { - SettingItem( - title = "Data Storage Location", - subtitle = "Default Location", - icon = Icons.Default.Info, - onClick = {/* TODO */ } - ) - SettingItem( - title = "Auto Backup", - subtitle = "Daily", - icon = Icons.Default.Info, - showSwitch = true - ) - SettingItem( - title = "Notification Settings", - subtitle = "Enabled", - icon = Icons.Default.Info, - showSwitch = true - ) - } - } - } -} - -@Composable -fun SettingItem( - title: String, - subtitle: String, - icon: ImageVector, - onClick: (() -> Unit)? = null, - showSwitch: Boolean = false -) { - Row( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(8.dp)) - .background(Color(0xFFF5F5F5)) - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(16.dp) - ) { - Icon( - imageVector = icon, - contentDescription = null, - tint = Color(0xFF007AFF) - ) - Column { - Text( - text = title, - fontSize = 16.sp, - color = Color.Black - ) - Text( - text = subtitle, - fontSize = 14.sp, - color = Color.Gray - ) - } - } - if (showSwitch) { - Switch( - checked = true, - onCheckedChange = {/* TODO */ }, - colors = SwitchDefaults.colors( - checkedThumbColor = Color(0xFF007AFF), - checkedTrackColor = Color(0xFF007AFF).copy(alpha = 0.5f) - ) - ) - } else if (onClick != null) { - TextButton(onClick = onClick) { - Text( - "Change", - color = Color(0xFF007AFF) - ) - } - } - } -} +//@Composable +//fun NavItem( +// icon: ImageVector, // 导航项图标 +// text: String, // 导航项文本 +// isSelected: Boolean, // 是否被选中 +// onClick: () -> Unit, // 点击事件回调 +// colors: AppThemes.Colors, // 当前颜色主题 +// isSidebarCollapsed: Boolean // 侧边栏是否折叠 +//) { +// val interactionSource = remember { MutableInteractionSource() } // 用于自定义点击效果 +// val backgroundColor = +// if (isSelected) colors.accent.copy(alpha = 0.15f) else Color.Transparent // 选中时背景色高亮 +// val contentColor = +// if (isSelected) colors.accent else colors.onSurface.copy(alpha = 0.8f) // 选中时内容颜色使用强调色 +// +// Row( // 使用 Row 布局导航项 +// modifier = Modifier +// .fillMaxWidth() // 填充宽度 +// .height(if (isSidebarCollapsed) 50.dp else 44.dp) // 根据折叠状态调整高度 +// .clip(RoundedCornerShape(8.dp)) // 圆角 +// .background(backgroundColor) // 背景色 +// .clickable( // 设置点击事件 +// onClick = onClick, +// interactionSource = interactionSource, +// indication = null // 不使用默认的点击涟漪效果,依赖背景色变化 +// ) +// .padding(horizontal = if (isSidebarCollapsed) 0.dp else 12.dp), // 折叠时水平内边距为0,使图标居中 +// verticalAlignment = Alignment.CenterVertically, // 垂直居中对齐 +// horizontalArrangement = if (isSidebarCollapsed) Arrangement.Center else Arrangement.Start // 折叠时水平居中,否则从左开始 +// ) { +// Icon( +// imageVector = icon, +// contentDescription = text.ifEmpty { null }, // 如果文本为空,则内容描述为null +// tint = contentColor, // 图标颜色 +// modifier = Modifier.size(if (isSidebarCollapsed) 28.dp else 22.dp) // 根据折叠状态调整图标大小 +// ) +// if (!isSidebarCollapsed) { // 如果侧边栏未折叠,则显示文本 +// Spacer(modifier = Modifier.width(12.dp)) // 图标和文本之间的间距 +// Text( +// text = text, +// color = contentColor, // 文本颜色 +// fontSize = 15.sp, // 字体大小 +// fontWeight = if (isSelected) FontWeight.SemiBold else FontWeight.Normal // 选中时字体加粗 +// ) +// } +// } +//} +// +//// Helper for styled cards +//// 风格化卡片辅助 Composable +//@Composable +//fun StyledCard( +// modifier: Modifier = Modifier, // 修饰符 +// colors: AppThemes.Colors, // 颜色主题 +// content: @Composable ColumnScope.() -> Unit // 卡片内容,是一个 ColumnScope 的 Composable lambda +//) { +// Card( +// modifier = modifier +// .fillMaxWidth() // 填充宽度 +// .clip(RoundedCornerShape(10.dp)), // 圆角 +// colors = CardDefaults.cardColors( +// containerColor = colors.surface // 卡片背景色 +// ), +// elevation = CardDefaults.cardElevation(defaultElevation = 1.dp), // 卡片阴影(轻微) +// border = BorderStroke(1.dp, colors.border.copy(alpha = 0.5f)), // 卡片边框(轻微) +// content = content // 卡片内容 +// ) +//} +// +//// Helper for styled action/tool buttons +//// 风格化操作/工具按钮辅助 Composable +//@Composable +//fun StyledButton( +// modifier: Modifier = Modifier, // 修饰符 +// icon: ImageVector, // 按钮图标 +// text: String, // 按钮文本 +// onClick: () -> Unit, // 点击事件回调 +// colors: AppThemes.Colors, // 颜色主题 +// enabled: Boolean = true // 按钮是否可用 +//) { +// Button( +// onClick = onClick, +// modifier = modifier, +// enabled = enabled, // 设置按钮是否可用 +// shape = RoundedCornerShape(8.dp), // 按钮形状(圆角) +// colors = ButtonDefaults.buttonColors( +// containerColor = colors.accent.copy(alpha = 0.1f), // 按钮背景色(半透明强调色) +// contentColor = colors.accent, // 按钮内容颜色(强调色) +// disabledContainerColor = colors.border.copy(alpha = 0.1f), // 禁用时背景色 +// disabledContentColor = colors.secondaryText.copy(alpha = 0.7f) // 禁用时内容颜色 +// ), +// border = BorderStroke(1.dp, colors.accent.copy(alpha = 0.3f)), // 按钮边框 +// contentPadding = PaddingValues(horizontal = 16.dp, vertical = 12.dp) // 内容内边距 +// ) { +// Row( // 使用 Row 布局图标和文本 +// verticalAlignment = Alignment.CenterVertically, // 垂直居中 +// horizontalArrangement = Arrangement.spacedBy(8.dp) // 图标和文本之间的间距 +// ) { +// Icon( +// imageVector = icon, +// contentDescription = null, +// modifier = Modifier.size(20.dp) +// ) // 图标 +// Text(text = text, fontSize = 14.sp, fontWeight = FontWeight.Medium) // 文本 +// } +// } +//} +// +// +//@Composable +//fun HomeScreen(colors: AppThemes.Colors) { +// Column( +// modifier = Modifier +// .fillMaxSize() +// .padding(8.dp) +// .verticalScroll(rememberScrollState()), // 添加垂直滚动 +// verticalArrangement = Arrangement.spacedBy(20.dp) +// ) { +// SelectionContainer { // 允许文本选择 +// Text( +// text = "Welcome Back, grtsinry43!", // 个性化欢迎语 +// style = MaterialTheme.typography.headlineSmall.copy( +// color = colors.onBackground, +// fontWeight = FontWeight.Bold +// ) +// ) +// } +// +// // Overview of today's screen time +// // 今日屏幕使用时间概览 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(8.dp) +// ) { +// Text( +// text = "Today's Screen Time", // 今日屏幕使用时间 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// Text( +// text = "3h 45m", // 占位符数据 +// style = MaterialTheme.typography.displaySmall.copy( +// color = colors.accent, +// fontWeight = FontWeight.Bold +// ), +// modifier = Modifier.align(Alignment.CenterHorizontally) +// ) +// Text( +// text = "You're on track with your daily goal!", // 占位符提示 +// style = MaterialTheme.typography.bodyMedium.copy(color = colors.secondaryText), +// modifier = Modifier.align(Alignment.CenterHorizontally) +// ) +// } +// } +// +// +// // Quick Glance: Top Apps Today +// // 快速浏览:今日热门应用 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// Text( +// text = "Quick Glance: Top Apps Today", // 快速浏览:今日热门应用 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// SimpleListItem( +// icon = Icons.Filled.SmartDisplay, +// text = "App A: 1h 15m", +// colors = colors +// ) // 示例应用A +// SimpleListItem( +// icon = Icons.Filled.PhotoCamera, +// text = "App B: 45m", +// colors = colors +// ) // 示例应用B +// SimpleListItem( +// icon = Icons.Filled.Chat, +// text = "App C: 30m", +// colors = colors +// ) // 示例应用C +// } +// } +// +// +// // Quick actions +// // 快捷操作 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(16.dp) +// ) { +// Text( +// text = "Quick Actions", // 快捷操作 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// Row( +// modifier = Modifier.fillMaxWidth(), +// horizontalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// StyledButton( +// modifier = Modifier.weight(1f), +// icon = Icons.Default.HourglassTop, // 专注时段图标 +// text = "Focus Session", // 开始专注时段 +// onClick = { /* TODO: Start focus session */ }, +// colors = colors +// ) +// StyledButton( +// modifier = Modifier.weight(1f), +// icon = Icons.Default.CalendarViewWeek, // 每周报告图标 +// text = "Weekly Report", // 查看每周报告 +// onClick = { /* TODO: Navigate to weekly report */ }, +// colors = colors +// ) +// } +// } +// } +// +// // Recent Alerts/Insights +// // 近期提醒/洞察 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// Text( +// text = "Recent Insights", // 近期洞察 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// ActivityItem( +// title = "You've exceeded your daily goal for App X.", // 应用X超出每日目标 +// time = "Today, 2:30 PM", // 时间 +// icon = Icons.Default.WarningAmber, // 警告图标 +// colors = colors +// ) +// ActivityItem( +// title = "Screen time was 20% higher yesterday.", // 昨日屏幕时间增加20% +// time = "Insight from yesterday", // 时间 +// icon = Icons.Default.TrendingUp, // 趋势向上图标 +// colors = colors +// ) +// } +// } +// } +//} +// +// +//// Placeholder for ActivityItem +//// 活动项占位符 Composable +//@Composable +//fun ActivityItem(title: String, time: String, icon: ImageVector, colors: AppThemes.Colors) { +// Row( +// modifier = Modifier +// .fillMaxWidth() +// .clip(RoundedCornerShape(8.dp)) +// .background(colors.surface.copy(alpha = 0.5f)) // 轻微透明背景 +// .border(1.dp, colors.border.copy(alpha = 0.3f), RoundedCornerShape(8.dp)) // 轻微透明边框 +// .padding(12.dp), +// verticalAlignment = Alignment.CenterVertically, +// horizontalArrangement = Arrangement.spacedBy(16.dp) +// ) { +// Icon( +// imageVector = icon, +// contentDescription = null, +// tint = colors.accent // 图标使用强调色 +// ) +// Column { +// Text( +// text = title, +// fontSize = 15.sp, +// color = colors.onSurface +// ) +// Text( +// text = time, +// fontSize = 13.sp, +// color = colors.secondaryText // 时间使用次要文本颜色 +// ) +// } +// } +//} +// +// +//@Composable +//fun AnalyticsScreen(colors: AppThemes.Colors) { +// var selectedTimeRange by remember { mutableStateOf("Last 7 Days") } // 记住选中的时间范围 +// val timeRanges = +// listOf("Today", "Yesterday", "Last 7 Days", "Last 30 Days", "Custom Range") // 可选时间范围 +// +// Column( +// modifier = Modifier +// .fillMaxSize() +// .padding(8.dp) +// .verticalScroll(rememberScrollState()), // 添加垂直滚动 +// verticalArrangement = Arrangement.spacedBy(20.dp) +// ) { +// Text( +// "Screen Time Analytics", // 屏幕时间分析 +// style = MaterialTheme.typography.headlineSmall.copy( +// color = colors.onBackground, +// fontWeight = FontWeight.Bold // 标题加粗 +// ) +// ) +// +// // Time Range Filter +// // 时间范围筛选器 +// Row( +// verticalAlignment = Alignment.CenterVertically, +// horizontalArrangement = Arrangement.spacedBy(8.dp) +// ) { +// Text( +// "Time Range:", +// style = MaterialTheme.typography.titleSmall.copy(color = colors.onBackground) +// ) // 时间范围标签 +// var expanded by remember { mutableStateOf(false) } // 下拉菜单是否展开 +// Box { +// OutlinedButton( +// onClick = { expanded = true }, +// shape = RoundedCornerShape(8.dp) +// ) { // 点击展开下拉菜单 +// Text(selectedTimeRange, color = colors.accent) // 显示当前选中的时间范围 +// Icon( +// Icons.Default.ArrowDropDown, +// contentDescription = "Select time range", +// tint = colors.accent +// ) // 下拉箭头图标 +// } +// DropdownMenu( // 下拉菜单 +// expanded = expanded, +// onDismissRequest = { expanded = false } // 点击外部关闭下拉菜单 +// ) { +// timeRanges.forEach { range -> +// DropdownMenuItem( +// text = { Text(range) }, +// onClick = { +// selectedTimeRange = range // 更新选中的时间范围 +// expanded = false // 关闭下拉菜单 +// // TODO: Update analytics data based on range // 根据选择的时间范围更新分析数据 +// } +// ) +// } +// } +// } +// } +// +// +// // Key Metrics Cards +// // 关键指标卡片 +// Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { +// MetricCard( +// title = "Total Screen Time", +// value = "25h 10m", +// icon = Icons.Default.Smartphone, +// colors = colors, +// modifier = Modifier.weight(1f) +// ) // 总屏幕时间 +// MetricCard( +// title = "Avg Daily Time", +// value = "3h 35m", +// icon = Icons.Default.AvTimer, +// colors = colors, +// modifier = Modifier.weight(1f) +// ) // 平均每日时间 +// } +// Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) { +// MetricCard( +// title = "Most Used App", +// value = "App A (8h)", +// icon = Icons.Default.StarOutline, +// colors = colors, +// modifier = Modifier.weight(1f) +// ) // 最常用应用 +// MetricCard( +// title = "Pickups", +// value = "75 today", +// icon = Icons.Default.TouchApp, +// colors = colors, +// modifier = Modifier.weight(1f) +// ) // 今日拿起次数 +// } +// +// +// // Charts Section +// // 图表区域 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(16.dp) +// ) { +// Text( +// "Usage Patterns", // 使用模式 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// // Placeholder for Daily/Weekly Screen Time Bar Chart +// // 每日/每周屏幕时间柱状图占位符 +// ChartPlaceholder( +// text = "Daily/Weekly Screen Time (Bar Chart)", +// colors = colors, +// modifier = Modifier.fillMaxWidth().height(200.dp) +// ) +// Spacer(modifier = Modifier.height(16.dp)) +// // Placeholder for App Usage Distribution Pie Chart +// // 应用使用分布饼图占位符 +// ChartPlaceholder( +// text = "App Usage Distribution (Pie Chart)", +// colors = colors, +// modifier = Modifier.fillMaxWidth().height(200.dp) +// ) +// } +// } +// +// // Analysis Tools +// // 分析工具 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(16.dp) +// ) { +// Text( +// "Analysis Tools", // 分析工具 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// Row( +// modifier = Modifier.fillMaxWidth(), +// horizontalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// StyledButton( +// modifier = Modifier.weight(1f), +// icon = Icons.Default.PieChartOutline, // 应用细分图标 +// text = "App Breakdown", // 应用细分 +// onClick = { /* TODO */ }, +// colors = colors +// ) +// StyledButton( +// modifier = Modifier.weight(1f), +// icon = Icons.Default.AccessTime, // 时间段图标 +// text = "Time of Day", // 按时间段分析 +// onClick = { /* TODO */ }, +// colors = colors +// ) +// } +// Row( +// modifier = Modifier.fillMaxWidth(), +// horizontalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// StyledButton( +// modifier = Modifier.weight(1f), +// icon = Icons.Default.TrackChanges, // 使用目标图标 +// text = "Usage Goals", // 使用目标 +// onClick = { /* TODO */ }, +// colors = colors +// ) +// StyledButton( +// modifier = Modifier.weight(1f), +// icon = Icons.Default.CompareArrows, // 比较时段图标 +// text = "Compare Periods", // 比较时段 +// onClick = { /* TODO */ }, +// colors = colors +// ) +// } +// } +// } +// } +//} +// +//@Composable +//fun MetricCard( +// title: String, +// value: String, +// icon: ImageVector, +// colors: AppThemes.Colors, +// modifier: Modifier = Modifier +//) { +// StyledCard(colors = colors, modifier = modifier) { // 指标卡片 +// Column( +// modifier = Modifier.padding(16.dp), +// horizontalAlignment = Alignment.CenterHorizontally, // 水平居中 +// verticalArrangement = Arrangement.spacedBy(8.dp) // 垂直间距 +// ) { +// Icon( +// imageVector = icon, +// contentDescription = title, +// tint = colors.accent, +// modifier = Modifier.size(32.dp) +// ) // 指标图标 +// Text( +// text = title, +// style = MaterialTheme.typography.labelLarge.copy(color = colors.secondaryText), +// textAlign = TextAlign.Center +// ) // 指标标题 +// Text( +// text = value, +// style = MaterialTheme.typography.titleLarge.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.Bold +// ), +// textAlign = TextAlign.Center +// ) // 指标值 +// } +// } +//} +// +//@Composable +//fun ChartPlaceholder(text: String, colors: AppThemes.Colors, modifier: Modifier = Modifier) { +// Box( // 图表占位符 +// modifier = modifier +// .background(colors.background.copy(alpha = 0.5f), RoundedCornerShape(8.dp)) // 半透明背景和圆角 +// .border(1.dp, colors.border, RoundedCornerShape(8.dp)) // 边框和圆角 +// .padding(16.dp), +// contentAlignment = Alignment.Center // 内容居中 +// ) { +// Text( +// text = text, // 占位符文本 +// color = colors.secondaryText, // 文本颜色 +// style = MaterialTheme.typography.bodyMedium, // 文本样式 +// textAlign = TextAlign.Center // 文本居中对齐 +// ) +// } +//} +// +// +//@Composable +//fun ReportsScreen(colors: AppThemes.Colors) { +// Column( +// modifier = Modifier +// .fillMaxSize() +// .padding(8.dp) +// .verticalScroll(rememberScrollState()), // 添加垂直滚动 +// verticalArrangement = Arrangement.spacedBy(20.dp) +// ) { +// Row( +// modifier = Modifier.fillMaxWidth(), +// horizontalArrangement = Arrangement.SpaceBetween, // 两端对齐 +// verticalAlignment = Alignment.CenterVertically // 垂直居中 +// ) { +// Text( +// "Screen Time Reports", // 屏幕时间报告 +// style = MaterialTheme.typography.headlineSmall.copy( +// color = colors.onBackground, +// fontWeight = FontWeight.Bold // 标题加粗 +// ) +// ) +// StyledButton( +// icon = Icons.Default.Addchart, // 生成报告图标 +// text = "Generate New Report", // 生成新报告 +// onClick = { /* TODO: Open report generation dialog */ }, // 打开报告生成对话框 +// colors = colors +// ) +// } +// +// +// StyledCard(colors = colors) { // 已生成报告列表卡片 +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(4.dp) // 列表项之间的紧凑间距 +// ) { +// Text( +// "Generated Reports", // 已生成报告 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ), +// modifier = Modifier.padding(bottom = 8.dp) // 标题下方间距 +// ) +// ReportItem( // 报告项示例1 +// title = "Weekly Summary - May 5-11, 2025", // 每周总结 +// period = "Generated: May 12, 2025", // 生成日期 +// icon = Icons.Default.CalendarToday, // 日历图标 +// colors = colors, +// onDownload = { /* TODO */ }, // 下载回调 +// onView = { /* TODO */ } // 查看回调 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) // 分隔线 +// ReportItem( // 报告项示例2 +// title = "Monthly App Usage - April 2025", // 每月应用使用情况 +// period = "Generated: May 1, 2025", // 生成日期 +// icon = Icons.Default.PieChart, // 饼图图标 +// colors = colors, +// onDownload = { /* TODO */ }, +// onView = { /* TODO */ } +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// ReportItem( // 报告项示例3 +// title = "Q1 Device Pickup Analysis", // Q1设备拿起分析 +// period = "Generated: April 5, 2025", // 生成日期 +// icon = Icons.Default.TouchApp, // 触摸应用图标 +// colors = colors, +// onDownload = { /* TODO */ }, +// onView = { /* TODO */ } +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// ReportItem( // 报告项示例4 +// title = "Focus Session Report - Project X", // 专注时段报告 - 项目X +// period = "Generated: May 10, 2025", // 生成日期 +// icon = Icons.Default.HourglassEmpty, // 沙漏图标 +// colors = colors, +// onDownload = { /* TODO */ }, +// onView = { /* TODO */ } +// ) +// } +// } +// // Placeholder if no reports +// // 如果没有报告,显示占位符 +// // Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { +// // Text("No reports generated yet.", color = colors.secondaryText, style = MaterialTheme.typography.bodyLarge) +// // } +// } +//} +// +//@Composable +//fun ReportItem( +// title: String, // 报告标题 +// period: String, // 报告周期或生成日期 +// icon: ImageVector, // 报告图标 +// colors: AppThemes.Colors, // 颜色主题 +// onDownload: () -> Unit, // 下载回调 +// onView: () -> Unit // 查看回调 +//) { +// Row( +// modifier = Modifier +// .fillMaxWidth() +// .clip(RoundedCornerShape(6.dp)) // 轻微圆角 +// .padding(vertical = 12.dp, horizontal = 8.dp), // 内边距 +// verticalAlignment = Alignment.CenterVertically // 垂直居中 +// ) { +// Icon( +// imageVector = icon, +// contentDescription = null, +// tint = colors.accent, // 图标使用强调色 +// modifier = Modifier.size(28.dp) // 图标大小 +// ) +// Spacer(modifier = Modifier.width(16.dp)) // 图标和文本之间的间距 +// Column(modifier = Modifier.weight(1f)) { // 文本列,占据剩余空间 +// Text( +// text = title, +// fontSize = 15.sp, +// color = colors.onSurface, +// fontWeight = FontWeight.Medium +// ) +// Text( +// text = period, +// fontSize = 13.sp, +// color = colors.secondaryText // 副标题使用次要文本颜色 +// ) +// } +// Spacer(modifier = Modifier.width(8.dp)) // 文本和按钮之间的间距 +// IconButton(onClick = onView, modifier = Modifier.size(36.dp)) { // 查看按钮,更大的点击区域 +// Icon( +// imageVector = Icons.Default.Visibility, // 查看图标 +// contentDescription = "View Report", // 内容描述 +// tint = colors.accentVariant // 图标使用强调色的变体 +// ) +// } +// IconButton(onClick = onDownload, modifier = Modifier.size(36.dp)) { // 下载按钮 +// Icon( +// imageVector = Icons.Default.Download, // 下载图标 +// contentDescription = "Download Report", // 内容描述 +// tint = colors.accentVariant +// ) +// } +// } +//} +// +//@Composable +//fun ProfileScreen(colors: AppThemes.Colors) { +// var nickname by remember { mutableStateOf("grtsinry43") } // 记住用户昵称 +// var email by remember { mutableStateOf("grtsinry43@outlook.com") } // 记住用户邮箱 (占位符) +// +// Column( +// modifier = Modifier +// .fillMaxSize() +// .padding(8.dp) +// .verticalScroll(rememberScrollState()), // 添加垂直滚动 +// verticalArrangement = Arrangement.spacedBy(20.dp) +// ) { +// Text( +// "User Profile", // 用户个人资料 +// style = MaterialTheme.typography.headlineSmall.copy( +// color = colors.onBackground, +// fontWeight = FontWeight.Bold // 标题加粗 +// ) +// ) +// +// // Profile Details Card +// // 个人资料详情卡片 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// horizontalAlignment = Alignment.CenterHorizontally, // 水平居中 +// verticalArrangement = Arrangement.spacedBy(16.dp) // 垂直间距 +// ) { +// Icon( +// imageVector = Icons.Filled.AccountCircle, // 用户头像图标 +// contentDescription = "User Avatar", // 内容描述 +// tint = colors.accent, // 图标颜色 +// modifier = Modifier.size(100.dp) // 图标大小 +// ) +// // TODO: Add option to change avatar // 添加更换头像的选项 +// +// OutlinedTextField( // 昵称输入框 +// value = nickname, +// onValueChange = { nickname = it }, +// label = { Text("Nickname") }, // 标签:昵称 +// singleLine = true, // 单行输入 +// modifier = Modifier.fillMaxWidth(), +// colors = OutlinedTextFieldDefaults.colors( // 自定义输入框颜色 +// focusedBorderColor = colors.accent, +// unfocusedBorderColor = colors.border, +// focusedLabelColor = colors.accent, +// cursorColor = colors.accent +// ) +// ) +// OutlinedTextField( // 邮箱输入框 +// value = email, +// onValueChange = { email = it }, +// label = { Text("Email") }, // 标签:邮箱 +// singleLine = true, +// modifier = Modifier.fillMaxWidth(), +// colors = OutlinedTextFieldDefaults.colors( +// focusedBorderColor = colors.accent, +// unfocusedBorderColor = colors.border, +// focusedLabelColor = colors.accent, +// cursorColor = colors.accent +// ) +// ) +// StyledButton( // 保存更改按钮 +// icon = Icons.Default.Save, // 保存图标 +// text = "Save Changes", // 保存更改 +// onClick = { /* TODO: Save profile changes */ }, // 保存个人资料更改 +// colors = colors, +// modifier = Modifier.fillMaxWidth(0.6f) +// .align(Alignment.CenterHorizontally) // 按钮宽度为父容器的60%,并居中 +// ) +// } +// } +// +// // Overall Statistics Card +// // 总体统计数据卡片 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// Text( +// "Overall Statistics", // 总体统计 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// SimpleListItem( +// icon = Icons.Filled.Timer, +// text = "Total Time Tracked: 1250 hours", +// colors = colors +// ) // 总追踪时间 +// SimpleListItem( +// icon = Icons.Filled.CheckCircleOutline, +// text = "Goals Met Streak: 15 days", +// colors = colors +// ) // 目标达成连胜天数 +// SimpleListItem( +// icon = Icons.Filled.EventAvailable, +// text = "Joined: January 1, 2024", +// colors = colors +// ) // 加入日期 +// } +// } +// +// // Account Actions +// // 账户操作卡片 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// Text( +// "Account Actions", // 账户操作 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ) +// ) +// StyledButton( // 更改密码按钮 +// icon = Icons.Default.LockReset, // 重置锁定图标 +// text = "Change Password", // 更改密码 +// onClick = { /* TODO */ }, +// colors = colors, +// modifier = Modifier.fillMaxWidth() +// ) +// StyledButton( // 删除账户按钮 +// icon = Icons.Default.DeleteForever, // 永久删除图标 +// text = "Delete Account", // 删除账户 +// onClick = { /* TODO: Show confirmation dialog */ }, // 显示确认对话框 +// colors = AppThemes.Colors( // 为删除按钮使用警示性颜色主题 +// background = colors.background, +// surface = colors.surface, +// onSurface = colors.onSurface, +// onBackground = colors.onBackground, +// accent = Color.Red.copy(alpha = 0.7f), // 红色强调色 +// accentVariant = Color.Red, +// border = colors.border, +// secondaryText = colors.secondaryText, +// onAccent = Color.White +// ), +// modifier = Modifier.fillMaxWidth() +// ) +// } +// } +// } +//} +// +//@Composable +//fun SettingsScreen( +// colors: AppThemes.Colors, // 颜色主题 +// isDarkTheme: Boolean, // 当前是否为暗色主题 +// onThemeChange: (Boolean) -> Unit // 主题更改回调 +//) { +// var autoBackupEnabled by remember { mutableStateOf(true) } // 自动备份是否启用 +// var notificationsEnabled by remember { mutableStateOf(true) } // 通知是否启用 +// var selectedTrackingApps by remember { mutableStateOf("All Apps") } // 选中的追踪应用 (示例状态) +// var trackingSensitivity by remember { mutableStateOf("Medium") } // 追踪灵敏度 (示例状态) +// +// +// Column( +// modifier = Modifier +// .fillMaxSize() +// .padding(8.dp) +// .verticalScroll(rememberScrollState()), // 添加垂直滚动,因为设置项可能很多 +// verticalArrangement = Arrangement.spacedBy(20.dp) +// ) { +// Text( +// "Application Settings", // 应用设置 +// style = MaterialTheme.typography.headlineSmall.copy( +// color = colors.onBackground, +// fontWeight = FontWeight.Bold // 标题加粗 +// ) +// ) +// +// // General Settings +// // 常规设置卡片 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(4.dp) // 设置项之间的紧凑间距 +// ) { +// Text( +// "General", // 常规 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ), +// modifier = Modifier.padding(bottom = 8.dp) // 组标题下方间距 +// ) +// SettingItem( // 暗色主题切换 +// title = "Dark Theme", // 暗色主题 +// subtitle = if (isDarkTheme) "Enabled" else "Disabled", // 已启用/已禁用 +// icon = Icons.Default.Brightness6, // 亮度图标 +// colors = colors, +// showSwitch = true, // 显示切换开关 +// switchChecked = isDarkTheme, // 开关状态 +// onSwitchChange = onThemeChange // 开关切换回调 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) // 分隔线 +// SettingItem( // 数据存储位置 +// title = "Data Storage Location", // 数据存储位置 +// subtitle = "/Users/grtsinry43/Documents/ActivityAnalyzer", // 示例路径 +// icon = Icons.Default.FolderOpen, // 打开文件夹图标 +// colors = colors, +// onClick = { /* TODO: Open file dialog or path editor */ } // 打开文件对话框或路径编辑器 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 自动备份 +// title = "Auto Backup", // 自动备份 +// subtitle = if (autoBackupEnabled) "Daily at 2:00 AM" else "Disabled", // 每日凌晨2点/已禁用 +// icon = Icons.Default.SaveAlt, // 保存图标 +// colors = colors, +// showSwitch = true, +// switchChecked = autoBackupEnabled, +// onSwitchChange = { autoBackupEnabled = it } +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 云同步 +// title = "Cloud Sync", // 云同步 +// subtitle = "Not Connected", // 未连接 (占位符) +// icon = Icons.Default.CloudQueue, // 云队列图标 +// colors = colors, +// onClick = { /* TODO: Cloud sync setup */ } // 云同步设置 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 导出数据 +// title = "Export Data", // 导出数据 +// subtitle = "Export your activity data (CSV, JSON)", // 导出活动数据 (CSV, JSON) +// icon = Icons.Default.Output, // 输出图标 +// colors = colors, +// onClick = { /* TODO: Data export options */ } // 数据导出选项 +// ) +// } +// } +// +// // Tracking Settings +// // 追踪设置卡片 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(4.dp) +// ) { +// Text( +// "Tracking", // 追踪 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ), +// modifier = Modifier.padding(bottom = 8.dp) +// ) +// SettingItem( // 要追踪的应用 +// title = "Apps to Track", // 要追踪的应用 +// subtitle = selectedTrackingApps, // 当前选中的应用 +// icon = Icons.Default.AppBlocking, // 应用阻止图标 (或类似) +// colors = colors, +// onClick = { /* TODO: Open app selection dialog */ } // 打开应用选择对话框 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 追踪灵敏度 +// title = "Tracking Sensitivity", // 追踪灵敏度 +// subtitle = "Ignore app opens shorter than: $trackingSensitivity", // 忽略短于...的应用打开 (示例) +// icon = Icons.Default.Tune, // 调整图标 +// colors = colors, +// onClick = { /* TODO: Open sensitivity options */ } // 打开灵敏度选项 +// ) +// } +// } +// +// +// // Notification Settings +// // 通知设置卡片 +// StyledCard(colors = colors) { +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(4.dp) +// ) { +// Text( +// "Notifications", // 通知 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ), +// modifier = Modifier.padding(bottom = 8.dp) +// ) +// SettingItem( // 屏幕时间限制通知 +// title = "Screen Time Limits", // 屏幕时间限制 +// subtitle = "Notify when daily/app limits exceeded", // 超出每日/应用限制时通知 +// icon = Icons.Default.NotificationsActive, // 活动通知图标 +// colors = colors, +// showSwitch = true, +// switchChecked = notificationsEnabled, // 假设此开关控制所有通知 +// onSwitchChange = { notificationsEnabled = it } +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 休息提醒 +// title = "Break Reminders", // 休息提醒 +// subtitle = "Get reminded to take breaks", // 获取休息提醒 +// icon = Icons.Default.SelfImprovement, // 自我提升/休息图标 +// colors = colors, +// onClick = { /* TODO: Configure break reminders */ } // 配置休息提醒 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 每周总结通知 +// title = "Weekly Summary Notification", // 每周总结通知 +// subtitle = "Receive a summary every Monday", // 每周一接收总结 +// icon = Icons.Default.MarkEmailRead, // 已读邮件图标 +// colors = colors, +// showSwitch = true, +// switchChecked = true, // 占位符 +// onSwitchChange = { /* TODO */ } +// ) +// } +// } +// } +//} +// +//@Composable +//fun AboutScreen(colors: AppThemes.Colors) { +// Column( +// modifier = Modifier +// .fillMaxSize() +// .padding(16.dp) +// .verticalScroll(rememberScrollState()), // 添加垂直滚动 +// verticalArrangement = Arrangement.spacedBy(20.dp), // 垂直间距 +// horizontalAlignment = Alignment.CenterHorizontally // 水平居中 +// ) { +// Icon( +// imageVector = Icons.Filled.Analytics, // 应用图标 +// contentDescription = "App Logo", // 内容描述 +// tint = colors.accent, // 图标颜色 +// modifier = Modifier.size(80.dp) // 图标大小 +// ) +// Text( +// "Activity Analyzer", // 应用名称 +// style = MaterialTheme.typography.headlineMedium.copy( +// color = colors.onBackground, +// fontWeight = FontWeight.Bold +// ) +// ) +// Text( +// "Version 1.0.0-beta", // 版本号 (从设置页移至此) +// style = MaterialTheme.typography.titleMedium.copy(color = colors.secondaryText) +// ) +// +// Spacer(modifier = Modifier.height(8.dp)) // 间距 +// +// StyledCard(colors = colors) { // 应用描述卡片 +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// Text( +// "Your personal screen time companion, helping you understand and manage your digital habits across platforms.", // 应用描述 +// style = MaterialTheme.typography.bodyLarge.copy(color = colors.onSurface), +// textAlign = TextAlign.Center // 文本居中 +// ) +// } +// } +// +// +// StyledCard(colors = colors) { // 开发者信息卡片 +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(4.dp) +// ) { +// Text( +// "Developer", // 开发者 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ), +// modifier = Modifier.padding(bottom = 8.dp) +// ) +// InfoItem(icon = Icons.Filled.Person, text = "grtsinry43", colors = colors) // 开发者昵称 +// Divider(color = colors.border.copy(alpha = 0.3f)) +// InfoItem( +// icon = Icons.Filled.Email, +// text = "grtsinry43@outlook.com", +// colors = colors, +// isLink = true, +// linkUrl = "mailto:grtsinry43@outlook.com" +// ) // 开发者邮箱 (可点击) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// InfoItem( +// icon = Icons.Filled.Language, +// text = "blog.grtsinry43.com", +// colors = colors, +// isLink = true, +// linkUrl = "https://blog.grtsinry43.com" +// ) // 开发者博客 (可点击) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// InfoItem( +// icon = Icons.Filled.Code, +// text = "github.com/grtsinry43", +// colors = colors, +// isLink = true, +// linkUrl = "https://github.com/grtsinry43" +// ) // 开发者 GitHub (可点击) +// } +// } +// +// StyledCard(colors = colors) { // 应用信息卡片 +// Column( +// modifier = Modifier.padding(16.dp), +// verticalArrangement = Arrangement.spacedBy(4.dp) +// ) { +// Text( +// "Application Info", // 应用信息 +// style = MaterialTheme.typography.titleMedium.copy( +// color = colors.onSurface, +// fontWeight = FontWeight.SemiBold +// ), +// modifier = Modifier.padding(bottom = 8.dp) +// ) +// SettingItem( // 检查更新 (复用 SettingItem) +// title = "Check for Updates", // 检查更新 +// subtitle = "Last checked: Today", // 上次检查时间 (占位符) +// icon = Icons.Default.SystemUpdateAlt, // 系统更新图标 +// colors = colors, +// onClick = { /* TODO: Implement update check */ } // 实现更新检查逻辑 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 致谢 +// title = "Acknowledgements", // 致谢 +// subtitle = "Libraries and resources used", // 使用的库和资源 +// icon = Icons.Default.FavoriteBorder, // 爱心边框图标 +// colors = colors, +// onClick = { /* TODO: Show acknowledgements dialog/screen */ } // 显示致谢对话框/屏幕 +// ) +// Divider(color = colors.border.copy(alpha = 0.3f)) +// SettingItem( // 许可证信息 +// title = "License Information", // 许可证信息 +// subtitle = "View application license", // 查看应用许可证 +// icon = Icons.Default.Gavel, // 法槌图标 (代表法律/许可) +// colors = colors, +// onClick = { /* TODO: Show license */ } // 显示许可证 +// ) +// } +// } +// Spacer(modifier = Modifier.weight(1f)) // 弹性空间,将版权信息推到底部 +// Text( +// "© 2025 grtsinry43. All rights reserved.", // 版权信息 +// style = MaterialTheme.typography.bodySmall.copy(color = colors.secondaryText), +// textAlign = TextAlign.Center, +// modifier = Modifier.padding(bottom = 8.dp) +// ) +// } +//} +// +// +//@Composable +//fun SettingItem( +// title: String, // 设置项标题 +// subtitle: String, // 设置项副标题/当前值 +// icon: ImageVector, // 设置项图标 +// colors: AppThemes.Colors, // 颜色主题 +// onClick: (() -> Unit)? = null, // 点击事件回调 (如果不是开关类型) +// showSwitch: Boolean = false, // 是否显示为切换开关 +// switchChecked: Boolean = false, // 开关当前状态 +// onSwitchChange: ((Boolean) -> Unit)? = null // 开关状态改变回调 +//) { +// Row( +// modifier = Modifier +// .fillMaxWidth() +// .clip(RoundedCornerShape(6.dp)) // 轻微圆角 +// .clickable( +// enabled = onClick != null && !showSwitch, +// onClick = onClick ?: {}) // 如果可点击且不是开关,则启用点击 +// .padding(vertical = 12.dp, horizontal = 8.dp), // 内边距 +// verticalAlignment = Alignment.CenterVertically // 垂直居中 +// ) { +// Icon( +// imageVector = icon, +// contentDescription = null, +// tint = colors.accentVariant, // 图标使用强调色的变体 +// modifier = Modifier.size(26.dp) // 图标大小 +// ) +// Spacer(modifier = Modifier.width(16.dp)) // 图标和文本之间的间距 +// Column(modifier = Modifier.weight(1f)) { // 文本列,占据剩余空间 +// Text( +// text = title, +// fontSize = 15.sp, +// color = colors.onSurface, +// fontWeight = FontWeight.Medium +// ) +// Text( +// text = subtitle, +// fontSize = 13.sp, +// color = colors.secondaryText // 副标题使用次要文本颜色 +// ) +// } +// Spacer(modifier = Modifier.width(8.dp)) // 文本和右侧控件之间的间距 +// if (showSwitch && onSwitchChange != null) { // 如果是开关类型 +// Switch( +// checked = switchChecked, +// onCheckedChange = onSwitchChange, +// colors = SwitchDefaults.colors( // 自定义开关颜色 +// checkedThumbColor = colors.accent, +// checkedTrackColor = colors.accent.copy(alpha = 0.5f), +// uncheckedThumbColor = colors.secondaryText, +// uncheckedTrackColor = colors.border.copy(alpha = 0.5f) +// ), +// modifier = Modifier.size(40.dp) // 确保开关不会太大 +// ) +// } else if (onClick != null && !showSwitch) { // 如果是可点击项 (非开关) +// Icon( +// imageVector = Icons.Default.ChevronRight, // 右箭头图标,表示可导航 +// contentDescription = "Go to setting", // 内容描述 +// tint = colors.secondaryText // 图标颜色 +// ) +// } +// } +//} +// +//// Simple list item for Home screen quick glance or Profile stats +//// 用于主屏幕快速浏览或个人资料统计的简单列表项 +//@Composable +//fun SimpleListItem(icon: ImageVector, text: String, colors: AppThemes.Colors) { +// Row( +// verticalAlignment = Alignment.CenterVertically, +// horizontalArrangement = Arrangement.spacedBy(12.dp) +// ) { +// Icon( +// imageVector = icon, +// contentDescription = null, +// tint = colors.accentVariant, +// modifier = Modifier.size(20.dp) +// ) // 图标 +// Text(text, style = MaterialTheme.typography.bodyMedium.copy(color = colors.onSurface)) // 文本 +// } +//} +// +//// Info item for About screen (can be a link) +//// 用于“关于”屏幕的信息项 (可以是链接) +//@Composable +//fun InfoItem( +// icon: ImageVector, +// text: String, +// colors: AppThemes.Colors, +// isLink: Boolean = false, +// linkUrl: String? = null +//) { +// // val uriHandler = LocalUriHandler.current // Needed for opening links // 打开链接需要 LocalUriHandler +// Row( +// modifier = Modifier +// .fillMaxWidth() +// .clip(RoundedCornerShape(6.dp)) +// .clickable(enabled = isLink && linkUrl != null, onClick = { // 如果是链接且URL不为空,则启用点击 +// if (isLink && linkUrl != null) { +// // uriHandler.openUri(linkUrl) // TODO: Requires LocalUriHandler, handle platform-specific link opening // 处理平台特定的链接打开方式 +// } +// }) +// .padding(vertical = 10.dp, horizontal = 8.dp), +// verticalAlignment = Alignment.CenterVertically +// ) { +// Icon( +// imageVector = icon, +// contentDescription = null, +// tint = colors.accentVariant, +// modifier = Modifier.size(24.dp) +// ) +// Spacer(modifier = Modifier.width(16.dp)) +// Text( +// text = text, +// fontSize = 15.sp, +// color = if (isLink) colors.accent else colors.onSurface, // 链接文本使用强调色 +// fontWeight = FontWeight.Medium +// ) +// } +//} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/main.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/main.kt index bc42181..5e27ecf 100644 --- a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/main.kt +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/main.kt @@ -1,13 +1,120 @@ package com.grtsinry43.activityanalyzer -import androidx.compose.ui.window.Window -import androidx.compose.ui.window.application +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Analytics // 用一个合适的图标作为托盘图标 +import androidx.compose.material3.Icon +import androidx.compose.runtime.* +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.compose.ui.graphics.toComposeImageBitmap +import androidx.compose.ui.res.loadImageBitmap +import androidx.compose.ui.res.useResource +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.* +import java.awt.image.BufferedImage +import javax.imageio.ImageIO + fun main() = application { - Window( - onCloseRequest = ::exitApplication, - title = "Activity Analyzer", - ) { - DesktopApp() + // 管理窗口状态,例如可见性、位置、大小 + val windowState = rememberWindowState( + size = DpSize(1024.dp, 768.dp), // 设置窗口的初始大小 +// position = WindowPosition(Win) // 初始位置居中 + ) + + // 管理托盘状态 + val trayState = rememberTrayState() + var isWindowVisible by remember { mutableStateOf(true) } // 控制窗口是否可见 + + // 尝试加载自定义托盘图标 (推荐使用 .ico 或 .png) + // 请将 "tray_icon.png" 替换为你的图标文件名,并确保它在 resources 目录下 + // 如果加载失败,则使用默认图标 + val trayIconPainter = try { + useResource("tray_icon.png") { stream -> + BitmapPainter(loadImageBitmap(stream)) + } + } catch (e: Exception) { + println("警告:无法加载自定义托盘图标 'tray_icon.png'。将使用默认图标。错误: ${e.message}") + null // 稍后会处理 null 情况 } + + // 系统托盘设置 + // 只有当窗口第一次变为不可见时,或者托盘图标加载成功时,才显示托盘图标 + // 这样可以避免在没有图标的情况下尝试创建托盘 + if (!isWindowVisible || trayIconPainter != null) { + Tray( + state = trayState, + icon = trayIconPainter ?: BitmapPainter(createDefaultTrayIcon()), // 如果自定义图标加载失败,使用一个备用图标 + tooltip = "Activity Analyzer", // 鼠标悬停在托盘图标上时显示的提示文字 + menu = { + // 托盘菜单项 + Item( + if (isWindowVisible) "隐藏窗口" else "显示窗口", + onClick = { + isWindowVisible = !isWindowVisible + if (isWindowVisible) { + windowState.isMinimized = false // 如果窗口被最小化了,恢复它 + } + } + ) + Separator() // 分隔线 + Item( + "退出应用", + onClick = ::exitApplication // 点击后退出整个应用 + ) + } + ) + } + + + // 主窗口设置 + if (isWindowVisible) { + Window( + onCloseRequest = { + // 点击关闭按钮时,可以选择隐藏到托盘而不是直接退出 + isWindowVisible = false + // 或者,如果你希望点击关闭直接退出应用,则使用: + // exitApplication() + }, + state = windowState, // 应用窗口状态 + title = "Activity Analyzer", + resizable = true, // 允许用户调整窗口大小 (默认为 true) + // icon = painterResource("app_icon.png") // 可选:设置窗口左上角的图标和任务栏图标 + ) { + // 在这里设置窗口的最小尺寸 + // 这会影响用户能将窗口缩小到的最小程度 + window.minimumSize = java.awt.Dimension(600, 400) + + // 你之前创建的 DesktopApp UI + // Assuming DesktopApp is a Composable function defined elsewhere + DesktopApp() + } + } +} + +// 创建一个简单的默认托盘图标 (如果自定义图标加载失败) +// 这是一个备选方案,实际项目中强烈建议使用合适的图片资源 +private fun createDefaultTrayIcon(): ImageBitmap { // Change return type to ImageBitmap + // 使用 Compose 图标作为示例,实际中你应该加载一个图像文件 + // 这里我们创建一个简单的 BufferedImage 代替 + val width = 64 + val height = 64 + val image = BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB) + val g = image.createGraphics() + try { + // 简单绘制一个蓝色方块作为示例 + g.color = java.awt.Color.BLUE + g.fillRect(0, 0, width, height) + g.color = java.awt.Color.WHITE + g.drawString("AA", 20, 40) // "Activity Analyzer" 缩写 + } finally { + g.dispose() + } + // Convert BufferedImage to ImageBitmap before returning + return image.toComposeImageBitmap() } \ No newline at end of file