feat: artist cards with image in search + fix action bar overflow
Search: replace SmallArtistChip (text pill) with ArtistCard showing circular profile image (72dp) + name below; works for both Navidrome artists (uses coverArt) and iTunes artists (uses artworkUrl100 if present) ArtistDetailScreen: convert action bar Row → LazyRow so Play / Shuffle / Konzerte pills sit comfortably with horizontal scroll instead of cramming Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
13e9ec9d9a
commit
3855207530
2 files changed
+46
-25
No files matched your search
@@ -197,22 +197,27 @@ fun ArtistDetailScreen(
|
||||
|
||||
// Action bar
|
||||
item {
|
||||
Row(
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(bottom = 8.dp),
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
) {
|
||||
ArtistActionPill(Icons.Default.PlayArrow, "Top Songs") {
|
||||
if (state.topSongs.isNotEmpty()) onPlay(state.topSongs, 0)
|
||||
item {
|
||||
ArtistActionPill(Icons.Default.PlayArrow, "Top Songs") {
|
||||
if (state.topSongs.isNotEmpty()) onPlay(state.topSongs, 0)
|
||||
}
|
||||
}
|
||||
ArtistActionPill(Icons.Default.Shuffle, "Shuffle") {
|
||||
if (state.topSongs.isNotEmpty()) onPlay(state.topSongs.shuffled(), 0)
|
||||
item {
|
||||
ArtistActionPill(Icons.Default.Shuffle, "Shuffle") {
|
||||
if (state.topSongs.isNotEmpty()) onPlay(state.topSongs.shuffled(), 0)
|
||||
}
|
||||
}
|
||||
val eventCount = state.events.size
|
||||
val konzertLabel = if (eventCount > 0) "Konzerte ($eventCount)" else "Konzerte"
|
||||
ArtistActionPill(Icons.Default.Event, konzertLabel) {
|
||||
vm.openEventsSheet()
|
||||
item {
|
||||
val eventCount = state.events.size
|
||||
val konzertLabel = if (eventCount > 0) "Konzerte ($eventCount)" else "Konzerte"
|
||||
ArtistActionPill(Icons.Default.Event, konzertLabel) {
|
||||
vm.openEventsSheet()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,12 +280,13 @@ private fun LibrarySearchContent(
|
||||
item {
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
items(artists, key = { it.id }) { a ->
|
||||
SmallArtistChip(a.name) { onArtistClick(a) }
|
||||
ArtistCard(name = a.name, imageUrl = coverUrl(a.coverArt)) { onArtistClick(a) }
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
if (albums.isNotEmpty()) {
|
||||
@@ -408,12 +409,16 @@ private fun GlobalExploreContent(
|
||||
item {
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
) {
|
||||
items(state.artists) { a ->
|
||||
SmallArtistChip(a.artistName ?: "") { vm.openArtistDetail(a) }
|
||||
ArtistCard(
|
||||
name = a.artistName ?: "",
|
||||
imageUrl = a.artworkUrl100?.replace("100x100bb", "300x300bb"),
|
||||
) { vm.openArtistDetail(a) }
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
}
|
||||
}
|
||||
if (state.albums.isNotEmpty()) {
|
||||
@@ -585,17 +590,28 @@ private fun ItunesTrackRow(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SmallArtistChip(name: String, onClick: () -> Unit) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
private fun ArtistCard(name: String, imageUrl: String?, onClick: () -> Unit) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(20.dp))
|
||||
.background(NsSurface2)
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 14.dp, vertical = 8.dp),
|
||||
.width(80.dp)
|
||||
.clickable(onClick = onClick),
|
||||
) {
|
||||
Text(name, fontFamily = Outfit, fontSize = 13.sp, color = NsOnSurface,
|
||||
maxLines = 1, overflow = TextOverflow.Ellipsis)
|
||||
AsyncImage(
|
||||
model = imageUrl,
|
||||
contentDescription = name,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
.size(72.dp)
|
||||
.clip(androidx.compose.foundation.shape.CircleShape)
|
||||
.background(NsSurface2),
|
||||
)
|
||||
Spacer(Modifier.height(6.dp))
|
||||
Text(
|
||||
name, fontFamily = Outfit, fontSize = 12.sp, fontWeight = FontWeight.Medium,
|
||||
color = NsOnSurface, maxLines = 2, overflow = TextOverflow.Ellipsis,
|
||||
textAlign = androidx.compose.ui.text.style.TextAlign.Center,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user