Enhance UI animations in SetPasswordScreen and SplashScreen

- Added animated visibility for elements in SetPasswordScreen to improve user experience during password setup.
- Introduced fade and scale animations for icons and text in SetPasswordScreen.
- Updated SplashScreen to include alpha animations for smoother transitions.
- Adjusted animation parameters for better performance and visual appeal.
- Addressed deprecation warnings related to Gradle configurations in the project.
This commit is contained in:
k1ngsterr1
2026-01-08 20:04:43 +05:00
parent 42ddfe5b18
commit fc54cc89df
5 changed files with 433 additions and 218 deletions

View File

@@ -50,6 +50,11 @@ fun ConfirmSeedPhraseScreen(
var userInputs by remember { mutableStateOf(List(4) { "" }) }
var showError by remember { mutableStateOf(false) }
var visible by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
visible = true
}
val allCorrect = wordsToConfirm.mapIndexed { i, (_, word) ->
userInputs[i].trim().lowercase() == word.lowercase()
@@ -100,7 +105,14 @@ fun ConfirmSeedPhraseScreen(
Spacer(modifier = Modifier.height(16.dp))
// Info Card
Row(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500)) + slideInVertically(
initialOffsetY = { -30 },
animationSpec = tween(500)
)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
@@ -122,6 +134,7 @@ fun ConfirmSeedPhraseScreen(
lineHeight = 18.sp
)
}
}
Spacer(modifier = Modifier.height(32.dp))
@@ -131,18 +144,26 @@ fun ConfirmSeedPhraseScreen(
wordsToConfirm[index].second.lowercase()
val hasInput = userInputs[index].isNotBlank()
WordInputField(
wordNumber = wordIndex + 1,
value = userInputs[index],
onValueChange = {
userInputs = userInputs.toMutableList().apply {
this[index] = it
}
showError = false
},
isCorrect = if (hasInput) isCorrect else null,
isDarkTheme = isDarkTheme
)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 100 + (index * 100))) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 100 + (index * 100))
)
) {
WordInputField(
wordNumber = wordIndex + 1,
value = userInputs[index],
onValueChange = {
userInputs = userInputs.toMutableList().apply {
this[index] = it
}
showError = false
},
isCorrect = if (hasInput) isCorrect else null,
isDarkTheme = isDarkTheme
)
}
Spacer(modifier = Modifier.height(16.dp))
}
@@ -164,7 +185,14 @@ fun ConfirmSeedPhraseScreen(
Spacer(modifier = Modifier.weight(1f))
// Continue Button
Button(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 500)) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 500)
)
) {
Button(
onClick = {
if (allCorrect) {
onConfirmed()
@@ -186,6 +214,7 @@ fun ConfirmSeedPhraseScreen(
fontWeight = FontWeight.SemiBold
)
}
}
Spacer(modifier = Modifier.height(32.dp))
}

View File

@@ -82,36 +82,56 @@ fun ImportSeedPhraseScreen(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(600, easing = FastOutSlowInEasing))
enter = fadeIn(tween(500, easing = FastOutSlowInEasing))
) {
Column(
modifier = Modifier
.fillMaxSize()
.fillMaxWidth()
.padding(horizontal = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Import Account",
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
color = textColor
)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500)) + slideInVertically(
initialOffsetY = { -20 },
animationSpec = tween(500)
)
) {
Text(
text = "Import Account",
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
color = textColor
)
}
Spacer(modifier = Modifier.height(12.dp))
Text(
text = "Enter your 12-word recovery phrase",
fontSize = 15.sp,
color = secondaryTextColor,
textAlign = TextAlign.Center
)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 100))
) {
Text(
text = "Enter your 12-word recovery phrase",
fontSize = 15.sp,
color = secondaryTextColor,
textAlign = TextAlign.Center
)
}
Spacer(modifier = Modifier.height(24.dp))
// Paste button
Button(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 200)) + scaleIn(
initialScale = 0.9f,
animationSpec = tween(500, delayMillis = 200)
)
) {
Button(
onClick = { showPasteDialog = true },
modifier = Modifier
.fillMaxWidth()
@@ -134,11 +154,16 @@ fun ImportSeedPhraseScreen(
fontWeight = FontWeight.SemiBold
)
}
}
Spacer(modifier = Modifier.height(24.dp))
// Clean grid
Column(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 300))
) {
Column(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
@@ -169,22 +194,35 @@ fun ImportSeedPhraseScreen(
}
}
}
}
// Error
if (error != null) {
Spacer(modifier = Modifier.height(12.dp))
Text(
text = error ?: "",
fontSize = 14.sp,
color = Color(0xFFE53935),
textAlign = TextAlign.Center
)
AnimatedVisibility(
visible = true,
enter = fadeIn(tween(300)) + scaleIn(initialScale = 0.9f)
) {
Text(
text = error ?: "",
fontSize = 14.sp,
color = Color(0xFFE53935),
textAlign = TextAlign.Center
)
}
}
Spacer(modifier = Modifier.weight(1f))
// Import button
Button(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 400)) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 400)
)
) {
Button(
onClick = {
val seedPhrase = words.map { it.trim() }
@@ -213,6 +251,7 @@ fun ImportSeedPhraseScreen(
shape = RoundedCornerShape(12.dp)
) {
Text("Continue", fontSize = 17.sp, fontWeight = FontWeight.Medium)
}
}
Spacer(modifier = Modifier.height(40.dp))

View File

@@ -66,34 +66,46 @@ fun SeedPhraseScreen(
}
}
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(300, easing = FastOutSlowInEasing))
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally
Spacer(modifier = Modifier.height(16.dp))
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500)) + slideInVertically(
initialOffsetY = { -20 },
animationSpec = tween(500)
)
) {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Your Recovery Phrase",
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
color = textColor
)
}
Spacer(modifier = Modifier.height(12.dp))
Text(
text = "Write down these 12 words in order.\nYou'll need them to restore your account.",
fontSize = 15.sp,
color = secondaryTextColor,
textAlign = TextAlign.Center,
lineHeight = 22.sp
)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 100)) + slideInVertically(
initialOffsetY = { -20 },
animationSpec = tween(500, delayMillis = 100)
)
) {
Text(
text = "Write down these 12 words in order.\nYou'll need them to restore your account.",
fontSize = 15.sp,
color = secondaryTextColor,
textAlign = TextAlign.Center,
lineHeight = 22.sp
)
}
Spacer(modifier = Modifier.height(32.dp))
@@ -112,35 +124,44 @@ fun SeedPhraseScreen(
)
}
} else {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 200))
) {
// Left column (words 1-6)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(12.dp)
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
for (i in 0..5) {
WordItem(
number = i + 1,
word = seedPhrase[i],
isDarkTheme = isDarkTheme
)
// Left column (words 1-6)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
for (i in 0..5) {
AnimatedWordItem(
number = i + 1,
word = seedPhrase[i],
isDarkTheme = isDarkTheme,
visible = visible,
delay = 300 + (i * 50)
)
}
}
}
// Right column (words 7-12)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
for (i in 6..11) {
WordItem(
number = i + 1,
word = seedPhrase[i],
isDarkTheme = isDarkTheme
)
// Right column (words 7-12)
Column(
modifier = Modifier.weight(1f),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
for (i in 6..11) {
AnimatedWordItem(
number = i + 1,
word = seedPhrase[i],
isDarkTheme = isDarkTheme,
visible = visible,
delay = 300 + (i * 50)
)
}
}
}
}
@@ -150,56 +171,71 @@ fun SeedPhraseScreen(
// Copy button
if (!isGenerating) {
TextButton(
onClick = {
hasCopied = true
scope.launch {
delay(2000)
hasCopied = false
}
}
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 600)) + scaleIn(
initialScale = 0.8f,
animationSpec = tween(500, delayMillis = 600)
)
) {
Icon(
imageVector = if (hasCopied) Icons.Default.Check else Icons.Default.ContentCopy,
contentDescription = null,
tint = if (hasCopied) Color(0xFF4CAF50) else PrimaryBlue,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = if (hasCopied) "Copied" else "Copy to clipboard",
color = if (hasCopied) Color(0xFF4CAF50) else PrimaryBlue,
fontSize = 15.sp
)
TextButton(
onClick = {
hasCopied = true
scope.launch {
delay(2000)
hasCopied = false
}
}
) {
Icon(
imageVector = if (hasCopied) Icons.Default.Check else Icons.Default.ContentCopy,
contentDescription = null,
tint = if (hasCopied) Color(0xFF4CAF50) else PrimaryBlue,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = if (hasCopied) "Copied" else "Copy to clipboard",
color = if (hasCopied) Color(0xFF4CAF50) else PrimaryBlue,
fontSize = 15.sp
)
}
}
}
Spacer(modifier = Modifier.weight(1f))
// Continue button
Button(
onClick = { onConfirm(seedPhrase) },
enabled = !isGenerating,
modifier = Modifier
.fillMaxWidth()
.height(50.dp),
colors = ButtonDefaults.buttonColors(
containerColor = PrimaryBlue,
contentColor = Color.White,
disabledContainerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8),
disabledContentColor = if (isDarkTheme) Color(0xFF666666) else Color(0xFF999999)
),
shape = RoundedCornerShape(12.dp)
) {
Text(
text = "Continue",
fontSize = 17.sp,
fontWeight = FontWeight.Medium
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 700)) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 700)
)
) {
Button(
onClick = { onConfirm(seedPhrase) },
enabled = !isGenerating,
modifier = Modifier
.fillMaxWidth()
.height(50.dp),
colors = ButtonDefaults.buttonColors(
containerColor = PrimaryBlue,
contentColor = Color.White,
disabledContainerColor = if (isDarkTheme) Color(0xFF3A3A3A) else Color(0xFFE8E8E8),
disabledContentColor = if (isDarkTheme) Color(0xFF666666) else Color(0xFF999999)
),
shape = RoundedCornerShape(12.dp)
) {
Text(
text = "Continue",
fontSize = 17.sp,
fontWeight = FontWeight.Medium
)
}
}
Spacer(modifier = Modifier.height(40.dp))
}
Spacer(modifier = Modifier.height(40.dp))
}
}
}
@@ -239,3 +275,28 @@ private fun WordItem(
)
}
}
@Composable
private fun AnimatedWordItem(
number: Int,
word: String,
isDarkTheme: Boolean,
visible: Boolean,
delay: Int,
modifier: Modifier = Modifier
) {
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(400, delayMillis = delay)) + slideInHorizontally(
initialOffsetX = { if (number <= 6) -50 else 50 },
animationSpec = tween(400, delayMillis = delay)
)
) {
WordItem(
number = number,
word = word,
isDarkTheme = isDarkTheme,
modifier = modifier
)
}
}

View File

@@ -54,6 +54,11 @@ fun SetPasswordScreen(
var confirmPasswordVisible by remember { mutableStateOf(false) }
var isCreating by remember { mutableStateOf(false) }
var error by remember { mutableStateOf<String?>(null) }
var visible by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
visible = true
}
val passwordsMatch = password == confirmPassword && password.isNotEmpty()
val passwordStrong = password.length >= 6
@@ -104,44 +109,72 @@ fun SetPasswordScreen(
Spacer(modifier = Modifier.height(16.dp))
// Lock Icon
Box(
modifier = Modifier
.size(80.dp)
.clip(RoundedCornerShape(20.dp))
.background(PrimaryBlue.copy(alpha = 0.1f)),
contentAlignment = Alignment.Center
) {
Icon(
Icons.Default.Lock,
contentDescription = null,
tint = PrimaryBlue,
modifier = Modifier.size(40.dp)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500)) + scaleIn(
initialScale = 0.5f,
animationSpec = tween(500, easing = FastOutSlowInEasing)
)
) {
Box(
modifier = Modifier
.size(80.dp)
.clip(RoundedCornerShape(20.dp))
.background(PrimaryBlue.copy(alpha = 0.1f)),
contentAlignment = Alignment.Center
) {
Icon(
Icons.Default.Lock,
contentDescription = null,
tint = PrimaryBlue,
modifier = Modifier.size(40.dp)
)
}
}
Spacer(modifier = Modifier.height(24.dp))
Text(
text = "Protect Your Account",
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = textColor
)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 100)) + slideInVertically(
initialOffsetY = { -20 },
animationSpec = tween(500, delayMillis = 100)
)
) {
Text(
text = "Protect Your Account",
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
color = textColor
)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = "This password encrypts your keys locally.\nYou'll need it to unlock Rosetta.",
fontSize = 14.sp,
color = secondaryTextColor,
textAlign = TextAlign.Center,
lineHeight = 20.sp
)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 200))
) {
Text(
text = "This password encrypts your keys locally.\nYou'll need it to unlock Rosetta.",
fontSize = 14.sp,
color = secondaryTextColor,
textAlign = TextAlign.Center,
lineHeight = 20.sp
)
}
Spacer(modifier = Modifier.height(32.dp))
// Password Field
OutlinedTextField(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 300)) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 300)
)
) {
OutlinedTextField(
value = password,
onValueChange = {
password = it
@@ -176,43 +209,59 @@ fun SetPasswordScreen(
imeAction = ImeAction.Next
)
)
}
// Password strength indicator
if (password.isNotEmpty()) {
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(400, delayMillis = 350)) + slideInHorizontally(
initialOffsetX = { -30 },
animationSpec = tween(400, delayMillis = 350)
)
) {
val strength = when {
password.length < 6 -> "Weak"
password.length < 10 -> "Medium"
else -> "Strong"
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
val strength = when {
password.length < 6 -> "Weak"
password.length < 10 -> "Medium"
else -> "Strong"
}
val strengthColor = when {
password.length < 6 -> Color(0xFFE53935)
password.length < 10 -> Color(0xFFFFA726)
else -> Color(0xFF4CAF50)
}
Icon(
imageVector = Icons.Default.Shield,
contentDescription = null,
tint = strengthColor,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "Password strength: $strength",
fontSize = 12.sp,
color = strengthColor
)
}
val strengthColor = when {
password.length < 6 -> Color(0xFFE53935)
password.length < 10 -> Color(0xFFFFA726)
else -> Color(0xFF4CAF50)
}
Icon(
imageVector = Icons.Default.Shield,
contentDescription = null,
tint = strengthColor,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "Password strength: $strength",
fontSize = 12.sp,
color = strengthColor
)
}
}
Spacer(modifier = Modifier.height(16.dp))
// Confirm Password Field
OutlinedTextField(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 400)) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 400)
)
) {
OutlinedTextField(
value = confirmPassword,
onValueChange = {
confirmPassword = it
@@ -248,74 +297,100 @@ fun SetPasswordScreen(
imeAction = ImeAction.Done
)
)
}
// Match indicator
if (confirmPassword.isNotEmpty()) {
Spacer(modifier = Modifier.height(8.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
val matchIcon = if (passwordsMatch) Icons.Default.Check else Icons.Default.Close
val matchColor = if (passwordsMatch) Color(0xFF4CAF50) else Color(0xFFE53935)
val matchText = if (passwordsMatch) "Passwords match" else "Passwords don't match"
Icon(
imageVector = matchIcon,
contentDescription = null,
tint = matchColor,
modifier = Modifier.size(16.dp)
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(400, delayMillis = 450)) + slideInHorizontally(
initialOffsetX = { -30 },
animationSpec = tween(400, delayMillis = 450)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = matchText,
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
val matchIcon = if (passwordsMatch) Icons.Default.Check else Icons.Default.Close
val matchColor = if (passwordsMatch) Color(0xFF4CAF50) else Color(0xFFE53935)
val matchText = if (passwordsMatch) "Passwords match" else "Passwords don't match"
Icon(
imageVector = matchIcon,
contentDescription = null,
tint = matchColor,
modifier = Modifier.size(16.dp)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = matchText,
fontSize = 12.sp,
color = matchColor
)
}
}
}
// Error message
error?.let { errorMsg ->
Spacer(modifier = Modifier.height(16.dp))
Text(
text = errorMsg,
fontSize = 14.sp,
color = Color(0xFFE53935),
textAlign = TextAlign.Center
)
AnimatedVisibility(
visible = true,
enter = fadeIn(tween(300)) + scaleIn(initialScale = 0.9f)
) {
Text(
text = errorMsg,
fontSize = 14.sp,
color = Color(0xFFE53935),
textAlign = TextAlign.Center
)
}
}
Spacer(modifier = Modifier.weight(1f))
// Info
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.background(cardColor)
.padding(16.dp),
verticalAlignment = Alignment.Top
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 500))
) {
Icon(
imageVector = Icons.Default.Info,
contentDescription = null,
tint = PrimaryBlue,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "Your password is never stored or sent anywhere. It's only used to encrypt your keys locally.",
fontSize = 13.sp,
color = secondaryTextColor,
lineHeight = 18.sp
)
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.background(cardColor)
.padding(16.dp),
verticalAlignment = Alignment.Top
) {
Icon(
imageVector = Icons.Default.Info,
contentDescription = null,
tint = PrimaryBlue,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "Your password is never stored or sent anywhere. It's only used to encrypt your keys locally.",
fontSize = 13.sp,
color = secondaryTextColor,
lineHeight = 18.sp
)
}
}
Spacer(modifier = Modifier.height(16.dp))
// Create Account Button
Button(
AnimatedVisibility(
visible = visible,
enter = fadeIn(tween(500, delayMillis = 600)) + slideInVertically(
initialOffsetY = { 50 },
animationSpec = tween(500, delayMillis = 600)
)
) {
Button(
onClick = {
if (!passwordStrong) {
error = "Password must be at least 6 characters"
@@ -384,8 +459,7 @@ fun SetPasswordScreen(
fontWeight = FontWeight.SemiBold
)
}
}
} }
Spacer(modifier = Modifier.height(32.dp))
}
}

View File

@@ -11,6 +11,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.rosetta.messenger.R
@@ -25,16 +26,23 @@ fun SplashScreen(
// Animation states
var startAnimation by remember { mutableStateOf(false) }
var alphaValue by remember { mutableStateOf(0f) }
val scale by animateFloatAsState(
targetValue = if (startAnimation) 1f else 0f,
targetValue = if (startAnimation) 1f else 0.3f,
animationSpec = spring(
dampingRatio = 0.5f,
dampingRatio = 0.6f,
stiffness = Spring.StiffnessLow
),
label = "scale"
)
val alpha by animateFloatAsState(
targetValue = alphaValue,
animationSpec = tween(600, easing = FastOutSlowInEasing),
label = "alpha"
)
val pulseScale by rememberInfiniteTransition(label = "pulse").animateFloat(
initialValue = 1f,
targetValue = 1.1f,
@@ -46,6 +54,8 @@ fun SplashScreen(
)
LaunchedEffect(Unit) {
delay(100)
alphaValue = 1f
startAnimation = true
delay(2000) // Show splash for 2 seconds
onSplashComplete()
@@ -62,6 +72,7 @@ fun SplashScreen(
modifier = Modifier
.size(180.dp)
.scale(scale * pulseScale)
.graphicsLayer { this.alpha = alpha }
.background(
color = Color(0xFF54A9EB).copy(alpha = 0.2f),
shape = CircleShape
@@ -75,6 +86,7 @@ fun SplashScreen(
modifier = Modifier
.size(150.dp)
.scale(scale)
.graphicsLayer { this.alpha = alpha }
.clip(CircleShape)
)
}