From d43dd51b1563d71da7fba3230ffd4a9d316debc1 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Fri, 25 Sep 2026 10:52:21 +0000 Subject: [PATCH] songs type label, disc header alignment, now playing back test - Now Playing: the type line reads "songs" for the library songs list, source line stays "Library" - Album detail: align the disc icon over the track numbers and the disc label with the track titles (16dp start + 18dp icon + 16dp gap, matching the ListItem columns) - Add NowPlayingBackTest covering back-from-overlay not popping the destination --- .../subtracks/ui/library/AlbumDetailScreen.kt | 6 +- .../subtracks/ui/playback/NowPlayingScreen.kt | 2 +- .../com/subtracks/ui/NowPlayingBackTest.kt | 68 +++++++++++++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 app/src/test/kotlin/com/subtracks/ui/NowPlayingBackTest.kt diff --git a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt index 97bc8f73..185b59af 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt @@ -149,15 +149,15 @@ fun AlbumDetailScreen( private fun DiscHeader(text: String) { Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(start = 8.dp, end = 16.dp, top = 28.dp, bottom = 4.dp), + modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 28.dp, bottom = 4.dp), ) { Icon( imageVector = Icons.Outlined.FiberSmartRecord, contentDescription = null, tint = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.size(20.dp), + modifier = Modifier.size(18.dp), ) - Spacer(Modifier.width(8.dp)) + Spacer(Modifier.width(16.dp)) Text( text = text.uppercase(), style = MaterialTheme.typography.labelLarge, diff --git a/app/src/main/kotlin/com/subtracks/ui/playback/NowPlayingScreen.kt b/app/src/main/kotlin/com/subtracks/ui/playback/NowPlayingScreen.kt index 857e8602..12c47441 100644 --- a/app/src/main/kotlin/com/subtracks/ui/playback/NowPlayingScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/playback/NowPlayingScreen.kt @@ -402,7 +402,7 @@ private fun QueueKind.label(): String = QueueKind.Album -> "album" QueueKind.Playlist -> "playlist" QueueKind.Song -> "song" - QueueKind.Songs -> "library" + QueueKind.Songs -> "songs" } private fun formatTime(milliseconds: Long): String { diff --git a/app/src/test/kotlin/com/subtracks/ui/NowPlayingBackTest.kt b/app/src/test/kotlin/com/subtracks/ui/NowPlayingBackTest.kt new file mode 100644 index 00000000..cb70ee08 --- /dev/null +++ b/app/src/test/kotlin/com/subtracks/ui/NowPlayingBackTest.kt @@ -0,0 +1,68 @@ +package com.subtracks.ui + +import androidx.activity.ComponentActivity +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers +import org.junit.Assert.assertFalse +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config(qualifiers = RobolectricDeviceQualifiers.PixelXL) +class NowPlayingBackTest { + @get:Rule + val composeRule = createAndroidComposeRule() + + @Test + fun backClosesTheOverlayBeforePoppingTheDestination() { + var overlayOpen by mutableStateOf(false) + var navController: NavHostController? = null + composeRule.setContent { + val nav = rememberNavController() + navController = nav + Box(Modifier.fillMaxSize()) { + NavHost(navController = nav, startDestination = "a") { + composable("a") { Text("A") } + composable("b") { Text("B") } + } + if (overlayOpen) { + Text("OVERLAY", modifier = Modifier.fillMaxSize()) + } + } + // Same ordering as MainNavigation: the overlay's back handler is registered after the + // NavHost, so it must consume back and leave the destination in place. + BackHandler(enabled = overlayOpen) { + overlayOpen = false + } + } + + composeRule.runOnIdle { navController!!.navigate("b") } + composeRule.onNodeWithText("B").assertExists() + composeRule.runOnIdle { overlayOpen = true } + composeRule.onNodeWithText("OVERLAY").assertExists() + + composeRule.runOnIdle { composeRule.activity.onBackPressedDispatcher.onBackPressed() } + composeRule.waitForIdle() + + assertFalse("the overlay should have closed", overlayOpen) + composeRule.onNodeWithText("B").assertExists() + } +}