@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Nishant Mishra
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.nsh07.pomodoro.ui.timerScreen
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.material3.AlertDialogDefaults
|
||||
import androidx.compose.material3.BasicAlertDialog
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import org.nsh07.pomodoro.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AlarmDialog(
|
||||
modifier: Modifier = Modifier,
|
||||
stopAlarm: () -> Unit
|
||||
) {
|
||||
BasicAlertDialog(
|
||||
onDismissRequest = stopAlarm,
|
||||
modifier = modifier
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier
|
||||
.wrapContentWidth()
|
||||
.wrapContentHeight()
|
||||
.clickable(onClick = stopAlarm),
|
||||
shape = MaterialTheme.shapes.extraLarge,
|
||||
tonalElevation = AlertDialogDefaults.TonalElevation,
|
||||
) {
|
||||
Column(modifier = Modifier.padding(24.dp)) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.alarm),
|
||||
contentDescription = "Alarm",
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Stop Alarm?",
|
||||
style = typography.headlineSmall,
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
Text(
|
||||
text = "Current timer session is complete. Tap anywhere to stop the alarm."
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Button(
|
||||
onClick = stopAlarm,
|
||||
modifier = Modifier.align(Alignment.End),
|
||||
) {
|
||||
Text("Ok")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,6 +111,9 @@ fun TimerScreen(
|
||||
onResult = {}
|
||||
)
|
||||
|
||||
if (timerState.alarmRinging)
|
||||
AlarmDialog { onAction(TimerAction.StopAlarm) }
|
||||
|
||||
Column(modifier = modifier) {
|
||||
TopAppBar(
|
||||
title = {
|
||||
|
||||
@@ -10,5 +10,6 @@ package org.nsh07.pomodoro.ui.timerScreen.viewModel
|
||||
sealed interface TimerAction {
|
||||
data object ResetTimer : TimerAction
|
||||
data object SkipTimer : TimerAction
|
||||
data object StopAlarm : TimerAction
|
||||
data object ToggleTimer : TimerAction
|
||||
}
|
||||
@@ -16,7 +16,8 @@ data class TimerState(
|
||||
val nextTimeStr: String = "5:00",
|
||||
val showBrandTitle: Boolean = true,
|
||||
val currentFocusCount: Int = 1,
|
||||
val totalFocusCount: Int = 4
|
||||
val totalFocusCount: Int = 4,
|
||||
val alarmRinging: Boolean = false
|
||||
)
|
||||
|
||||
enum class TimerMode {
|
||||
|
||||
@@ -8,19 +8,23 @@
|
||||
package org.nsh07.pomodoro.ui.timerScreen.viewModel
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.media.MediaPlayer
|
||||
import android.os.SystemClock
|
||||
import android.provider.Settings
|
||||
import androidx.compose.material3.ColorScheme
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
|
||||
import androidx.lifecycle.application
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
@@ -46,12 +50,13 @@ import kotlin.text.Typography.middleDot
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
class TimerViewModel(
|
||||
application: Application,
|
||||
private val preferenceRepository: PreferenceRepository,
|
||||
private val statRepository: StatRepository,
|
||||
private val timerRepository: TimerRepository,
|
||||
private val notificationBuilder: NotificationCompat.Builder,
|
||||
private val notificationManager: NotificationManagerCompat
|
||||
) : ViewModel() {
|
||||
) : AndroidViewModel(application) {
|
||||
private val _timerState = MutableStateFlow(
|
||||
TimerState(
|
||||
totalTime = timerRepository.focusTime,
|
||||
@@ -73,6 +78,11 @@ class TimerViewModel(
|
||||
|
||||
private lateinit var cs: ColorScheme
|
||||
|
||||
private val alarm = MediaPlayer.create(
|
||||
this.application,
|
||||
Settings.System.DEFAULT_ALARM_ALERT_URI ?: Settings.System.DEFAULT_RINGTONE_URI
|
||||
)
|
||||
|
||||
init {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
timerRepository.focusTime =
|
||||
@@ -126,6 +136,7 @@ class TimerViewModel(
|
||||
when (action) {
|
||||
TimerAction.ResetTimer -> resetTimer()
|
||||
TimerAction.SkipTimer -> skipTimer()
|
||||
TimerAction.StopAlarm -> stopAlarm()
|
||||
TimerAction.ToggleTimer -> toggleTimer()
|
||||
}
|
||||
}
|
||||
@@ -331,9 +342,24 @@ class TimerViewModel(
|
||||
)
|
||||
.setShowWhen(true)
|
||||
.setWhen(System.currentTimeMillis() + remainingTime) // Sets the Live Activity/Now Bar chip time
|
||||
.setSilent(!complete)
|
||||
.setSilent(true)
|
||||
.build()
|
||||
)
|
||||
|
||||
if (complete) {
|
||||
alarm.start()
|
||||
_timerState.update { currentState ->
|
||||
currentState.copy(alarmRinging = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun stopAlarm() {
|
||||
alarm.pause()
|
||||
alarm.seekTo(0)
|
||||
_timerState.update { currentState ->
|
||||
currentState.copy(alarmRinging = false)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -374,6 +400,7 @@ class TimerViewModel(
|
||||
.setOngoing(true)
|
||||
|
||||
TimerViewModel(
|
||||
application = application,
|
||||
preferenceRepository = appPreferenceRepository,
|
||||
statRepository = appStatRepository,
|
||||
timerRepository = appTimerRepository,
|
||||
|
||||
16
app/src/main/res/drawable/alarm.xml
Normal file
16
app/src/main/res/drawable/alarm.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<!--
|
||||
~ Copyright (c) 2025 Nishant Mishra
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#e3e3e3"
|
||||
android:pathData="M520,504v-144q0,-17 -11.5,-28.5T480,320q-17,0 -28.5,11.5T440,360v159q0,8 3,15.5t9,13.5l112,112q11,11 28,11t28,-11q11,-11 11,-28t-11,-28L520,504ZM480,880q-75,0 -140.5,-28.5t-114,-77q-48.5,-48.5 -77,-114T120,520q0,-75 28.5,-140.5t77,-114q48.5,-48.5 114,-77T480,160q75,0 140.5,28.5t114,77q48.5,48.5 77,114T840,520q0,75 -28.5,140.5t-77,114q-48.5,48.5 -114,77T480,880ZM82,292q-11,-11 -11,-28t11,-28l114,-114q11,-11 28,-11t28,11q11,11 11,28t-11,28L138,292q-11,11 -28,11t-28,-11ZM878,292q-11,11 -28,11t-28,-11L708,178q-11,-11 -11,-28t11,-28q11,-11 28,-11t28,11l114,114q11,11 11,28t-11,28Z" />
|
||||
</vector>
|
||||
Reference in New Issue
Block a user