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
This commit is contained in:
austinried
2026-10-04 00:29:58 +00:00
parent b10006cba1
commit d43dd51b15
3 changed files with 72 additions and 4 deletions
@@ -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,
@@ -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 {
@@ -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<ComponentActivity>()
@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()
}
}