fix(home,onboarding): correct navigation and state handling

This commit is contained in:
null 2026-06-16 02:18:28 -05:00
parent db177bc792
commit 342c3276a0
2 changed files with 106 additions and 39 deletions

View File

@ -1,5 +1,12 @@
package com.couplesconnect.app.ui.home
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@ -12,15 +19,18 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
@ -31,6 +41,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
@ -102,10 +113,6 @@ private fun HomeContent(
streakCount = state.streakCount
)
if (!state.isPaired && !state.isLoading) {
InvitePartnerCard(onInvite = onInvite)
}
when {
state.isLoading -> LoadingHomeCard()
state.error != null -> ErrorHomeCard(message = state.error, onRefresh = onRefresh)
@ -133,6 +140,16 @@ private fun HomeContent(
}
}
}
if (!state.isPaired && !state.isLoading) {
PulsingInviteFab(
onClick = onInvite,
modifier = Modifier
.align(Alignment.BottomEnd)
.navigationBarsPadding()
.padding(24.dp)
)
}
}
}
@ -169,44 +186,95 @@ private fun HomeHeader(
}
@Composable
private fun InvitePartnerCard(onInvite: () -> Unit) {
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(26.dp),
colors = CardDefaults.cardColors(containerColor = Color(0xFFFFF4F0)),
elevation = CardDefaults.cardElevation(defaultElevation = 6.dp)
private fun PulsingInviteFab(
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
val infiniteTransition = rememberInfiniteTransition(label = "fab_pulse")
val ring1Scale by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = 2.2f,
animationSpec = infiniteRepeatable(
animation = tween(1400, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "ring1"
)
val ring1Alpha by infiniteTransition.animateFloat(
initialValue = 0.6f,
targetValue = 0f,
animationSpec = infiniteRepeatable(
animation = tween(1400, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "ring1a"
)
val ring2Scale by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = 2.2f,
animationSpec = infiniteRepeatable(
animation = tween(1400, delayMillis = 500, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "ring2"
)
val ring2Alpha by infiniteTransition.animateFloat(
initialValue = 0.6f,
targetValue = 0f,
animationSpec = infiniteRepeatable(
animation = tween(1400, delayMillis = 500, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "ring2a"
)
val fabScale by infiniteTransition.animateFloat(
initialValue = 1f,
targetValue = 1.08f,
animationSpec = infiniteRepeatable(
animation = tween(700, easing = FastOutSlowInEasing),
repeatMode = RepeatMode.Reverse
),
label = "fabscale"
)
Box(
modifier = modifier.size(72.dp),
contentAlignment = Alignment.Center
) {
Row(
modifier = Modifier.padding(18.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically
// Expanding ring 1
Box(
modifier = Modifier
.size(56.dp)
.scale(ring1Scale)
.background(
color = Color(0xFFE07A5F).copy(alpha = ring1Alpha),
shape = CircleShape
)
)
// Expanding ring 2 (offset start)
Box(
modifier = Modifier
.size(56.dp)
.scale(ring2Scale)
.background(
color = Color(0xFFE07A5F).copy(alpha = ring2Alpha),
shape = CircleShape
)
)
// FAB
FloatingActionButton(
onClick = onClick,
modifier = Modifier.size(56.dp).scale(fabScale),
containerColor = Color(0xFFE07A5F),
contentColor = Color.White,
shape = CircleShape
) {
Icon(
Icons.Filled.Favorite,
contentDescription = null,
tint = Color(0xFFE07A5F),
Icons.Filled.Add,
contentDescription = "Invite partner",
modifier = Modifier.size(28.dp)
)
Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "Invite your partner",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = Color(0xFF27211F)
)
Text(
text = "Share a code to connect and start answering together.",
style = MaterialTheme.typography.bodySmall,
color = Color(0xFF4E4642)
)
}
Button(
onClick = onInvite,
shape = RoundedCornerShape(14.dp),
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFE07A5F))
) {
Text("Invite", color = Color.White)
}
}
}
}

View File

@ -37,8 +37,7 @@ class OnboardingViewModel @Inject constructor(
val user = runCatching { userRepository.getUser(authState.userId) }.getOrNull()
val destination = when {
user == null || user.displayName.isBlank() -> "create_profile"
user.coupleId != null -> "home"
else -> "create_invite"
else -> "home"
}
_uiState.update { it.copy(isCheckingAuth = false, navigateTo = destination) }
}