feat(subsonic): browse endpoints — getArtists/getAlbum/search3/… (#295) #8
@@ -27,15 +27,21 @@ private const val GRADIENT_TWEEN_MS = 600
|
|||||||
* androidx.palette on a background thread, and animates the result
|
* androidx.palette on a background thread, and animates the result
|
||||||
* via [animateColorAsState] so track changes tween smoothly.
|
* via [animateColorAsState] so track changes tween smoothly.
|
||||||
*
|
*
|
||||||
* Returns [Color.Transparent] while the bitmap is loading or on
|
* The held color is NOT reset when [coverUrl] changes — it stays on
|
||||||
* any failure — callers should layer a fallback (e.g.
|
* the previous track's dominant until the new palette resolves, so the
|
||||||
* `MaterialTheme.colorScheme.surface`) underneath the gradient
|
* gradient tweens old→new directly instead of dipping toward the
|
||||||
* tint so the screen never sits on a flat black.
|
* fallback mid-swap. Mirrors `now_playing_screen.dart`'s preload-then-
|
||||||
|
* swap ("keep the previous dominant"); the cover image swaps smoothly
|
||||||
|
* via `CoverPrefetcher`, which warms the next track's bytes into Coil.
|
||||||
|
*
|
||||||
|
* Starts at [Color.Transparent] (cold mount) and resets to it only
|
||||||
|
* when a track has no cover — callers layer a base color underneath so
|
||||||
|
* the screen never sits on flat black.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun rememberDominantColor(coverUrl: String?): Color {
|
fun rememberDominantColor(coverUrl: String?): Color {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var extracted by remember(coverUrl) { mutableStateOf(Color.Transparent) }
|
var extracted by remember { mutableStateOf(Color.Transparent) }
|
||||||
|
|
||||||
LaunchedEffect(coverUrl) {
|
LaunchedEffect(coverUrl) {
|
||||||
if (coverUrl.isNullOrEmpty()) {
|
if (coverUrl.isNullOrEmpty()) {
|
||||||
@@ -47,6 +53,7 @@ fun rememberDominantColor(coverUrl: String?): Color {
|
|||||||
.allowHardware(false)
|
.allowHardware(false)
|
||||||
.build()
|
.build()
|
||||||
val result = SingletonImageLoader.get(context).execute(request)
|
val result = SingletonImageLoader.get(context).execute(request)
|
||||||
|
// Keep the previous dominant on load failure rather than dropping.
|
||||||
if (result !is SuccessResult) return@LaunchedEffect
|
if (result !is SuccessResult) return@LaunchedEffect
|
||||||
val bitmap = result.image.toBitmap()
|
val bitmap = result.image.toBitmap()
|
||||||
val palette = withContext(Dispatchers.Default) {
|
val palette = withContext(Dispatchers.Default) {
|
||||||
|
|||||||
Reference in New Issue
Block a user