This commit is contained in:
grtsinry43 2025-05-12 08:51:44 +08:00
parent 502aaf51f0
commit 9e17e190cc
Signed by: grtsinry43
GPG Key ID: F3305FB3A978C934
25 changed files with 3024 additions and 2094 deletions

View File

@ -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
)
}
}

View File

@ -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)
)
}
}

View File

@ -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
)
}
}

View File

@ -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
)
}
}

View File

@ -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 = {}
)
}
}

View File

@ -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 = {}
)
}
}

View File

@ -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
)
}
}

View File

@ -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
)
}

View File

@ -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")
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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 = {})
}
}

View File

@ -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
)
}

View File

@ -1,7 +1,6 @@
package com.grtsinry43.activityanalyzer package com.grtsinry43.activityanalyzer
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@ -13,13 +12,19 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color 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.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
import androidx.compose.foundation.text.selection.SelectionContainer 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 @Composable
@Preview @Preview
@ -175,927 +180,3 @@ 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)
)
}
}

View File

@ -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
)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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 = {}
)
}
}