Animate progress
This commit is contained in:
@@ -4,6 +4,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.nsh07.pomodoro.ui.timerScreen.TimerScreen
|
||||
@@ -16,6 +17,15 @@ fun AppScreen(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
val remainingTime by viewModel.time.collectAsStateWithLifecycle()
|
||||
|
||||
TimerScreen(uiState = uiState, resetTimer = viewModel::resetTimer, toggleTimer = viewModel::toggleTimer, modifier = modifier)
|
||||
val progress by rememberUpdatedState((uiState.totalTime.toFloat() - remainingTime) / uiState.totalTime)
|
||||
|
||||
TimerScreen(
|
||||
uiState = uiState,
|
||||
progress = { progress },
|
||||
resetTimer = viewModel::resetTimer,
|
||||
toggleTimer = viewModel::toggleTimer,
|
||||
modifier = modifier
|
||||
)
|
||||
}
|
||||
@@ -49,6 +49,7 @@ import org.nsh07.pomodoro.ui.viewModel.UiState
|
||||
@Composable
|
||||
fun TimerScreen(
|
||||
uiState: UiState,
|
||||
progress: () -> Float,
|
||||
resetTimer: () -> Unit,
|
||||
toggleTimer: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
@@ -144,7 +145,7 @@ fun TimerScreen(
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator(
|
||||
progress = { (uiState.totalTime.toFloat() - uiState.remainingTime) / uiState.totalTime },
|
||||
progress = progress,
|
||||
modifier = Modifier.size(350.dp),
|
||||
color = color,
|
||||
trackColor = colorContainer,
|
||||
@@ -238,5 +239,5 @@ fun TimerScreenPreview() {
|
||||
val uiState = UiState(
|
||||
timeStr = "08:34", nextTimeStr = "5:00"
|
||||
)
|
||||
TimerScreen(uiState, {}, {})
|
||||
TimerScreen(uiState, { 0.3f }, {}, {})
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ data class UiState(
|
||||
val timerMode: TimerMode = TimerMode.FOCUS,
|
||||
val timeStr: String = "25:00",
|
||||
val totalTime: Int = 25 * 60,
|
||||
val remainingTime: Int = 25 * 60,
|
||||
val timerRunning: Boolean = false,
|
||||
val nextTimerMode: TimerMode = TimerMode.SHORT_BREAK,
|
||||
val nextTimeStr: String = "5:00"
|
||||
|
||||
@@ -12,36 +12,36 @@ import kotlinx.coroutines.launch
|
||||
import java.util.Locale
|
||||
|
||||
class UiViewModel : ViewModel() {
|
||||
val focusTime = 10
|
||||
val shortBreakTime = 5
|
||||
val longBreakTime = 20
|
||||
val focusTime = 10000
|
||||
val shortBreakTime = 5000
|
||||
val longBreakTime = 20000
|
||||
|
||||
private val _uiState = MutableStateFlow(
|
||||
UiState(
|
||||
totalTime = focusTime,
|
||||
remainingTime = focusTime,
|
||||
timeStr = secondsToStr(focusTime),
|
||||
nextTimeStr = secondsToStr(shortBreakTime)
|
||||
timeStr = millisecondsToStr(focusTime),
|
||||
nextTimeStr = millisecondsToStr(shortBreakTime)
|
||||
)
|
||||
)
|
||||
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
|
||||
var timerJob: Job? = null
|
||||
|
||||
var time = focusTime
|
||||
private val _time = MutableStateFlow(focusTime)
|
||||
val time: StateFlow<Int> = _time.asStateFlow()
|
||||
|
||||
var cycles = 0
|
||||
|
||||
fun resetTimer() {
|
||||
time = focusTime
|
||||
_time.update { focusTime }
|
||||
cycles = 0
|
||||
|
||||
_uiState.update { currentState ->
|
||||
currentState.copy(
|
||||
timerMode = TimerMode.FOCUS,
|
||||
timeStr = secondsToStr(time),
|
||||
totalTime = time,
|
||||
remainingTime = time,
|
||||
timeStr = millisecondsToStr(time.value),
|
||||
totalTime = time.value,
|
||||
nextTimerMode = TimerMode.SHORT_BREAK,
|
||||
nextTimeStr = secondsToStr(shortBreakTime)
|
||||
nextTimeStr = millisecondsToStr(shortBreakTime)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -57,58 +57,55 @@ class UiViewModel : ViewModel() {
|
||||
timerJob = viewModelScope.launch {
|
||||
while (true) {
|
||||
if (!uiState.value.timerRunning) break
|
||||
time--
|
||||
_time.update { it - 10 }
|
||||
|
||||
if (time < 0) {
|
||||
if (time.value < 0) {
|
||||
cycles++
|
||||
|
||||
if (cycles % 2 == 0) {
|
||||
time = focusTime
|
||||
_time.update { focusTime }
|
||||
_uiState.update { currentState ->
|
||||
currentState.copy(
|
||||
timerMode = TimerMode.FOCUS,
|
||||
timeStr = secondsToStr(time),
|
||||
totalTime = time,
|
||||
remainingTime = time,
|
||||
timeStr = millisecondsToStr(time.value),
|
||||
totalTime = time.value,
|
||||
nextTimerMode = if (cycles % 6 == 0) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK,
|
||||
nextTimeStr = if (cycles % 6 == 0) secondsToStr(longBreakTime) else secondsToStr(
|
||||
nextTimeStr = if (cycles % 6 == 0) millisecondsToStr(longBreakTime) else millisecondsToStr(
|
||||
shortBreakTime
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val long = cycles % 7 == 0
|
||||
time = if (long) longBreakTime else shortBreakTime
|
||||
_time.update { if (long) longBreakTime else shortBreakTime }
|
||||
|
||||
_uiState.update { currentState ->
|
||||
currentState.copy(
|
||||
timerMode = if (long) TimerMode.LONG_BREAK else TimerMode.SHORT_BREAK,
|
||||
timeStr = secondsToStr(time),
|
||||
totalTime = time,
|
||||
remainingTime = time,
|
||||
timeStr = millisecondsToStr(time.value),
|
||||
totalTime = time.value,
|
||||
nextTimerMode = TimerMode.FOCUS,
|
||||
nextTimeStr = secondsToStr(focusTime)
|
||||
nextTimeStr = millisecondsToStr(focusTime)
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_uiState.update { currentState ->
|
||||
currentState.copy(
|
||||
timeStr = secondsToStr(time),
|
||||
remainingTime = time
|
||||
timeStr = millisecondsToStr(time.value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
delay(1000)
|
||||
delay(10)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun secondsToStr(t: Int): String {
|
||||
val min = t / 60
|
||||
val sec = t % 60
|
||||
private fun millisecondsToStr(t: Int): String {
|
||||
val min = (t / 1000) / 60
|
||||
val sec = (t / 1000) % 60
|
||||
return String.format(locale = Locale.getDefault(), "%02d:%02d", min, sec)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user