feat(timer): save elapsed time every minute along with on reset/skip

Closes: #154
This commit is contained in:
Nishant Mishra
2025-11-29 20:17:39 +05:30
parent 94449139a8
commit 2c9ea87384

View File

@@ -40,6 +40,8 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import org.nsh07.pomodoro.R import org.nsh07.pomodoro.R
import org.nsh07.pomodoro.TomatoApplication import org.nsh07.pomodoro.TomatoApplication
import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerMode import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerMode
@@ -59,10 +61,11 @@ class TimerService : Service() {
private val _timerState by lazy { appContainer.timerState } private val _timerState by lazy { appContainer.timerState }
private val _time by lazy { appContainer.time } private val _time by lazy { appContainer.time }
private val timeStateFlow by lazy { _time.asStateFlow() } /**
* Remaining time
*/
private var time: Long private var time: Long
get() = timeStateFlow.value get() = _time.value
set(value) = _time.update { value } set(value) = _time.update { value }
private val timerState by lazy { _timerState.asStateFlow() } private val timerState by lazy { _timerState.asStateFlow() }
@@ -72,6 +75,9 @@ class TimerService : Service() {
private var pauseTime = 0L private var pauseTime = 0L
private var pauseDuration = 0L private var pauseDuration = 0L
private var lastSavedDuration = 0L
private val saveLock = Mutex()
private var job = SupervisorJob() private var job = SupervisorJob()
private val timerScope = CoroutineScope(Dispatchers.IO + job) private val timerScope = CoroutineScope(Dispatchers.IO + job)
private val skipScope = CoroutineScope(Dispatchers.IO + job) private val skipScope = CoroutineScope(Dispatchers.IO + job)
@@ -107,6 +113,7 @@ class TimerService : Service() {
runBlocking { runBlocking {
job.cancel() job.cancel()
saveTimeToDb() saveTimeToDb()
lastSavedDuration = 0
setDoNotDisturb(false) setDoNotDisturb(false)
notificationManager.cancel(1) notificationManager.cancel(1)
alarm?.release() alarm?.release()
@@ -192,6 +199,13 @@ class TimerService : Service() {
timeStr = millisecondsToStr(time) timeStr = millisecondsToStr(time)
) )
} }
val totalTime = timerState.value.totalTime
if (totalTime - time < lastSavedDuration)
lastSavedDuration =
0 // Sanity check, prevents errors if service is force closed
if (totalTime - time - lastSavedDuration > 60000)
saveTimeToDb()
} }
delay((1000f / timerRepository.timerFrequency).toLong()) delay((1000f / timerRepository.timerFrequency).toLong())
@@ -310,6 +324,7 @@ class TimerService : Service() {
private suspend fun resetTimer() { private suspend fun resetTimer() {
updateProgressSegments() updateProgressSegments()
saveTimeToDb() saveTimeToDb()
lastSavedDuration = 0
time = timerRepository.focusTime time = timerRepository.focusTime
cycles = 0 cycles = 0
startTime = 0L startTime = 0L
@@ -334,6 +349,7 @@ class TimerService : Service() {
saveTimeToDb() saveTimeToDb()
updateProgressSegments() updateProgressSegments()
showTimerNotification(0, paused = true, complete = !fromButton) showTimerNotification(0, paused = true, complete = !fromButton)
lastSavedDuration = 0
startTime = 0L startTime = 0L
pauseTime = 0L pauseTime = 0L
pauseDuration = 0L pauseDuration = 0L
@@ -460,14 +476,18 @@ class TimerService : Service() {
} }
suspend fun saveTimeToDb() { suspend fun saveTimeToDb() {
when (timerState.value.timerMode) { saveLock.withLock {
TimerMode.FOCUS -> statRepository.addFocusTime( val elapsedTime = timerState.value.totalTime - time
(timerState.value.totalTime - time).coerceAtLeast( when (timerState.value.timerMode) {
0L TimerMode.FOCUS -> statRepository.addFocusTime(
(elapsedTime - lastSavedDuration).coerceAtLeast(0L)
) )
)
else -> statRepository.addBreakTime((timerState.value.totalTime - time).coerceAtLeast(0L)) else -> statRepository.addBreakTime(
(elapsedTime - lastSavedDuration).coerceAtLeast(0L)
)
}
lastSavedDuration = elapsedTime
} }
} }