Significantly increase clock accuracy using SystemClock

This commit is contained in:
Nishant Mishra
2025-06-30 20:12:15 +05:30
parent af664ab89c
commit befbc708e0

View File

@@ -1,5 +1,6 @@
package org.nsh07.pomodoro.ui.viewModel package org.nsh07.pomodoro.ui.viewModel
import android.os.SystemClock
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@@ -30,11 +31,17 @@ class UiViewModel : ViewModel() {
private val _time = MutableStateFlow(focusTime) private val _time = MutableStateFlow(focusTime)
val time: StateFlow<Int> = _time.asStateFlow() val time: StateFlow<Int> = _time.asStateFlow()
var cycles = 0 private var cycles = 0
private var startTime = 0L
private var pauseTime = 0L
private var pauseDuration = 0L
fun resetTimer() { fun resetTimer() {
_time.update { focusTime } _time.update { focusTime }
cycles = 0 cycles = 0
startTime = 0L
pauseTime = 0L
pauseDuration = 0L
_uiState.update { currentState -> _uiState.update { currentState ->
currentState.copy( currentState.copy(
@@ -53,32 +60,51 @@ class UiViewModel : ViewModel() {
currentState.copy(timerRunning = false) currentState.copy(timerRunning = false)
} }
timerJob?.cancel() timerJob?.cancel()
pauseTime = SystemClock.elapsedRealtime()
} else { } else {
_uiState.update { it.copy(timerRunning = true) } _uiState.update { it.copy(timerRunning = true) }
if (pauseTime != 0L) pauseDuration += SystemClock.elapsedRealtime() - pauseTime
timerJob = viewModelScope.launch { timerJob = viewModelScope.launch {
while (true) { while (true) {
if (!uiState.value.timerRunning) break if (!uiState.value.timerRunning) break
_time.update { it - 100 } if (startTime == 0L) startTime = SystemClock.elapsedRealtime()
_time.update {
when (uiState.value.timerMode) {
TimerMode.FOCUS ->
focusTime - (SystemClock.elapsedRealtime() - startTime - pauseDuration).toInt()
TimerMode.SHORT_BREAK ->
shortBreakTime - (SystemClock.elapsedRealtime() - startTime - pauseDuration).toInt()
TimerMode.LONG_BREAK ->
longBreakTime - (SystemClock.elapsedRealtime() - startTime - pauseDuration).toInt()
}
}
if (time.value < 0) { if (time.value < 0) {
startTime = 0L
pauseTime = 0L
pauseDuration = 0L
cycles++ cycles++
if (cycles % 2 == 0) { if (cycles % 2 == 0) {
_time.update { focusTime } _time.update { focusTime }
_uiState.update { currentState -> _uiState.update { currentState ->
currentState.copy( currentState.copy(
timerMode = TimerMode.FOCUS, timerMode = TimerMode.FOCUS,
timeStr = millisecondsToStr(time.value), timeStr = millisecondsToStr(time.value),
totalTime = time.value, totalTime = time.value,
nextTimerMode = if (cycles % 6 == 0) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK, nextTimerMode = if (cycles % 6 == 0) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK,
nextTimeStr = if (cycles % 6 == 0) millisecondsToStr(longBreakTime) else millisecondsToStr( nextTimeStr = if (cycles % 6 == 0) millisecondsToStr(
longBreakTime
) else millisecondsToStr(
shortBreakTime shortBreakTime
) )
) )
} }
} else { } else {
val long = cycles % 7 == 0 val long = cycles % 7 == 0
_time.update { if (long) longBreakTime else shortBreakTime } _time.update { if (long) longBreakTime else shortBreakTime }
_uiState.update { currentState -> _uiState.update { currentState ->
currentState.copy( currentState.copy(