package com.suno.android.common_ui.components.aura import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import kotlinx.coroutines.android.awaitFrame import kotlinx.coroutines.isActive import kotlin.time.Duration.Companion.nanoseconds import kotlin.time.DurationUnit @Composable fun rememberAuraState( enabled: Boolean = true, ): AuraState { val state = remember { AuraState(initialEnabled = enabled) } // used to delay pausing timer until disable animation is finished var shouldCountTime by remember { mutableStateOf(enabled) } /* * used to animate enable/disable transition. Brings animation to a smooth stop, and smoothly transitions colors to gray */ LaunchedEffect(enabled) { state.enabledScalar.animateTo( targetValue = if (enabled) 1f else 0f, animationSpec = spring( stiffness = Spring.StiffnessVeryLow, ), ) shouldCountTime = enabled } LaunchedEffect(shouldCountTime) { var lastTime = awaitFrame() while (isActive && shouldCountTime) { val newTime = awaitFrame() val delta = newTime - lastTime lastTime = newTime state.time += delta.nanoseconds.toDouble(DurationUnit.SECONDS).toFloat() * state.enabledScalar.value } } return state } class AuraState( initialTime: Float = 0f, initialEnabled: Boolean = true, ) { var time by mutableStateOf(initialTime) var enabledScalar = Animatable(if (initialEnabled) 1f else 0f) }