diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt index d74f2aa..5aad189 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/screens/TimerSettings.kt @@ -40,7 +40,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape @@ -132,46 +131,59 @@ fun TimerSettings( settingsState.dndEnabled, settingsState.aodEnabled, settingsState.autostartNextSession, + settingsState.lockScreenInAod, isPlus, serviceRunning ) { listOf( - SettingsSwitchItem( - checked = settingsState.autostartNextSession, - icon = R.drawable.autoplay, - label = R.string.auto_start_next_session, - description = R.string.auto_start_next_session_desc, - onClick = { onAction(SettingsAction.SaveAutostartNextSession(it)) } - ), - SettingsSwitchItem( - checked = settingsState.dndEnabled, - enabled = !serviceRunning, - icon = R.drawable.dnd, - label = R.string.dnd, - description = R.string.dnd_desc, - onClick = { - if (it && notificationManagerService?.isNotificationPolicyAccessGranted() == false) { - val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) - Toast.makeText( - context, - "Enable permission for \"$appName\"", - Toast.LENGTH_LONG - ) - .show() - context.startActivity(intent) - } else if (!it && notificationManagerService?.isNotificationPolicyAccessGranted() == true) { - notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) + listOf( + SettingsSwitchItem( + checked = settingsState.autostartNextSession, + icon = R.drawable.autoplay, + label = R.string.auto_start_next_timer, + description = R.string.auto_start_next_timer_desc, + onClick = { onAction(SettingsAction.SaveAutostartNextSession(it)) } + ), + SettingsSwitchItem( + checked = settingsState.dndEnabled, + enabled = !serviceRunning, + icon = R.drawable.dnd, + label = R.string.dnd, + description = R.string.dnd_desc, + onClick = { + if (it && notificationManagerService?.isNotificationPolicyAccessGranted() == false) { + val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS) + Toast.makeText( + context, + "Enable permission for \"$appName\"", + Toast.LENGTH_LONG + ) + .show() + context.startActivity(intent) + } else if (!it && notificationManagerService?.isNotificationPolicyAccessGranted() == true) { + notificationManagerService.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL) + } + onAction(SettingsAction.SaveDndEnabled(it)) } - onAction(SettingsAction.SaveDndEnabled(it)) - } + ) ), - SettingsSwitchItem( - checked = settingsState.aodEnabled, - enabled = isPlus, - icon = R.drawable.aod, - label = R.string.always_on_display, - description = R.string.always_on_display_desc, - onClick = { onAction(SettingsAction.SaveAodEnabled(it)) } + listOf( + SettingsSwitchItem( + checked = settingsState.aodEnabled, + enabled = isPlus, + icon = R.drawable.aod, + label = R.string.always_on_display, + description = R.string.always_on_display_desc, + onClick = { onAction(SettingsAction.SaveAodEnabled(it)) } + ), + SettingsSwitchItem( + checked = settingsState.lockScreenInAod && isPlus, + enabled = isPlus, + icon = R.drawable.mobile_lock_portrait, + label = R.string.secure_aod, + description = R.string.secure_aod_desc, + onClick = { onAction(SettingsAction.SaveLockScreenInAod(it)) } + ) ) ) } @@ -328,7 +340,7 @@ fun TimerSettings( } item { Spacer(Modifier.height(12.dp)) } - itemsIndexed(if (isPlus) switchItems else switchItems.take(2)) { index, item -> + itemsIndexed(switchItems[0]) { index, item -> ListItem( leadingContent = { Icon( @@ -364,20 +376,63 @@ fun TimerSettings( }, colors = listItemColors, modifier = Modifier.clip( - if (isPlus) when (index) { + when (index) { 0 -> topListItemShape - switchItems.size - 1 -> bottomListItemShape - else -> middleListItemShape - } - else when (index) { - 0 -> topListItemShape - switchItems.size - 2 -> bottomListItemShape + switchItems[0].size - 1 -> bottomListItemShape else -> middleListItemShape } ) ) } + if (isPlus) { + item { Spacer(Modifier.height(12.dp)) } + itemsIndexed(switchItems[1]) { index, item -> + ListItem( + leadingContent = { + Icon( + painterResource(item.icon), + contentDescription = null, + modifier = Modifier.padding(top = 4.dp) + ) + }, + headlineContent = { Text(stringResource(item.label)) }, + supportingContent = { Text(stringResource(item.description)) }, + trailingContent = { + Switch( + checked = item.checked, + onCheckedChange = { item.onClick(it) }, + enabled = item.enabled, + thumbContent = { + if (item.checked) { + Icon( + painter = painterResource(R.drawable.check), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } else { + Icon( + painter = painterResource(R.drawable.clear), + contentDescription = null, + modifier = Modifier.size(SwitchDefaults.IconSize), + ) + } + }, + colors = switchColors + ) + }, + colors = listItemColors, + modifier = Modifier.clip( + when (index) { + 0 -> topListItemShape + switchItems[1].size - 1 -> bottomListItemShape + else -> middleListItemShape + } + ) + ) + } + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { item { Spacer(Modifier.height(12.dp)) } item { @@ -430,7 +485,7 @@ fun TimerSettings( item { PlusDivider(setShowPaywall) } - items(switchItems.drop(1)) { item -> + itemsIndexed(switchItems[1]) { index, item -> ListItem( leadingContent = { Icon( @@ -465,7 +520,13 @@ fun TimerSettings( ) }, colors = listItemColors, - modifier = Modifier.clip(cardShape) + modifier = Modifier.clip( + when (index) { + 0 -> topListItemShape + switchItems[1].size - 1 -> bottomListItemShape + else -> middleListItemShape + } + ) ) } } diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsAction.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsAction.kt index 34f244c..b9cf69b 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsAction.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsAction.kt @@ -29,6 +29,7 @@ sealed interface SettingsAction { data class SaveMediaVolumeForAlarm(val enabled: Boolean) : SettingsAction data class SaveSingleProgressBar(val enabled: Boolean) : SettingsAction data class SaveAutostartNextSession(val enabled: Boolean) : SettingsAction + data class SaveLockScreenInAod(val enabled: Boolean) : SettingsAction data class SaveAlarmSound(val uri: Uri?) : SettingsAction data class SaveTheme(val theme: String) : SettingsAction data class SaveColorScheme(val color: Color) : SettingsAction diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsState.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsState.kt index c839866..1ecdd23 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsState.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsState.kt @@ -34,6 +34,7 @@ data class SettingsState( val mediaVolumeForAlarm: Boolean = false, val singleProgressBar: Boolean = false, val autostartNextSession: Boolean = false, + val lockScreenInAod: Boolean = true, val focusTime: Long = 25 * 60 * 1000L, val shortBreakTime: Long = 5 * 60 * 1000L, diff --git a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt index aac7009..2ab6250 100644 --- a/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt +++ b/app/src/main/java/org/nsh07/pomodoro/ui/settingsScreen/viewModel/SettingsViewModel.kt @@ -115,6 +115,7 @@ class SettingsViewModel( is SettingsAction.SaveMediaVolumeForAlarm -> saveMediaVolumeForAlarm(action.enabled) is SettingsAction.SaveSingleProgressBar -> saveSingleProgressBar(action.enabled) is SettingsAction.SaveAutostartNextSession -> saveAutostartNextSession(action.enabled) + is SettingsAction.SaveLockScreenInAod -> saveLockScreenInAod(action.enabled) is SettingsAction.SaveColorScheme -> saveColorScheme(action.color) is SettingsAction.SaveTheme -> saveTheme(action.theme) is SettingsAction.SaveBlackTheme -> saveBlackTheme(action.enabled) @@ -302,6 +303,18 @@ class SettingsViewModel( } } + private fun saveLockScreenInAod(lockScreenInAod: Boolean) { + viewModelScope.launch { + _settingsState.update { currentState -> + currentState.copy(lockScreenInAod = lockScreenInAod) + } + preferenceRepository.saveBooleanPreference( + "lock_screen_in_aod", + lockScreenInAod + ) + } + } + suspend fun reloadSettings() { var settingsState = _settingsState.value val focusTime = @@ -375,6 +388,8 @@ class SettingsViewModel( "autostart_next_session", settingsState.autostartNextSession ) + val lockScreenInAod = preferenceRepository.getBooleanPreference("lock_screen_in_aod") + ?: preferenceRepository.saveBooleanPreference("lock_screen_in_aod", true) _settingsState.update { currentState -> currentState.copy( @@ -392,7 +407,8 @@ class SettingsViewModel( dndEnabled = dndEnabled, mediaVolumeForAlarm = mediaVolumeForAlarm, singleProgressBar = singleProgressBar, - autostartNextSession = autostartNextSession + autostartNextSession = autostartNextSession, + lockScreenInAod = lockScreenInAod ) } diff --git a/app/src/main/res/drawable/mobile_lock_portrait.xml b/app/src/main/res/drawable/mobile_lock_portrait.xml new file mode 100644 index 0000000..4c8a264 --- /dev/null +++ b/app/src/main/res/drawable/mobile_lock_portrait.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0d2b3dd..0c54743 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,7 +15,7 @@ ~ If not, see . --> - + Alarm Ring alarm when a timer completes Alarm sound @@ -68,7 +68,7 @@ Focus durations at different times of the day Rate on Google Play Restart - Selected + Selected Session length Focus intervals in one session: %1$d Settings @@ -107,6 +107,8 @@ Plays on headphones only. If headphones are disconnected, alarm plays through speaker at media volume. Session-only progress Show progress for the current session only in notifications, rather than the full sequence. - Start next session after stopping an alarm - Auto start next session + Start next timer after stopping an alarm + Auto start next timer + Secure AOD + Automatically lock your device after a timeout, while keeping the AOD visible \ No newline at end of file