Skip to content

Commit

Permalink
fix: service에서 특정 임계점 넘지 못하게 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
lee-ji-hoon committed Sep 4, 2024
1 parent d64f731 commit 0a7ba58
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import java.util.*
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch

data class PomodoroTimerState(
val focusTime: Int = 0,
val focusExceededTime: Int = 0,
val maxFocusTime: Int = 0,
val restTime: Int = 0,
val restExceededTime: Int = 0,
val maxRestTime: Int = 0,
val title: String = "",
val categoryType: PomodoroCategoryType = PomodoroCategoryType.DEFAULT,
val cat: CatType = CatType.CHEESE,
Expand Down Expand Up @@ -67,50 +68,24 @@ class PomodoroTimerViewModel @Inject constructor(
private val pomodoroInitialDataUseCase: InsertPomodoroInitialDataUseCase
) : BaseViewModel<PomodoroTimerState, PomodoroTimerEvent, PomodoroTimerEffect>() {

private var maxFocusTime: Int = 0
private var maxRestTime: Int = 0
private val currentFocusTimerId = MutableStateFlow("")

private val combinedTimerData = currentFocusTimerId.flatMapLatest { timerId ->
pomodoroTimerRepository.getPomodoroTimer(timerId)
}

init {
loadTimerData()
}

private fun loadTimerData() {
viewModelScope.launch {
combinedTimerData.collect { timerData ->
timerData?.let { updateTimerState(it) }
}
}
}

private fun updateTimerState(timerData: PomodoroTimerEntity) {
val currentFocusTime = timerData.focusedTime.coerceAtMost(maxFocusTime)
val currentRestTime = timerData.restedTime.coerceAtMost(maxRestTime)
val focusExceededTime = (timerData.focusedTime - maxFocusTime).coerceAtLeast(0)
val restExceededTime = (timerData.restedTime - maxRestTime).coerceAtLeast(0)

if (timerData.focusedTime == maxFocusTime) {
setEffect(PomodoroTimerEffect.PomodoroFocusEffect.SendEndFocusAlarm)
}

if (timerData.restedTime == maxRestTime) {
setEffect(PomodoroTimerEffect.PomodoroRestEffect.SendEndRestAlarm)
}

updateState {
copy(
focusTime = currentFocusTime,
focusExceededTime = focusExceededTime,
restTime = currentRestTime,
restExceededTime = restExceededTime
)
}

if (focusExceededTime == PomodoroConstants.MAX_EXCEEDED_TIME) {
setEffect(PomodoroTimerEffect.PomodoroFocusEffect.ForceGoRest)
}
}

override fun setInitialState(): PomodoroTimerState = PomodoroTimerState()

override fun handleEvent(event: PomodoroTimerEvent) {
Expand All @@ -125,16 +100,18 @@ class PomodoroTimerViewModel @Inject constructor(

private fun loadPomodoroSettingData() {
viewModelScope.launch {
val selectedPomodoroSetting = getSelectedPomodoroSettingUseCase().first().toModel()
val cat = userRepository.getMyInfo().cat.toModel()
maxFocusTime = (selectedPomodoroSetting.focusTime.times(60))
maxRestTime = (selectedPomodoroSetting.restTime.times(60))
updateState {
copy(
title = selectedPomodoroSetting.title,
categoryType = selectedPomodoroSetting.categoryType,
cat = cat.type
)
getSelectedPomodoroSettingUseCase().collect { entity ->
val selectedPomodoroSetting = entity.toModel()
val cat = userRepository.getMyInfo().cat.toModel()
updateState {
copy(
title = selectedPomodoroSetting.title,
categoryType = selectedPomodoroSetting.categoryType,
cat = cat.type,
maxFocusTime = (selectedPomodoroSetting.focusTime.times(60)),
maxRestTime = (selectedPomodoroSetting.restTime.times(60))
)
}
}
}
}
Expand All @@ -146,4 +123,32 @@ class PomodoroTimerViewModel @Inject constructor(
pomodoroInitialDataUseCase(focusTimeKey)
}
}

private fun updateTimerState(timerData: PomodoroTimerEntity) {
val currentFocusTime = timerData.focusedTime.coerceAtMost(state.value.maxFocusTime)
val currentRestTime = timerData.restedTime.coerceAtMost(state.value.maxRestTime)
val focusExceededTime = (timerData.focusedTime - state.value.maxFocusTime).coerceAtLeast(0)
val restExceededTime = (timerData.restedTime - state.value.maxRestTime).coerceAtLeast(0)

if (timerData.focusedTime == state.value.maxFocusTime) {
setEffect(PomodoroTimerEffect.PomodoroFocusEffect.SendEndFocusAlarm)
}

if (timerData.restedTime == state.value.maxRestTime) {
setEffect(PomodoroTimerEffect.PomodoroRestEffect.SendEndRestAlarm)
}

updateState {
copy(
focusTime = currentFocusTime,
focusExceededTime = focusExceededTime,
restTime = currentRestTime,
restExceededTime = restExceededTime
)
}

if (focusExceededTime == PomodoroConstants.MAX_EXCEEDED_TIME) {
setEffect(PomodoroTimerEffect.PomodoroFocusEffect.ForceGoRest)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -112,9 +113,14 @@ fun PomodoroFocusRoute(
pomodoroFocusViewModel.handleEvent(PomodoroFocusEvent.Pause)
}

LaunchedEffect(state.maxFocusTime) {
if (state.maxFocusTime != 0) {
context.startTimer(true, state.maxFocusTime)
}
}

DisposableEffect(key1 = Unit) {
pomodoroTimerViewModel.handleEvent(PomodoroTimerEvent.Start)
context.startTimer(true)
onDispose {
stopInterrupt(context)
context.stopTimer(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -76,9 +77,13 @@ fun PomodoroRestRoute(
// NOTHING
}

DisposableEffect(Unit) {
context.startTimer(false)
LaunchedEffect(timerState.maxRestTime) {
if (timerState.maxRestTime != 0) {
context.startTimer(false, timerState.maxRestTime)
}
}

DisposableEffect(Unit) {
onDispose {
context.stopTimer(false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.app.Service
import android.content.Intent
import android.os.IBinder
import com.pomonyang.mohanyang.data.repository.pomodoro.PomodoroTimerRepository
import com.pomonyang.mohanyang.presentation.screen.PomodoroConstants.MAX_EXCEEDED_TIME
import com.pomonyang.mohanyang.presentation.screen.PomodoroConstants.TIMER_DELAY
import dagger.hilt.android.AndroidEntryPoint
import java.util.*
Expand All @@ -25,20 +26,24 @@ class PomodoroTimerService : Service() {

private var scope = CoroutineScope(Dispatchers.IO)

private var focusTimeElapsed = 0 // 초 단위로 경과된 시간 저장
private var restTimeElapsed = 0 // 초 단위로 경과된 시간 저장

override fun onBind(intent: Intent?): IBinder? = null

override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
val isFocus = intent.getBooleanExtra(PomodoroTimerServiceExtras.INTENT_TIMER_IS_FOCUS, true)
val maxTime = intent.getIntExtra(PomodoroTimerServiceExtras.INTENT_TIMER_MAX_TIME, 0) // maxTime은 초 단위로 전달
val action = intent.action

Timber.d("[지훈] ${object {}.javaClass.enclosingMethod?.name} isFocus $isFocus / $action")

when (action) {
PomodoroTimerServiceExtras.ACTION_TIMER_START -> {
if (isFocus) {
startFocusTimer()
startFocusTimer(maxTime)
} else {
startRestTimer()
startRestTimer(maxTime)
}
}

Expand All @@ -60,12 +65,20 @@ class PomodoroTimerService : Service() {
return super.stopService(name)
}

private fun startFocusTimer() {
private fun startFocusTimer(maxTime: Int) {
if (focusTimer == null) {
focusTimeElapsed = 0
focusTimer = fixedRateTimer(initialDelay = TIMER_DELAY, period = TIMER_DELAY) {
scope.launch {
Timber.d("[지훈] Focus 타이머 작동 중 ${this@fixedRateTimer.scheduledExecutionTime()}")
pomodoroTimerRepository.incrementFocusedTime()
focusTimeElapsed += (TIMER_DELAY / TIMER_DELAY).toInt() // 경과 시간 누적 (TIMER_DELAY는 밀리초이므로 초 단위로 변환)

if (focusTimeElapsed > maxTime + MAX_EXCEEDED_TIME) {
Timber.d("[지훈] Focus 타이머가 maxTime $maxTime 에 도달하여 중지됨")
stopFocusTimer()
} else {
Timber.d("[지훈] Focus 타이머 작동 중 / 경과 시간: $focusTimeElapsed")
pomodoroTimerRepository.incrementFocusedTime()
}
}
}
}
Expand All @@ -77,12 +90,19 @@ class PomodoroTimerService : Service() {
Timber.d("[지훈] Focus 타이머 중지")
}

private fun startRestTimer() {
private fun startRestTimer(maxTime: Int) {
if (restTimer == null) {
restTimeElapsed = 0
restTimer = fixedRateTimer(initialDelay = TIMER_DELAY, period = TIMER_DELAY) {
scope.launch {
Timber.d("[지훈] Rest 타이머 작동 중 ${this@fixedRateTimer.scheduledExecutionTime()}")
pomodoroTimerRepository.incrementRestedTime()
restTimeElapsed += (TIMER_DELAY / TIMER_DELAY).toInt() // 경과 시간 누적 (TIMER_DELAY는 밀리초이므로 초 단위로 변환)
if (restTimeElapsed > maxTime + MAX_EXCEEDED_TIME) {
Timber.d("[지훈] Rest 타이머가 maxTime $maxTime 에 도달하여 중지됨")
stopRestTimer()
} else {
Timber.d("[지훈] Rest 타이머 작동 중 / 경과 시간: $restTimeElapsed")
pomodoroTimerRepository.incrementRestedTime()
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.pomonyang.mohanyang.presentation.util

object PomodoroTimerServiceExtras {

const val INTENT_TIMER_IS_FOCUS = "mohanyang.intent.TIMER_FOCUS"
const val INTENT_TIMER_MAX_TIME = "mohanyang.intent.MAX_TIME"
const val ACTION_TIMER_START = "mohanyang.action.TIMER_START"
const val ACTION_TIMER_STOP = "mohanyang.action.TIMER_STOP"
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package com.pomonyang.mohanyang.presentation.util

import android.content.Context
import android.content.Intent
import androidx.core.os.bundleOf

fun Context.startTimer(isFocus: Boolean) {
fun Context.startTimer(isFocus: Boolean, maxTime: Int) {
startService(
Intent(this, PomodoroTimerService::class.java).apply {
action = PomodoroTimerServiceExtras.ACTION_TIMER_START
putExtra(PomodoroTimerServiceExtras.INTENT_TIMER_IS_FOCUS, isFocus)
putExtras(
bundleOf(
PomodoroTimerServiceExtras.INTENT_TIMER_IS_FOCUS to isFocus,
PomodoroTimerServiceExtras.INTENT_TIMER_MAX_TIME to maxTime
)
)
}
)
}
Expand Down

0 comments on commit 0a7ba58

Please sign in to comment.