diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt index 13ab8b6..97f6c2d 100644 --- a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/App.kt @@ -18,48 +18,15 @@ 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 com.grtsinry43.activityanalyzer.screens.MobileAboutScreen +import com.grtsinry43.activityanalyzer.screens.MobileAnalyticsScreen +import com.grtsinry43.activityanalyzer.screens.MobileHomeScreen +import com.grtsinry43.activityanalyzer.screens.MobileProfileScreen +import com.grtsinry43.activityanalyzer.screens.MobileReportsScreen +import com.grtsinry43.activityanalyzer.screens.MobileSettingsScreen +import com.grtsinry43.activityanalyzer.theme.AppThemes import kotlinx.coroutines.launch -// --- 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 @ExperimentalMaterial3Api @@ -223,1130 +190,3 @@ fun App() { } } } - -// --- 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/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ActivityItemC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ActivityItemC.kt new file mode 100644 index 0000000..78aef5e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ActivityItemC.kt @@ -0,0 +1,81 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Info +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } + } +} + +@Preview +@Composable +fun ActivityItemPreview() { + MaterialTheme { + ActivityItem( + title = "Sample Activity", + time = "10:00 AM", + icon = Icons.Default.Info, + colors = AppThemes.LightThemeColors + ) + } +} + +@Preview +@Composable +fun ActivityItemDarkPreview() { + MaterialTheme { + ActivityItem( + title = "Sample Activity (Dark)", + time = "10:00 AM", + icon = Icons.Default.Info, + colors = AppThemes.DarkThemeColors + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ChartPlaceholderC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ChartPlaceholderC.kt new file mode 100644 index 0000000..29cf698 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ChartPlaceholderC.kt @@ -0,0 +1,60 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } +} + +@Preview +@Composable +fun ChartPlaceholderPreview() { + MaterialTheme { + ChartPlaceholder( + text = "Sample Chart Placeholder", + colors = AppThemes.LightThemeColors, + modifier = Modifier.fillMaxWidth().height(200.dp) + ) + } +} + +@Preview +@Composable +fun ChartPlaceholderDarkPreview() { + MaterialTheme { + ChartPlaceholder( + text = "Sample Chart Placeholder (Dark)", + colors = AppThemes.DarkThemeColors, + modifier = Modifier.fillMaxWidth().height(200.dp) + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/InfoItemC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/InfoItemC.kt new file mode 100644 index 0000000..1999093 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/InfoItemC.kt @@ -0,0 +1,95 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Info +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@Composable +fun InfoItem( + icon: ImageVector, + text: String, + colors: AppThemes.Colors, + isLink: Boolean = false, + linkUrl: String? = null, // Not used in preview, but kept for component signature + onClick: (() -> Unit)? = null +) { + 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) */ } // Link opening logic removed for preview + }) + .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 + ) + } +} + +@Preview +@Composable +fun InfoItemPreview() { + MaterialTheme { + InfoItem( + icon = Icons.Default.Info, + text = "This is an informational item.", + colors = AppThemes.LightThemeColors + ) + } +} + +@Preview +@Composable +fun InfoItemLinkPreview() { + MaterialTheme { + InfoItem( + icon = Icons.Default.Info, + text = "This is a clickable link item.", + colors = AppThemes.LightThemeColors, + isLink = true, + linkUrl = "https://example.com", + onClick = {} + ) + } +} + +@Preview +@Composable +fun InfoItemDarkPreview() { + MaterialTheme { + InfoItem( + icon = Icons.Default.Info, + text = "This is an informational item (Dark).", + colors = AppThemes.DarkThemeColors + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/MetricCardC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/MetricCardC.kt new file mode 100644 index 0000000..aace9a2 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/MetricCardC.kt @@ -0,0 +1,80 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Star +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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 com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } + } +} + +@Preview +@Composable +fun MetricCardPreview() { + MaterialTheme { + MetricCard( + title = "Total Users", + value = "1,234", + icon = Icons.Default.Star, + colors = AppThemes.LightThemeColors + ) + } +} + +@Preview +@Composable +fun MetricCardDarkPreview() { + MaterialTheme { + MetricCard( + title = "Active Sessions (Dark)", + value = "56", + icon = Icons.Default.Star, // Placeholder + colors = AppThemes.DarkThemeColors + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ReportItemC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ReportItemC.kt new file mode 100644 index 0000000..fb5cb9a --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/ReportItemC.kt @@ -0,0 +1,98 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.Visibility +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } + } +} + +@Preview +@Composable +fun ReportItemPreview() { + MaterialTheme { + ReportItem( + title = "Weekly Summary", + period = "May 5 - May 11", + icon = Icons.Default.Edit, // Changed to avoid conflict with other previews + colors = AppThemes.LightThemeColors, + onDownload = {}, + onView = {} + ) + } +} + +@Preview +@Composable +fun ReportItemDarkPreview() { + MaterialTheme { + ReportItem( + title = "Monthly Summary (Dark)", + period = "April 2024", + icon = Icons.Default.Visibility, // Changed to avoid conflict + colors = AppThemes.DarkThemeColors, + onDownload = {}, + onView = {} + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/SettingItemC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/SettingItemC.kt new file mode 100644 index 0000000..5affdd2 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/SettingItemC.kt @@ -0,0 +1,136 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ChevronRight +import androidx.compose.material.icons.filled.Settings +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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) + ) + } + } +} + +@Preview +@Composable +fun SettingItemPreview() { + MaterialTheme { + SettingItem( + title = "Display Settings", + subtitle = "Configure screen brightness and theme", + icon = Icons.Default.Settings, + colors = AppThemes.LightThemeColors, + onClick = {} + ) + } +} + +@Preview +@Composable +fun SettingItemWithSwitchPreview() { + MaterialTheme { + SettingItem( + title = "Enable Notifications", + subtitle = "Receive updates and alerts", + icon = Icons.Default.Settings, // Placeholder + colors = AppThemes.LightThemeColors, + showSwitch = true, + switchChecked = true, + onSwitchChange = {} + ) + } +} + +@Preview +@Composable +fun SettingItemDarkPreview() { + MaterialTheme { + SettingItem( + title = "Storage Settings (Dark)", + subtitle = "Manage local and cloud storage", + icon = Icons.Default.Settings, // Placeholder + colors = AppThemes.DarkThemeColors, + onClick = {} + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/SimpleListItemC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/SimpleListItemC.kt new file mode 100644 index 0000000..e42ae1f --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/SimpleListItemC.kt @@ -0,0 +1,71 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.List +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + ) + } +} + +@Preview +@Composable +fun SimpleListItemPreview() { + MaterialTheme { + SimpleListItem( + icon = Icons.Default.List, + text = "Sample List Item", + colors = AppThemes.LightThemeColors + ) + } +} + +@Preview +@Composable +fun SimpleListItemDarkPreview() { + MaterialTheme { + SimpleListItem( + icon = Icons.Default.List, + text = "Sample List Item (Dark)", + colors = AppThemes.DarkThemeColors + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/StyledButtonC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/StyledButtonC.kt new file mode 100644 index 0000000..4b19506 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/StyledButtonC.kt @@ -0,0 +1,72 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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) + } + } +} + +@Preview +@Composable +fun StyledButtonPreview() { + StyledButton( + icon = Icons.Default.Favorite, + text = "Preview Button", + onClick = {}, + colors = AppThemes.LightThemeColors + ) +} + +@Preview +@Composable +fun StyledButtonDarkPreview() { + StyledButton( + icon = Icons.Default.Favorite, + text = "Preview Button Dark", + onClick = {}, + colors = AppThemes.DarkThemeColors + ) +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/StyledCard.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/StyledCard.kt new file mode 100644 index 0000000..518ffa2 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/components/StyledCard.kt @@ -0,0 +1,45 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) +} + +@Preview +@Composable +fun StyledCardPreview() { + StyledCard( + colors = AppThemes.LightThemeColors + ) { + // Preview content + Text("123") + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileAboutScreenC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileAboutScreenC.kt new file mode 100644 index 0000000..251e626 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileAboutScreenC.kt @@ -0,0 +1,165 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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 com.grtsinry43.activityanalyzer.components.InfoItem +import com.grtsinry43.activityanalyzer.components.SettingItem +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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) + ) + } +} + +@Preview +@Composable +fun MobileAboutScreenPreview() { + MaterialTheme { + MobileAboutScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun MobileAboutScreenDarkPreview() { + MaterialTheme { + MobileAboutScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileAnalyticsScreenC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileAnalyticsScreenC.kt new file mode 100644 index 0000000..9c082ed --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileAnalyticsScreenC.kt @@ -0,0 +1,191 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.components.ChartPlaceholder +import com.grtsinry43.activityanalyzer.components.MetricCard +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 = MaterialTheme.shapes.medium, + 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 + ) + } + } + } +} + +@Preview +@Composable +fun MobileAnalyticsScreenPreview() { + MaterialTheme { + MobileAnalyticsScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun MobileAnalyticsScreenDarkPreview() { + MaterialTheme { + MobileAnalyticsScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileHomeScreenC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileHomeScreenC.kt new file mode 100644 index 0000000..5892949 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileHomeScreenC.kt @@ -0,0 +1,174 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.components.ActivityItem +import com.grtsinry43.activityanalyzer.components.SimpleListItem +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } + } + } +} + +@Preview +@Composable +fun MobileHomeScreenPreview() { + MaterialTheme { + MobileHomeScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun MobileHomeScreenDarkPreview() { + MaterialTheme { + MobileHomeScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileProfileScreenC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileProfileScreenC.kt new file mode 100644 index 0000000..a502a84 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileProfileScreenC.kt @@ -0,0 +1,188 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +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 androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.components.SimpleListItem +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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) + } + } + } + } +} + +@Preview +@Composable +fun MobileProfileScreenPreview() { + MaterialTheme { + MobileProfileScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun MobileProfileScreenDarkPreview() { + MaterialTheme { + MobileProfileScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileReportsScreenC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileReportsScreenC.kt new file mode 100644 index 0000000..d911a50 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileReportsScreenC.kt @@ -0,0 +1,104 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +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 androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.components.ReportItem +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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) + // } + } +} + +@Preview +@Composable +fun MobileReportsScreenPreview() { + MaterialTheme { + MobileReportsScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun MobileReportsScreenDarkPreview() { + MaterialTheme { + MobileReportsScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileSettingsScreenC.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileSettingsScreenC.kt new file mode 100644 index 0000000..70911d4 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/screens/MobileSettingsScreenC.kt @@ -0,0 +1,182 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.components.SettingItem +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) +} + +@Preview +@Composable +fun MobileSettingsScreenPreview() { + MaterialTheme { + MobileSettingsScreen(colors = AppThemes.LightThemeColors, isDarkTheme = false, onThemeChange = {}) + } +} + +@Preview +@Composable +fun MobileSettingsScreenDarkPreview() { + MaterialTheme { + MobileSettingsScreen(colors = AppThemes.DarkThemeColors, isDarkTheme = true, onThemeChange = {}) + } +} diff --git a/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/theme/AppThemes.kt b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/theme/AppThemes.kt new file mode 100644 index 0000000..5fc7136 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/grtsinry43/activityanalyzer/theme/AppThemes.kt @@ -0,0 +1,43 @@ +package com.grtsinry43.activityanalyzer.theme + +import androidx.compose.ui.graphics.Color + +// --- 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 + ) +} \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt index 13314d6..1b0ffa2 100644 --- a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/DesktopApp.kt @@ -1,7 +1,6 @@ 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 @@ -13,13 +12,19 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier 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.foundation.text.selection.SelectionContainer +import com.grtsinry43.activityanalyzer.components.* +import com.grtsinry43.activityanalyzer.screens.AboutScreen +import com.grtsinry43.activityanalyzer.screens.AnalyticsScreen +import com.grtsinry43.activityanalyzer.screens.HomeScreen +import com.grtsinry43.activityanalyzer.screens.ProfileScreen +import com.grtsinry43.activityanalyzer.screens.ReportsScreen +import com.grtsinry43.activityanalyzer.screens.SettingsScreen +import com.grtsinry43.activityanalyzer.theme.AppThemes @Composable @Preview @@ -174,928 +179,4 @@ fun DesktopApp() { } } } -} - -@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 // 选中时字体加粗 - ) - } - } -} - -@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 - ) - } - } - } -} - -@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 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 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) - ) - } } \ No newline at end of file diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/components/NavItemC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/components/NavItemC.kt new file mode 100644 index 0000000..6d322ef --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/components/NavItemC.kt @@ -0,0 +1,132 @@ +package com.grtsinry43.activityanalyzer.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Home +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +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.unit.dp +import androidx.compose.ui.unit.sp +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 // 选中时字体加粗 + ) + } + } +} + +@Preview +@Composable +fun NavItemSelectedPreview() { + MaterialTheme { + NavItem( + icon = Icons.Default.Home, + text = "Home", + isSelected = true, + onClick = {}, + colors = AppThemes.LightThemeColors, + isSidebarCollapsed = false + ) + } +} + +@Preview +@Composable +fun NavItemUnselectedPreview() { + MaterialTheme { + NavItem( + icon = Icons.Default.Home, + text = "Home", + isSelected = false, + onClick = {}, + colors = AppThemes.LightThemeColors, + isSidebarCollapsed = false + ) + } +} + +@Preview +@Composable +fun NavItemSelectedCollapsedPreview() { + MaterialTheme { + NavItem( + icon = Icons.Default.Home, + text = "Home", // Text won't be visible + isSelected = true, + onClick = {}, + colors = AppThemes.LightThemeColors, + isSidebarCollapsed = true + ) + } +} + +@Preview +@Composable +fun NavItemDarkSelectedPreview() { + MaterialTheme { + NavItem( + icon = Icons.Default.Home, + text = "Home", + isSelected = true, + onClick = {}, + colors = AppThemes.DarkThemeColors, + isSidebarCollapsed = false + ) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/AboutScreenC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/AboutScreenC.kt new file mode 100644 index 0000000..6da697c --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/AboutScreenC.kt @@ -0,0 +1,173 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.components.InfoItem +import com.grtsinry43.activityanalyzer.components.SettingItem +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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, // 应用Logo图标 (示例) + 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)) // 间距 + + // App Description Card + // 应用描述卡片 + 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 // 文本居中 + ) + } + } + + // Developer Info Card + // 开发者信息卡片 + 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, // Github图标 + text = "github.com/grtsinry43", // Github用户名 + colors = colors, + isLink = true, + linkUrl = "https://github.com/grtsinry43" // Github链接 + ) // GitHub (可点击) + } + } + + // Application Info Card + // 应用信息卡片 + 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) + ) + } +} + +@Preview +@Composable +fun AboutScreenPreview() { + MaterialTheme { + AboutScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun AboutScreenDarkPreview() { + MaterialTheme { + AboutScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/AnalyticsScreenC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/AnalyticsScreenC.kt new file mode 100644 index 0000000..4c111e9 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/AnalyticsScreenC.kt @@ -0,0 +1,222 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +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 androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.components.ChartPlaceholder +import com.grtsinry43.activityanalyzer.components.MetricCard +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } + } + } + } +} + +@Preview +@Composable +fun AnalyticsScreenPreview() { + MaterialTheme { + AnalyticsScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun AnalyticsScreenDarkPreview() { + MaterialTheme { + AnalyticsScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/HomeScreenC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/HomeScreenC.kt new file mode 100644 index 0000000..b6ddfd9 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/HomeScreenC.kt @@ -0,0 +1,184 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.components.ActivityItem +import com.grtsinry43.activityanalyzer.components.SimpleListItem +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + SimpleListItem( + icon = Icons.Filled.PhotoCamera, // 示例图标 + text = "App B: 45m", // 示例数据 + colors = colors + ) + SimpleListItem( + icon = Icons.Filled.Chat, // 示例图标 + text = "App C: 30m", // 示例数据 + colors = colors + ) + } + } + + // 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.", // 您已超出App 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 + ) + } + } + } +} + +@Preview +@Composable +fun HomeScreenPreview() { + MaterialTheme { + HomeScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun HomeScreenDarkPreview() { + MaterialTheme { + HomeScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/ProfileScreenC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/ProfileScreenC.kt new file mode 100644 index 0000000..047b090 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/ProfileScreenC.kt @@ -0,0 +1,183 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +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 androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.components.SimpleListItem +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 Card + // 账户操作卡片 + 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() + ) + } + } + } +} + +@Preview +@Composable +fun ProfileScreenPreview() { + MaterialTheme { + ProfileScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun ProfileScreenDarkPreview() { + MaterialTheme { + ProfileScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/ReportsScreenC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/ReportsScreenC.kt new file mode 100644 index 0000000..34800ca --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/ReportsScreenC.kt @@ -0,0 +1,123 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.components.ReportItem +import com.grtsinry43.activityanalyzer.components.StyledButton +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 + ) + } + + // Generated Reports List + // 已生成报告列表 + 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) +// } + } +} + +@Preview +@Composable +fun ReportsScreenPreview() { + MaterialTheme { + ReportsScreen(colors = AppThemes.LightThemeColors) + } +} + +@Preview +@Composable +fun ReportsScreenDarkPreview() { + MaterialTheme { + ReportsScreen(colors = AppThemes.DarkThemeColors) + } +} diff --git a/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/SettingsScreenC.kt b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/SettingsScreenC.kt new file mode 100644 index 0000000..d0959a2 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/com/grtsinry43/activityanalyzer/screens/SettingsScreenC.kt @@ -0,0 +1,207 @@ +package com.grtsinry43.activityanalyzer.screens + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.grtsinry43.activityanalyzer.components.SettingItem +import com.grtsinry43.activityanalyzer.components.StyledCard +import com.grtsinry43.activityanalyzer.theme.AppThemes +import org.jetbrains.compose.ui.tooling.preview.Preview + +@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 Card + // 通用设置卡片 + 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 Card + // 追踪设置卡片 + 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 Card + // 通知设置卡片 + 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 */ } + ) + } + } + } +} + +@Preview +@Composable +fun SettingsScreenPreview() { + MaterialTheme { + SettingsScreen( + colors = AppThemes.LightThemeColors, + isDarkTheme = false, + onThemeChange = {} + ) + } +} + +@Preview +@Composable +fun SettingsScreenDarkPreview() { + MaterialTheme { + SettingsScreen( + colors = AppThemes.DarkThemeColors, + isDarkTheme = true, + onThemeChange = {} + ) + } +}