From 34c842c2d5f63626437f6eccbc2b01f9e9bf6865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Orzech?= Date: Wed, 28 Jan 2026 00:17:30 +0100 Subject: [PATCH] Refactor SunCard entrance animation to be shared Moved the entrance animation logic from SunCard to MainScreen so that all cards share a single entrance animation instance. SunCard now receives entranceProgress as a parameter, simplifying its internal state and ensuring consistent animation timing across cards. --- .../main/java/com/sunzones/ui/main/MainScreen.kt | 16 +++++++++++++++- .../com/sunzones/ui/main/components/SunCard.kt | 11 ++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/sunzones/ui/main/MainScreen.kt b/app/src/main/java/com/sunzones/ui/main/MainScreen.kt index 9b2b58d..b77b360 100644 --- a/app/src/main/java/com/sunzones/ui/main/MainScreen.kt +++ b/app/src/main/java/com/sunzones/ui/main/MainScreen.kt @@ -1,5 +1,8 @@ package com.sunzones.ui.main +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -15,6 +18,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -47,6 +51,15 @@ fun MainScreen( val uiState by viewModel.uiState.collectAsState() var showAddSheet by remember { mutableStateOf(false) } + // Entrance animation — runs once on screen load, shared by all cards + val entranceProgress = remember { Animatable(0f) } + LaunchedEffect(Unit) { + entranceProgress.animateTo( + targetValue = 1f, + animationSpec = tween(durationMillis = 1200, easing = FastOutSlowInEasing) + ) + } + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { viewModel.refresh() } @@ -110,7 +123,8 @@ fun MainScreen( onDelete = { viewModel.deleteLocation(location.id) }, monthlyDaylight = uiState.yearlyDaylight[location.id], gradientColors = blendedGradient, - pageOffset = pageOffset + pageOffset = pageOffset, + entranceProgress = entranceProgress.value ) } diff --git a/app/src/main/java/com/sunzones/ui/main/components/SunCard.kt b/app/src/main/java/com/sunzones/ui/main/components/SunCard.kt index 8d1274a..16663e9 100644 --- a/app/src/main/java/com/sunzones/ui/main/components/SunCard.kt +++ b/app/src/main/java/com/sunzones/ui/main/components/SunCard.kt @@ -86,6 +86,7 @@ fun SunCard( monthlyDaylight: List?, gradientColors: List = listOf(NightTop, NightBottom), pageOffset: Float = 0f, + entranceProgress: Float = 1f, modifier: Modifier = Modifier ) { var showDeleteDialog by remember { mutableStateOf(false) } @@ -99,15 +100,7 @@ fun SunCard( } } - // Step 5: Entrance animation - val entranceProgress = remember { Animatable(0f) } - LaunchedEffect(Unit) { - entranceProgress.animateTo( - targetValue = 1f, - animationSpec = tween(durationMillis = 1200, easing = FastOutSlowInEasing) - ) - } - val entrance = entranceProgress.value + val entrance = entranceProgress // Step 4: Living sky ambient val ambientTransition = rememberInfiniteTransition(label = "ambient")