Skip to content

Instantly share code, notes, and snippets.

val cards = Cards(
initialItems = listOf(
Routing.ProfileCard(0, "Lara"), // Will be top
Routing.ProfileCard(1, "Kate"), // Will be bottom
Routing.ProfileCard(2, "Brad"), // Queued = 0
Routing.ProfileCard(3, "Megan"), // ...etc.
Routing.ProfileCard(4, "Michael"),
Routing.ProfileCard(0, "Lara"),
Routing.ProfileCard(1, "Kate"),
Routing.ProfileCard(2, "Brad"),
lifecycle.coroutineScope.launchWhenStarted {
delay(1000)
repeat(3) {
delay(2000)
cards.indicateLike()
delay(1000)
cards.indicatePass()
delay(1000)
cards.votePass()
delay(1000)
class CardsTransitionHandler<T>(
private val transitionSpec: TransitionSpec<Cards.State, Float> = {
spring(stiffness = Spring.StiffnessVeryLow)
}
) : ModifierTransitionHandler<T, Cards.State>() {
private fun Cards.State.toProps() =
when (this) {
is Queued -> queued
is Bottom -> bottom
private fun Cards.State.toProps() =
when (this) {
is Queued -> queued
is Bottom -> bottom
is Top -> top
is VoteLike -> voteLike
is VotePass -> votePass
}
// Scaled down to 0% (not visible)
private val queued = Props(
scale = 0f,
)
// Scaled down to 85%
private val bottom = Props(
scale = 0.85f,
)
data class Props(
val offsetX: Dp = 0.dp,
val scale: Float = 1f,
val rotationZ: Float = 0f,
val zIndex: Float = 0f,
)
internal class PromoteAll<T : Any> : CardsOperation<T> {
override fun invoke(elements: CardsElements<T>): CardsElements<T> =
elements.map {
it.transitionTo(
// This uses State.next() we defined earlier:
newTargetState = it.targetState.next(),
operation = this
)
}
class VoteLike<T : Any> internal constructor() : CardsOperation<T> {
// Returns a modified list of elements with new target states applied
override fun invoke(elements: CardsElements<T>): CardsElements<T> =
elements.map { element ->
if (element.targetState == Cards.State.Top) {
element.transitionTo(
newTargetState = Cards.State.VoteLike,
operation = this
)
class Cards<T : Any>(
initialItems: List<T> = listOf(),
) : BaseNavModel<T, State>(
screenResolver = CardsOnScreenResolver, // <- What's on screen?
finalStates = setOf(VoteLike, VotePass), // <- What's destroyed?
savedStateMap = null
)
internal object CardsOnScreenResolver : OnScreenStateResolver<State> {
override fun isOnScreen(state: State): Boolean =
when (state) {
is State.Bottom,
is State.Top -> true
is State.Queued,
is State.VoteLike,
is State.VotePass -> false
}
}