v2 - Home Screen Streamlined

This commit is contained in:
2026-05-15 14:34:41 +03:00
parent be70a3d3de
commit c0e3d8af39
135 changed files with 546 additions and 289 deletions
@@ -20,6 +20,7 @@ object Routes {
const val GAME_RESULTS = "results/{gameId}"
const val LEADERBOARD = "leaderboard"
const val CUSTOM_RULES = "custom_rules"
const val ABOUT = "about"
fun activeGame(id: Long) = "game/$id"
fun roundEntry(id: Long) = "round/$id"
@@ -51,7 +52,8 @@ fun Phase10NavHost(navController: NavHostController) {
onStartNew = { navController.navigate(Routes.GAME_SETUP) },
onLeaderboard = { navController.navigate(Routes.LEADERBOARD) },
onManagePlayers = { navController.navigate(Routes.PLAYER_ROSTER) },
onCustomRules = { navController.navigate(Routes.CUSTOM_RULES) }
onCustomRules = { navController.navigate(Routes.CUSTOM_RULES) },
onAbout = { navController.navigate(Routes.ABOUT) }
)
}
@@ -144,5 +146,9 @@ fun Phase10NavHost(navController: NavHostController) {
onBack = { navController.popBackStack() }
)
}
composable(Routes.ABOUT) {
AboutScreen(onBack = { navController.popBackStack() })
}
}
}
@@ -0,0 +1,205 @@
package com.crsmthw.phase10tracker.ui.screens
import android.content.Intent
import androidx.core.net.toUri
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
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.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.OpenInNew
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.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.crsmthw.phase10tracker.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AboutScreen(onBack: () -> Unit) {
val context = LocalContext.current
fun openUrl(url: String) {
context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
}
Scaffold(
topBar = {
TopAppBar(
title = { Text("About") },
navigationIcon = {
IconButton(onClick = onBack) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, "Back")
}
}
)
}
) { padding ->
Column(
modifier = Modifier
.fillMaxSize()
.padding(padding)
.verticalScroll(rememberScrollState())
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(24.dp)
) {
// App icon + name
Image(
painter = painterResource(id = R.drawable.ic_launcher_foreground),
contentDescription = null,
modifier = Modifier
.size(100.dp)
.clip(MaterialTheme.shapes.extraLarge)
.background(MaterialTheme.colorScheme.primary)
)
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
"Phase 10 Tracker",
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold
)
Text(
"Ad-free. Open source. Always.",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
HorizontalDivider()
// Credits
Card(
modifier = Modifier.fillMaxWidth(),
shape = MaterialTheme.shapes.extraLarge,
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Column(
modifier = Modifier.padding(20.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
Text(
"Credits",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold
)
Row(verticalAlignment = Alignment.CenterVertically) {
Text("❤️", style = MaterialTheme.typography.titleMedium)
Spacer(Modifier.width(8.dp))
Column {
Text(
"Made by CrsMthw and Claude",
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium
)
Text(
"App design & development",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text("❤️", style = MaterialTheme.typography.titleMedium)
Spacer(Modifier.width(8.dp))
Column {
Text(
"Icon by Shubbu",
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Medium
)
Text(
"App icon design",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
// GitHub
Card(
modifier = Modifier
.fillMaxWidth()
.clickable { openUrl("https://github.com/CrsMthw") },
shape = MaterialTheme.shapes.extraLarge,
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(20.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
Icons.Filled.Code,
contentDescription = null,
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(28.dp)
)
Spacer(Modifier.width(16.dp))
Column(modifier = Modifier.weight(1f)) {
Text(
"GitHub",
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.SemiBold
)
Text(
"github.com/CrsMthw",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Icon(
Icons.AutoMirrored.Filled.OpenInNew,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(18.dp)
)
}
}
// Buy Me a Coffee button
Image(
painter = painterResource(id = R.drawable.bmc_button),
contentDescription = "Buy me a coffee",
modifier = Modifier
.fillMaxWidth()
.height(72.dp)
.clip(MaterialTheme.shapes.extraLarge)
.clickable { openUrl("https://buymeacoffee.com/crsmthw") }
)
HorizontalDivider()
// Bottom tagline
Text(
"Because the people didn't deserve\nanother ad-infested score tracker.",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
textAlign = TextAlign.Center
)
Spacer(Modifier.height(8.dp))
}
}
}
@@ -26,7 +26,8 @@ fun HomeScreen(
onStartNew: () -> Unit,
onLeaderboard: () -> Unit,
onManagePlayers: () -> Unit,
onCustomRules: () -> Unit
onCustomRules: () -> Unit,
onAbout: () -> Unit
) {
val hasActiveGame by vm.hasActiveGame.collectAsState()
val activeGameId by vm.activeGameId.collectAsState()
@@ -58,11 +59,8 @@ fun HomeScreen(
)
},
actions = {
IconButton(onClick = onManagePlayers) {
Icon(Icons.Outlined.Group, contentDescription = "Manage Players")
}
IconButton(onClick = onLeaderboard) {
Icon(Icons.Outlined.EmojiEvents, contentDescription = "Leaderboard")
IconButton(onClick = onAbout) {
Icon(Icons.Filled.Info, contentDescription = "About")
}
},
colors = TopAppBarDefaults.topAppBarColors(
@@ -206,4 +204,4 @@ private fun ResumeGameDialog(
OutlinedButton(onClick = onStartNew) { Text("New Game") }
}
)
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB