When mapping invalid notification event, only drop that one (#5137)

Previously, this meant the code processing the whole notification batch result failed and other notifications would be lost too.
This commit is contained in:
Jorge Martin Espinosa 2025-08-08 11:56:15 +02:00 committed by GitHub
parent 1afcce2b97
commit 2a50b9ab8d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 77 additions and 34 deletions

View file

@ -8,6 +8,7 @@
package io.element.android.libraries.matrix.impl.notification
import io.element.android.libraries.core.bool.orFalse
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId
@ -30,31 +31,33 @@ class NotificationMapper(
eventId: EventId,
roomId: RoomId,
notificationItem: NotificationItem
): NotificationData {
return notificationItem.use { item ->
val isDm = isDm(
isDirect = item.roomInfo.isDirect,
activeMembersCount = item.roomInfo.joinedMembersCount.toInt(),
)
NotificationData(
sessionId = sessionId,
eventId = eventId,
// FIXME once the `NotificationItem` in the SDK returns the thread id
threadId = null,
roomId = roomId,
senderAvatarUrl = item.senderInfo.avatarUrl,
senderDisplayName = item.senderInfo.displayName,
senderIsNameAmbiguous = item.senderInfo.isNameAmbiguous,
roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { isDm },
roomDisplayName = item.roomInfo.displayName,
isDirect = item.roomInfo.isDirect,
isDm = isDm,
isEncrypted = item.roomInfo.isEncrypted.orFalse(),
isNoisy = item.isNoisy.orFalse(),
timestamp = item.timestamp() ?: clock.epochMillis(),
content = item.event.use { notificationContentMapper.map(it) },
hasMention = item.hasMention.orFalse(),
)
): Result<NotificationData> {
return runCatchingExceptions {
notificationItem.use { item ->
val isDm = isDm(
isDirect = item.roomInfo.isDirect,
activeMembersCount = item.roomInfo.joinedMembersCount.toInt(),
)
NotificationData(
sessionId = sessionId,
eventId = eventId,
// FIXME once the `NotificationItem` in the SDK returns the thread id
threadId = null,
roomId = roomId,
senderAvatarUrl = item.senderInfo.avatarUrl,
senderDisplayName = item.senderInfo.displayName,
senderIsNameAmbiguous = item.senderInfo.isNameAmbiguous,
roomAvatarUrl = item.roomInfo.avatarUrl ?: item.senderInfo.avatarUrl.takeIf { isDm },
roomDisplayName = item.roomInfo.displayName,
isDirect = item.roomInfo.isDirect,
isDm = isDm,
isEncrypted = item.roomInfo.isEncrypted.orFalse(),
isNoisy = item.isNoisy.orFalse(),
timestamp = item.timestamp() ?: clock.epochMillis(),
content = item.event.use { notificationContentMapper.map(it) }.getOrThrow(),
hasMention = item.hasMention.orFalse(),
)
}
}
}
}
@ -62,11 +65,13 @@ class NotificationMapper(
class NotificationContentMapper {
private val timelineEventToNotificationContentMapper = TimelineEventToNotificationContentMapper()
fun map(notificationEvent: NotificationEvent): NotificationContent =
fun map(notificationEvent: NotificationEvent): Result<NotificationContent> =
when (notificationEvent) {
is NotificationEvent.Timeline -> timelineEventToNotificationContentMapper.map(notificationEvent.event)
is NotificationEvent.Invite -> NotificationContent.Invite(
senderId = UserId(notificationEvent.sender),
is NotificationEvent.Invite -> Result.success(
NotificationContent.Invite(
senderId = UserId(notificationEvent.sender),
)
)
}
}

View file

@ -53,7 +53,9 @@ class RustNotificationService(
is BatchNotificationResult.Ok -> {
when (val status = result.status) {
is NotificationStatus.Event -> {
put(eventId, Result.success(notificationMapper.map(sessionId, eventId, roomId, status.item)))
val result = notificationMapper.map(sessionId, eventId, roomId, status.item)
result.onFailure { Timber.e(it, "Could not map notification event $eventId") }
put(eventId, result)
}
is NotificationStatus.EventNotFound -> {
Timber.e("Could not retrieve event for notification with $eventId - event not found")

View file

@ -7,6 +7,7 @@
package io.element.android.libraries.matrix.impl.notification
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.notification.CallNotifyType
@ -21,10 +22,12 @@ import org.matrix.rustcomponents.sdk.TimelineEventType
import org.matrix.rustcomponents.sdk.use
class TimelineEventToNotificationContentMapper {
fun map(timelineEvent: TimelineEvent): NotificationContent {
return timelineEvent.use {
timelineEvent.eventType().use { eventType ->
eventType.toContent(senderId = UserId(timelineEvent.senderId()))
fun map(timelineEvent: TimelineEvent): Result<NotificationContent> {
return runCatchingExceptions {
timelineEvent.use {
timelineEvent.eventType().use { eventType ->
eventType.toContent(senderId = UserId(timelineEvent.senderId()))
}
}
}
}