mirror of
https://github.com/austinried/subtracks.git
synced 2026-11-11 15:29:15 +01:00
keep the artwork transition animating when the base scheme changes
This commit is contained in:
@@ -9,6 +9,7 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.graphics.lerp
|
import androidx.compose.ui.graphics.lerp
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
@@ -40,12 +41,14 @@ fun rememberAnimatedArtworkColors(
|
|||||||
): ArtworkColors {
|
): ArtworkColors {
|
||||||
var from by remember { mutableStateOf(target ?: base) }
|
var from by remember { mutableStateOf(target ?: base) }
|
||||||
var to by remember { mutableStateOf(target ?: base) }
|
var to by remember { mutableStateOf(target ?: base) }
|
||||||
|
var onBase by remember { mutableStateOf(target == null) }
|
||||||
val progress = remember { Animatable(1f) }
|
val progress = remember { Animatable(1f) }
|
||||||
|
val currentBase by rememberUpdatedState(base)
|
||||||
|
|
||||||
LaunchedEffect(target, base, durationMillis) {
|
LaunchedEffect(target, durationMillis) {
|
||||||
val next = target ?: base
|
val next = target ?: currentBase
|
||||||
if (next !== to) {
|
if (next === to) return@LaunchedEffect
|
||||||
if (to === base) {
|
if (onBase) {
|
||||||
from = next
|
from = next
|
||||||
to = next
|
to = next
|
||||||
} else {
|
} else {
|
||||||
@@ -54,7 +57,7 @@ fun rememberAnimatedArtworkColors(
|
|||||||
progress.snapTo(0f)
|
progress.snapTo(0f)
|
||||||
progress.animateTo(1f, tween(durationMillis = durationMillis))
|
progress.animateTo(1f, tween(durationMillis = durationMillis))
|
||||||
}
|
}
|
||||||
}
|
onBase = target == null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from === to) return to
|
if (from === to) return to
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import androidx.activity.ComponentActivity
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.graphics.luminance
|
import androidx.compose.ui.graphics.luminance
|
||||||
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
@@ -89,6 +91,47 @@ class ArtworkExtractionTest {
|
|||||||
assertEquals(artworkColorsFromSeed(placeholderSeed("Kid A")).scheme.primary, colors?.scheme?.primary)
|
assertEquals(artworkColorsFromSeed(placeholderSeed("Kid A")).scheme.primary, colors?.scheme?.primary)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun fadesFromThePlaceholderToTheArtworkSeed() {
|
||||||
|
val placeholder = artworkColorsFromSeed(placeholderSeed("Kid A"))
|
||||||
|
val art = artworkColorsFromSeed(0xFF3A7BD5.toInt())
|
||||||
|
val artwork = mutableStateOf(placeholder)
|
||||||
|
val seen = mutableListOf<androidx.compose.ui.graphics.Color>()
|
||||||
|
composeRule.setContent {
|
||||||
|
SubtracksTheme {
|
||||||
|
val colors = rememberAnimatedArtworkColors(artwork.value, baseArtworkColors())
|
||||||
|
SideEffect { seen += colors.scheme.background }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
composeRule.runOnIdle { artwork.value = art }
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
assertEquals(art.scheme.background, seen.last())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun aChangingBaseSchemeDoesNotStrandTheArtworkTransition() {
|
||||||
|
val placeholder = artworkColorsFromSeed(placeholderSeed("Kid A"))
|
||||||
|
val art = artworkColorsFromSeed(0xFF3A7BD5.toInt())
|
||||||
|
val artwork = mutableStateOf(placeholder)
|
||||||
|
var baseTick by mutableStateOf(0)
|
||||||
|
val seen = mutableListOf<androidx.compose.ui.graphics.Color>()
|
||||||
|
composeRule.setContent {
|
||||||
|
SubtracksTheme {
|
||||||
|
val base = remember(baseTick) { artworkColorsFromSeed(baseTick) }
|
||||||
|
val colors = rememberAnimatedArtworkColors(artwork.value, base)
|
||||||
|
SideEffect {
|
||||||
|
seen += colors.scheme.background
|
||||||
|
if (artwork.value !== placeholder && baseTick < 20) baseTick++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
composeRule.runOnIdle { artwork.value = art }
|
||||||
|
composeRule.waitForIdle()
|
||||||
|
assertEquals(art.scheme.background, seen.last())
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun keepsContentStateWhenArtworkArrives() {
|
fun keepsContentStateWhenArtworkArrives() {
|
||||||
val artwork = mutableStateOf<ArtworkColors?>(null)
|
val artwork = mutableStateOf<ArtworkColors?>(null)
|
||||||
|
|||||||
Reference in New Issue
Block a user