Ignore fallback notification when the room list is rendered.

Add more tests.
This commit is contained in:
Benoit Marty 2026-02-12 10:46:20 +01:00 committed by Benoit Marty
parent 73c3ffac2d
commit 50264a9ab0
5 changed files with 316 additions and 34 deletions

View file

@ -22,12 +22,20 @@ import io.element.android.libraries.matrix.ui.media.ImageLoaderHolder
import io.element.android.libraries.push.api.notifications.NotificationCleaner
import io.element.android.libraries.push.api.notifications.NotificationIdProvider
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator
import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.shouldIgnoreEventInRoom
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableRingingCallEvent
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
import io.element.android.libraries.sessionstorage.api.observer.SessionListener
import io.element.android.libraries.sessionstorage.api.observer.SessionObserver
import io.element.android.services.appnavstate.api.AppNavigationState
import io.element.android.services.appnavstate.api.AppNavigationStateService
import io.element.android.services.appnavstate.api.NavigationState
import io.element.android.services.appnavstate.api.currentRoomId
import io.element.android.services.appnavstate.api.currentSessionId
import io.element.android.services.appnavstate.api.currentThreadId
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@ -97,14 +105,11 @@ class DefaultNotificationDrawerManager(
* Events might be grouped and there might not be one notification per event!
*/
suspend fun onNotifiableEventReceived(notifiableEvent: NotifiableEvent) {
if (notifiableEvent.shouldIgnoreEventInRoom(appNavigationStateService.appNavigationState.value)) {
return
}
renderEvents(listOf(notifiableEvent))
onNotifiableEventsReceived(listOf(notifiableEvent))
}
suspend fun onNotifiableEventsReceived(notifiableEvents: List<NotifiableEvent>) {
val eventsToNotify = notifiableEvents.filter { !it.shouldIgnoreEventInRoom(appNavigationStateService.appNavigationState.value) }
val eventsToNotify = notifiableEvents.filter { !it.shouldIgnoreRegardingApplicationState(appNavigationStateService.appNavigationState.value) }
renderEvents(eventsToNotify)
}
@ -206,3 +211,30 @@ class DefaultNotificationDrawerManager(
}
}
}
/**
* Used to check if a notification should be ignored based on the current application navigation state.
*/
private fun NotifiableEvent.shouldIgnoreRegardingApplicationState(appNavigationState: AppNavigationState): Boolean {
if (!appNavigationState.isInForeground) return false
return appNavigationState.navigationState.currentSessionId() == sessionId &&
when (this) {
is NotifiableRingingCallEvent -> {
// Never ignore ringing call notifications
// Note that NotifiableRingingCallEvent are not handled by DefaultNotificationDrawerManage
false
}
is FallbackNotifiableEvent -> {
// Ignore if the room list is currently displayed
appNavigationState.navigationState is NavigationState.Session
}
is InviteNotifiableEvent,
is SimpleNotifiableEvent -> {
roomId == appNavigationState.navigationState.currentRoomId()
}
is NotifiableMessageEvent -> {
roomId == appNavigationState.navigationState.currentRoomId() &&
threadId == appNavigationState.navigationState.currentThreadId()
}
}
}

View file

@ -15,10 +15,6 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.timeline.item.event.EventType
import io.element.android.services.appnavstate.api.AppNavigationState
import io.element.android.services.appnavstate.api.currentRoomId
import io.element.android.services.appnavstate.api.currentSessionId
import io.element.android.services.appnavstate.api.currentThreadId
data class NotifiableMessageEvent(
override val sessionId: SessionId,
@ -56,24 +52,3 @@ data class NotifiableMessageEvent(
val imageUri: Uri?
get() = imageUriString?.toUri()
}
/**
* Used to check if a notification should be ignored based on the current app and navigation state.
*/
fun NotifiableEvent.shouldIgnoreEventInRoom(appNavigationState: AppNavigationState): Boolean {
val currentSessionId = appNavigationState.navigationState.currentSessionId() ?: return false
return when (val currentRoomId = appNavigationState.navigationState.currentRoomId()) {
null -> false
else -> {
// Never ignore ringing call notifications
if (this is NotifiableRingingCallEvent) {
false
} else {
appNavigationState.isInForeground &&
sessionId == currentSessionId &&
roomId == currentRoomId &&
(this as? NotifiableMessageEvent)?.threadId == appNavigationState.navigationState.currentThreadId()
}
}
}
}