fix: Next timer not starting when current timer was completed

This commit is contained in:
Nishant Mishra
2025-09-14 16:48:25 +05:30
parent f28fc8a2c1
commit c1c2f57ddc
3 changed files with 70 additions and 47 deletions

View File

@@ -19,44 +19,56 @@ fun NotificationCompat.Builder.addTimerActions(
context: Context, context: Context,
@DrawableRes playPauseIcon: Int, @DrawableRes playPauseIcon: Int,
playPauseText: String playPauseText: String
): NotificationCompat.Builder { ): NotificationCompat.Builder = this
this .addAction(
.addAction( playPauseIcon,
playPauseIcon, playPauseText,
playPauseText, PendingIntent.getService(
PendingIntent.getService( context,
context, 0,
0, Intent(context, TimerService::class.java).also {
Intent(context, TimerService::class.java).also { it.action = TimerService.Actions.TOGGLE.toString()
it.action = TimerService.Actions.TOGGLE.toString() },
}, FLAG_IMMUTABLE
FLAG_IMMUTABLE
)
) )
.addAction( )
R.drawable.restart, .addAction(
"Reset", R.drawable.restart,
PendingIntent.getService( "Reset",
context, PendingIntent.getService(
0, context,
Intent(context, TimerService::class.java).also { 0,
it.action = TimerService.Actions.RESET.toString() Intent(context, TimerService::class.java).also {
}, it.action = TimerService.Actions.RESET.toString()
FLAG_IMMUTABLE },
) FLAG_IMMUTABLE
) )
.addAction( )
R.drawable.skip_next, .addAction(
"Skip", R.drawable.skip_next,
PendingIntent.getService( "Skip",
context, PendingIntent.getService(
0, context,
Intent(context, TimerService::class.java).also { 0,
it.action = TimerService.Actions.SKIP.toString() Intent(context, TimerService::class.java).also {
}, it.action = TimerService.Actions.SKIP.toString()
FLAG_IMMUTABLE },
) FLAG_IMMUTABLE
) )
)
return this fun NotificationCompat.Builder.addStopAlarmAction(
} context: Context
): NotificationCompat.Builder = this
.addAction(
R.drawable.alarm,
"Stop alarm",
PendingIntent.getService(
context,
0,
Intent(context, TimerService::class.java).also {
it.action = TimerService.Actions.STOP_ALARM.toString()
},
FLAG_IMMUTABLE
)
)

View File

@@ -57,9 +57,9 @@ class TimerService : Service() {
private var pauseTime = 0L private var pauseTime = 0L
private var pauseDuration = 0L private var pauseDuration = 0L
private val timerJob = SupervisorJob() private var job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + timerJob) private val scope = CoroutineScope(Dispatchers.IO + job)
private val skipScope = CoroutineScope(Dispatchers.IO) private val skipScope = CoroutineScope(Dispatchers.IO + job)
private lateinit var alarm: MediaPlayer private lateinit var alarm: MediaPlayer
@@ -145,11 +145,10 @@ class TimerService : Service() {
if (time < 0) { if (time < 0) {
skipTimer() skipTimer()
_timerState.update { currentState -> _timerState.update { currentState ->
currentState.copy(timerRunning = false) currentState.copy(timerRunning = false)
} }
timerJob.cancel() break
} else { } else {
_timerState.update { currentState -> _timerState.update { currentState ->
currentState.copy( currentState.copy(
@@ -168,6 +167,8 @@ class TimerService : Service() {
fun showTimerNotification( fun showTimerNotification(
remainingTime: Int, paused: Boolean = false, complete: Boolean = false remainingTime: Int, paused: Boolean = false, complete: Boolean = false
) { ) {
if (complete) notificationBuilder.clearActions().addStopAlarmAction(this)
val totalTime = when (timerState.value.timerMode) { val totalTime = when (timerState.value.timerMode) {
TimerMode.FOCUS -> timerRepository.focusTime.toInt() TimerMode.FOCUS -> timerRepository.focusTime.toInt()
TimerMode.SHORT_BREAK -> timerRepository.shortBreakTime.toInt() TimerMode.SHORT_BREAK -> timerRepository.shortBreakTime.toInt()
@@ -224,7 +225,7 @@ class TimerService : Service() {
) )
) )
.setWhen(System.currentTimeMillis() + remainingTime) // Sets the Live Activity/Now Bar chip time .setWhen(System.currentTimeMillis() + remainingTime) // Sets the Live Activity/Now Bar chip time
.setShortCriticalText(millisecondsToStr(time)) .setShortCriticalText(millisecondsToStr(time.coerceAtLeast(0)))
.build() .build()
) )
@@ -309,6 +310,16 @@ class TimerService : Service() {
_timerState.update { currentState -> _timerState.update { currentState ->
currentState.copy(alarmRinging = false) currentState.copy(alarmRinging = false)
} }
notificationBuilder.clearActions().addTimerActions(this, R.drawable.play, "Start")
showTimerNotification(
when (timerState.value.timerMode) {
TimerMode.FOCUS -> timerRepository.focusTime.toInt()
TimerMode.SHORT_BREAK -> timerRepository.shortBreakTime.toInt()
else -> timerRepository.longBreakTime.toInt()
},
paused = true,
complete = false
)
} }
suspend fun saveTimeToDb() { suspend fun saveTimeToDb() {
@@ -336,7 +347,7 @@ class TimerService : Service() {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
runBlocking { runBlocking {
timerJob.cancel() job.cancel()
saveTimeToDb() saveTimeToDb()
notificationManager.cancel(1) notificationManager.cancel(1)
} }

View File

@@ -205,7 +205,7 @@ fun TimerScreen(
color = color, color = color,
trackColor = colorContainer, trackColor = colorContainer,
strokeWidth = 16.dp, strokeWidth = 16.dp,
gapSize = 16.dp gapSize = 8.dp
) )
} else { } else {
CircularWavyProgressIndicator( CircularWavyProgressIndicator(
@@ -229,7 +229,7 @@ fun TimerScreen(
cap = StrokeCap.Round, cap = StrokeCap.Round,
), ),
wavelength = 60.dp, wavelength = 60.dp,
gapSize = 16.dp gapSize = 8.dp
) )
} }
var expanded by remember { mutableStateOf(timerState.showBrandTitle) } var expanded by remember { mutableStateOf(timerState.showBrandTitle) }
@@ -300,10 +300,10 @@ fun TimerScreen(
{ {
FilledIconToggleButton( FilledIconToggleButton(
onCheckedChange = { checked -> onCheckedChange = { checked ->
onAction(TimerAction.ToggleTimer)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && checked) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && checked) {
permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS) permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
} }
onAction(TimerAction.ToggleTimer)
}, },
checked = timerState.timerRunning, checked = timerState.timerRunning,
colors = IconButtonDefaults.filledIconToggleButtonColors( colors = IconButtonDefaults.filledIconToggleButtonColors(