From 6d32fe2bd32e176dea3a180e7fdef42b3bfe3e8e Mon Sep 17 00:00:00 2001 From: Seb3thehacker Date: Thu, 5 Nov 2026 17:48:14 -0800 Subject: [PATCH] App screens drop the back button when it would only lead to Home or the app grid, which the nav bar already does --- .../app/seb3thehacker/gearslip/car/CarNavigator.kt | 8 ++++++++ .../java/app/seb3thehacker/gearslip/car/MediaScreen.kt | 10 +++++++--- .../app/seb3thehacker/gearslip/car/MessagesScreen.kt | 2 +- .../app/seb3thehacker/gearslip/car/ScreenHeader.kt | 8 ++++---- 4 files changed, 20 insertions(+), 8 deletions(-) diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarNavigator.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarNavigator.kt index e8e8ee2..0f5a071 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarNavigator.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarNavigator.kt @@ -83,6 +83,14 @@ class CarNavigator(startId: String) { stack.add(Crumb(screen, label, labelRes)) } + /** + * Whether a back button on this screen leads anywhere the nav bar doesn't: false when the + * screen under it is Home or the app grid, which the nav bar's own buttons already reach. + * Android Auto shows no back button on an app's first screen for the same reason. + */ + val backLeadsSomewhere: Boolean + get() = stack.size >= 2 && stack[stack.size - 2].screen.let { it != CarScreen.Home && it != CarScreen.Apps } + /** The one way back to a clean slate: resets the whole trail to just Home. */ fun home() { stack.clear() diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt index e1fdb7a..a440177 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MediaScreen.kt @@ -259,10 +259,14 @@ fun MediaScreen(app: MediaApp, onExit: () -> Unit) { @Composable private fun AppIdentity(app: MediaApp, onExit: () -> Unit, modifier: Modifier = Modifier) { val icon = remember(app) { findEntry(app.component.flattenToString())?.icon } + val navigator = LocalCarNavigator.current Row(modifier, verticalAlignment = Alignment.CenterVertically) { - // The same back button as every other screen's header, in the same place. - GsIconButton(Icons.Filled.ArrowBack, stringResource(R.string.back), onExit) - Spacer(Modifier.width(12.dp)) + // Shown on the same terms as every other screen's header: only when it leads somewhere + // the nav bar doesn't. + if (navigator.backLeadsSomewhere) { + GsIconButton(Icons.Filled.ArrowBack, stringResource(R.string.back), onExit) + Spacer(Modifier.width(12.dp)) + } icon?.let { Image(it, null, Modifier.size(26.dp).clip(RoundedCornerShape(7.dp))) Spacer(Modifier.width(10.dp)) diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MessagesScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MessagesScreen.kt index fb811c3..a1ee65e 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MessagesScreen.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/MessagesScreen.kt @@ -72,7 +72,7 @@ fun MessagesScreen(packageName: String) { Column(Modifier.fillMaxSize().padding(start = 16.dp, end = 16.dp, top = 16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) { Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) { - GsIconButton(Icons.AutoMirrored.Filled.ArrowBack, stringResource(R.string.back), navigator::back) + if (navigator.backLeadsSomewhere) GsIconButton(Icons.AutoMirrored.Filled.ArrowBack, stringResource(R.string.back), navigator::back) entry?.icon?.let { Image(it, contentDescription = null, modifier = Modifier.size(36.dp).clip(RoundedCornerShape(8.dp))) } Text(label, style = MaterialTheme.typography.headlineSmall, fontWeight = FontWeight.Bold) } diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/ScreenHeader.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/ScreenHeader.kt index 2e9550b..6c0cdd0 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/ScreenHeader.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/ScreenHeader.kt @@ -19,9 +19,9 @@ import androidx.compose.ui.unit.dp import app.seb3thehacker.gearslip.car.theme.GsIconButton /** - * The top of every screen reached from Home: a back button in the current theme, the title, and - * room on the right for the screen's own controls. A car touchscreen has no hardware back button, - * so this is the way out of a screen. + * The top of every screen reached from Home: the title, room on the right for the screen's own + * controls, and a back button when the screen under this one is more than Home or the app grid - + * those the nav bar already reaches, so a back button there only repeated it. */ @Composable fun ScreenHeader(title: String, modifier: Modifier = Modifier, trailing: @Composable RowScope.() -> Unit = {}) { @@ -31,7 +31,7 @@ fun ScreenHeader(title: String, modifier: Modifier = Modifier, trailing: @Compos verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp), ) { - GsIconButton(Icons.AutoMirrored.Filled.ArrowBack, stringResource(R.string.back), navigator::back) + if (navigator.backLeadsSomewhere) GsIconButton(Icons.AutoMirrored.Filled.ArrowBack, stringResource(R.string.back), navigator::back) Text( title, style = MaterialTheme.typography.headlineSmall,