ui: show the singular and plural artist rows separately

Track info now lists the Artist field and the plural Artists field as
their own rows, hiding Artists when it would repeat the Artist value.
Keep one Artist sort row, also hidden when it matches the artist name.
This commit is contained in:
austinried
2026-10-21 14:24:18 +00:00
parent 319ff4b645
commit 2f95a89682
5 changed files with 28 additions and 23 deletions
@@ -9,6 +9,14 @@ internal fun Song.artistSubtitle(): String? = artistSubtitle(artist, artists)
internal fun Song.artistNames(): List<String> = artistNames(artist, artists)
internal fun Song.artistList(): String? =
artists
.map { it.name }
.filter { it.isNotBlank() }
.distinct()
.joinToString(ARTIST_SEPARATOR)
.takeIf { it.isNotEmpty() }
internal fun artistNames(
artist: String?,
artists: List<ArtistRef>,
@@ -46,20 +46,13 @@ fun SongInfoDialog(
title = { Text(stringResource(R.string.info)) },
text = {
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
val multipleArtists = song.artistNames().size > 1
val regularArtistSort = song.artist?.takeIf { it.isNotBlank() } ?: song.artistRefs.firstOrNull()?.name
val artist = song.artist?.takeIf { it.isNotBlank() }
val regularArtistSort = artist ?: song.artists.firstOrNull()?.name
InfoRow(stringResource(R.string.resources_sort_by_title), song.title)
InfoRow(stringResource(R.string.info_sort_title), song.sortName.takeIfDifferentFrom(song.title))
InfoRow(
stringResource(
if (multipleArtists) R.string.info_artists else R.string.resources_filter_artist,
),
song.artistSubtitle(),
)
InfoRow(
stringResource(if (multipleArtists) R.string.info_artists_sort else R.string.info_artist_sort),
song.artistSort.takeIfDifferentFrom(regularArtistSort),
)
InfoRow(stringResource(R.string.resources_filter_artist), artist)
InfoRow(stringResource(R.string.info_artists), song.artistList().takeIfDifferentFrom(artist))
InfoRow(stringResource(R.string.info_artist_sort), song.artistSort.takeIfDifferentFrom(regularArtistSort))
InfoRow(stringResource(R.string.resources_filter_album), song.album)
InfoRow(stringResource(R.string.info_duration), song.duration?.let(DateUtils::formatElapsedTime))
InfoRow(
-1
View File
@@ -198,7 +198,6 @@
<string name="info_channels">Channels</string>
<string name="info_close">Close</string>
<string name="info_artists">Artists</string>
<string name="info_artists_sort">Artists sort</string>
<string name="info_album_artists">Album artists</string>
<string name="info_album_artist_sort">Album artist sort</string>
<string name="info_sort_title">Sort title</string>
@@ -215,7 +215,7 @@ class LibraryInfoDialogTest {
}
@Test
fun aSingleArtistTrackUsesSingularLabels() {
fun aSingleArtistTrackHidesTheDuplicateArtistsRow() {
composeRule.setContent {
SubtracksTheme {
SongInfoDialog(
@@ -236,7 +236,7 @@ class LibraryInfoDialogTest {
}
@Test
fun duplicateAndBlankArtistRefsStaySingular() {
fun duplicateAndBlankArtistRefsDoNotAddAnArtistsRow() {
composeRule.setContent {
SubtracksTheme {
SongInfoDialog(
@@ -259,7 +259,7 @@ class LibraryInfoDialogTest {
}
@Test
fun aMixedArtistTrackUsesPluralLabelsForBothRows() {
fun aMixedArtistTrackShowsBothTheArtistAndArtistsRows() {
composeRule.setContent {
SubtracksTheme {
SongInfoDialog(
@@ -277,10 +277,12 @@ class LibraryInfoDialogTest {
}
}
composeRule.onNodeWithText("Artist").assertIsDisplayed()
composeRule.onNodeWithText("Artists").assertIsDisplayed()
composeRule.onNodeWithText("Artists sort").assertIsDisplayed()
composeRule.onNodeWithText("Artist").assertDoesNotExist()
composeRule.onNodeWithText("Artist sort").assertDoesNotExist()
composeRule.onNodeWithText("Artist A").assertIsDisplayed()
composeRule.onNodeWithText("Artist A · Artist B").assertIsDisplayed()
composeRule.onNodeWithText("Artist sort").assertIsDisplayed()
composeRule.onNodeWithText("Artists sort").assertDoesNotExist()
composeRule.onNodeWithText("Alpha").assertIsDisplayed()
}
@@ -304,7 +306,7 @@ class LibraryInfoDialogTest {
}
@Test
fun aMixedArtistTrackWithoutASortShowsOnlyTheArtistsRow() {
fun aMixedArtistTrackWithoutASortStillShowsBothArtistRows() {
composeRule.setContent {
SubtracksTheme {
SongInfoDialog(
@@ -322,9 +324,11 @@ class LibraryInfoDialogTest {
}
}
composeRule.onNodeWithText("Artist").assertIsDisplayed()
composeRule.onNodeWithText("Artists").assertIsDisplayed()
composeRule.onNodeWithText("Artist A").assertIsDisplayed()
composeRule.onNodeWithText("Artist A · Artist B").assertIsDisplayed()
composeRule.onNodeWithText("Artists sort").assertDoesNotExist()
composeRule.onNodeWithText("Artist sort").assertDoesNotExist()
}
@Test
@@ -48,7 +48,7 @@ class SongArtistDisplayTest {
}
@Test
fun theInfoDialogListsThePluralArtistsWithTheSingularArtistFirst() {
fun theInfoDialogShowsTheSingularArtistAndThePluralArtistsSeparately() {
composeRule.setContent {
SubtracksTheme {
SongInfoDialog(
@@ -62,6 +62,7 @@ class SongArtistDisplayTest {
}
}
composeRule.onNodeWithText("Two · One · Three").assertIsDisplayed()
composeRule.onNodeWithText("Two").assertIsDisplayed()
composeRule.onNodeWithText("One · Two · Three").assertIsDisplayed()
}
}