DemandAttention.kt

/*
 * This file is part of GNU Taler
 * (C) 2024 Taler Systems S.A.
 *
 * GNU Taler is free software; you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3, or (at your option) any later version.
 *
 * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
 */

package net.taler.wallet.compose

import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.repeatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.offset
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay

@Composable
fun DemandAttention(
    initialDelayMillis: Long = 400,
    wiggleWidth: Float = 5f,
    wiggleCount: Int = 2,
    demandAttention: Boolean = true,
    content: @Composable () -> Unit,
) {
    val offsetX = remember { Animatable(0f) }

    suspend fun wiggle() {
        offsetX.animateTo(
            targetValue = -wiggleWidth,
            animationSpec = tween(80, easing = LinearEasing),
        )

        offsetX.animateTo(
            targetValue = wiggleWidth,
            animationSpec = repeatable(
                iterations = 5,
                animation = tween(90, easing = LinearEasing),
                repeatMode = RepeatMode.Reverse,
            )
        )

        offsetX.animateTo(
            targetValue = 0f,
            animationSpec = tween(80, easing = LinearEasing),
        )
    }

    LaunchedEffect(demandAttention) {
        if (demandAttention) {
            delay(initialDelayMillis)
            repeat(wiggleCount) {
                wiggle()
            }
        }
    }

    Box(Modifier.offset(offsetX.value.dp, 0.dp)) {
        content()
    }
}