desaturate the playing row's art behind the primary indicator

Back to the primary border and glyph, and drop the playing cover's
saturation so the accent reads against its own artwork.
This commit is contained in:
austinried
2026-10-04 00:30:02 +00:00
parent 3eef4e79b6
commit aa954ffc3e
2 changed files with 14 additions and 2 deletions
@@ -32,6 +32,7 @@ import androidx.compose.ui.draw.shadow
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.FilterQuality
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
@@ -70,6 +71,7 @@ fun CoverArt(
showPlaceholder: Boolean = true,
square: Boolean = true,
elevation: Dp = 0.dp,
colorFilter: ColorFilter? = null,
) {
val context = LocalPlatformContext.current
var failed by remember(ref, thumbnailRef) { mutableStateOf(false) }
@@ -93,6 +95,7 @@ fun CoverArt(
onThumbnailLoaded = { thumbnailLoaded = true },
onThumbnailRatio = { thumbnailRatio = it },
contentScale = ContentScale.Crop,
colorFilter = colorFilter,
) {
if (ref != null) {
AsyncImage(
@@ -100,6 +103,7 @@ fun CoverArt(
contentDescription = null,
contentScale = ContentScale.Crop,
filterQuality = FilterQuality.High,
colorFilter = colorFilter,
onSuccess = { success ->
success.painter.intrinsicSize
.ratioOrNull()
@@ -154,12 +158,14 @@ fun CoverArt(
onThumbnailLoaded = { thumbnailLoaded = true },
onThumbnailRatio = { thumbnailRatio = it },
contentScale = ContentScale.Fit,
colorFilter = colorFilter,
) {
if (ref != null) {
Image(
painter = painter,
contentDescription = null,
contentScale = ContentScale.Fit,
colorFilter = colorFilter,
modifier = Modifier.fillMaxSize(),
)
}
@@ -180,6 +186,7 @@ private fun BoxScope.CoverArtContent(
onThumbnailLoaded: () -> Unit,
onThumbnailRatio: (Float) -> Unit,
contentScale: ContentScale,
colorFilter: ColorFilter?,
main: @Composable () -> Unit,
) {
val context = LocalPlatformContext.current
@@ -196,6 +203,7 @@ private fun BoxScope.CoverArtContent(
model = remember(thumbnailRef) { imageRequest(context, thumbnailRef, crossfade = false) },
contentDescription = null,
contentScale = contentScale,
colorFilter = colorFilter,
onSuccess = { success ->
onThumbnailLoaded()
success.painter.intrinsicSize
@@ -30,6 +30,8 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.geometry.RoundRect
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.ColorMatrix
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.PathOperation
import androidx.compose.ui.graphics.asAndroidPath
@@ -66,6 +68,7 @@ private val PLAY_SHADOW_RADIUS = 3.dp
private val PLAY_SHADOW = Color.Black.copy(alpha = 0.6f)
private val INNER_SHADOW_RADIUS = 8.dp
private val INNER_SHADOW = Color.Black.copy(alpha = 0.85f)
private val DESATURATE = ColorFilter.colorMatrix(ColorMatrix().apply { setToSaturation(0.45f) })
private val PLAY_ARROW = Icons.Rounded.PlayArrow
private val PLAY_ARROW_PATH: Path by lazy { buildVectorPath(PLAY_ARROW) }
@@ -168,13 +171,14 @@ private fun CoverArtCell(
ref = ref,
name = name,
modifier = Modifier.size(48.dp).clip(shape),
colorFilter = if (isPlaying) DESATURATE else null,
)
if (isPlaying) {
Box(Modifier.matchParentSize().drawBehind { drawInnerShadow() })
Box(
Modifier
.matchParentSize()
.border(1.5.dp, Color.White, shape),
.border(1.5.dp, MaterialTheme.colorScheme.primary, shape),
)
PlayIndicator(
shadow = true,
@@ -216,7 +220,7 @@ private fun PlayIndicator(
shadow: Boolean,
modifier: Modifier = Modifier,
) {
val tint = Color.White
val tint = MaterialTheme.colorScheme.primary
if (shadow) {
val radius = with(LocalDensity.current) { PLAY_SHADOW_RADIUS.toPx() }
Canvas(modifier.semantics { contentDescription = "Playing" }) {