feat(settings): add a settings option to disable AOD

disabled by default
This commit is contained in:
Nishant Mishra
2025-10-21 11:41:38 +05:30
parent 518f172054
commit 4293f0d5f1
10 changed files with 148 additions and 84 deletions

View File

@@ -51,7 +51,10 @@ class MainActivity : ComponentActivity() {
appContainer.appTimerRepository.colorScheme = colorScheme
}
AppScreen(timerViewModel = timerViewModel, isAODEnabled = true)
AppScreen(
timerViewModel = timerViewModel,
isAODEnabled = preferencesState.aodEnabled
)
}
}
}

View File

@@ -177,8 +177,8 @@ fun SharedTransitionScope.AlwaysOnDisplay(
}
}
val x by animateIntAsState(randomX)
val y by animateIntAsState(randomY)
val x by animateIntAsState(randomX, motionScheme.slowSpatialSpec())
val y by animateIntAsState(randomY, motionScheme.slowSpatialSpec())
Box(
modifier = modifier

View File

@@ -15,6 +15,7 @@ import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -143,6 +144,7 @@ fun SettingsScreenRoot(
onAlarmEnabledChange = viewModel::saveAlarmEnabled,
onVibrateEnabledChange = viewModel::saveVibrateEnabled,
onBlackThemeChange = viewModel::saveBlackTheme,
onAodEnabledChange = viewModel::saveAodEnabled,
onAlarmSoundChanged = {
viewModel.saveAlarmSound(it)
Intent(context, TimerService::class.java).apply {
@@ -170,6 +172,7 @@ private fun SettingsScreen(
onAlarmEnabledChange: (Boolean) -> Unit,
onVibrateEnabledChange: (Boolean) -> Unit,
onBlackThemeChange: (Boolean) -> Unit,
onAodEnabledChange: (Boolean) -> Unit,
onAlarmSoundChanged: (Uri?) -> Unit,
onThemeChange: (String) -> Unit,
onColorSchemeChange: (Color) -> Unit,
@@ -181,14 +184,14 @@ private fun SettingsScreen(
checkedIconColor = colorScheme.primary,
)
val themeMap: Map<String, Pair<Int, String>> = remember {
val themeMap: Map<String, Pair<Int, Int>> = remember {
mapOf(
"auto" to Pair(
R.drawable.brightness_auto,
context.getString(R.string.system_default)
R.string.system_default
),
"light" to Pair(R.drawable.light_mode, context.getString(R.string.light)),
"dark" to Pair(R.drawable.dark_mode, context.getString(R.string.dark))
"light" to Pair(R.drawable.light_mode, R.string.light),
"dark" to Pair(R.drawable.dark_mode, R.string.dark)
)
}
val reverseThemeMap: Map<String, String> = remember {
@@ -232,27 +235,39 @@ private fun SettingsScreen(
putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, alarmSound.toUri())
}
val switchItems = remember(preferencesState.blackTheme, alarmEnabled, vibrateEnabled) {
val switchItems = remember(
preferencesState.blackTheme,
preferencesState.aodEnabled,
alarmEnabled,
vibrateEnabled
) {
listOf(
SettingsSwitchItem(
checked = preferencesState.blackTheme,
icon = R.drawable.contrast,
label = context.getString(R.string.black_theme),
description = context.getString(R.string.black_theme_desc),
label = R.string.black_theme,
description = R.string.black_theme_desc,
onClick = onBlackThemeChange
),
SettingsSwitchItem(
checked = preferencesState.aodEnabled,
icon = R.drawable.aod,
label = R.string.always_on_display,
description = R.string.always_on_display_desc,
onClick = onAodEnabledChange
),
SettingsSwitchItem(
checked = alarmEnabled,
icon = R.drawable.alarm_on,
label = context.getString(R.string.alarm),
description = context.getString(R.string.alarm_desc),
label = R.string.alarm,
description = R.string.alarm_desc,
onClick = onAlarmEnabledChange
),
SettingsSwitchItem(
checked = vibrateEnabled,
icon = R.drawable.mobile_vibrate,
label = context.getString(R.string.vibrate),
description = context.getString(R.string.vibrate_desc),
label = R.string.vibrate,
description = R.string.vibrate_desc,
onClick = onVibrateEnabledChange
)
)
@@ -404,14 +419,13 @@ private fun SettingsScreen(
.clip(middleListItemShape)
)
}
item {
val item = switchItems[0]
itemsIndexed(switchItems.take(2)) { index, item ->
ListItem(
leadingContent = {
Icon(painterResource(item.icon), contentDescription = null)
},
headlineContent = { Text(item.label) },
supportingContent = { Text(item.description) },
headlineContent = { Text(stringResource(item.label)) },
supportingContent = { Text(stringResource(item.description)) },
trailingContent = {
Switch(
checked = item.checked,
@@ -435,7 +449,9 @@ private fun SettingsScreen(
)
},
colors = listItemColors,
modifier = Modifier.clip(bottomListItemShape)
modifier = Modifier
.padding(top = if (index != 0) 16.dp else 0.dp)
.clip(if (index == 0) bottomListItemShape else cardShape)
)
}
@@ -454,13 +470,13 @@ private fun SettingsScreen(
.clickable(onClick = { ringtonePickerLauncher.launch(intent) })
)
}
itemsIndexed(switchItems.drop(1)) { index, item ->
itemsIndexed(switchItems.drop(2)) { index, item ->
ListItem(
leadingContent = {
Icon(painterResource(item.icon), contentDescription = null)
},
headlineContent = { Text(item.label) },
supportingContent = { Text(item.description) },
headlineContent = { Text(stringResource(item.label)) },
supportingContent = { Text(stringResource(item.description)) },
trailingContent = {
Switch(
checked = item.checked,
@@ -487,7 +503,7 @@ private fun SettingsScreen(
modifier = Modifier
.clip(
when (index) {
switchItems.lastIndex - 1 -> bottomListItemShape
switchItems.lastIndex - 2 -> bottomListItemShape
else -> middleListItemShape
}
)
@@ -546,6 +562,7 @@ fun SettingsScreenPreview() {
onAlarmEnabledChange = {},
onVibrateEnabledChange = {},
onBlackThemeChange = {},
onAodEnabledChange = {},
onAlarmSoundChanged = {},
onThemeChange = {},
onColorSchemeChange = {},
@@ -557,7 +574,7 @@ fun SettingsScreenPreview() {
data class SettingsSwitchItem(
val checked: Boolean,
@param:DrawableRes val icon: Int,
val label: String,
val description: String,
@param:StringRes val label: Int,
@param:StringRes val description: Int,
val onClick: (Boolean) -> Unit
)

View File

@@ -31,11 +31,12 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
@@ -50,14 +51,16 @@ import org.nsh07.pomodoro.ui.theme.TomatoShapeDefaults.topListItemShape
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun ThemeDialog(
themeMap: Map<String, Pair<Int, String>>,
themeMap: Map<String, Pair<Int, Int>>,
reverseThemeMap: Map<String, String>,
theme: String,
setShowThemeDialog: (Boolean) -> Unit,
onThemeChange: (String) -> Unit
) {
val selectedOption =
remember { mutableStateOf(themeMap[theme]!!.second) }
remember { mutableIntStateOf(themeMap[theme]!!.second) }
val context = LocalContext.current
BasicAlertDialog(
onDismissRequest = { setShowThemeDialog(false) }
@@ -80,7 +83,7 @@ fun ThemeDialog(
verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = Modifier.selectableGroup()
) {
themeMap.entries.forEachIndexed { index: Int, pair: Map.Entry<String, Pair<Int, String>> ->
themeMap.entries.forEachIndexed { index: Int, pair: Map.Entry<String, Pair<Int, Int>> ->
val text = pair.value.second
val selected = text == selectedOption.value
@@ -94,7 +97,10 @@ fun ThemeDialog(
}
},
headlineContent = {
Text(text = text, style = MaterialTheme.typography.bodyLarge)
Text(
text = stringResource(text),
style = MaterialTheme.typography.bodyLarge
)
},
colors = if (!selected) listItemColors else selectedListItemColors,
modifier = Modifier
@@ -110,7 +116,11 @@ fun ThemeDialog(
selected = (text == selectedOption.value),
onClick = {
selectedOption.value = text
onThemeChange(reverseThemeMap[selectedOption.value]!!)
onThemeChange(
reverseThemeMap[context.getString(
selectedOption.intValue
)]!!
)
},
role = Role.RadioButton
)

View File

@@ -25,7 +25,7 @@ import org.nsh07.pomodoro.ui.theme.CustomColors.listItemColors
@Composable
fun ThemePickerListItem(
theme: String,
themeMap: Map<String, Pair<Int, String>>,
themeMap: Map<String, Pair<Int, Int>>,
reverseThemeMap: Map<String, String>,
items: Int,
index: Int,
@@ -53,7 +53,7 @@ fun ThemePickerListItem(
},
headlineContent = { Text(stringResource(R.string.theme)) },
supportingContent = {
Text(themeMap[theme]!!.second)
Text(stringResource(themeMap[theme]!!.second))
},
colors = listItemColors,
items = items,

View File

@@ -14,5 +14,6 @@ import androidx.compose.ui.graphics.Color
data class PreferencesState(
val theme: String = "auto",
val colorScheme: String = Color.White.toString(),
val blackTheme: Boolean = false
val blackTheme: Boolean = false,
val aodEnabled: Boolean = false
)

View File

@@ -80,12 +80,15 @@ class SettingsViewModel(
?: preferenceRepository.saveStringPreference("color_scheme", Color.White.toString())
val blackTheme = preferenceRepository.getBooleanPreference("black_theme")
?: preferenceRepository.saveBooleanPreference("black_theme", false)
val aodEnabled = preferenceRepository.getBooleanPreference("aod_enabled")
?: preferenceRepository.saveBooleanPreference("aod_enabled", false)
_preferencesState.update { currentState ->
currentState.copy(
theme = theme,
colorScheme = colorScheme,
blackTheme = blackTheme
blackTheme = blackTheme,
aodEnabled = aodEnabled
)
}
}
@@ -196,6 +199,15 @@ class SettingsViewModel(
}
}
fun saveAodEnabled(aodEnabled: Boolean) {
viewModelScope.launch {
_preferencesState.update { currentState ->
currentState.copy(aodEnabled = aodEnabled)
}
preferenceRepository.saveBooleanPreference("aod_enabled", aodEnabled)
}
}
companion object {
val Factory: ViewModelProvider.Factory = viewModelFactory {
initializer {

View File

@@ -95,6 +95,9 @@ class TimerViewModel(
)
).toUri()
preferenceRepository.getBooleanPreference("aod_enabled")
?: preferenceRepository.saveBooleanPreference("aod_enabled", false)
_time.update { timerRepository.focusTime }
cycles = 0
startTime = 0L