media: the tabs fill the header again, and the nav bar goes see-through over the player so the cover's glow runs behind it

This commit is contained in:
Seb3thehacker committed 2026-10-26 20:28:47 -07:00
1 parent 738b99ff9e
commit e1948a823f
3 files changed
+25 -20

No files matched your search

@@ -167,8 +167,13 @@ internal fun CarNavBar(navigator: CarNavigator) {
val running = rememberRunningApps() val running = rememberRunningApps()
// A full-width strip along the bottom, casting the theme's panel shadow up onto the map so the // A full-width strip along the bottom, casting the theme's panel shadow up onto the map so the
// bar sits above it rather than beside it. // bar sits above it rather than beside it. Over the player it's see-through instead, so the
Surface(Modifier.gsBarShadow(), color = MaterialTheme.colorScheme.surfaceContainer) { // player's background and the cover's glow carry on behind it.
val overPlayer = navigator.current == CarScreen.Media
Surface(
if (overPlayer) Modifier else Modifier.gsBarShadow(),
color = if (overPlayer) androidx.compose.ui.graphics.Color.Transparent else MaterialTheme.colorScheme.surfaceContainer,
) {
BoxWithConstraints(Modifier.fillMaxWidth().height(NAV_BAR_HEIGHT).padding(horizontal = 10.dp)) { BoxWithConstraints(Modifier.fillMaxWidth().height(NAV_BAR_HEIGHT).padding(horizontal = 10.dp)) {
Row(Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) { Row(Modifier.fillMaxSize(), verticalAlignment = Alignment.CenterVertically) {
// Home and Apps are two different places now, not a toggle on one button - the // Home and Apps are two different places now, not a toggle on one button - the
@@ -294,8 +294,9 @@ fun CarUi() {
.fillMaxSize() .fillMaxSize()
.graphicsLayer { if (fromHome) alpha = enter.value } .graphicsLayer { if (fromHome) alpha = enter.value }
.background(MaterialTheme.colorScheme.background) .background(MaterialTheme.colorScheme.background)
// The bar never hides here, so keep the screen clear of it. // The bar never hides here, so keep the screen clear of it. The
.padding(bottom = if (!keyboardVisible && !fullscreen) NAV_BAR_HEIGHT else 0.dp) // player runs on under the see-through bar and keeps clear itself.
.padding(bottom = if (!keyboardVisible && !fullscreen && screen != CarScreen.Media) NAV_BAR_HEIGHT else 0.dp)
// Keeps touches that miss this screen's controls off the map. // Keeps touches that miss this screen's controls off the map.
.pointerInput(Unit) { detectTapGestures { } }, .pointerInput(Unit) { detectTapGestures { } },
) { ) {
@@ -308,7 +309,9 @@ fun CarUi() {
when (screen) { when (screen) {
CarScreen.Home -> Unit CarScreen.Home -> Unit
CarScreen.Apps -> CarLauncher() CarScreen.Apps -> CarLauncher()
CarScreen.Media -> mediaApp?.let { MediaScreen(it) { navigator.back() } } CarScreen.Media -> CompositionLocalProvider(
LocalNavBarInset provides if (!keyboardVisible && !fullscreen) NAV_BAR_HEIGHT else 0.dp,
) { mediaApp?.let { MediaScreen(it) { navigator.back() } } }
CarScreen.Browse -> BrowseAppScreen(navigator) CarScreen.Browse -> BrowseAppScreen(navigator)
CarScreen.Settings -> CarSettingsScreen() CarScreen.Settings -> CarSettingsScreen()
CarScreen.Dashboard -> CarDashboardScreen() CarScreen.Dashboard -> CarDashboardScreen()
@@ -110,7 +110,7 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) {
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Surface(Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
if (phase == CarMedia.Phase.READY && !searching) AlbumGlow(art, Modifier.fillMaxSize(), wide = true) if (phase == CarMedia.Phase.READY && !searching) AlbumGlow(art, Modifier.fillMaxSize(), wide = true)
if (phase != CarMedia.Phase.READY) { if (phase != CarMedia.Phase.READY) {
Column(Modifier.fillMaxSize()) { Column(Modifier.fillMaxSize().padding(bottom = LocalNavBarInset.current)) {
AppIdentity(app, onExit, Modifier.padding(horizontal = 16.dp, vertical = 10.dp)) AppIdentity(app, onExit, Modifier.padding(horizontal = 16.dp, vertical = 10.dp))
when (phase) { when (phase) {
CarMedia.Phase.REJECTED -> when (rejection) { CarMedia.Phase.REJECTED -> when (rejection) {
@@ -143,7 +143,7 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) {
} }
if (searching) { if (searching) {
SearchPanel( Box(Modifier.padding(bottom = LocalNavBarInset.current)) { SearchPanel(
appLabel = app.label, appLabel = app.label,
media = media, media = media,
canPickForYou = now.canSearch, canPickForYou = now.canSearch,
@@ -161,7 +161,7 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) {
tab = Tab.NOW_PLAYING tab = Tab.NOW_PLAYING
}, },
onClose = { searching = false }, onClose = { searching = false },
) ) }
return@Surface return@Surface
} }
@@ -194,7 +194,9 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) {
} }
} }
BoxWithConstraints(Modifier.fillMaxSize().padding(start = 16.dp, end = 16.dp, top = 10.dp, bottom = 8.dp)) { BoxWithConstraints(
Modifier.fillMaxSize().padding(start = 16.dp, end = 16.dp, top = 10.dp, bottom = 8.dp + LocalNavBarInset.current),
) {
// A small screen, or a big one at Extra large size, has no room for two columns: the // A small screen, or a big one at Extra large size, has no room for two columns: the
// app and the tabs share one bar, and a list takes the whole width. The nav bar keeps // app and the tabs share one bar, and a list takes the whole width. The nav bar keeps
// the controls, so nothing is lost. // the controls, so nothing is lost.
@@ -233,15 +235,10 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) {
} }
} }
Column(Modifier.weight(1.2f).fillMaxHeight()) { Column(Modifier.weight(1.2f).fillMaxHeight()) {
// Each tab takes a share of the row, but a long word (a translation, a big // The tabs share the row evenly; a long word (a translation, a big text size)
// text size) can still scroll the row rather than be cut off. // shrinks to fit its tab instead.
Row( Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Modifier.fillMaxWidth().horizontalScroll(rememberScrollState()), tabs(Modifier.weight(1f))
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
Row(Modifier.weight(1f, fill = false), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
tabs(Modifier.widthIn(min = 96.dp))
}
searchButton() searchButton()
} }
search?.let { SearchStatus(it, app.label, media::dismissSearch) } search?.let { SearchStatus(it, app.label, media::dismissSearch) }
@@ -424,8 +421,8 @@ private fun MediaTab(label: String, selected: Boolean, modifier: Modifier, onCli
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.titleSmall,
fontWeight = if (selected) FontWeight.Bold else FontWeight.Normal, fontWeight = if (selected) FontWeight.Bold else FontWeight.Normal,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, autoSize = TextAutoSize.StepBased(minFontSize = 11.sp, maxFontSize = MaterialTheme.typography.titleSmall.fontSize),
modifier = Modifier.padding(horizontal = 12.dp), modifier = Modifier.padding(horizontal = 8.dp),
) )
} }
} }