From fdc1c3f6c57a5170d11a58f15537395ee3d26ce4 Mon Sep 17 00:00:00 2001 From: Nishant Mishra Date: Mon, 15 Sep 2025 20:02:24 +0530 Subject: [PATCH] feat: Implement an alarm sound picker in the Settings screen Closes: #36 --- .../ui/settingsScreen/SettingsScreen.kt | 68 ++++++++++++++++++- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt index 37334df..98db86c 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/SettingsScreen.kt @@ -7,9 +7,18 @@ package org.nsh07.pomodoro.ui.settingsScreen +import android.app.Activity +import android.content.Intent +import android.media.RingtoneManager +import android.net.Uri +import android.os.Build +import android.provider.Settings +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.DrawableRes import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -45,6 +54,7 @@ import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberSliderState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -54,6 +64,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.tooling.preview.Devices @@ -68,7 +79,6 @@ import org.nsh07.pomodoro.ui.theme.AppFonts.robotoFlexTopBar import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors import org.nsh07.pomodoro.ui.theme.CustomColors.topBarColors import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.bottomListItemShape -import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.cardShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.middleListItemShape import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape import org.nsh07.pomodoro.ui.theme.TomatoTheme @@ -132,6 +142,41 @@ private fun SettingsScreen( checkedIconColor = colorScheme.primary, ) + var selectedSoundUri by remember { mutableStateOf(Settings.System.DEFAULT_ALARM_ALERT_URI) } + var selectedSoundName by remember { mutableStateOf("...") } + val context = LocalContext.current + + // 2. The Activity Result Launcher + val ringtonePickerLauncher = rememberLauncherForActivityResult( + contract = ActivityResultContracts.StartActivityForResult() + ) { result -> + // This block is executed when the user picks a sound and returns to the app + if (result.resultCode == Activity.RESULT_OK) { + val uri = + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + result.data?.getParcelableExtra( + RingtoneManager.EXTRA_RINGTONE_PICKED_URI, + Uri::class.java + ) + } else { + @Suppress("DEPRECATION") + result.data?.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI) + } + selectedSoundUri = uri + } + } + + // 3. The Intent to launch the picker + val intent = Intent(RingtoneManager.ACTION_RINGTONE_PICKER).apply { + // We want to show only alarm sounds + putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM) + // A title for the picker + putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "Alarm sound") + + // If a sound is already selected, show it as checked + putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, selectedSoundUri) + } + val switchItems = remember(alarmEnabled, vibrateEnabled) { listOf( SettingsSwitchItem( @@ -151,6 +196,12 @@ private fun SettingsScreen( ) } + LaunchedEffect(selectedSoundUri) { + selectedSoundName = + RingtoneManager.getRingtone(context, selectedSoundUri) + .getTitle(context) + } + Column(modifier.nestedScroll(scrollBehavior.nestedScrollConnection)) { TopAppBar( title = { @@ -266,7 +317,20 @@ private fun SettingsScreen( } }, colors = listItemColors, - modifier = Modifier.clip(cardShape) + modifier = Modifier.clip(topListItemShape) + ) + } + item { + ListItem( + leadingContent = { + Icon(painterResource(R.drawable.alarm), null) + }, + headlineContent = { Text("Alarm sound") }, + supportingContent = { Text(selectedSoundName) }, + colors = listItemColors, + modifier = Modifier + .clip(bottomListItemShape) + .clickable(onClick = { ringtonePickerLauncher.launch(intent) }) ) } item { Spacer(Modifier.height(12.dp)) }