diff --git a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt index 84c0a34e4..32686d261 100644 --- a/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt +++ b/app/src/main/java/com/todoroo/astrid/activity/TaskListFragment.kt @@ -89,6 +89,7 @@ import org.tasks.caldav.BaseCaldavCalendarSettingsActivity import org.tasks.compose.FilterSelectionActivity.Companion.launch import org.tasks.compose.FilterSelectionActivity.Companion.registerForListPickerResult import org.tasks.compose.NotificationsDisabledBanner +import org.tasks.compose.QuietHoursBanner import org.tasks.compose.SubscriptionNagBanner import org.tasks.compose.rememberReminderPermissionState import org.tasks.data.TaskContainer @@ -128,6 +129,7 @@ import org.tasks.kmp.org.tasks.time.DateStyle import org.tasks.kmp.org.tasks.time.getRelativeDateTime import org.tasks.markdown.MarkdownProvider import org.tasks.preferences.Device +import org.tasks.preferences.MainPreferences import org.tasks.preferences.Preferences import org.tasks.scheduling.NotificationSchedulerIntentService import org.tasks.sync.SyncAdapters @@ -376,6 +378,8 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL } val showNotificationBanner = state.warnNotificationsDisabled && (!hasRemindersPermission || notificationPermissions?.status is PermissionStatus.Denied) + val showSubscriptionNag = !showNotificationBanner && state.begForSubscription + val showQuietHoursWarning = !showNotificationBanner && !showSubscriptionNag && state.warnQuietHoursEnabled NotificationsDisabledBanner( visible = showNotificationBanner, settings = { @@ -390,7 +394,7 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL dismiss = { listViewModel.dismissNotificationBanner() }, ) SubscriptionNagBanner( - visible = state.begForSubscription && !showNotificationBanner, + visible = showSubscriptionNag, subscribe = { listViewModel.dismissPurchaseBanner(clickedPurchase = true) if (Tasks.IS_GOOGLE_PLAY) { @@ -404,6 +408,16 @@ class TaskListFragment : Fragment(), OnRefreshListener, Toolbar.OnMenuItemClickL listViewModel.dismissPurchaseBanner(clickedPurchase = false) }, ) + QuietHoursBanner( + visible = showQuietHoursWarning, + showSettings = { + listViewModel.dismissQuietHoursBanner() + context.startActivity(Intent(context, MainPreferences::class.java)) + }, + dismiss = { + listViewModel.dismissQuietHoursBanner() + } + ) } } return binding.root diff --git a/app/src/main/java/com/todoroo/astrid/alarms/AlarmService.kt b/app/src/main/java/com/todoroo/astrid/alarms/AlarmService.kt index 4929d6634..d81ed0b2c 100644 --- a/app/src/main/java/com/todoroo/astrid/alarms/AlarmService.kt +++ b/app/src/main/java/com/todoroo/astrid/alarms/AlarmService.kt @@ -72,6 +72,9 @@ class AlarmService @Inject constructor( ): Long { if (preferences.isCurrentlyQuietHours) { return preferences.adjustForQuietHours(currentTimeMillis()) + } else { + // reset quiet hours warning if not currently quiet hours + preferences.warnQuietHoursDisabled = true } val (overdue, _) = getAlarms() overdue diff --git a/app/src/main/java/org/tasks/compose/Banner.kt b/app/src/main/java/org/tasks/compose/Banner.kt index 0d8291d90..7aed3cf5c 100644 --- a/app/src/main/java/org/tasks/compose/Banner.kt +++ b/app/src/main/java/org/tasks/compose/Banner.kt @@ -54,6 +54,24 @@ fun SubscriptionNagBanner( ) } +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun QuietHoursBanner( + visible: Boolean, + showSettings: () -> Unit, + dismiss: () -> Unit, +) { + AnimatedBanner( + visible = visible, + title = stringResource(R.string.quiet_hours_in_effect), + body = stringResource(R.string.quiet_hours_summary), + dismissText = stringResource(id = R.string.dismiss), + onDismiss = dismiss, + action = stringResource(id = R.string.TLA_menu_settings), + onAction = showSettings, + ) +} + @ExperimentalAnimationApi @Composable fun BeastModeBanner( @@ -95,3 +113,11 @@ private fun BeastModePreview() = TasksTheme { private fun SubscriptionNagPreview() = TasksTheme { SubscriptionNagBanner(visible = true, subscribe = {}, dismiss = {}) } + +@ExperimentalAnimationApi +@Preview(showBackground = true) +@Preview(showBackground = true, backgroundColor = 0x202124, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun QuietHoursPreview() = TasksTheme { + QuietHoursBanner(visible = true, showSettings = {}, dismiss = {}) +} diff --git a/app/src/main/java/org/tasks/preferences/Preferences.kt b/app/src/main/java/org/tasks/preferences/Preferences.kt index becad1d3b..993119ffc 100644 --- a/app/src/main/java/org/tasks/preferences/Preferences.kt +++ b/app/src/main/java/org/tasks/preferences/Preferences.kt @@ -565,6 +565,10 @@ class Preferences @JvmOverloads constructor( get() = getBoolean(R.string.p_warn_notifications_disabled, true) set(value) = setBoolean(R.string.p_warn_notifications_disabled, value) + var warnQuietHoursDisabled: Boolean + get() = getBoolean(R.string.p_warn_quiet_hours_enabled, true) + set(value) = setBoolean(R.string.p_warn_quiet_hours_enabled, value) + var lastSubscribeRequest: Long get() = getLong(R.string.p_last_subscribe_request, 0L) set(value) = setLong(R.string.p_last_subscribe_request, value) diff --git a/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt b/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt index 383457618..86c378d7a 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/MainSettingsFragment.kt @@ -144,6 +144,7 @@ class MainSettingsFragment : InjectingPreferenceFragment() { super.onResume() updateBackupWarning() + updateQuietHoursWarning() updateWidgetVisibility() } @@ -196,6 +197,12 @@ class MainSettingsFragment : InjectingPreferenceFragment() { (findPreference(R.string.backup_BPr_header) as IconPreference).iconVisible = backupWarning } + private fun updateQuietHoursWarning() { + val pref = findPreference(R.string.notifications) as IconPreference + setupErrorIcon(pref, hasError = false, hasWarning = preferences.isCurrentlyQuietHours) + pref.iconVisible = preferences.isCurrentlyQuietHours + } + private fun setup(account: CaldavAccount, pref: IconPreference) { pref.setTitle(account.prefTitle) pref.summary = account.name diff --git a/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt b/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt index 888928639..ee98725f5 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt @@ -158,6 +158,7 @@ class Notifications : InjectingPreferenceFragment() { super.onResume() checkBatteryOptimizations() + updateQuietHoursWarning() } private fun checkBatteryOptimizations() { @@ -166,6 +167,16 @@ class Notifications : InjectingPreferenceFragment() { !powerManager.isIgnoringBatteryOptimizations(getString(R.string.app_package)) } + private fun updateQuietHoursWarning() { + val pref = findPreference(R.string.p_rmd_enable_quiet) + if (preferences.isCurrentlyQuietHours) { + pref.setIcon(R.drawable.ic_outline_error_outline_24px) + tintIcons(pref, requireContext().getColor(org.tasks.kmp.R.color.orange_500)) + } else { + pref.icon = null + } + } + override fun onDestroy() { super.onDestroy() diff --git a/app/src/main/java/org/tasks/ui/TaskListViewModel.kt b/app/src/main/java/org/tasks/ui/TaskListViewModel.kt index 9d906ccd1..e7a641e42 100644 --- a/app/src/main/java/org/tasks/ui/TaskListViewModel.kt +++ b/app/src/main/java/org/tasks/ui/TaskListViewModel.kt @@ -66,6 +66,7 @@ class TaskListViewModel @Inject constructor( val begForSubscription: Boolean = false, val warnNotificationsDisabled: Boolean = false, val syncOngoing: Boolean = false, + val warnQuietHoursEnabled: Boolean = false, val collapsed: Set = setOf(SectionedDataSource.HEADER_COMPLETED), ) @@ -197,9 +198,12 @@ class TaskListViewModel @Inject constructor( } fun updateBannerState() { - viewModelScope.launch(Dispatchers.Default) { + viewModelScope.launch(Dispatchers.IO) { _state.update { - it.copy(warnNotificationsDisabled = preferences.warnNotificationsDisabled) + it.copy( + warnNotificationsDisabled = preferences.warnNotificationsDisabled, + warnQuietHoursEnabled = preferences.isCurrentlyQuietHours && preferences.warnQuietHoursDisabled, + ) } if (!inventory.hasPro && !firebase.subscribeCooldown) { @@ -210,6 +214,13 @@ class TaskListViewModel @Inject constructor( } } + fun dismissQuietHoursBanner() = viewModelScope.launch(Dispatchers.IO) { + preferences.warnQuietHoursDisabled = false + _state.update { + it.copy(warnQuietHoursEnabled = false) + } + } + companion object { fun Context.createSearchQuery(query: String): Filter = SearchFilter(getString(R.string.FLA_search_filter, query), query) diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index 4558f3124..c468e3352 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -408,6 +408,7 @@ install_date default_location warn_notifications_disabled + warn_quiet_hours_enabled showed_purchase_dialog billing_flow_result diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2f67ad185..4fa516eed 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -306,6 +306,7 @@ File %1$s contained %2$s.\n\n Sound Vibrations Quiet hours + Quiet hours are in effect Attachment folder Backup folder Google Drive backup diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 0f5aeb7bf..4f5b44302 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -13,10 +13,12 @@ app:title="@string/preferences_look_and_feel" app:allowDividerAbove="true" /> - +