diff --git a/feature/home/src/main/java/com/hanbang/home/result/LottoResultScreen.kt b/feature/home/src/main/java/com/hanbang/home/result/LottoResultScreen.kt index 82a9e4c..112ce41 100644 --- a/feature/home/src/main/java/com/hanbang/home/result/LottoResultScreen.kt +++ b/feature/home/src/main/java/com/hanbang/home/result/LottoResultScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush @@ -34,6 +35,11 @@ import androidx.compose.ui.res.vectorResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import com.airbnb.lottie.compose.LottieAnimation +import com.airbnb.lottie.compose.LottieCompositionSpec +import com.airbnb.lottie.compose.LottieConstants +import com.airbnb.lottie.compose.animateLottieCompositionAsState +import com.airbnb.lottie.compose.rememberLottieComposition import com.hanbang.designsystem.R import com.hanbang.designsystem.button.HbBoxButton import com.hanbang.designsystem.button.HbButtonColorType @@ -78,7 +84,7 @@ private fun LottoResultBackground( onClickBack: () -> Unit = {}, onClickHome: () -> Unit = {} ) { - Column( + Box( modifier = Modifier .fillMaxSize() .background( @@ -89,25 +95,54 @@ private fun LottoResultBackground( .systemBarsPadding() .navigationBarsPadding() ) { - TopAppBar( - title = "당첨 결과", - titleType = TopAppBarTitleType.CENTER, - contentColor = Gray1, - containerColor = Color.Transparent, - onNavigationClick = onClickBack + val confettiLottieComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(com.hanbang.home.R.raw.lotto_result_confetti)) + val confettiLottieProgress by animateLottieCompositionAsState( + composition = confettiLottieComposition, + isPlaying = true, + iterations = LottieConstants.IterateForever ) - LottoResultContent( + + LottieAnimation( + composition = confettiLottieComposition, + progress = { confettiLottieProgress }, modifier = Modifier - .weight(1f, fill = true), - state = state + .padding(top = 32.dp, start = 12.dp) + .size(146.dp) + .align(Alignment.TopStart) ) - HbBoxButton( - modifier = Modifier.padding(start = 24.dp, end = 24.dp, bottom = 24.dp), - text = "메인으로 가기", - colors = HbButtonColorType.primary, - styles = HbButtonStyles.large, - onClick = onClickHome + + LottieAnimation( + composition = confettiLottieComposition, + progress = { confettiLottieProgress }, + modifier = Modifier + .padding(top = 92.dp, end = 12.dp) + .size(146.dp) + .align(Alignment.TopEnd) ) + + Column( + modifier = Modifier.fillMaxSize() + ) { + TopAppBar( + title = "당첨 결과", + titleType = TopAppBarTitleType.CENTER, + contentColor = Gray1, + containerColor = Color.Transparent, + onNavigationClick = onClickBack + ) + LottoResultContent( + modifier = Modifier + .weight(1f, fill = true), + state = state + ) + HbBoxButton( + modifier = Modifier.padding(start = 24.dp, end = 24.dp, bottom = 24.dp), + text = "메인으로 가기", + colors = HbButtonColorType.primary, + styles = HbButtonStyles.large, + onClick = onClickHome + ) + } } } @@ -239,7 +274,9 @@ private fun LottoResultContent( }, style = SattoTheme.typography.body14Bold, color = Gray2, - modifier = Modifier.align(Alignment.CenterStart).padding(start = 24.dp) + modifier = Modifier + .align(Alignment.CenterStart) + .padding(start = 24.dp) ) } } diff --git a/feature/home/src/main/java/com/hanbang/home/result/LottoResultUiState.kt b/feature/home/src/main/java/com/hanbang/home/result/LottoResultUiState.kt index ff8b02e..491e1df 100644 --- a/feature/home/src/main/java/com/hanbang/home/result/LottoResultUiState.kt +++ b/feature/home/src/main/java/com/hanbang/home/result/LottoResultUiState.kt @@ -6,12 +6,9 @@ data class LottoResultUiState( val resultNumbers: List = emptyList(), val bonusNumber: Int = 0, val rank: Int = Int.MAX_VALUE, - val prizeAmount: Long = 0L, - val isPlayingAnim: Boolean = false + val prizeAmount: Long = 0L ) { val isRanked = rank in 1..5 } -sealed interface LottoResultEvent { - -} +sealed interface LottoResultEvent diff --git a/feature/home/src/main/java/com/hanbang/home/result/LottoResultViewModel.kt b/feature/home/src/main/java/com/hanbang/home/result/LottoResultViewModel.kt index e83121c..c9106b6 100644 --- a/feature/home/src/main/java/com/hanbang/home/result/LottoResultViewModel.kt +++ b/feature/home/src/main/java/com/hanbang/home/result/LottoResultViewModel.kt @@ -3,11 +3,9 @@ package com.hanbang.home.result import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.navigation.toRoute -import com.hanbang.domain.usecase.CheckLottoResultUseCase import com.hanbang.navigation.feature.lottoresult.RouteLottoResult import com.hanbang.navigation.feature.lottoresult.toRouteLottoResultModel import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.first import org.orbitmvi.orbit.Container import org.orbitmvi.orbit.ContainerHost import org.orbitmvi.orbit.viewmodel.container @@ -15,14 +13,24 @@ import javax.inject.Inject @HiltViewModel class LottoResultViewModel @Inject constructor( - savedStateHandle: SavedStateHandle, - private val checkLottoResultUseCase: CheckLottoResultUseCase + savedStateHandle: SavedStateHandle ): ContainerHost, ViewModel() { override val container: Container = container( initialState = LottoResultUiState(), onCreate = { val route = savedStateHandle.toRoute().lottoResultJson.toRouteLottoResultModel() - + intent { + reduce { + state.copy( + round = route.round, + recommendedNumbers = route.recommendedNumbers, + resultNumbers = route.resultNumbers, + bonusNumber = route.bonusNumber, + rank = route.rank, + prizeAmount = route.prizeAmount + ) + } + } } ) } \ No newline at end of file diff --git a/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdScreen.kt b/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdScreen.kt index cbe7f4a..8ce1b0b 100644 --- a/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdScreen.kt +++ b/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdScreen.kt @@ -1,16 +1,19 @@ package com.hanbang.home.result.ad +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview @@ -65,13 +68,6 @@ private fun LottoResultAdContent( ) { val isPlaying = remember(state.isPlaying) { mutableStateOf(state.isPlaying) } - val pigLottieComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.lotto_result_pig)) - val pigLottieProgress by animateLottieCompositionAsState( - composition = pigLottieComposition, - isPlaying = isPlaying.value, - iterations = LottieConstants.IterateForever, - ) - val textLottieComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.lotto_result_text)) val textLottieProgress by animateLottieCompositionAsState( composition = textLottieComposition, @@ -79,6 +75,16 @@ private fun LottoResultAdContent( iterations = 1 ) + val textFinished by remember { derivedStateOf { textLottieProgress >= 1f } } + + val pigLottieComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.lotto_result_pig)) + val pigLottieProgress by animateLottieCompositionAsState( + composition = pigLottieComposition, + isPlaying = isPlaying.value && textFinished, + iterations = LottieConstants.IterateForever, + ) + val pigAlpha by animateFloatAsState(targetValue = if (textFinished) 1f else 0f) + Column( modifier = Modifier .fillMaxSize() @@ -108,7 +114,8 @@ private fun LottoResultAdContent( ) { LottieAnimation( composition = pigLottieComposition, - progress = { pigLottieProgress } + progress = { pigLottieProgress }, + modifier = Modifier.alpha(pigAlpha) ) LottieAnimation( composition = textLottieComposition, diff --git a/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdViewModel.kt b/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdViewModel.kt index 3456402..c8d48a0 100644 --- a/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdViewModel.kt +++ b/feature/home/src/main/java/com/hanbang/home/result/ad/LottoResultAdViewModel.kt @@ -48,13 +48,13 @@ class LottoResultAdViewModel @Inject constructor( animationJob?.cancel() animationJob = viewModelScope.launch(coroutineExceptionHandler) { + val delayDeferred = async { delay(state.TOTAL_MILLIS - state.elapsedMillis) } val lottoDeferred = async { checkLottoResultUseCase(resultAdRoute.round).first() } currentMillis = System.currentTimeMillis() reduce { state.copy(isPlaying = true) } - val delayDeferred = async { delay(state.TOTAL_MILLIS - state.elapsedMillis) } - val response = lottoDeferred.await() delayDeferred.await() + val response = lottoDeferred.await() reduce { state.copy(isPlaying = false) } postSideEffect( diff --git a/feature/home/src/main/res/raw/lotto_result_confetti.lottie b/feature/home/src/main/res/raw/lotto_result_confetti.lottie new file mode 100644 index 0000000..7d7c4a7 Binary files /dev/null and b/feature/home/src/main/res/raw/lotto_result_confetti.lottie differ