From da75b4e6edcba44306edd642b255a96d277c8a27 Mon Sep 17 00:00:00 2001 From: HyunWoo Lee Date: Fri, 17 Jan 2025 00:52:25 +0900 Subject: [PATCH] =?UTF-8?q?[#1011]=20=ED=83=80=EC=9D=B4=EB=A8=B8=20?= =?UTF-8?q?=EC=9D=B4=EC=8A=88=20=ED=95=B4=EC=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../certificate/CertificationScreen.kt | 9 ++++-- .../feature/certificate/CertificationState.kt | 14 +++++++-- .../certificate/CertificationViewModel.kt | 31 +++++++++++-------- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationScreen.kt b/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationScreen.kt index d56405847..91ec81e3a 100644 --- a/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationScreen.kt +++ b/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationScreen.kt @@ -41,6 +41,7 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -52,6 +53,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.flowWithLifecycle +import kotlinx.coroutines.launch import org.sopt.official.R import org.sopt.official.R.drawable.ic_auth_memeber_error import org.sopt.official.R.drawable.ic_auth_process_first @@ -83,6 +85,7 @@ internal fun CertificationRoute( viewModel: CertificationViewModel = hiltViewModel() ) { val lifecycleOwner = LocalLifecycleOwner.current + val scope = rememberCoroutineScope() val context = LocalContext.current val state by viewModel.state.collectAsStateWithLifecycle() @@ -107,8 +110,10 @@ internal fun CertificationRoute( onCreateCodeClick = { onShowSnackBar() // TODO: 실제 전화번호 넣기 by leeeyubin - viewModel.createCode(status) - viewModel.startTimer(state.currentTime) + scope.launch { + viewModel.createCode(status) + viewModel.startTimer() + } }, onCertificateClick = { // TODO: 실제 인증코드 넣기 by leeeyubin diff --git a/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationState.kt b/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationState.kt index 32b230635..397d90e06 100644 --- a/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationState.kt +++ b/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationState.kt @@ -1,7 +1,17 @@ package org.sopt.official.feature.auth.feature.certificate +import java.util.Locale + data class CertificationState( val phone: String = "", val code: String = "", - val currentTime: String = "03:00" -) \ No newline at end of file + val currentTimeValue: Int = 180 +) { + val currentTime: String + get() = String.format( + Locale.US, + "%02d:%02d", + currentTimeValue / 60, + currentTimeValue % 60 + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationViewModel.kt b/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationViewModel.kt index 1d47834f7..d07222578 100644 --- a/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationViewModel.kt +++ b/app/src/main/java/org/sopt/official/feature/auth/feature/certificate/CertificationViewModel.kt @@ -3,6 +3,8 @@ package org.sopt.official.feature.auth.feature.certificate import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow @@ -11,13 +13,14 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update +import kotlinx.coroutines.isActive import kotlinx.coroutines.launch import org.sopt.official.domain.auth.model.InformationWithCode import org.sopt.official.domain.auth.model.InitialInformation import org.sopt.official.domain.auth.model.UserPhoneNumber import org.sopt.official.domain.auth.repository.AuthRepository import org.sopt.official.feature.auth.model.AuthStatus -import java.util.Locale +import timber.log.Timber import javax.inject.Inject @HiltViewModel @@ -31,6 +34,8 @@ class CertificationViewModel @Inject constructor( private val _sideEffect = MutableSharedFlow() val sideEffect: SharedFlow = _sideEffect.asSharedFlow() + private var timerJob: Job? = null + fun updatePhone(phone: String) { _state.update { currentState -> currentState.copy( @@ -98,26 +103,26 @@ class CertificationViewModel @Inject constructor( } } - fun startTimer(currentTime: String) { - viewModelScope.launch { - var (minutes, seconds) = currentTime.split(":").map { it.toInt() } - var totalSeconds: Int = minutes * 60 + seconds - - while (totalSeconds > 0) { + suspend fun startTimer() { + timerJob?.cancelAndJoin() + timerJob = null + _state.update { currentState -> + currentState.copy( + currentTimeValue = 180 + ) + } + timerJob = viewModelScope.launch { + while (isActive) { delay(1000L) - - totalSeconds-- - minutes = totalSeconds / 60 - seconds = totalSeconds % 60 + Timber.d("totalSeconds: ${state.value}") _state.update { currentState -> currentState.copy( - currentTime = String.format(Locale.US, "%02d:%02d", minutes, seconds) + currentTimeValue = currentState.currentTimeValue - 1 ) } } delay(1000L) - // TODO : 에러 화면 띄우기 by leeeyubin } } }