compute and persist the artist name busy flag with the artwork seed

- ArtworkSeedStore now carries the flag; artwork_seeds gains a nullable nameBusy column
  (DB v12, migration 11->12) so it survives cold starts with no decode
- resolve() computes the flag from the same bitmap it extracts the colour seed from, so
  there is no second decode, and persists it alongside the seed
- overlaidNameBusy reuses the seed job and reads the cached flag synchronously, so the
  scrim is known before the art shows; drop the fade
- bottomBandBusy now uses perceptual (gamma-space) luma, edge density and a bright
  fraction, which catches busy art on dark backgrounds (issue #40) that mean/variance missed
This commit is contained in:
austinried
2026-10-04 00:29:58 +00:00
parent 658b7f9452
commit f4ca0fd6d4
8 changed files with 916 additions and 48 deletions
@@ -1,7 +1,5 @@
package com.subtracks.ui.library
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -73,7 +71,6 @@ private val ART_HEIGHT = 420.dp
private val TITLE_INSET = 16.dp
private val FADE_LEAD = 24.dp
private const val THEME_TRANSITION_MS = 100
private const val SCRIM_FADE_MS = 180
internal const val ARTIST_NAME_SCRIM_TAG = "artistNameScrim"
@Composable
@@ -148,7 +145,6 @@ fun ArtistDetailScreen(
),
)
val nameBusy = rememberOverlaidNameBusy(art ?: artThumbnail)
val nameScrimAlpha by animateFloatAsState(if (nameBusy) 1f else 0f, tween(SCRIM_FADE_MS), label = "artistNameScrim")
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onBackground) {
ArtworkTheme(artwork) {
@@ -185,14 +181,13 @@ fun ArtistDetailScreen(
showPlaceholder = art == null,
modifier = Modifier.fillMaxWidth().height(ART_HEIGHT),
)
if (nameScrimAlpha > 0f) {
if (nameBusy) {
Box(
modifier =
Modifier
.align(Alignment.BottomStart)
.fillMaxWidth()
.height(ART_HEIGHT * 0.4f)
.graphicsLayer { alpha = nameScrimAlpha }
.background(
Brush.verticalGradient(
listOf(Color.Transparent, Color.Black.copy(alpha = 0.6f)),