ui: move artist actions back onto the meta row

Keep the type and count on the same row as the star and more buttons, and move
that row down to where it sat before the split. Give the Albums and Appears on
headers the album and microphone icons alongside the disc-title styling.
This commit is contained in:
austinried
2026-10-19 04:57:33 +00:00
parent 4f6a292e74
commit b8b5594d04
2 changed files with 23 additions and 15 deletions
@@ -33,6 +33,8 @@ import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Album
import androidx.compose.material.icons.rounded.Mic
import androidx.compose.material.icons.rounded.MoreHoriz import androidx.compose.material.icons.rounded.MoreHoriz
import androidx.compose.material.icons.rounded.Shuffle import androidx.compose.material.icons.rounded.Shuffle
import androidx.compose.material.icons.rounded.Star import androidx.compose.material.icons.rounded.Star
@@ -64,6 +66,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
@@ -256,8 +259,12 @@ fun ArtistDetailScreen(
) )
val albumCountText = pluralStringResource(R.plurals.resources_album_count, albumCount.toInt(), albumCount) val albumCountText = pluralStringResource(R.plurals.resources_album_count, albumCount.toInt(), albumCount)
val metaText = if (albumsLoaded) stringResource(R.string.artist_meta, artistType, albumCountText) else "" val metaText = if (albumsLoaded) stringResource(R.string.artist_meta, artistType, albumCountText) else ""
val actionsInHeader = albums.albumCredits.isNotEmpty() || albums.appearances.isNotEmpty() val metaTop =
val actions: @Composable () -> Unit = { ArtistActions(artist, starred, onToggleStar, onMore) } TITLE_INSET +
with(density) {
MaterialTheme.typography.labelLarge.lineHeight
.toDp()
}
var titleHeightPx by remember { mutableFloatStateOf(0f) } var titleHeightPx by remember { mutableFloatStateOf(0f) }
val titleHeight = if (titleHeightPx > 0f) with(density) { titleHeightPx.toDp() } else lineHeight val titleHeight = if (titleHeightPx > 0f) with(density) { titleHeightPx.toDp() } else lineHeight
val titleMaxLines = val titleMaxLines =
@@ -387,10 +394,10 @@ fun ArtistDetailScreen(
} }
} }
Column( Column(
modifier = Modifier.fillMaxWidth().padding(start = 16.dp, end = 8.dp, top = TITLE_INSET), modifier = Modifier.fillMaxWidth().padding(start = 16.dp, end = 8.dp, top = metaTop),
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth().defaultMinSize(minHeight = 48.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Text( Text(
@@ -399,14 +406,14 @@ fun ArtistDetailScreen(
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.weight(1f), modifier = Modifier.weight(1f),
) )
if (!actionsInHeader) actions() ArtistActions(artist, starred, onToggleStar, onMore)
} }
} }
} }
} }
if (albums.albumCredits.isNotEmpty()) { if (albums.albumCredits.isNotEmpty()) {
item(span = { GridItemSpan(maxLineSpan) }) { item(span = { GridItemSpan(maxLineSpan) }) {
ArtistSectionHeader(stringResource(R.string.artist_section_albums), trailing = actions) ArtistSectionHeader(stringResource(R.string.artist_section_albums), Icons.Rounded.Album)
} }
itemsIndexed(albums.albumCredits, key = { _, album -> album.id }) { index, album -> itemsIndexed(albums.albumCredits, key = { _, album -> album.id }) { index, album ->
ArtistAlbumCard( ArtistAlbumCard(
@@ -424,10 +431,7 @@ fun ArtistDetailScreen(
} }
if (albums.appearances.isNotEmpty()) { if (albums.appearances.isNotEmpty()) {
item(span = { GridItemSpan(maxLineSpan) }) { item(span = { GridItemSpan(maxLineSpan) }) {
ArtistSectionHeader( ArtistSectionHeader(stringResource(R.string.artist_section_appearances), Icons.Rounded.Mic)
stringResource(R.string.artist_section_appearances),
trailing = if (albums.albumCredits.isEmpty()) actions else null,
)
} }
itemsIndexed(albums.appearances, key = { _, album -> album.id }) { index, album -> itemsIndexed(albums.appearances, key = { _, album -> album.id }) { index, album ->
ArtistAlbumCard( ArtistAlbumCard(
@@ -488,21 +492,26 @@ fun ArtistDetailScreen(
@Composable @Composable
private fun ArtistSectionHeader( private fun ArtistSectionHeader(
text: String, text: String,
trailing: (@Composable () -> Unit)? = null, icon: ImageVector,
) { ) {
Row( Row(
modifier = Modifier.fillMaxWidth().defaultMinSize(minHeight = 48.dp).padding(start = 16.dp, end = 8.dp),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth().padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 4.dp),
) { ) {
Icon(
imageVector = icon,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.size(18.dp),
)
Spacer(Modifier.width(16.dp))
Text( Text(
text = text.uppercase(), text = text.uppercase(),
style = MaterialTheme.typography.labelLarge, style = MaterialTheme.typography.labelLarge,
fontWeight = FontWeight.SemiBold, fontWeight = FontWeight.SemiBold,
letterSpacing = 1.sp, letterSpacing = 1.sp,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.weight(1f),
) )
trailing?.invoke()
} }
} }
@@ -70,7 +70,6 @@ class ArtistDetailScreenTest {
) )
composeRule.onNodeWithText("Album artist · 1 album").assertExists() composeRule.onNodeWithText("Album artist · 1 album").assertExists()
composeRule.onNode(hasScrollAction()).performScrollToNode(hasText("ALBUMS"))
composeRule.onNodeWithContentDescription("More options").assertExists() composeRule.onNodeWithContentDescription("More options").assertExists()
} }