From 33e47e965465fffd2adc6456fb21b612ac73b7d0 Mon Sep 17 00:00:00 2001 From: austinried <4966622+austinried@users.noreply.github.com> Date: Fri, 25 Sep 2026 08:56:19 +0000 Subject: [PATCH] suffix repeated disc titles with their disc number When two discs of an album share a title, showing "Live" alone is ambiguous, so render "Live: Disc 1"/"Live: Disc 2". Unique titles stay as-is. Also drop the header from titleLarge to a semibold titleMedium so longer titles fit on one line. --- .../subtracks/ui/library/AlbumDetailScreen.kt | 35 +++++++++++++------ .../kotlin/com/subtracks/ui/AlbumDiscsTest.kt | 10 ++++++ 2 files changed, 35 insertions(+), 10 deletions(-) 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 5c4e5170..14af47e3 100644 --- a/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt +++ b/app/src/main/kotlin/com/subtracks/ui/library/AlbumDetailScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.subtracks.data.model.Album @@ -72,7 +73,23 @@ fun AlbumDetailScreen( modifier: Modifier = Modifier, ) { val multiDisc = songs.map { it.disc ?: 1L }.distinct().size > 1 - val discTitles = remember(discs) { discs.associate { it.disc to it.title } } + val discLabels = + remember(discs) { + val repeated = + discs + .map { it.title } + .filter { it.isNotBlank() } + .groupingBy { it } + .eachCount() + .filterValues { it > 1 } + .keys + discs.associate { disc -> + disc.disc to + disc.title.takeIf { it.isNotBlank() }?.let { title -> + if (title in repeated) "$title: Disc ${disc.disc}" else title + } + } + } HeroDetailScaffold( artwork = artwork, title = album?.name.orEmpty(), @@ -100,9 +117,9 @@ fun AlbumDetailScreen( var lastDisc: Long? = null songs.forEachIndexed { index, song -> val disc = song.disc ?: 1L - val discTitle = discTitles[disc] - if (disc != lastDisc && (multiDisc || !discTitle.isNullOrBlank())) { - item(key = "disc:$disc") { DiscHeader(disc, discTitle) } + val discLabel = discLabels[disc] + if (disc != lastDisc && (multiDisc || discLabel != null)) { + item(key = "disc:$disc") { DiscHeader(discLabel ?: "Disc $disc") } } lastDisc = disc item(key = song.id) { @@ -120,13 +137,11 @@ fun AlbumDetailScreen( } @Composable -private fun DiscHeader( - disc: Long, - title: String?, -) { +private fun DiscHeader(text: String) { Text( - text = title?.takeIf { it.isNotBlank() } ?: "Disc $disc", - style = MaterialTheme.typography.titleLarge, + text = text, + style = MaterialTheme.typography.titleMedium, + fontWeight = FontWeight.SemiBold, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 20.dp, bottom = 4.dp), ) diff --git a/app/src/test/kotlin/com/subtracks/ui/AlbumDiscsTest.kt b/app/src/test/kotlin/com/subtracks/ui/AlbumDiscsTest.kt index b2b9db94..67db0381 100644 --- a/app/src/test/kotlin/com/subtracks/ui/AlbumDiscsTest.kt +++ b/app/src/test/kotlin/com/subtracks/ui/AlbumDiscsTest.kt @@ -44,6 +44,16 @@ class AlbumDiscsTest { assertEquals(0, nodesWithText("Disc 1")) } + @Test + fun repeatedDiscTitlesGetTheDiscNumber() { + setContent( + listOf(song("s-a", disc = 1, track = 1), song("s-b", disc = 2, track = 1)), + discs = listOf(disc(1, "Live"), disc(2, "Live")), + ) + assertEquals(1, nodesWithText("Live: Disc 1")) + assertEquals(1, nodesWithText("Live: Disc 2")) + } + @Test fun discHeadersFallBackToTheDiscNumber() { setContent(listOf(song("s-a", disc = 1, track = 1), song("s-b", disc = 2, track = 1)))