Merge pull request #22: one centred column for the main menu

A short list spread across a grid read as a page half empty. Verified by
ci.yml run 109.
This commit is contained in:
adrianoftyriel
2026-08-08 11:38:27 -06:00
committed by GitHub
@@ -2,14 +2,15 @@ package org.prolibertate.games.ui
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.GridItemSpan import androidx.compose.foundation.lazy.grid.GridItemSpan
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
@@ -214,7 +215,7 @@ private fun AppContent(
// Main menu // Main menu
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun MainMenuScreen( fun MainMenuScreen(
showComingSoon: Boolean, showComingSoon: Boolean,
@@ -233,45 +234,52 @@ fun MainMenuScreen(
) )
} }
) { padding -> ) { padding ->
Column( // Only the top of the tree. Trick-taking is reached through Card Games,
// which is where somebody looking for it would go.
val sections = GameMenu.entries.filter {
it.isTopLevel && GameCatalog.hasAnything(it, includeComingSoon = showComingSoon)
}
// One column, held in the middle. There are only ever a handful of
// entries here now that the games themselves live a level down, and a
// short list spread across a grid reads as a page half empty rather
// than as a menu. Capped in width so it does not become a row of very
// wide buttons on a tablet.
Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(padding) .padding(padding)
.padding(horizontal = 12.dp), .padding(horizontal = 12.dp),
contentAlignment = Alignment.Center,
) { ) {
// Wraps rather than running off the edge: two buttons and a narrow Column(
// phone would otherwise push the second one past the screen. modifier = Modifier
FlowRow( .widthIn(max = 340.dp)
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp), .fillMaxWidth()
horizontalArrangement = Arrangement.spacedBy(8.dp), .verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(4.dp),
) {
OutlinedButton(onClick = onJoinGame) { Text("Join a game nearby") }
// Not a game, and deliberately not in the catalogue: it keeps
// score for whatever is being played on the actual table.
OutlinedButton(onClick = onScorekeeper) { Text("Scorekeeper") }
}
// The column count follows the available width, so a phone in
// portrait gets two and a tablet in landscape gets four or more.
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 172.dp),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(),
) { ) {
// Only the top of the tree. Trick-taking is reached through sections.forEach { section ->
// Card Games, which is where somebody looking for it would go.
val sections = GameMenu.entries.filter {
it.isTopLevel && GameCatalog.hasAnything(it, includeComingSoon = showComingSoon)
}
items(sections) { section ->
SectionTile( SectionTile(
menu = section, menu = section,
count = countIn(section, showComingSoon), count = countIn(section, showComingSoon),
onClick = { onPickSection(section) }, onClick = { onPickSection(section) },
) )
} }
// Below the games, and full width like them, so the column
// stays one column all the way down.
OutlinedButton(
onClick = onJoinGame,
modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
) { Text("Join a game nearby") }
// Not a game, and deliberately not in the catalogue: it keeps
// score for whatever is being played on the actual table.
OutlinedButton(
onClick = onScorekeeper,
modifier = Modifier.fillMaxWidth(),
) { Text("Scorekeeper") }
} }
} }
} }