diff --git a/app/src/main/java/com/bnyro/clock/obj/ScheduledObject.kt b/app/src/main/java/com/bnyro/clock/obj/ScheduledObject.kt index dd3e8c7d..a3850657 100644 --- a/app/src/main/java/com/bnyro/clock/obj/ScheduledObject.kt +++ b/app/src/main/java/com/bnyro/clock/obj/ScheduledObject.kt @@ -10,5 +10,6 @@ data class ScheduledObject( var currentPosition: MutableState = mutableStateOf(0), val initialPosition: Int = currentPosition.value, var state: MutableState = mutableStateOf(WatchState.IDLE), - var ringtone: Uri? = null + var ringtone: Uri? = null, + var vibrate: Boolean = false ) diff --git a/app/src/main/java/com/bnyro/clock/services/TimerService.kt b/app/src/main/java/com/bnyro/clock/services/TimerService.kt index 38d09f07..99473e96 100644 --- a/app/src/main/java/com/bnyro/clock/services/TimerService.kt +++ b/app/src/main/java/com/bnyro/clock/services/TimerService.kt @@ -73,6 +73,7 @@ class TimerService : ScheduleService() { ) .setSmallIcon(R.drawable.ic_notification) .setSound(scheduledObject.ringtone ?: RingtoneHelper.getDefault(this)) + .setVibrate(NotificationHelper.vibrationPattern.takeIf { scheduledObject.vibrate }) .setContentTitle(getString(R.string.timer_finished)) .setContentText(scheduledObject.label.value) .build() @@ -96,6 +97,13 @@ class TimerService : ScheduleService() { } } + fun updateVibrate(id: Int, vibrate: Boolean) { + scheduledObjects.firstOrNull { it.id == id }?.let { + it.vibrate = vibrate + invokeChangeListener() + } + } + override fun getStartNotification() = NotificationCompat.Builder( this, NotificationHelper.TIMER_SERVICE_CHANNEL diff --git a/app/src/main/java/com/bnyro/clock/ui/components/TimerItem.kt b/app/src/main/java/com/bnyro/clock/ui/components/TimerItem.kt index e4d26657..c2f4188b 100644 --- a/app/src/main/java/com/bnyro/clock/ui/components/TimerItem.kt +++ b/app/src/main/java/com/bnyro/clock/ui/components/TimerItem.kt @@ -14,6 +14,7 @@ import androidx.compose.material.icons.filled.Notifications import androidx.compose.material.icons.filled.Pause import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Checkbox import androidx.compose.material3.ElevatedCard import androidx.compose.material3.FilledIconButton import androidx.compose.material3.Icon @@ -113,7 +114,8 @@ fun TimerItem(obj: ScheduledObject, index: Int, timerModel: TimerModel) { } } LinearProgressIndicator( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(start = 16.dp, end = 16.dp, bottom = 16.dp) .height(8.dp), progress = obj.currentPosition.value / obj.initialPosition.toFloat(), @@ -157,9 +159,25 @@ fun TimerItem(obj: ScheduledObject, index: Int, timerModel: TimerModel) { ) } if (showRingtoneEditor) { - RingtonePickerDialog(onDismissRequest = { - showRingtoneEditor = false - }) { _, uri -> + RingtonePickerDialog( + onDismissRequest = { + showRingtoneEditor = false + }, + bottomContent = { + Row( + modifier = Modifier.align(Alignment.Start), + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = obj.vibrate, + onCheckedChange = { + timerModel.service?.updateVibrate(obj.id, it) + } + ) + Text(text = stringResource(R.string.vibrate)) + } + } + ) { _, uri -> timerModel.service?.updateRingtone(obj.id, uri) } } diff --git a/app/src/main/java/com/bnyro/clock/ui/dialog/RingtonePickerDialog.kt b/app/src/main/java/com/bnyro/clock/ui/dialog/RingtonePickerDialog.kt index b705570a..f18611d7 100644 --- a/app/src/main/java/com/bnyro/clock/ui/dialog/RingtonePickerDialog.kt +++ b/app/src/main/java/com/bnyro/clock/ui/dialog/RingtonePickerDialog.kt @@ -5,14 +5,16 @@ import androidx.activity.compose.rememberLauncherForActivityResult import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.NotificationsActive import androidx.compose.material3.AlertDialog @@ -35,6 +37,7 @@ import com.bnyro.clock.util.PickPersistentFileContract @Composable fun RingtonePickerDialog( onDismissRequest: () -> Unit, + bottomContent: @Composable ColumnScope.() -> Unit = {}, onSelection: (String, Uri) -> Unit ) { val context = LocalContext.current @@ -67,37 +70,45 @@ fun RingtonePickerDialog( Text(stringResource(com.bnyro.clock.R.string.sound)) }, text = { - val scrollState = rememberScrollState() Column( modifier = Modifier .fillMaxWidth() - .heightIn(400.dp, 500.dp) - .verticalScroll(scrollState), + .heightIn(400.dp, 500.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { if (ringingToneModel.sounds.isEmpty()) { CircularProgressIndicator() } else { - ringingToneModel.sounds.forEach { (title, uri) -> - Row( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(10.dp)) - .clickable { - onSelection.invoke(title, uri) - onDismissRequest.invoke() + LazyColumn( + modifier = Modifier.weight(1f), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + ) { + items(ringingToneModel.sounds) { (title, uri) -> + Row( + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(10.dp)) + .clickable { + onSelection.invoke(title, uri) + onDismissRequest.invoke() + } + .padding(horizontal = 10.dp, vertical = 2.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(title) + Spacer(modifier = Modifier.weight(1f)) + ClickableIcon(imageVector = Icons.Default.NotificationsActive) { + ringingToneModel.playRingingTone(context, uri) } - .padding(horizontal = 10.dp, vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Text(title) - Spacer(modifier = Modifier.weight(1f)) - ClickableIcon(imageVector = Icons.Default.NotificationsActive) { - ringingToneModel.playRingingTone(context, uri) } } } + + Spacer(modifier = Modifier.height(16.dp)) + + bottomContent() } } }