v2 - Home Screen Streamlined
This commit is contained in:
@@ -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 |
Reference in New Issue
Block a user