fix(#145): review round A — group-blocked deep-link, status refresh race, hint dismiss on open
This commit is contained in:
1 parent
955dccff2b
commit
2e71e4dc5f
4 files changed
+22
-17
No files matched your search
@@ -106,15 +106,17 @@ class ReminderChannels @Inject constructor(
|
||||
fun status(calendarIds: Collection<Long>): ReminderChannelStatus {
|
||||
val manager = manager
|
||||
val appEnabled = manager.areNotificationsEnabled()
|
||||
val blocked = blockedReminderCalendars(
|
||||
calendarIds = calendarIds,
|
||||
appEnabled = appEnabled,
|
||||
channels = manager.notificationChannels.associate {
|
||||
it.id to ReminderChannelState(it.importance == NotificationManager.IMPORTANCE_NONE, it.group)
|
||||
val channels = manager.notificationChannels.associate {
|
||||
it.id to ReminderChannelState(it.importance == NotificationManager.IMPORTANCE_NONE, it.group)
|
||||
}
|
||||
val blockedGroups = manager.notificationChannelGroups.filter { it.isBlocked }.mapTo(HashSet()) { it.id }
|
||||
return ReminderChannelStatus(
|
||||
appBlocked = !appEnabled,
|
||||
blockedCalendarIds = blockedReminderCalendars(calendarIds, appEnabled, channels, blockedGroups),
|
||||
groupBlockedCalendarIds = calendarIds.filterTo(HashSet()) {
|
||||
channels[reminderChannelId(it)]?.groupId in blockedGroups
|
||||
},
|
||||
blockedGroupIds = manager.notificationChannelGroups.filter { it.isBlocked }.mapTo(HashSet()) { it.id },
|
||||
)
|
||||
return ReminderChannelStatus(appBlocked = !appEnabled, blockedCalendarIds = blocked)
|
||||
}
|
||||
|
||||
private fun plan(
|
||||
@@ -141,8 +143,7 @@ class ReminderChannels @Inject constructor(
|
||||
if (channels.isEmpty()) return
|
||||
val byId = existing.associateBy { it.id }
|
||||
val template = byId[LEGACY_REMINDER_CHANNEL_ID]
|
||||
// Only a channel's first creation sets its behaviour; later calls just
|
||||
// rename it, so an existing one passes its own importance back.
|
||||
// Importance only applies on creation; an existing channel keeps its own.
|
||||
manager.createNotificationChannels(
|
||||
channels.map { spec ->
|
||||
val current = byId[spec.id]
|
||||
@@ -210,4 +211,6 @@ class ReminderChannels @Inject constructor(
|
||||
data class ReminderChannelStatus(
|
||||
val appBlocked: Boolean = false,
|
||||
val blockedCalendarIds: Set<Long> = emptySet(),
|
||||
/** The blocked ones whose whole account group is off, which only the app's own screen can undo. */
|
||||
val groupBlockedCalendarIds: Set<Long> = emptySet(),
|
||||
)
|
||||
@@ -104,7 +104,6 @@ internal fun NotificationsScreen(
|
||||
val scope = rememberCoroutineScope()
|
||||
val channelStatus by viewModel.channelStatus.collectAsStateWithLifecycle()
|
||||
val calendarIds = state.reminderCalendars.map { it.id }
|
||||
// Re-read whenever the screen returns from the system settings it links to.
|
||||
LifecycleResumeEffect(calendarIds) {
|
||||
viewModel.refreshChannelStatus(calendarIds)
|
||||
onPauseOrDispose { }
|
||||
@@ -112,8 +111,8 @@ internal fun NotificationsScreen(
|
||||
val openCalendarSound: (Long) -> Unit = { calendarId ->
|
||||
scope.launch {
|
||||
val channelId = viewModel.reminderChannelFor(calendarId)
|
||||
// With the whole app blocked, only the app's own screen can allow it.
|
||||
context.openNotificationSettings(channelId.takeUnless { channelStatus.appBlocked })
|
||||
val appScreen = channelStatus.appBlocked || calendarId in channelStatus.groupBlockedCalendarIds
|
||||
context.openNotificationSettings(channelId.takeUnless { appScreen })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +125,7 @@ internal fun NotificationsScreen(
|
||||
if (IS_SAMSUNG && !state.notificationCategoryHintDismissed) {
|
||||
NotificationCategoryHint(
|
||||
onOpen = {
|
||||
viewModel.dismissNotificationCategoryHint()
|
||||
scope.launch {
|
||||
viewModel.syncReminderChannels()
|
||||
context.openNotificationSettings()
|
||||
@@ -207,9 +207,7 @@ internal fun NotificationsScreen(
|
||||
onClick = { showSnooze = true },
|
||||
)
|
||||
|
||||
// Per-calendar settings, folded behind one header: every switched-on
|
||||
// calendar gets its notification switch and sound (#145, #272); the ones
|
||||
// you can edit also keep, drop or replace the default reminders.
|
||||
// Per-calendar notifications and reminder overrides (#145, #272).
|
||||
if (state.reminderCalendars.isNotEmpty()) {
|
||||
Spacer(Modifier.height(24.dp))
|
||||
GroupedRow(
|
||||
|
||||
@@ -50,6 +50,7 @@ import de.jeanlucmakiola.calendula.ui.theme.AppFontSettings
|
||||
import de.jeanlucmakiola.calendula.ui.theme.FONT_CUSTOM_TOKEN
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -377,8 +378,11 @@ class SettingsViewModel @Inject constructor(
|
||||
/** What the system blocks of the reminders; re-read with [refreshChannelStatus] (#145). */
|
||||
val channelStatus: StateFlow<ReminderChannelStatus> = _channelStatus.asStateFlow()
|
||||
|
||||
private var channelStatusJob: Job? = null
|
||||
|
||||
fun refreshChannelStatus(calendarIds: Collection<Long>) {
|
||||
viewModelScope.launch {
|
||||
channelStatusJob?.cancel()
|
||||
channelStatusJob = viewModelScope.launch {
|
||||
onChannels { status(calendarIds) }?.let { _channelStatus.value = it }
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
Submodule floret-kit updated: 730c9eb25a...20b136aaf7.
Reference in new issue
Block a user