package com.craigvg.lichun_android.ui.components.indicators import androidx.compose.animation.core.* import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.craigvg.lichun_android.ui.theme.AppColors import com.craigvg.lichun_android.ui.theme.AppSpacing @Composable fun LoadingView( message: String = "Starting your life journey...", modifier: Modifier = Modifier ) { val infiniteTransition = rememberInfiniteTransition(label = "loading") val pulseScale by infiniteTransition.animateFloat( initialValue = 0.92f, targetValue = 1.08f, animationSpec = infiniteRepeatable( animation = tween(1500, easing = EaseInOut), repeatMode = RepeatMode.Reverse ), label = "pulse" ) val bounceOffset by infiniteTransition.animateFloat( initialValue = 0f, targetValue = -12f, animationSpec = infiniteRepeatable( animation = tween(1800, easing = EaseInOut), repeatMode = RepeatMode.Reverse ), label = "bounce" ) val dotScale1 by infiniteTransition.animateFloat( initialValue = 0.7f, targetValue = 1.3f, animationSpec = infiniteRepeatable( animation = tween(800, easing = EaseInOut), repeatMode = RepeatMode.Reverse ), label = "dot1" ) val dotScale2 by infiniteTransition.animateFloat( initialValue = 1.3f, targetValue = 0.7f, animationSpec = infiniteRepeatable( animation = tween(800, easing = EaseInOut, delayMillis = 200), repeatMode = RepeatMode.Reverse ), label = "dot2" ) val dotScale3 by infiniteTransition.animateFloat( initialValue = 0.7f, targetValue = 1.3f, animationSpec = infiniteRepeatable( animation = tween(800, easing = EaseInOut, delayMillis = 400), repeatMode = RepeatMode.Reverse ), label = "dot3" ) Box( modifier = modifier .fillMaxSize() .background( Brush.verticalGradient( colors = listOf( Color(0xFFFFF5F0), Color(0xFFFFE8DC), Color(0xFFFFD6C4), AppColors.surfaceElevated.copy(alpha = 0.8f) ) ) ), contentAlignment = Alignment.Center ) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center ) { Spacer(modifier = Modifier.weight(1f)) // Heart icon with bounce Box(contentAlignment = Alignment.Center) { // Glow ring Box( modifier = Modifier .size(120.dp) .scale(pulseScale) .alpha(0.3f) .background( Brush.radialGradient( colors = listOf( Color(0xFFFFB4D2).copy(alpha = 0.3f), Color.Transparent ) ), CircleShape ) ) Icon( imageVector = Icons.Default.Favorite, contentDescription = null, modifier = Modifier .size(50.dp) .scale(pulseScale) .offset(y = bounceOffset.dp), tint = Color(0xFFFFB4D2) ) } Spacer(modifier = Modifier.height(AppSpacing.lg)) // App name Text( text = "BaoLife", fontSize = 48.sp, fontWeight = FontWeight.Bold, color = AppColors.primary ) Text( text = "Your Life Awaits", fontSize = 16.sp, fontWeight = FontWeight.Medium, color = AppColors.secondaryText, letterSpacing = 2.sp ) Spacer(modifier = Modifier.weight(1f)) // Loading dots Row( horizontalArrangement = Arrangement.spacedBy(AppSpacing.sm), verticalAlignment = Alignment.CenterVertically ) { listOf(dotScale1, dotScale2, dotScale3).forEach { scale -> Box( modifier = Modifier .size(12.dp) .scale(scale) .background( Brush.linearGradient( listOf(AppColors.primary, AppColors.accent) ), CircleShape ) ) } } Spacer(modifier = Modifier.height(AppSpacing.md)) Text( text = message, fontSize = 14.sp, fontWeight = FontWeight.Medium, color = AppColors.secondaryText, textAlign = TextAlign.Center, modifier = Modifier.padding(horizontal = AppSpacing.lg) ) Spacer(modifier = Modifier.height(AppSpacing.xxl)) } } }