diff --git a/core/common/kotlin/src/main/java/team/ppac/common/kotlin/model/ReactionState.kt b/core/common/kotlin/src/main/java/team/ppac/common/kotlin/model/ReactionState.kt new file mode 100644 index 00000000..3ab9e6b2 --- /dev/null +++ b/core/common/kotlin/src/main/java/team/ppac/common/kotlin/model/ReactionState.kt @@ -0,0 +1,56 @@ +package team.ppac.common.kotlin.model + +import java.util.concurrent.atomic.AtomicBoolean +import java.util.concurrent.atomic.AtomicInteger + +class ReactionState { + private val _isFirstClickEvent = AtomicBoolean(true) + private val _reactionCount = AtomicInteger(0) + private val _isUpdating = AtomicBoolean(false) + private var lastClickTime: Long = 0 + + val reactionCount: Int + get() = _reactionCount.get() + + val isUpdating: Boolean + get() = _isUpdating.get() + + val isFirstClickEvent: Boolean + get() = _isFirstClickEvent.get() + + fun setIsFirstClickEvent(value: Boolean) { + _isFirstClickEvent.set(value) + } + + fun addReactionCount(count: Int) { + _reactionCount.addAndGet(count) + } + + fun startUpdate() { + _isUpdating.compareAndSet(false, true) + .also { print("isRelease Setting = ${_isUpdating.get()}") } + } + + fun endUpdate() { + _isUpdating.set(false) + } + + fun releaseState() { + _reactionCount.set(0) + _isFirstClickEvent.set(true) + } + + fun isDoubleClickEvent(): Boolean { + val currentClickTime: Long = System.currentTimeMillis() + return if (currentClickTime - lastClickTime <= DOUBLE_CLICK_INTERVAL) { + true + } else { + lastClickTime = System.currentTimeMillis() + false + } + } + + companion object { + private const val DOUBLE_CLICK_INTERVAL = 400 + } +} \ No newline at end of file diff --git a/core/designsystem/src/main/kotlin/team/ppac/designsystem/util/extension/NoRippleClickable.kt b/core/designsystem/src/main/kotlin/team/ppac/designsystem/util/extension/NoRippleClickable.kt index bcbf2549..0d4dfe4a 100644 --- a/core/designsystem/src/main/kotlin/team/ppac/designsystem/util/extension/NoRippleClickable.kt +++ b/core/designsystem/src/main/kotlin/team/ppac/designsystem/util/extension/NoRippleClickable.kt @@ -62,6 +62,6 @@ private fun Modifier.singleClickable( enabled = enabled, onClickLabel = onClickLabel, role = role, - onClick = { multipleEventsCutter.processEvent(onClick) }, + onClick = { onClick() }, // Todo(hyejin.ju) 함수 분리해야함 ) } diff --git a/feature/detail/src/main/java/team/ppac/detail/DetailViewModel.kt b/feature/detail/src/main/java/team/ppac/detail/DetailViewModel.kt index 9cf570a6..bb165f44 100644 --- a/feature/detail/src/main/java/team/ppac/detail/DetailViewModel.kt +++ b/feature/detail/src/main/java/team/ppac/detail/DetailViewModel.kt @@ -5,7 +5,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import team.ppac.common.android.base.BaseViewModel +import team.ppac.common.kotlin.model.ReactionState import team.ppac.designsystem.foundation.FarmemeIcon import team.ppac.detail.mapper.toDetailMemeUiModel import team.ppac.detail.mvi.DetailIntent @@ -29,8 +31,8 @@ class DetailViewModel @Inject constructor( private val emitRefreshEventUseCase: EmitRefreshEventUseCase, ) : BaseViewModel(savedStateHandle) { - var isFirstClickEvent : Boolean = false - var reactionCount = 0 + private val reactionState = ReactionState() + init { launch { getMeme(currentState.memeId) @@ -50,15 +52,24 @@ class DetailViewModel @Inject constructor( } } + override suspend fun handleIntent(intent: DetailIntent) { when (intent) { is DetailIntent.ClickFunnyButton -> { - if(reactionCount == 0 && "연타"){ + if (!reactionState.isUpdating && reactionState.isDoubleClickEvent()) { incrementReactionCount() postSideEffect(DetailSideEffect.RunRisingEffect) - reactionCount++ + reactionState.addReactionCount(1) + if (reactionState.isFirstClickEvent) { + reactionState.setIsFirstClickEvent(false) + launch { + updateReactionCountWithDelay() + } + } } else { - updateReactionCount() + incrementReactionCount() + postSideEffect(DetailSideEffect.RunRisingEffect) + updateReactionCount(1) } } @@ -163,20 +174,26 @@ class DetailViewModel @Inject constructor( } } - private suspend fun updateReactionCount(reactionCount :Int){ + private suspend fun updateReactionCountWithDelay() { + delay(1000) + reactionState.startUpdate() + updateReactionCount(reactionState.reactionCount) // Todo(hyejin.ju) API 연결 해야함 + reactionState.releaseState() + reactionState.endUpdate() + } + + private suspend fun updateReactionCount(reactionCount: Int) { runCatching { - reactMemeUseCase(currentState.memeId,reactionCount) + reactMemeUseCase(currentState.memeId) }.onFailure { reduce { copy( detailMemeUiModel = detailMemeUiModel.copy( - reactionCount = detailMemeUiModel.reactionCount - reactionCount, + reactionCount = detailMemeUiModel.reactionCount - 1, isReaction = false ) ) } - }.onSuccess { - reactionCount = 0 } }