From f4f81ee94c2a9d37029f112d4ea7545ba3ce48c0 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 15 Sep 2025 16:28:30 +0530 Subject: [PATCH] fix: Improve TimerService code by using lazy init instead of lateinit var --- .../nsh07/pomodoro/service/TimerService.kt | 166 +++++++----------- 1 file changed, 64 insertions(+), 102 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt index 234e276..4045491 100644 --- a/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt +++ b/app/src/main/java/org/nsh07/pomodoro/service/TimerService.kt @@ -20,41 +20,35 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import org.nsh07.pomodoro.R import org.nsh07.pomodoro.TomatoApplication -import org.nsh07.pomodoro.data.AppContainer -import org.nsh07.pomodoro.data.StatRepository -import org.nsh07.pomodoro.data.TimerRepository import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerMode -import org.nsh07.pomodoro.ui.timerScreen.viewModel.TimerState import org.nsh07.pomodoro.utils.millisecondsToStr import kotlin.text.Typography.middleDot class TimerService : Service() { - private lateinit var appContainer: AppContainer - - private lateinit var timerRepository: TimerRepository - private lateinit var statRepository: StatRepository - private lateinit var notificationManager: NotificationManagerCompat - private lateinit var notificationBuilder: NotificationCompat.Builder - private lateinit var _timerState: MutableStateFlow - private lateinit var _time: MutableStateFlow - - val timeStateFlow by lazy { - _time.asStateFlow() + private val appContainer by lazy { + (application as TomatoApplication).container } - var time: Long + private val timerRepository by lazy { appContainer.appTimerRepository } + private val statRepository by lazy { appContainer.appStatRepository } + private val notificationManager by lazy { NotificationManagerCompat.from(this) } + private val notificationBuilder by lazy { appContainer.notificationBuilder } + private val _timerState by lazy { appContainer.timerState } + private val _time by lazy { appContainer.time } + + private val timeStateFlow by lazy { _time.asStateFlow() } + + private var time: Long get() = timeStateFlow.value set(value) = _time.update { value } - lateinit var timerState: StateFlow + private val timerState by lazy { _timerState.asStateFlow() } private var cycles = 0 private var startTime = 0L @@ -67,19 +61,16 @@ class TimerService : Service() { private val alarm by lazy { MediaPlayer.create( - this, - Settings.System.DEFAULT_ALARM_ALERT_URI ?: Settings.System.DEFAULT_RINGTONE_URI + this, Settings.System.DEFAULT_ALARM_ALERT_URI ?: Settings.System.DEFAULT_RINGTONE_URI ) } private val vibrator by lazy { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - val vibratorManager = - getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager + val vibratorManager = getSystemService(VIBRATOR_MANAGER_SERVICE) as VibratorManager vibratorManager.defaultVibrator } else { - @Suppress("DEPRECATION") - getSystemService(VIBRATOR_SERVICE) as Vibrator + @Suppress("DEPRECATION") getSystemService(VIBRATOR_SERVICE) as Vibrator } } @@ -89,18 +80,6 @@ class TimerService : Service() { return null } - override fun onCreate() { - appContainer = (application as TomatoApplication).container - timerRepository = appContainer.appTimerRepository - statRepository = appContainer.appStatRepository - notificationManager = NotificationManagerCompat.from(this) - notificationBuilder = appContainer.notificationBuilder - _timerState = appContainer.timerState - _time = appContainer.time - - timerState = _timerState.asStateFlow() - } - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { when (intent?.action) { Actions.TOGGLE.toString() -> { @@ -123,26 +102,18 @@ class TimerService : Service() { private fun toggleTimer() { if (timerState.value.timerRunning) { - notificationBuilder - .clearActions() - .addTimerActions( - this, - R.drawable.play, - "Start" - ) + notificationBuilder.clearActions().addTimerActions( + this, R.drawable.play, "Start" + ) showTimerNotification(time.toInt(), paused = true) _timerState.update { currentState -> currentState.copy(timerRunning = false) } pauseTime = SystemClock.elapsedRealtime() } else { - notificationBuilder - .clearActions() - .addTimerActions( - this, - R.drawable.pause, - "Stop" - ) + notificationBuilder.clearActions().addTimerActions( + this, R.drawable.pause, "Stop" + ) _timerState.update { it.copy(timerRunning = true) } if (pauseTime != 0L) pauseDuration += SystemClock.elapsedRealtime() - pauseTime @@ -214,59 +185,52 @@ class TimerService : Service() { else (remainingTime.toFloat() / 60000f).toInt() notificationManager.notify( - 1, - notificationBuilder - .setContentTitle( - if (!complete) { - "$currentTimer $middleDot $remainingTimeString min remaining" + if (paused) " $middleDot Paused" else "" - } else "$currentTimer $middleDot Completed" - ) - .setContentText("Up next: $nextTimer (${timerState.value.nextTimeStr})") - .setStyle( - NotificationCompat.ProgressStyle().also { - // Add all the Focus, Short break and long break intervals in order - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { - // Android 16 and later supports live updates - // Set progress bar sections if on Baklava or later - for (i in 0..= Build.VERSION_CODES.BAKLAVA) { + // Android 16 and later supports live updates + // Set progress bar sections if on Baklava or later + for (i in 0.. timerRepository.focusTime.toInt() - TimerMode.SHORT_BREAK -> timerRepository.shortBreakTime.toInt() - else -> timerRepository.longBreakTime.toInt() - } - ) + timerRepository.focusTime.toInt() + ).setColor(cs.primary.toArgb()) + ) + else if (i != (timerRepository.sessionLength * 2 - 1)) it.addProgressSegment( + NotificationCompat.ProgressStyle.Segment( + timerRepository.shortBreakTime.toInt() + ).setColor(cs.tertiary.toArgb()) + ) + else it.addProgressSegment( + NotificationCompat.ProgressStyle.Segment( + timerRepository.longBreakTime.toInt() + ).setColor(cs.tertiary.toArgb()) ) } - } - .setProgress( // Set the current progress by filling the previous intervals and part of the current interval - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { - (totalTime - remainingTime) + ((cycles + 1) / 2) * timerRepository.focusTime.toInt() + (cycles / 2) * timerRepository.shortBreakTime.toInt() - } else (totalTime - remainingTime) + } else { + it.addProgressSegment( + NotificationCompat.ProgressStyle.Segment( + when (timerState.value.timerMode) { + TimerMode.FOCUS -> timerRepository.focusTime.toInt() + TimerMode.SHORT_BREAK -> timerRepository.shortBreakTime.toInt() + else -> timerRepository.longBreakTime.toInt() + } + ) ) - ) + } + } + .setProgress( // Set the current progress by filling the previous intervals and part of the current interval + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { + (totalTime - remainingTime) + ((cycles + 1) / 2) * timerRepository.focusTime.toInt() + (cycles / 2) * timerRepository.shortBreakTime.toInt() + } else (totalTime - remainingTime) + )) .setWhen(System.currentTimeMillis() + remainingTime) // Sets the Live Activity/Now Bar chip time - .setShortCriticalText(millisecondsToStr(time.coerceAtLeast(0))) - .build() - ) + .setShortCriticalText(millisecondsToStr(time.coerceAtLeast(0))).build()) if (complete) { startAlarm() @@ -376,9 +340,7 @@ class TimerService : Service() { TimerMode.FOCUS -> timerRepository.focusTime.toInt() TimerMode.SHORT_BREAK -> timerRepository.shortBreakTime.toInt() else -> timerRepository.longBreakTime.toInt() - }, - paused = true, - complete = false + }, paused = true, complete = false ) }