Notification: show userId in notification when several accounts are configured.

This commit is contained in:
Benoit Marty 2025-10-25 15:31:10 +02:00 committed by Benoit Marty
parent 45b5783b23
commit 031ca4f333
20 changed files with 265 additions and 202 deletions

View file

@ -24,11 +24,12 @@ class FakeEnterpriseService(
private val defaultHomeserverListResult: () -> List<String> = { emptyList() }, private val defaultHomeserverListResult: () -> List<String> = { emptyList() },
private val isAllowedToConnectToHomeserverResult: (String) -> Boolean = { lambdaError() }, private val isAllowedToConnectToHomeserverResult: (String) -> Boolean = { lambdaError() },
initialSemanticColors: SemanticColorsLightDark = SemanticColorsLightDark.default, initialSemanticColors: SemanticColorsLightDark = SemanticColorsLightDark.default,
initialBrandColor: Color? = null,
private val overrideBrandColorResult: (SessionId?, String?) -> Unit = { _, _ -> lambdaError() }, private val overrideBrandColorResult: (SessionId?, String?) -> Unit = { _, _ -> lambdaError() },
private val firebasePushGatewayResult: () -> String? = { lambdaError() }, private val firebasePushGatewayResult: () -> String? = { lambdaError() },
private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() },
) : EnterpriseService { ) : EnterpriseService {
private val brandColorState = MutableStateFlow<Color?>(null) private val brandColorState = MutableStateFlow(initialBrandColor)
private val semanticColorsState = MutableStateFlow(initialSemanticColors) private val semanticColorsState = MutableStateFlow(initialSemanticColors)
override suspend fun isEnterpriseUser(sessionId: SessionId): Boolean = simulateLongTask { override suspend fun isEnterpriseUser(sessionId: SessionId): Boolean = simulateLongTask {

View file

@ -7,6 +7,7 @@
package io.element.android.libraries.matrix.test package io.element.android.libraries.matrix.test
import androidx.annotation.ColorInt
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.core.DeviceId import io.element.android.libraries.matrix.api.core.DeviceId
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
@ -99,4 +100,5 @@ const val A_FORMATTED_DATE = "April 6, 1980 at 6:35 PM"
const val A_LOGIN_HINT = "mxid:@alice:example.org" const val A_LOGIN_HINT = "mxid:@alice:example.org"
const val A_COLOR_INT = 0xFF0000 @ColorInt
const val A_COLOR_INT: Int = 0xFFFF0000.toInt()

View file

@ -10,7 +10,6 @@ package io.element.android.libraries.push.impl.notifications
import android.app.Notification import android.app.Notification
import android.graphics.Typeface import android.graphics.Typeface
import android.text.style.StyleSpan import android.text.style.StyleSpan
import androidx.annotation.ColorInt
import androidx.core.text.buildSpannedString import androidx.core.text.buildSpannedString
import androidx.core.text.inSpans import androidx.core.text.inSpans
import coil3.ImageLoader import coil3.ImageLoader
@ -19,8 +18,8 @@ import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.SessionId 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.ThreadId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator 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.FallbackNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
@ -31,39 +30,37 @@ import io.element.android.services.toolbox.api.strings.StringProvider
interface NotificationDataFactory { interface NotificationDataFactory {
suspend fun toNotifications( suspend fun toNotifications(
messages: List<NotifiableMessageEvent>, messages: List<NotifiableMessageEvent>,
currentUser: MatrixUser,
imageLoader: ImageLoader, imageLoader: ImageLoader,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<RoomNotification> ): List<RoomNotification>
@JvmName("toNotificationInvites") @JvmName("toNotificationInvites")
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
fun toNotifications( fun toNotifications(
invites: List<InviteNotifiableEvent>, invites: List<InviteNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> ): List<OneShotNotification>
@JvmName("toNotificationSimpleEvents") @JvmName("toNotificationSimpleEvents")
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
fun toNotifications( fun toNotifications(
simpleEvents: List<SimpleNotifiableEvent>, simpleEvents: List<SimpleNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> ): List<OneShotNotification>
@JvmName("toNotificationFallbackEvents") @JvmName("toNotificationFallbackEvents")
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
fun toNotifications( fun toNotifications(
fallback: List<FallbackNotifiableEvent>, fallback: List<FallbackNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> ): List<OneShotNotification>
fun createSummaryNotification( fun createSummaryNotification(
currentUser: MatrixUser,
roomNotifications: List<RoomNotification>, roomNotifications: List<RoomNotification>,
invitationNotifications: List<OneShotNotification>, invitationNotifications: List<OneShotNotification>,
simpleNotifications: List<OneShotNotification>, simpleNotifications: List<OneShotNotification>,
fallbackNotifications: List<OneShotNotification>, fallbackNotifications: List<OneShotNotification>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): SummaryNotification ): SummaryNotification
} }
@ -77,9 +74,8 @@ class DefaultNotificationDataFactory(
) : NotificationDataFactory { ) : NotificationDataFactory {
override suspend fun toNotifications( override suspend fun toNotifications(
messages: List<NotifiableMessageEvent>, messages: List<NotifiableMessageEvent>,
currentUser: MatrixUser,
imageLoader: ImageLoader, imageLoader: ImageLoader,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<RoomNotification> { ): List<RoomNotification> {
val messagesToDisplay = messages.filterNot { it.canNotBeDisplayed() } val messagesToDisplay = messages.filterNot { it.canNotBeDisplayed() }
.groupBy { it.roomId } .groupBy { it.roomId }
@ -90,13 +86,12 @@ class DefaultNotificationDataFactory(
eventsByThreadId.map { (threadId, events) -> eventsByThreadId.map { (threadId, events) ->
val notification = roomGroupMessageCreator.createRoomMessage( val notification = roomGroupMessageCreator.createRoomMessage(
currentUser = currentUser,
events = events, events = events,
roomId = roomId, roomId = roomId,
threadId = threadId, threadId = threadId,
imageLoader = imageLoader, imageLoader = imageLoader,
existingNotification = getExistingNotificationForMessages(currentUser.userId, roomId, threadId), existingNotification = getExistingNotificationForMessages(notificationAccountParams.user.userId, roomId, threadId),
color = color, notificationAccountParams = notificationAccountParams,
) )
RoomNotification( RoomNotification(
notification = notification, notification = notification,
@ -121,12 +116,12 @@ class DefaultNotificationDataFactory(
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
override fun toNotifications( override fun toNotifications(
invites: List<InviteNotifiableEvent>, invites: List<InviteNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> { ): List<OneShotNotification> {
return invites.map { event -> return invites.map { event ->
OneShotNotification( OneShotNotification(
key = event.roomId.value, key = event.roomId.value,
notification = notificationCreator.createRoomInvitationNotification(event, color), notification = notificationCreator.createRoomInvitationNotification(notificationAccountParams, event),
summaryLine = event.description, summaryLine = event.description,
isNoisy = event.noisy, isNoisy = event.noisy,
timestamp = event.timestamp timestamp = event.timestamp
@ -138,12 +133,12 @@ class DefaultNotificationDataFactory(
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
override fun toNotifications( override fun toNotifications(
simpleEvents: List<SimpleNotifiableEvent>, simpleEvents: List<SimpleNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> { ): List<OneShotNotification> {
return simpleEvents.map { event -> return simpleEvents.map { event ->
OneShotNotification( OneShotNotification(
key = event.eventId.value, key = event.eventId.value,
notification = notificationCreator.createSimpleEventNotification(event, color), notification = notificationCreator.createSimpleEventNotification(notificationAccountParams, event),
summaryLine = event.description, summaryLine = event.description,
isNoisy = event.noisy, isNoisy = event.noisy,
timestamp = event.timestamp timestamp = event.timestamp
@ -155,12 +150,12 @@ class DefaultNotificationDataFactory(
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
override fun toNotifications( override fun toNotifications(
fallback: List<FallbackNotifiableEvent>, fallback: List<FallbackNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> { ): List<OneShotNotification> {
return fallback.map { event -> return fallback.map { event ->
OneShotNotification( OneShotNotification(
key = event.eventId.value, key = event.eventId.value,
notification = notificationCreator.createFallbackNotification(event, color), notification = notificationCreator.createFallbackNotification(notificationAccountParams, event),
summaryLine = event.description.orEmpty(), summaryLine = event.description.orEmpty(),
isNoisy = false, isNoisy = false,
timestamp = event.timestamp timestamp = event.timestamp
@ -169,23 +164,21 @@ class DefaultNotificationDataFactory(
} }
override fun createSummaryNotification( override fun createSummaryNotification(
currentUser: MatrixUser,
roomNotifications: List<RoomNotification>, roomNotifications: List<RoomNotification>,
invitationNotifications: List<OneShotNotification>, invitationNotifications: List<OneShotNotification>,
simpleNotifications: List<OneShotNotification>, simpleNotifications: List<OneShotNotification>,
fallbackNotifications: List<OneShotNotification>, fallbackNotifications: List<OneShotNotification>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): SummaryNotification { ): SummaryNotification {
return when { return when {
roomNotifications.isEmpty() && invitationNotifications.isEmpty() && simpleNotifications.isEmpty() -> SummaryNotification.Removed roomNotifications.isEmpty() && invitationNotifications.isEmpty() && simpleNotifications.isEmpty() -> SummaryNotification.Removed
else -> SummaryNotification.Update( else -> SummaryNotification.Update(
summaryGroupMessageCreator.createSummaryNotification( summaryGroupMessageCreator.createSummaryNotification(
currentUser = currentUser,
roomNotifications = roomNotifications, roomNotifications = roomNotifications,
invitationNotifications = invitationNotifications, invitationNotifications = invitationNotifications,
simpleNotifications = simpleNotifications, simpleNotifications = simpleNotifications,
fallbackNotifications = fallbackNotifications, fallbackNotifications = fallbackNotifications,
color = color, notificationAccountParams = notificationAccountParams,
) )
) )
} }

View file

@ -15,6 +15,7 @@ import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.libraries.core.log.logger.LoggerTag import io.element.android.libraries.core.log.logger.LoggerTag
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.api.notifications.NotificationIdProvider import io.element.android.libraries.push.api.notifications.NotificationIdProvider
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator 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.FallbackNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent
@ -22,6 +23,7 @@ import io.element.android.libraries.push.impl.notifications.model.NotifiableEven
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent 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.NotifiableRingingCallEvent
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
import io.element.android.libraries.sessionstorage.api.SessionStore
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import timber.log.Timber import timber.log.Timber
@ -32,6 +34,7 @@ class NotificationRenderer(
private val notificationDisplayer: NotificationDisplayer, private val notificationDisplayer: NotificationDisplayer,
private val notificationDataFactory: NotificationDataFactory, private val notificationDataFactory: NotificationDataFactory,
private val enterpriseService: EnterpriseService, private val enterpriseService: EnterpriseService,
private val sessionStore: SessionStore,
) { ) {
suspend fun render( suspend fun render(
currentUser: MatrixUser, currentUser: MatrixUser,
@ -41,18 +44,23 @@ class NotificationRenderer(
) { ) {
val color = enterpriseService.brandColorsFlow(currentUser.userId).first()?.toArgb() val color = enterpriseService.brandColorsFlow(currentUser.userId).first()?.toArgb()
?: NotificationConfig.NOTIFICATION_ACCENT_COLOR ?: NotificationConfig.NOTIFICATION_ACCENT_COLOR
val numberOfAccounts = sessionStore.getAllSessions().size
val notificationAccountParams = NotificationAccountParams(
user = currentUser,
color = color,
showSessionId = numberOfAccounts > 1,
)
val groupedEvents = eventsToProcess.groupByType() val groupedEvents = eventsToProcess.groupByType()
val roomNotifications = notificationDataFactory.toNotifications(groupedEvents.roomEvents, currentUser, imageLoader, color) val roomNotifications = notificationDataFactory.toNotifications(groupedEvents.roomEvents, imageLoader, notificationAccountParams)
val invitationNotifications = notificationDataFactory.toNotifications(groupedEvents.invitationEvents, color) val invitationNotifications = notificationDataFactory.toNotifications(groupedEvents.invitationEvents, notificationAccountParams)
val simpleNotifications = notificationDataFactory.toNotifications(groupedEvents.simpleEvents, color) val simpleNotifications = notificationDataFactory.toNotifications(groupedEvents.simpleEvents, notificationAccountParams)
val fallbackNotifications = notificationDataFactory.toNotifications(groupedEvents.fallbackEvents, color) val fallbackNotifications = notificationDataFactory.toNotifications(groupedEvents.fallbackEvents, notificationAccountParams)
val summaryNotification = notificationDataFactory.createSummaryNotification( val summaryNotification = notificationDataFactory.createSummaryNotification(
currentUser = currentUser,
roomNotifications = roomNotifications, roomNotifications = roomNotifications,
invitationNotifications = invitationNotifications, invitationNotifications = invitationNotifications,
simpleNotifications = simpleNotifications, simpleNotifications = simpleNotifications,
fallbackNotifications = fallbackNotifications, fallbackNotifications = fallbackNotifications,
color = color, notificationAccountParams = notificationAccountParams,
) )
// Remove summary first to avoid briefly displaying it after dismissing the last notification // Remove summary first to avoid briefly displaying it after dismissing the last notification

View file

@ -9,15 +9,14 @@ package io.element.android.libraries.push.impl.notifications
import android.app.Notification import android.app.Notification
import android.graphics.Bitmap import android.graphics.Bitmap
import androidx.annotation.ColorInt
import coil3.ImageLoader import coil3.ImageLoader
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.api.notifications.NotificationBitmapLoader import io.element.android.libraries.push.api.notifications.NotificationBitmapLoader
import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator
import io.element.android.libraries.push.impl.notifications.factories.isSmartReplyError import io.element.android.libraries.push.impl.notifications.factories.isSmartReplyError
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
@ -25,13 +24,12 @@ import io.element.android.services.toolbox.api.strings.StringProvider
interface RoomGroupMessageCreator { interface RoomGroupMessageCreator {
suspend fun createRoomMessage( suspend fun createRoomMessage(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
events: List<NotifiableMessageEvent>, events: List<NotifiableMessageEvent>,
roomId: RoomId, roomId: RoomId,
threadId: ThreadId?, threadId: ThreadId?,
imageLoader: ImageLoader, imageLoader: ImageLoader,
existingNotification: Notification?, existingNotification: Notification?,
@ColorInt color: Int,
): Notification ): Notification
} }
@ -42,13 +40,12 @@ class DefaultRoomGroupMessageCreator(
private val notificationCreator: NotificationCreator, private val notificationCreator: NotificationCreator,
) : RoomGroupMessageCreator { ) : RoomGroupMessageCreator {
override suspend fun createRoomMessage( override suspend fun createRoomMessage(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
events: List<NotifiableMessageEvent>, events: List<NotifiableMessageEvent>,
roomId: RoomId, roomId: RoomId,
threadId: ThreadId?, threadId: ThreadId?,
imageLoader: ImageLoader, imageLoader: ImageLoader,
existingNotification: Notification?, existingNotification: Notification?,
@ColorInt color: Int,
): Notification { ): Notification {
val lastKnownRoomEvent = events.last() val lastKnownRoomEvent = events.last()
val roomName = lastKnownRoomEvent.roomName ?: lastKnownRoomEvent.senderDisambiguatedDisplayName ?: "Room name (${roomId.value.take(8)}…)" val roomName = lastKnownRoomEvent.roomName ?: lastKnownRoomEvent.senderDisambiguatedDisplayName ?: "Room name (${roomId.value.take(8)}…)"
@ -66,8 +63,9 @@ class DefaultRoomGroupMessageCreator(
val smartReplyErrors = events.filter { it.isSmartReplyError() } val smartReplyErrors = events.filter { it.isSmartReplyError() }
val roomIsDm = !roomIsGroup val roomIsDm = !roomIsGroup
return notificationCreator.createMessagesListNotification( return notificationCreator.createMessagesListNotification(
notificationAccountParams = notificationAccountParams,
RoomEventGroupInfo( RoomEventGroupInfo(
sessionId = currentUser.userId, sessionId = notificationAccountParams.user.userId,
roomId = roomId, roomId = roomId,
roomDisplayName = roomName, roomDisplayName = roomName,
isDm = roomIsDm, isDm = roomIsDm,
@ -80,11 +78,9 @@ class DefaultRoomGroupMessageCreator(
largeIcon = largeBitmap, largeIcon = largeBitmap,
lastMessageTimestamp = lastMessageTimestamp, lastMessageTimestamp = lastMessageTimestamp,
tickerText = tickerText, tickerText = tickerText,
currentUser = currentUser,
existingNotification = existingNotification, existingNotification = existingNotification,
imageLoader = imageLoader, imageLoader = imageLoader,
events = events, events = events,
color = color,
) )
} }

View file

@ -8,22 +8,20 @@
package io.element.android.libraries.push.impl.notifications package io.element.android.libraries.push.impl.notifications
import android.app.Notification import android.app.Notification
import androidx.annotation.ColorInt
import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.R
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator
import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.strings.StringProvider
interface SummaryGroupMessageCreator { interface SummaryGroupMessageCreator {
fun createSummaryNotification( fun createSummaryNotification(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
roomNotifications: List<RoomNotification>, roomNotifications: List<RoomNotification>,
invitationNotifications: List<OneShotNotification>, invitationNotifications: List<OneShotNotification>,
simpleNotifications: List<OneShotNotification>, simpleNotifications: List<OneShotNotification>,
fallbackNotifications: List<OneShotNotification>, fallbackNotifications: List<OneShotNotification>,
@ColorInt color: Int,
): Notification ): Notification
} }
@ -42,12 +40,11 @@ class DefaultSummaryGroupMessageCreator(
private val notificationCreator: NotificationCreator, private val notificationCreator: NotificationCreator,
) : SummaryGroupMessageCreator { ) : SummaryGroupMessageCreator {
override fun createSummaryNotification( override fun createSummaryNotification(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
roomNotifications: List<RoomNotification>, roomNotifications: List<RoomNotification>,
invitationNotifications: List<OneShotNotification>, invitationNotifications: List<OneShotNotification>,
simpleNotifications: List<OneShotNotification>, simpleNotifications: List<OneShotNotification>,
fallbackNotifications: List<OneShotNotification>, fallbackNotifications: List<OneShotNotification>,
@ColorInt color: Int,
): Notification { ): Notification {
val summaryIsNoisy = roomNotifications.any { it.shouldBing } || val summaryIsNoisy = roomNotifications.any { it.shouldBing } ||
invitationNotifications.any { it.isNoisy } || invitationNotifications.any { it.isNoisy } ||
@ -61,11 +58,10 @@ class DefaultSummaryGroupMessageCreator(
val nbEvents = roomNotifications.size + simpleNotifications.size val nbEvents = roomNotifications.size + simpleNotifications.size
val sumTitle = stringProvider.getQuantityString(R.plurals.notification_compat_summary_title, nbEvents, nbEvents) val sumTitle = stringProvider.getQuantityString(R.plurals.notification_compat_summary_title, nbEvents, nbEvents)
return notificationCreator.createSummaryListNotification( return notificationCreator.createSummaryListNotification(
currentUser, notificationAccountParams = notificationAccountParams,
sumTitle, sumTitle,
noisy = summaryIsNoisy, noisy = summaryIsNoisy,
lastMessageTimestamp = lastMessageTimestamp, lastMessageTimestamp = lastMessageTimestamp,
color = color,
) )
} }
} }

View file

@ -0,0 +1,17 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.push.impl.notifications.factories
import androidx.annotation.ColorInt
import io.element.android.libraries.matrix.api.user.MatrixUser
data class NotificationAccountParams(
val user: MatrixUser,
@ColorInt val color: Int,
val showSessionId: Boolean,
)

View file

@ -47,42 +47,40 @@ interface NotificationCreator {
* Create a notification for a Room. * Create a notification for a Room.
*/ */
suspend fun createMessagesListNotification( suspend fun createMessagesListNotification(
notificationAccountParams: NotificationAccountParams,
roomInfo: RoomEventGroupInfo, roomInfo: RoomEventGroupInfo,
threadId: ThreadId?, threadId: ThreadId?,
largeIcon: Bitmap?, largeIcon: Bitmap?,
lastMessageTimestamp: Long, lastMessageTimestamp: Long,
tickerText: String, tickerText: String,
currentUser: MatrixUser,
existingNotification: Notification?, existingNotification: Notification?,
imageLoader: ImageLoader, imageLoader: ImageLoader,
events: List<NotifiableMessageEvent>, events: List<NotifiableMessageEvent>,
@ColorInt color: Int,
): Notification ): Notification
fun createRoomInvitationNotification( fun createRoomInvitationNotification(
notificationAccountParams: NotificationAccountParams,
inviteNotifiableEvent: InviteNotifiableEvent, inviteNotifiableEvent: InviteNotifiableEvent,
@ColorInt color: Int,
): Notification ): Notification
fun createSimpleEventNotification( fun createSimpleEventNotification(
notificationAccountParams: NotificationAccountParams,
simpleNotifiableEvent: SimpleNotifiableEvent, simpleNotifiableEvent: SimpleNotifiableEvent,
@ColorInt color: Int,
): Notification ): Notification
fun createFallbackNotification( fun createFallbackNotification(
notificationAccountParams: NotificationAccountParams,
fallbackNotifiableEvent: FallbackNotifiableEvent, fallbackNotifiableEvent: FallbackNotifiableEvent,
@ColorInt color: Int,
): Notification ): Notification
/** /**
* Create the summary notification. * Create the summary notification.
*/ */
fun createSummaryListNotification( fun createSummaryListNotification(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
compatSummary: String, compatSummary: String,
noisy: Boolean, noisy: Boolean,
lastMessageTimestamp: Long, lastMessageTimestamp: Long,
@ColorInt color: Int,
): Notification ): Notification
fun createDiagnosticNotification( fun createDiagnosticNotification(
@ -118,16 +116,15 @@ class DefaultNotificationCreator(
* Create a notification for a Room. * Create a notification for a Room.
*/ */
override suspend fun createMessagesListNotification( override suspend fun createMessagesListNotification(
notificationAccountParams: NotificationAccountParams,
roomInfo: RoomEventGroupInfo, roomInfo: RoomEventGroupInfo,
threadId: ThreadId?, threadId: ThreadId?,
largeIcon: Bitmap?, largeIcon: Bitmap?,
lastMessageTimestamp: Long, lastMessageTimestamp: Long,
tickerText: String, tickerText: String,
currentUser: MatrixUser,
existingNotification: Notification?, existingNotification: Notification?,
imageLoader: ImageLoader, imageLoader: ImageLoader,
events: List<NotifiableMessageEvent>, events: List<NotifiableMessageEvent>,
@ColorInt color: Int,
): Notification { ): Notification {
// Build the pending intent for when the notification is clicked // Build the pending intent for when the notification is clicked
val eventId = events.firstOrNull()?.eventId val eventId = events.firstOrNull()?.eventId
@ -135,7 +132,6 @@ class DefaultNotificationCreator(
threadId != null -> pendingIntentFactory.createOpenThreadPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId, threadId) threadId != null -> pendingIntentFactory.createOpenThreadPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId, threadId)
else -> pendingIntentFactory.createOpenRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId) else -> pendingIntentFactory.createOpenRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId)
} }
val smallIcon = CommonDrawables.ic_notification
val containsMissedCall = events.any { it.type == EventType.RTC_NOTIFICATION } val containsMissedCall = events.any { it.type == EventType.RTC_NOTIFICATION }
val channelId = if (containsMissedCall) { val channelId = if (containsMissedCall) {
notificationChannels.getChannelForIncomingCall(false) notificationChannels.getChannelForIncomingCall(false)
@ -172,7 +168,7 @@ class DefaultNotificationCreator(
val messagingStyle = existingNotification?.let { val messagingStyle = existingNotification?.let {
MessagingStyle.extractMessagingStyleFromNotification(it) MessagingStyle.extractMessagingStyleFromNotification(it)
} ?: messagingStyleFromCurrentUser( } ?: messagingStyleFromCurrentUser(
user = currentUser, user = notificationAccountParams.user,
imageLoader = imageLoader, imageLoader = imageLoader,
roomName = roomInfo.roomDisplayName, roomName = roomInfo.roomDisplayName,
isThread = threadId != null, isThread = threadId != null,
@ -187,9 +183,7 @@ class DefaultNotificationCreator(
.setWhen(lastMessageTimestamp) .setWhen(lastMessageTimestamp)
// MESSAGING_STYLE sets title and content for API 16 and above devices. // MESSAGING_STYLE sets title and content for API 16 and above devices.
.setStyle(messagingStyle) .setStyle(messagingStyle)
.setSmallIcon(smallIcon) .configureWith(notificationAccountParams)
// Set primary color (important for Wear 2.0 Notifications).
.setColor(color)
// Sets priority for 25 and below. For 26 and above, 'priority' is deprecated for // Sets priority for 25 and below. For 26 and above, 'priority' is deprecated for
// 'importance' which is set in the NotificationChannel. The integers representing // 'importance' which is set in the NotificationChannel. The integers representing
// 'priority' are different from 'importance', so make sure you don't mix them. // 'priority' are different from 'importance', so make sure you don't mix them.
@ -202,7 +196,7 @@ class DefaultNotificationCreator(
setSound(it) setSound(it)
} }
*/ */
setLights(color, 500, 500) setLights(notificationAccountParams.color, 500, 500)
} else { } else {
priority = NotificationCompat.PRIORITY_LOW priority = NotificationCompat.PRIORITY_LOW
} }
@ -234,10 +228,9 @@ class DefaultNotificationCreator(
} }
override fun createRoomInvitationNotification( override fun createRoomInvitationNotification(
notificationAccountParams: NotificationAccountParams,
inviteNotifiableEvent: InviteNotifiableEvent, inviteNotifiableEvent: InviteNotifiableEvent,
@ColorInt color: Int,
): Notification { ): Notification {
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(inviteNotifiableEvent.noisy) val channelId = notificationChannels.getChannelIdForMessage(inviteNotifiableEvent.noisy)
return NotificationCompat.Builder(context, channelId) return NotificationCompat.Builder(context, channelId)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
@ -245,8 +238,7 @@ class DefaultNotificationCreator(
.setContentText(inviteNotifiableEvent.description.annotateForDebug(6)) .setContentText(inviteNotifiableEvent.description.annotateForDebug(6))
.setGroup(inviteNotifiableEvent.sessionId.value) .setGroup(inviteNotifiableEvent.sessionId.value)
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL)
.setSmallIcon(smallIcon) .configureWith(notificationAccountParams)
.setColor(color)
.apply { .apply {
addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent)) addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent))
addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent)) addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent))
@ -261,7 +253,7 @@ class DefaultNotificationCreator(
setSound(it) setSound(it)
} }
*/ */
setLights(color, 500, 500) setLights(notificationAccountParams.color, 500, 500)
} else { } else {
priority = NotificationCompat.PRIORITY_LOW priority = NotificationCompat.PRIORITY_LOW
} }
@ -277,10 +269,9 @@ class DefaultNotificationCreator(
} }
override fun createSimpleEventNotification( override fun createSimpleEventNotification(
notificationAccountParams: NotificationAccountParams,
simpleNotifiableEvent: SimpleNotifiableEvent, simpleNotifiableEvent: SimpleNotifiableEvent,
@ColorInt color: Int,
): Notification { ): Notification {
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(simpleNotifiableEvent.noisy) val channelId = notificationChannels.getChannelIdForMessage(simpleNotifiableEvent.noisy)
return NotificationCompat.Builder(context, channelId) return NotificationCompat.Builder(context, channelId)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
@ -288,8 +279,7 @@ class DefaultNotificationCreator(
.setContentText(simpleNotifiableEvent.description.annotateForDebug(8)) .setContentText(simpleNotifiableEvent.description.annotateForDebug(8))
.setGroup(simpleNotifiableEvent.sessionId.value) .setGroup(simpleNotifiableEvent.sessionId.value)
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL)
.setSmallIcon(smallIcon) .configureWith(notificationAccountParams)
.setColor(color)
.setAutoCancel(true) .setAutoCancel(true)
.setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(simpleNotifiableEvent.sessionId, simpleNotifiableEvent.roomId, null)) .setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(simpleNotifiableEvent.sessionId, simpleNotifiableEvent.roomId, null))
.apply { .apply {
@ -301,7 +291,7 @@ class DefaultNotificationCreator(
setSound(it) setSound(it)
} }
*/ */
setLights(color, 500, 500) setLights(notificationAccountParams.color, 500, 500)
} else { } else {
priority = NotificationCompat.PRIORITY_LOW priority = NotificationCompat.PRIORITY_LOW
} }
@ -310,10 +300,9 @@ class DefaultNotificationCreator(
} }
override fun createFallbackNotification( override fun createFallbackNotification(
notificationAccountParams: NotificationAccountParams,
fallbackNotifiableEvent: FallbackNotifiableEvent, fallbackNotifiableEvent: FallbackNotifiableEvent,
@ColorInt color: Int,
): Notification { ): Notification {
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(false) val channelId = notificationChannels.getChannelIdForMessage(false)
return NotificationCompat.Builder(context, channelId) return NotificationCompat.Builder(context, channelId)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
@ -321,8 +310,7 @@ class DefaultNotificationCreator(
.setContentText(fallbackNotifiableEvent.description.orEmpty().annotateForDebug(8)) .setContentText(fallbackNotifiableEvent.description.orEmpty().annotateForDebug(8))
.setGroup(fallbackNotifiableEvent.sessionId.value) .setGroup(fallbackNotifiableEvent.sessionId.value)
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL)
.setSmallIcon(smallIcon) .configureWith(notificationAccountParams)
.setColor(color)
.setAutoCancel(true) .setAutoCancel(true)
.setWhen(fallbackNotifiableEvent.timestamp) .setWhen(fallbackNotifiableEvent.timestamp)
// Ideally we'd use `createOpenRoomPendingIntent` here, but the broken notification might apply to an invite // Ideally we'd use `createOpenRoomPendingIntent` here, but the broken notification might apply to an invite
@ -343,24 +331,22 @@ class DefaultNotificationCreator(
* Create the summary notification. * Create the summary notification.
*/ */
override fun createSummaryListNotification( override fun createSummaryListNotification(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
compatSummary: String, compatSummary: String,
noisy: Boolean, noisy: Boolean,
lastMessageTimestamp: Long, lastMessageTimestamp: Long,
@ColorInt color: Int,
): Notification { ): Notification {
val smallIcon = CommonDrawables.ic_notification
val channelId = notificationChannels.getChannelIdForMessage(noisy) val channelId = notificationChannels.getChannelIdForMessage(noisy)
val userId = notificationAccountParams.user.userId
return NotificationCompat.Builder(context, channelId) return NotificationCompat.Builder(context, channelId)
.setOnlyAlertOnce(true) .setOnlyAlertOnce(true)
// used in compat < N, after summary is built based on child notifications // used in compat < N, after summary is built based on child notifications
.setWhen(lastMessageTimestamp) .setWhen(lastMessageTimestamp)
.setCategory(NotificationCompat.CATEGORY_MESSAGE) .setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setSmallIcon(smallIcon) .setGroup(userId.value)
.setGroup(currentUser.userId.value)
// set this notification as the summary for the group // set this notification as the summary for the group
.setGroupSummary(true) .setGroupSummary(true)
.setColor(color) .configureWith(notificationAccountParams)
.apply { .apply {
if (noisy) { if (noisy) {
// Compat // Compat
@ -370,14 +356,14 @@ class DefaultNotificationCreator(
setSound(it) setSound(it)
} }
*/ */
setLights(color, 500, 500) setLights(notificationAccountParams.color, 500, 500)
} else { } else {
// compat // compat
priority = NotificationCompat.PRIORITY_LOW priority = NotificationCompat.PRIORITY_LOW
} }
} }
.setContentIntent(pendingIntentFactory.createOpenSessionPendingIntent(currentUser.userId)) .setContentIntent(pendingIntentFactory.createOpenSessionPendingIntent(userId))
.setDeleteIntent(pendingIntentFactory.createDismissSummaryPendingIntent(currentUser.userId)) .setDeleteIntent(pendingIntentFactory.createDismissSummaryPendingIntent(userId))
.build() .build()
} }
@ -487,4 +473,12 @@ class DefaultNotificationCreator(
} }
} }
private fun NotificationCompat.Builder.configureWith(notificationAccountParams: NotificationAccountParams) = apply {
setSmallIcon(CommonDrawables.ic_notification)
setColor(notificationAccountParams.color)
if (notificationAccountParams.showSessionId) {
setSubText(notificationAccountParams.user.userId.value)
}
}
fun NotifiableMessageEvent.isSmartReplyError() = outGoingMessage && outGoingMessageFailed fun NotifiableMessageEvent.isSmartReplyError() = outGoingMessage && outGoingMessageFailed

View file

@ -13,7 +13,6 @@ import androidx.core.app.NotificationCompat
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.appconfig.NotificationConfig import io.element.android.appconfig.NotificationConfig
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.test.A_COLOR_INT
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_TIMESTAMP import io.element.android.libraries.matrix.test.A_TIMESTAMP
import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser
@ -21,6 +20,7 @@ import io.element.android.libraries.matrix.ui.media.AVATAR_THUMBNAIL_SIZE_IN_PIX
import io.element.android.libraries.matrix.ui.media.MediaRequestData import io.element.android.libraries.matrix.ui.media.MediaRequestData
import io.element.android.libraries.push.impl.notifications.factories.MARK_AS_READ_ACTION_TITLE import io.element.android.libraries.push.impl.notifications.factories.MARK_AS_READ_ACTION_TITLE
import io.element.android.libraries.push.impl.notifications.factories.QUICK_REPLY_ACTION_TITLE import io.element.android.libraries.push.impl.notifications.factories.QUICK_REPLY_ACTION_TITLE
import io.element.android.libraries.push.impl.notifications.factories.aNotificationAccountParams
import io.element.android.libraries.push.impl.notifications.factories.createNotificationCreator import io.element.android.libraries.push.impl.notifications.factories.createNotificationCreator
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
import io.element.android.libraries.push.test.notifications.FakeImageLoader import io.element.android.libraries.push.test.notifications.FakeImageLoader
@ -44,7 +44,7 @@ class DefaultBaseRoomGroupMessageCreatorTest {
val sut = createRoomGroupMessageCreator() val sut = createRoomGroupMessageCreator()
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage( val result = sut.createRoomMessage(
currentUser = aMatrixUser(), notificationAccountParams = aNotificationAccountParams(),
events = listOf( events = listOf(
aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy( aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy(
imageUriString = "aUri", imageUriString = "aUri",
@ -54,7 +54,6 @@ class DefaultBaseRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null, existingNotification = null,
threadId = null, threadId = null,
color = A_COLOR_INT,
) )
assertThat(result.number).isEqualTo(1) assertThat(result.number).isEqualTo(1)
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@ -68,7 +67,7 @@ class DefaultBaseRoomGroupMessageCreatorTest {
val sut = createRoomGroupMessageCreator() val sut = createRoomGroupMessageCreator()
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage( val result = sut.createRoomMessage(
currentUser = aMatrixUser(), notificationAccountParams = aNotificationAccountParams(),
events = listOf( events = listOf(
aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy( aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy(
noisy = true, noisy = true,
@ -78,7 +77,6 @@ class DefaultBaseRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null, existingNotification = null,
threadId = null, threadId = null,
color = A_COLOR_INT,
) )
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
assertThat(result.priority).isEqualTo(NotificationCompat.PRIORITY_DEFAULT) assertThat(result.priority).isEqualTo(NotificationCompat.PRIORITY_DEFAULT)
@ -130,9 +128,11 @@ class DefaultBaseRoomGroupMessageCreatorTest {
sdkIntProvider = FakeBuildVersionSdkIntProvider(api) sdkIntProvider = FakeBuildVersionSdkIntProvider(api)
) )
val result = sut.createRoomMessage( val result = sut.createRoomMessage(
currentUser = aMatrixUser( notificationAccountParams = aNotificationAccountParams(
// Some user avatar user = aMatrixUser(
avatarUrl = A_USER_AVATAR_1, // Some user avatar
avatarUrl = A_USER_AVATAR_1,
)
), ),
events = listOf( events = listOf(
aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy( aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy(
@ -144,7 +144,6 @@ class DefaultBaseRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null, existingNotification = null,
threadId = null, threadId = null,
color = A_COLOR_INT,
) )
assertThat(result.number).isEqualTo(1) assertThat(result.number).isEqualTo(1)
assertThat(fakeImageLoader.getCoilRequests()).containsExactlyElementsIn(expectedCoilRequests) assertThat(fakeImageLoader.getCoilRequests()).containsExactlyElementsIn(expectedCoilRequests)
@ -155,7 +154,7 @@ class DefaultBaseRoomGroupMessageCreatorTest {
val sut = createRoomGroupMessageCreator() val sut = createRoomGroupMessageCreator()
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage( val result = sut.createRoomMessage(
currentUser = aMatrixUser(), notificationAccountParams = aNotificationAccountParams(),
events = listOf( events = listOf(
aNotifiableMessageEvent(timestamp = A_TIMESTAMP), aNotifiableMessageEvent(timestamp = A_TIMESTAMP),
aNotifiableMessageEvent(timestamp = A_TIMESTAMP + 10), aNotifiableMessageEvent(timestamp = A_TIMESTAMP + 10),
@ -164,7 +163,6 @@ class DefaultBaseRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null, existingNotification = null,
threadId = null, threadId = null,
color = A_COLOR_INT,
) )
assertThat(result.number).isEqualTo(2) assertThat(result.number).isEqualTo(2)
assertThat(result.`when`).isEqualTo(A_TIMESTAMP + 10) assertThat(result.`when`).isEqualTo(A_TIMESTAMP + 10)
@ -183,7 +181,7 @@ class DefaultBaseRoomGroupMessageCreatorTest {
val sut = createRoomGroupMessageCreator() val sut = createRoomGroupMessageCreator()
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage( val result = sut.createRoomMessage(
currentUser = aMatrixUser(), notificationAccountParams = aNotificationAccountParams(),
events = listOf( events = listOf(
aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy( aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy(
outGoingMessage = true, outGoingMessage = true,
@ -194,7 +192,6 @@ class DefaultBaseRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null, existingNotification = null,
threadId = null, threadId = null,
color = A_COLOR_INT,
) )
val actionTitles = result.actions?.map { it.title } val actionTitles = result.actions?.map { it.title }
assertThat(actionTitles).isEqualTo( assertThat(actionTitles).isEqualTo(
@ -210,7 +207,7 @@ class DefaultBaseRoomGroupMessageCreatorTest {
val sut = createRoomGroupMessageCreator() val sut = createRoomGroupMessageCreator()
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = sut.createRoomMessage( val result = sut.createRoomMessage(
currentUser = aMatrixUser(), notificationAccountParams = aNotificationAccountParams(),
events = listOf( events = listOf(
aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy( aNotifiableMessageEvent(timestamp = A_TIMESTAMP).copy(
roomIsDm = true, roomIsDm = true,
@ -220,7 +217,6 @@ class DefaultBaseRoomGroupMessageCreatorTest {
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
existingNotification = null, existingNotification = null,
threadId = null, threadId = null,
color = A_COLOR_INT,
) )
assertThat(result.number).isEqualTo(1) assertThat(result.number).isEqualTo(1)
assertThat(result.`when`).isEqualTo(A_TIMESTAMP) assertThat(result.`when`).isEqualTo(A_TIMESTAMP)

View file

@ -8,8 +8,10 @@
package io.element.android.libraries.push.impl.notifications package io.element.android.libraries.push.impl.notifications
import android.app.Notification import android.app.Notification
import androidx.compose.ui.graphics.Color
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.enterprise.test.FakeEnterpriseService
import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_AVATAR_URL
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
@ -21,12 +23,15 @@ import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.FakeMatrixClientProvider import io.element.android.libraries.matrix.test.FakeMatrixClientProvider
import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.components.aMatrixUser
import io.element.android.libraries.push.api.notifications.NotificationIdProvider import io.element.android.libraries.push.api.notifications.NotificationIdProvider
import io.element.android.libraries.push.impl.notifications.factories.aNotificationAccountParams
import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolder import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolder
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.services.appnavstate.api.AppNavigationState import io.element.android.services.appnavstate.api.AppNavigationState
import io.element.android.services.appnavstate.api.AppNavigationStateService import io.element.android.services.appnavstate.api.AppNavigationStateService
import io.element.android.services.appnavstate.api.NavigationState import io.element.android.services.appnavstate.api.NavigationState
@ -64,8 +69,8 @@ class DefaultNotificationDrawerManagerTest {
// For now just call all the API. Later, add more valuable tests. // For now just call all the API. Later, add more valuable tests.
val matrixUser = aMatrixUser(id = A_SESSION_ID.value, displayName = "alice", avatarUrl = "mxc://data") val matrixUser = aMatrixUser(id = A_SESSION_ID.value, displayName = "alice", avatarUrl = "mxc://data")
val mockRoomGroupMessageCreator = FakeRoomGroupMessageCreator( val mockRoomGroupMessageCreator = FakeRoomGroupMessageCreator(
createRoomMessageResult = lambdaRecorder { user, _, roomId, _, _, existingNotification -> createRoomMessageResult = lambdaRecorder { notificationAccountParams, _, roomId, _, _, existingNotification ->
assertThat(user).isEqualTo(matrixUser) assertThat(notificationAccountParams.user).isEqualTo(matrixUser)
assertThat(roomId).isEqualTo(A_ROOM_ID) assertThat(roomId).isEqualTo(A_ROOM_ID)
assertThat(existingNotification).isNull() assertThat(existingNotification).isNull()
Notification() Notification()
@ -128,6 +133,9 @@ class DefaultNotificationDrawerManagerTest {
val defaultNotificationDrawerManager = createDefaultNotificationDrawerManager( val defaultNotificationDrawerManager = createDefaultNotificationDrawerManager(
matrixClientProvider = matrixClientProvider, matrixClientProvider = matrixClientProvider,
roomGroupMessageCreator = messageCreator, roomGroupMessageCreator = messageCreator,
enterpriseService = FakeEnterpriseService(
initialBrandColor = Color.Red,
)
) )
// Gets a display name from MatrixClient.getUserProfile // Gets a display name from MatrixClient.getUserProfile
matrixClient.givenGetProfileResult(A_SESSION_ID, Result.success(aMatrixUser(id = A_SESSION_ID.value, displayName = "alice"))) matrixClient.givenGetProfileResult(A_SESSION_ID, Result.success(aMatrixUser(id = A_SESSION_ID.value, displayName = "alice")))
@ -144,15 +152,29 @@ class DefaultNotificationDrawerManagerTest {
messageCreator.createRoomMessageResult.assertions() messageCreator.createRoomMessageResult.assertions()
.isCalledExactly(3) .isCalledExactly(3)
.withSequence( .withSequence(
listOf(value(aMatrixUser(id = A_SESSION_ID.value, displayName = "alice")), any(), any(), any(), any(), any()),
listOf(value(aMatrixUser(id = A_SESSION_ID.value, displayName = A_SESSION_ID.value)), any(), any(), any(), any(), any()),
listOf( listOf(
value(aMatrixUser(id = A_SESSION_ID.value, displayName = A_SESSION_ID.value, avatarUrl = AN_AVATAR_URL)), value(aNotificationAccountParams(user = aMatrixUser(id = A_SESSION_ID.value, displayName = "alice"))),
any(),
any(),
any(),
any(),
any(),
),
listOf(
value(aNotificationAccountParams(user = aMatrixUser(id = A_SESSION_ID.value, displayName = A_SESSION_ID.value))),
any(),
any(),
any(),
any(),
any(),
),
listOf(
value(aNotificationAccountParams(user = aMatrixUser(id = A_SESSION_ID.value, displayName = A_SESSION_ID.value, avatarUrl = AN_AVATAR_URL))),
any(),
any(), any(),
any(), any(),
any(), any(),
any(), any(),
any()
), ),
) )
@ -194,6 +216,8 @@ class DefaultNotificationDrawerManagerTest {
summaryGroupMessageCreator: SummaryGroupMessageCreator = FakeSummaryGroupMessageCreator(), summaryGroupMessageCreator: SummaryGroupMessageCreator = FakeSummaryGroupMessageCreator(),
activeNotificationsProvider: FakeActiveNotificationsProvider = FakeActiveNotificationsProvider(), activeNotificationsProvider: FakeActiveNotificationsProvider = FakeActiveNotificationsProvider(),
matrixClientProvider: FakeMatrixClientProvider = FakeMatrixClientProvider(), matrixClientProvider: FakeMatrixClientProvider = FakeMatrixClientProvider(),
sessionStore: SessionStore = InMemorySessionStore(),
enterpriseService: EnterpriseService = FakeEnterpriseService(),
): DefaultNotificationDrawerManager { ): DefaultNotificationDrawerManager {
val context = RuntimeEnvironment.getApplication() val context = RuntimeEnvironment.getApplication()
return DefaultNotificationDrawerManager( return DefaultNotificationDrawerManager(
@ -207,7 +231,8 @@ class DefaultNotificationDrawerManagerTest {
activeNotificationsProvider = activeNotificationsProvider, activeNotificationsProvider = activeNotificationsProvider,
stringProvider = FakeStringProvider(), stringProvider = FakeStringProvider(),
), ),
enterpriseService = FakeEnterpriseService(), enterpriseService = enterpriseService,
sessionStore = sessionStore,
), ),
appNavigationStateService = appNavigationStateService, appNavigationStateService = appNavigationStateService,
coroutineScope = this, coroutineScope = this,

View file

@ -7,7 +7,6 @@
package io.element.android.libraries.push.impl.notifications package io.element.android.libraries.push.impl.notifications
import io.element.android.features.enterprise.test.FakeEnterpriseService
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID
@ -18,7 +17,6 @@ import io.element.android.libraries.matrix.test.notification.FakeNotificationSer
import io.element.android.libraries.matrix.test.notification.aNotificationData import io.element.android.libraries.matrix.test.notification.aNotificationData
import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDataFactory import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDataFactory
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer
import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.fixtures.aNotifiableMessageEvent
import io.element.android.libraries.push.test.notifications.FakeCallNotificationEventResolver import io.element.android.libraries.push.test.notifications.FakeCallNotificationEventResolver
import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolder import io.element.android.libraries.push.test.notifications.FakeImageLoaderHolder
@ -53,10 +51,8 @@ class DefaultOnMissedCallNotificationHandlerTest {
matrixClientProvider = matrixClientProvider, matrixClientProvider = matrixClientProvider,
defaultNotificationDrawerManager = DefaultNotificationDrawerManager( defaultNotificationDrawerManager = DefaultNotificationDrawerManager(
notificationManager = mockk(relaxed = true), notificationManager = mockk(relaxed = true),
notificationRenderer = NotificationRenderer( notificationRenderer = createNotificationRenderer(
notificationDisplayer = FakeNotificationDisplayer(),
notificationDataFactory = dataFactory, notificationDataFactory = dataFactory,
enterpriseService = FakeEnterpriseService(),
), ),
appNavigationStateService = FakeAppNavigationStateService(), appNavigationStateService = FakeAppNavigationStateService(),
coroutineScope = backgroundScope, coroutineScope = backgroundScope,

View file

@ -10,9 +10,8 @@ package io.element.android.libraries.push.impl.notifications
import android.app.Notification import android.app.Notification
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.test.A_COLOR_INT
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.ui.components.aMatrixUser import io.element.android.libraries.push.impl.notifications.factories.aNotificationAccountParams
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.services.toolbox.test.strings.FakeStringProvider
import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP import io.element.android.services.toolbox.test.systemclock.A_FAKE_TIMESTAMP
@ -34,7 +33,7 @@ class DefaultSummaryGroupMessageCreatorTest {
) )
val result = summaryCreator.createSummaryNotification( val result = summaryCreator.createSummaryNotification(
currentUser = aMatrixUser(), notificationAccountParams = aNotificationAccountParams(),
roomNotifications = listOf( roomNotifications = listOf(
RoomNotification( RoomNotification(
notification = Notification(), notification = Notification(),
@ -49,12 +48,11 @@ class DefaultSummaryGroupMessageCreatorTest {
invitationNotifications = emptyList(), invitationNotifications = emptyList(),
simpleNotifications = emptyList(), simpleNotifications = emptyList(),
fallbackNotifications = emptyList(), fallbackNotifications = emptyList(),
color = A_COLOR_INT,
) )
notificationCreator.createSummaryListNotificationResult.assertions() notificationCreator.createSummaryListNotificationResult.assertions()
.isCalledOnce() .isCalledOnce()
.with(any(), nonNull(), any(), any()) .with(any(), any(), nonNull(), any(), any())
// Set from the events included // Set from the events included
@Suppress("DEPRECATION") @Suppress("DEPRECATION")

View file

@ -11,9 +11,9 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
import io.element.android.libraries.matrix.test.A_COLOR_INT
import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_ROOM_ID
import io.element.android.libraries.matrix.test.A_SESSION_ID import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.push.impl.notifications.factories.aNotificationAccountParams
import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator
@ -51,10 +51,13 @@ class NotificationDataFactoryTest {
@Test @Test
fun `given a room invitation when mapping to notification then it's added`() = testWith(notificationDataFactory) { fun `given a room invitation when mapping to notification then it's added`() = testWith(notificationDataFactory) {
val expectedNotification = notificationCreator.createRoomInvitationNotificationResult(AN_INVITATION_EVENT) val expectedNotification = notificationCreator.createRoomInvitationNotificationResult(
aNotificationAccountParams(),
AN_INVITATION_EVENT,
)
val roomInvitation = listOf(AN_INVITATION_EVENT) val roomInvitation = listOf(AN_INVITATION_EVENT)
val result = toNotifications(roomInvitation, A_COLOR_INT) val result = toNotifications(roomInvitation, aNotificationAccountParams())
assertThat(result).isEqualTo( assertThat(result).isEqualTo(
listOf( listOf(
@ -71,10 +74,13 @@ class NotificationDataFactoryTest {
@Test @Test
fun `given a simple event when mapping to notification then it's added`() = testWith(notificationDataFactory) { fun `given a simple event when mapping to notification then it's added`() = testWith(notificationDataFactory) {
val expectedNotification = notificationCreator.createRoomInvitationNotificationResult(AN_INVITATION_EVENT) val expectedNotification = notificationCreator.createRoomInvitationNotificationResult(
aNotificationAccountParams(),
AN_INVITATION_EVENT,
)
val roomInvitation = listOf(A_SIMPLE_EVENT) val roomInvitation = listOf(A_SIMPLE_EVENT)
val result = toNotifications(roomInvitation, A_COLOR_INT) val result = toNotifications(roomInvitation, aNotificationAccountParams())
assertThat(result).isEqualTo( assertThat(result).isEqualTo(
listOf( listOf(
@ -94,13 +100,14 @@ class NotificationDataFactoryTest {
val events = listOf(A_MESSAGE_EVENT) val events = listOf(A_MESSAGE_EVENT)
val expectedNotification = RoomNotification( val expectedNotification = RoomNotification(
notification = fakeRoomGroupMessageCreator.createRoomMessage( notification = fakeRoomGroupMessageCreator.createRoomMessage(
currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL), notificationAccountParams = aNotificationAccountParams(
user = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
),
events = events, events = events,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
threadId = null, threadId = null,
imageLoader = FakeImageLoader().getImageLoader(), imageLoader = FakeImageLoader().getImageLoader(),
existingNotification = null, existingNotification = null,
color = A_COLOR_INT,
), ),
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
summaryLine = "A room name: Bob Hello world!", summaryLine = "A room name: Bob Hello world!",
@ -113,10 +120,11 @@ class NotificationDataFactoryTest {
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = toNotifications( val result = toNotifications(
notificationAccountParams = aNotificationAccountParams(
user = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
),
messages = roomWithMessage, messages = roomWithMessage,
currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
color = A_COLOR_INT,
) )
assertThat(result.size).isEqualTo(1) assertThat(result.size).isEqualTo(1)
@ -130,10 +138,11 @@ class NotificationDataFactoryTest {
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = toNotifications( val result = toNotifications(
notificationAccountParams = aNotificationAccountParams(
user = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
),
messages = redactedRoom, messages = redactedRoom,
currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
color = A_COLOR_INT,
) )
assertThat(result).isEmpty() assertThat(result).isEmpty()
@ -151,13 +160,14 @@ class NotificationDataFactoryTest {
val withRedactedRemoved = listOf(A_MESSAGE_EVENT.copy(eventId = EventId("\$not-redacted"))) val withRedactedRemoved = listOf(A_MESSAGE_EVENT.copy(eventId = EventId("\$not-redacted")))
val expectedNotification = RoomNotification( val expectedNotification = RoomNotification(
notification = fakeRoomGroupMessageCreator.createRoomMessage( notification = fakeRoomGroupMessageCreator.createRoomMessage(
currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL), notificationAccountParams = aNotificationAccountParams(
user = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
),
events = withRedactedRemoved, events = withRedactedRemoved,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
threadId = null, threadId = null,
imageLoader = FakeImageLoader().getImageLoader(), imageLoader = FakeImageLoader().getImageLoader(),
existingNotification = null, existingNotification = null,
color = A_COLOR_INT,
), ),
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
summaryLine = "A room name: Bob Hello world!", summaryLine = "A room name: Bob Hello world!",
@ -169,10 +179,11 @@ class NotificationDataFactoryTest {
val fakeImageLoader = FakeImageLoader() val fakeImageLoader = FakeImageLoader()
val result = toNotifications( val result = toNotifications(
notificationAccountParams = aNotificationAccountParams(
user = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
),
messages = roomWithRedactedMessage, messages = roomWithRedactedMessage,
currentUser = MatrixUser(A_SESSION_ID, A_SESSION_ID.value, MY_AVATAR_URL),
imageLoader = fakeImageLoader.getImageLoader(), imageLoader = fakeImageLoader.getImageLoader(),
color = A_COLOR_INT,
) )
assertThat(result.size).isEqualTo(1) assertThat(result.size).isEqualTo(1)

View file

@ -7,6 +7,7 @@
package io.element.android.libraries.push.impl.notifications package io.element.android.libraries.push.impl.notifications
import io.element.android.features.enterprise.api.EnterpriseService
import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.features.enterprise.test.FakeEnterpriseService
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID
@ -15,6 +16,7 @@ import io.element.android.libraries.matrix.test.A_SESSION_ID
import io.element.android.libraries.push.api.notifications.NotificationIdProvider import io.element.android.libraries.push.api.notifications.NotificationIdProvider
import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider import io.element.android.libraries.push.impl.notifications.fake.FakeActiveNotificationsProvider
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDataFactory
import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer import io.element.android.libraries.push.impl.notifications.fake.FakeNotificationDisplayer
import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator import io.element.android.libraries.push.impl.notifications.fake.FakeRoomGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator import io.element.android.libraries.push.impl.notifications.fake.FakeSummaryGroupMessageCreator
@ -24,6 +26,8 @@ import io.element.android.libraries.push.impl.notifications.fixtures.aSimpleNoti
import io.element.android.libraries.push.impl.notifications.fixtures.anInviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.fixtures.anInviteNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableEvent
import io.element.android.libraries.push.test.notifications.FakeImageLoader import io.element.android.libraries.push.test.notifications.FakeImageLoader
import io.element.android.libraries.sessionstorage.api.SessionStore
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.element.android.services.toolbox.test.strings.FakeStringProvider
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
import io.element.android.tests.testutils.lambda.value import io.element.android.tests.testutils.lambda.value
@ -56,10 +60,9 @@ class NotificationRendererTest {
) )
private val notificationIdProvider = NotificationIdProvider private val notificationIdProvider = NotificationIdProvider
private val notificationRenderer = NotificationRenderer( private val notificationRenderer = createNotificationRenderer(
notificationDisplayer = notificationDisplayer, notificationDisplayer = notificationDisplayer,
notificationDataFactory = notificationDataFactory, notificationDataFactory = notificationDataFactory,
enterpriseService = FakeEnterpriseService(),
) )
@Test @Test
@ -83,7 +86,7 @@ class NotificationRendererTest {
@Test @Test
fun `given a simple notification is added when rendering then show the simple notification and update summary`() = runTest { fun `given a simple notification is added when rendering then show the simple notification and update summary`() = runTest {
notificationCreator.createSimpleNotificationResult = lambdaRecorder { _ -> ONE_SHOT_NOTIFICATION.copy(key = AN_EVENT_ID.value).notification } notificationCreator.createSimpleNotificationResult = lambdaRecorder { _, _ -> ONE_SHOT_NOTIFICATION.copy(key = AN_EVENT_ID.value).notification }
renderEventsAsNotifications(listOf(aSimpleNotifiableEvent(eventId = AN_EVENT_ID))) renderEventsAsNotifications(listOf(aSimpleNotifiableEvent(eventId = AN_EVENT_ID)))
@ -95,7 +98,7 @@ class NotificationRendererTest {
@Test @Test
fun `given an invitation notification is added when rendering then show the invitation notification and update summary`() = runTest { fun `given an invitation notification is added when rendering then show the invitation notification and update summary`() = runTest {
notificationCreator.createRoomInvitationNotificationResult = lambdaRecorder { _ -> ONE_SHOT_NOTIFICATION.copy(key = AN_EVENT_ID.value).notification } notificationCreator.createRoomInvitationNotificationResult = lambdaRecorder { _, _ -> ONE_SHOT_NOTIFICATION.copy(key = AN_EVENT_ID.value).notification }
renderEventsAsNotifications(listOf(anInviteNotifiableEvent())) renderEventsAsNotifications(listOf(anInviteNotifiableEvent()))
@ -114,3 +117,15 @@ class NotificationRendererTest {
) )
} }
} }
fun createNotificationRenderer(
notificationDisplayer: NotificationDisplayer = FakeNotificationDisplayer(),
notificationDataFactory: NotificationDataFactory = FakeNotificationDataFactory(),
enterpriseService: EnterpriseService = FakeEnterpriseService(),
sessionStore: SessionStore = InMemorySessionStore(),
) = NotificationRenderer(
notificationDisplayer = notificationDisplayer,
notificationDataFactory = notificationDataFactory,
enterpriseService = enterpriseService,
sessionStore = sessionStore,
)

View file

@ -65,6 +65,7 @@ class DefaultNotificationCreatorTest {
fun `test createFallbackNotification`() { fun `test createFallbackNotification`() {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val result = sut.createFallbackNotification( val result = sut.createFallbackNotification(
notificationAccountParams = aNotificationAccountParams(),
FallbackNotifiableEvent( FallbackNotifiableEvent(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -77,7 +78,6 @@ class DefaultNotificationCreatorTest {
timestamp = A_FAKE_TIMESTAMP, timestamp = A_FAKE_TIMESTAMP,
cause = null, cause = null,
), ),
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedCategory = null, expectedCategory = null,
@ -88,6 +88,7 @@ class DefaultNotificationCreatorTest {
fun `test createSimpleEventNotification`() { fun `test createSimpleEventNotification`() {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val result = sut.createSimpleEventNotification( val result = sut.createSimpleEventNotification(
notificationAccountParams = aNotificationAccountParams(),
SimpleNotifiableEvent( SimpleNotifiableEvent(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -103,7 +104,6 @@ class DefaultNotificationCreatorTest {
isRedacted = false, isRedacted = false,
isUpdated = false, isUpdated = false,
), ),
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedCategory = null, expectedCategory = null,
@ -114,6 +114,7 @@ class DefaultNotificationCreatorTest {
fun `test createSimpleEventNotification noisy`() { fun `test createSimpleEventNotification noisy`() {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val result = sut.createSimpleEventNotification( val result = sut.createSimpleEventNotification(
notificationAccountParams = aNotificationAccountParams(),
SimpleNotifiableEvent( SimpleNotifiableEvent(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -129,7 +130,6 @@ class DefaultNotificationCreatorTest {
isRedacted = false, isRedacted = false,
isUpdated = false, isUpdated = false,
), ),
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedCategory = null, expectedCategory = null,
@ -140,6 +140,7 @@ class DefaultNotificationCreatorTest {
fun `test createRoomInvitationNotification`() { fun `test createRoomInvitationNotification`() {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val result = sut.createRoomInvitationNotification( val result = sut.createRoomInvitationNotification(
notificationAccountParams = aNotificationAccountParams(),
InviteNotifiableEvent( InviteNotifiableEvent(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -156,7 +157,6 @@ class DefaultNotificationCreatorTest {
isUpdated = false, isUpdated = false,
roomName = "roomName", roomName = "roomName",
), ),
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedCategory = null, expectedCategory = null,
@ -174,6 +174,7 @@ class DefaultNotificationCreatorTest {
fun `test createRoomInvitationNotification noisy`() { fun `test createRoomInvitationNotification noisy`() {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val result = sut.createRoomInvitationNotification( val result = sut.createRoomInvitationNotification(
notificationAccountParams = aNotificationAccountParams(),
InviteNotifiableEvent( InviteNotifiableEvent(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -190,7 +191,6 @@ class DefaultNotificationCreatorTest {
isUpdated = false, isUpdated = false,
roomName = "roomName", roomName = "roomName",
), ),
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedCategory = null, expectedCategory = null,
@ -202,11 +202,10 @@ class DefaultNotificationCreatorTest {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val matrixUser = aMatrixUser() val matrixUser = aMatrixUser()
val result = sut.createSummaryListNotification( val result = sut.createSummaryListNotification(
currentUser = matrixUser, notificationAccountParams = aNotificationAccountParams(user = matrixUser),
compatSummary = "compatSummary", compatSummary = "compatSummary",
noisy = false, noisy = false,
lastMessageTimestamp = 123_456L, lastMessageTimestamp = 123_456L,
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedGroup = matrixUser.userId.value, expectedGroup = matrixUser.userId.value,
@ -218,11 +217,10 @@ class DefaultNotificationCreatorTest {
val sut = createNotificationCreator() val sut = createNotificationCreator()
val matrixUser = aMatrixUser() val matrixUser = aMatrixUser()
val result = sut.createSummaryListNotification( val result = sut.createSummaryListNotification(
currentUser = matrixUser, notificationAccountParams = aNotificationAccountParams(user = matrixUser),
compatSummary = "compatSummary", compatSummary = "compatSummary",
noisy = true, noisy = true,
lastMessageTimestamp = 123_456L, lastMessageTimestamp = 123_456L,
color = A_COLOR_INT,
) )
result.commonAssertions( result.commonAssertions(
expectedGroup = matrixUser.userId.value, expectedGroup = matrixUser.userId.value,
@ -232,8 +230,8 @@ class DefaultNotificationCreatorTest {
@Test @Test
fun `test createMessagesListNotification`() = runTest { fun `test createMessagesListNotification`() = runTest {
val sut = createNotificationCreator() val sut = createNotificationCreator()
aMatrixUser()
val result = sut.createMessagesListNotification( val result = sut.createMessagesListNotification(
notificationAccountParams = aNotificationAccountParams(),
roomInfo = RoomEventGroupInfo( roomInfo = RoomEventGroupInfo(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -247,11 +245,9 @@ class DefaultNotificationCreatorTest {
largeIcon = null, largeIcon = null,
lastMessageTimestamp = 123_456L, lastMessageTimestamp = 123_456L,
tickerText = "tickerText", tickerText = "tickerText",
currentUser = aMatrixUser(),
existingNotification = null, existingNotification = null,
imageLoader = FakeImageLoader().getImageLoader(), imageLoader = FakeImageLoader().getImageLoader(),
events = listOf(aNotifiableMessageEvent()), events = listOf(aNotifiableMessageEvent()),
color = A_COLOR_INT,
) )
result.commonAssertions() result.commonAssertions()
} }
@ -259,8 +255,8 @@ class DefaultNotificationCreatorTest {
@Test @Test
fun `test createMessagesListNotification should bing and thread`() = runTest { fun `test createMessagesListNotification should bing and thread`() = runTest {
val sut = createNotificationCreator() val sut = createNotificationCreator()
aMatrixUser()
val result = sut.createMessagesListNotification( val result = sut.createMessagesListNotification(
notificationAccountParams = aNotificationAccountParams(),
roomInfo = RoomEventGroupInfo( roomInfo = RoomEventGroupInfo(
sessionId = A_SESSION_ID, sessionId = A_SESSION_ID,
roomId = A_ROOM_ID, roomId = A_ROOM_ID,
@ -274,11 +270,9 @@ class DefaultNotificationCreatorTest {
largeIcon = null, largeIcon = null,
lastMessageTimestamp = 123_456L, lastMessageTimestamp = 123_456L,
tickerText = "tickerText", tickerText = "tickerText",
currentUser = aMatrixUser(),
existingNotification = null, existingNotification = null,
imageLoader = FakeImageLoader().getImageLoader(), imageLoader = FakeImageLoader().getImageLoader(),
events = listOf(aNotifiableMessageEvent()), events = listOf(aNotifiableMessageEvent()),
color = A_COLOR_INT,
) )
result.commonAssertions() result.commonAssertions()
} }

View file

@ -0,0 +1,23 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.push.impl.notifications.factories
import androidx.annotation.ColorInt
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.test.A_COLOR_INT
import io.element.android.libraries.matrix.ui.components.aMatrixUser
fun aNotificationAccountParams(
user: MatrixUser = aMatrixUser(),
@ColorInt color: Int = A_COLOR_INT,
showSessionId: Boolean = false,
) = NotificationAccountParams(
user = user,
color = color,
showSessionId = showSessionId,
)

View file

@ -12,81 +12,84 @@ import android.graphics.Bitmap
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import coil3.ImageLoader import coil3.ImageLoader
import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.RoomEventGroupInfo import io.element.android.libraries.push.impl.notifications.RoomEventGroupInfo
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator import io.element.android.libraries.push.impl.notifications.factories.NotificationCreator
import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION
import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent 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.InviteNotifiableEvent
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
import io.element.android.tests.testutils.lambda.LambdaFourParamsRecorder import io.element.android.tests.testutils.lambda.LambdaFiveParamsRecorder
import io.element.android.tests.testutils.lambda.LambdaListAnyParamsRecorder import io.element.android.tests.testutils.lambda.LambdaListAnyParamsRecorder
import io.element.android.tests.testutils.lambda.LambdaNoParamRecorder
import io.element.android.tests.testutils.lambda.LambdaOneParamRecorder import io.element.android.tests.testutils.lambda.LambdaOneParamRecorder
import io.element.android.tests.testutils.lambda.LambdaTwoParamsRecorder
import io.element.android.tests.testutils.lambda.lambdaAnyRecorder import io.element.android.tests.testutils.lambda.lambdaAnyRecorder
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
class FakeNotificationCreator( class FakeNotificationCreator(
var createMessagesListNotificationResult: LambdaListAnyParamsRecorder<Notification> = lambdaAnyRecorder { A_NOTIFICATION }, var createMessagesListNotificationResult: LambdaListAnyParamsRecorder<Notification> = lambdaAnyRecorder { A_NOTIFICATION },
var createRoomInvitationNotificationResult: LambdaOneParamRecorder<InviteNotifiableEvent, Notification> = lambdaRecorder { _ -> A_NOTIFICATION }, var createRoomInvitationNotificationResult: LambdaTwoParamsRecorder<NotificationAccountParams, InviteNotifiableEvent, Notification> =
var createSimpleNotificationResult: LambdaOneParamRecorder<SimpleNotifiableEvent, Notification> = lambdaRecorder { _ -> A_NOTIFICATION }, lambdaRecorder { _, _ -> A_NOTIFICATION },
var createFallbackNotificationResult: LambdaOneParamRecorder<FallbackNotifiableEvent, Notification> = lambdaRecorder { _ -> A_NOTIFICATION }, var createSimpleNotificationResult: LambdaTwoParamsRecorder<NotificationAccountParams, SimpleNotifiableEvent, Notification> =
var createSummaryListNotificationResult: LambdaFourParamsRecorder<MatrixUser, String, Boolean, Long, Notification> = lambdaRecorder { _, _ -> A_NOTIFICATION },
lambdaRecorder { _, _, _, _ -> A_NOTIFICATION }, var createFallbackNotificationResult: LambdaTwoParamsRecorder<NotificationAccountParams, FallbackNotifiableEvent, Notification> =
var createDiagnosticNotificationResult: LambdaNoParamRecorder<Notification> = lambdaRecorder<Notification> { A_NOTIFICATION }, lambdaRecorder { _, _ -> A_NOTIFICATION },
var createSummaryListNotificationResult: LambdaFiveParamsRecorder<
NotificationAccountParams, String, Boolean, Long, NotificationAccountParams, Notification
> = lambdaRecorder { _, _, _, _, _ -> A_NOTIFICATION },
var createDiagnosticNotificationResult: LambdaOneParamRecorder<Int, Notification> =
lambdaRecorder<Int, Notification> { _ -> A_NOTIFICATION },
) : NotificationCreator { ) : NotificationCreator {
override suspend fun createMessagesListNotification( override suspend fun createMessagesListNotification(
notificationAccountParams: NotificationAccountParams,
roomInfo: RoomEventGroupInfo, roomInfo: RoomEventGroupInfo,
threadId: ThreadId?, threadId: ThreadId?,
largeIcon: Bitmap?, largeIcon: Bitmap?,
lastMessageTimestamp: Long, lastMessageTimestamp: Long,
tickerText: String, tickerText: String,
currentUser: MatrixUser,
existingNotification: Notification?, existingNotification: Notification?,
imageLoader: ImageLoader, imageLoader: ImageLoader,
events: List<NotifiableMessageEvent>, events: List<NotifiableMessageEvent>,
@ColorInt color: Int,
): Notification { ): Notification {
return createMessagesListNotificationResult( return createMessagesListNotificationResult(
listOf(roomInfo, threadId, largeIcon, lastMessageTimestamp, tickerText, currentUser, existingNotification, imageLoader, events) listOf(notificationAccountParams, roomInfo, threadId, largeIcon, lastMessageTimestamp, tickerText, existingNotification, imageLoader, events)
) )
} }
override fun createRoomInvitationNotification( override fun createRoomInvitationNotification(
notificationAccountParams: NotificationAccountParams,
inviteNotifiableEvent: InviteNotifiableEvent, inviteNotifiableEvent: InviteNotifiableEvent,
@ColorInt color: Int,
): Notification { ): Notification {
return createRoomInvitationNotificationResult(inviteNotifiableEvent) return createRoomInvitationNotificationResult(notificationAccountParams, inviteNotifiableEvent)
} }
override fun createSimpleEventNotification( override fun createSimpleEventNotification(
notificationAccountParams: NotificationAccountParams,
simpleNotifiableEvent: SimpleNotifiableEvent, simpleNotifiableEvent: SimpleNotifiableEvent,
@ColorInt color: Int,
): Notification { ): Notification {
return createSimpleNotificationResult(simpleNotifiableEvent) return createSimpleNotificationResult(notificationAccountParams, simpleNotifiableEvent)
} }
override fun createFallbackNotification( override fun createFallbackNotification(
notificationAccountParams: NotificationAccountParams,
fallbackNotifiableEvent: FallbackNotifiableEvent, fallbackNotifiableEvent: FallbackNotifiableEvent,
@ColorInt color: Int,
): Notification { ): Notification {
return createFallbackNotificationResult(fallbackNotifiableEvent) return createFallbackNotificationResult(notificationAccountParams, fallbackNotifiableEvent)
} }
override fun createSummaryListNotification( override fun createSummaryListNotification(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
compatSummary: String, compatSummary: String,
noisy: Boolean, noisy: Boolean,
lastMessageTimestamp: Long, lastMessageTimestamp: Long,
@ColorInt color: Int,
): Notification { ): Notification {
return createSummaryListNotificationResult(currentUser, compatSummary, noisy, lastMessageTimestamp) return createSummaryListNotificationResult(notificationAccountParams, compatSummary, noisy, lastMessageTimestamp, notificationAccountParams)
} }
override fun createDiagnosticNotification( override fun createDiagnosticNotification(
@ColorInt color: Int, @ColorInt color: Int,
): Notification { ): Notification {
return createDiagnosticNotificationResult() return createDiagnosticNotificationResult(color)
} }
} }

View file

@ -7,13 +7,12 @@
package io.element.android.libraries.push.impl.notifications.fake package io.element.android.libraries.push.impl.notifications.fake
import androidx.annotation.ColorInt
import coil3.ImageLoader import coil3.ImageLoader
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.NotificationDataFactory import io.element.android.libraries.push.impl.notifications.NotificationDataFactory
import io.element.android.libraries.push.impl.notifications.OneShotNotification import io.element.android.libraries.push.impl.notifications.OneShotNotification
import io.element.android.libraries.push.impl.notifications.RoomNotification import io.element.android.libraries.push.impl.notifications.RoomNotification
import io.element.android.libraries.push.impl.notifications.SummaryNotification import io.element.android.libraries.push.impl.notifications.SummaryNotification
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION
import io.element.android.libraries.push.impl.notifications.model.FallbackNotifiableEvent 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.InviteNotifiableEvent
@ -25,14 +24,15 @@ import io.element.android.tests.testutils.lambda.LambdaThreeParamsRecorder
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
class FakeNotificationDataFactory( class FakeNotificationDataFactory(
var messageEventToNotificationsResult: LambdaThreeParamsRecorder<List<NotifiableMessageEvent>, MatrixUser, ImageLoader, List<RoomNotification>> = var messageEventToNotificationsResult: LambdaThreeParamsRecorder<
lambdaRecorder { _, _, _ -> emptyList() }, List<NotifiableMessageEvent>, ImageLoader, NotificationAccountParams, List<RoomNotification>
> = lambdaRecorder { _, _, _ -> emptyList() },
var summaryToNotificationsResult: LambdaFiveParamsRecorder< var summaryToNotificationsResult: LambdaFiveParamsRecorder<
MatrixUser,
List<RoomNotification>, List<RoomNotification>,
List<OneShotNotification>, List<OneShotNotification>,
List<OneShotNotification>, List<OneShotNotification>,
List<OneShotNotification>, List<OneShotNotification>,
NotificationAccountParams,
SummaryNotification SummaryNotification
> = lambdaRecorder { _, _, _, _, _ -> SummaryNotification.Update(A_NOTIFICATION) }, > = lambdaRecorder { _, _, _, _, _ -> SummaryNotification.Update(A_NOTIFICATION) },
var inviteToNotificationsResult: LambdaOneParamRecorder<List<InviteNotifiableEvent>, List<OneShotNotification>> = lambdaRecorder { _ -> emptyList() }, var inviteToNotificationsResult: LambdaOneParamRecorder<List<InviteNotifiableEvent>, List<OneShotNotification>> = lambdaRecorder { _ -> emptyList() },
@ -42,18 +42,17 @@ class FakeNotificationDataFactory(
) : NotificationDataFactory { ) : NotificationDataFactory {
override suspend fun toNotifications( override suspend fun toNotifications(
messages: List<NotifiableMessageEvent>, messages: List<NotifiableMessageEvent>,
currentUser: MatrixUser,
imageLoader: ImageLoader, imageLoader: ImageLoader,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<RoomNotification> { ): List<RoomNotification> {
return messageEventToNotificationsResult(messages, currentUser, imageLoader) return messageEventToNotificationsResult(messages, imageLoader, notificationAccountParams)
} }
@JvmName("toNotificationInvites") @JvmName("toNotificationInvites")
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
override fun toNotifications( override fun toNotifications(
invites: List<InviteNotifiableEvent>, invites: List<InviteNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> { ): List<OneShotNotification> {
return inviteToNotificationsResult(invites) return inviteToNotificationsResult(invites)
} }
@ -62,7 +61,7 @@ class FakeNotificationDataFactory(
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
override fun toNotifications( override fun toNotifications(
simpleEvents: List<SimpleNotifiableEvent>, simpleEvents: List<SimpleNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> { ): List<OneShotNotification> {
return simpleEventToNotificationsResult(simpleEvents) return simpleEventToNotificationsResult(simpleEvents)
} }
@ -71,25 +70,24 @@ class FakeNotificationDataFactory(
@Suppress("INAPPLICABLE_JVM_NAME") @Suppress("INAPPLICABLE_JVM_NAME")
override fun toNotifications( override fun toNotifications(
fallback: List<FallbackNotifiableEvent>, fallback: List<FallbackNotifiableEvent>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): List<OneShotNotification> { ): List<OneShotNotification> {
return fallbackEventToNotificationsResult(fallback) return fallbackEventToNotificationsResult(fallback)
} }
override fun createSummaryNotification( override fun createSummaryNotification(
currentUser: MatrixUser,
roomNotifications: List<RoomNotification>, roomNotifications: List<RoomNotification>,
invitationNotifications: List<OneShotNotification>, invitationNotifications: List<OneShotNotification>,
simpleNotifications: List<OneShotNotification>, simpleNotifications: List<OneShotNotification>,
fallbackNotifications: List<OneShotNotification>, fallbackNotifications: List<OneShotNotification>,
@ColorInt color: Int, notificationAccountParams: NotificationAccountParams,
): SummaryNotification { ): SummaryNotification {
return summaryToNotificationsResult( return summaryToNotificationsResult(
currentUser,
roomNotifications, roomNotifications,
invitationNotifications, invitationNotifications,
simpleNotifications, simpleNotifications,
fallbackNotifications, fallbackNotifications,
notificationAccountParams,
) )
} }
} }

View file

@ -8,12 +8,11 @@
package io.element.android.libraries.push.impl.notifications.fake package io.element.android.libraries.push.impl.notifications.fake
import android.app.Notification import android.app.Notification
import androidx.annotation.ColorInt
import coil3.ImageLoader import coil3.ImageLoader
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.matrix.api.core.ThreadId
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.RoomGroupMessageCreator import io.element.android.libraries.push.impl.notifications.RoomGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
import io.element.android.tests.testutils.lambda.LambdaSixParamsRecorder import io.element.android.tests.testutils.lambda.LambdaSixParamsRecorder
@ -22,18 +21,18 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder
// We just can't make the param types fit // We just can't make the param types fit
@Suppress("MaxLineLength", "ktlint:standard:max-line-length", "ktlint:standard:parameter-wrapping") @Suppress("MaxLineLength", "ktlint:standard:max-line-length", "ktlint:standard:parameter-wrapping")
class FakeRoomGroupMessageCreator( class FakeRoomGroupMessageCreator(
var createRoomMessageResult: LambdaSixParamsRecorder<MatrixUser, List<NotifiableMessageEvent>, RoomId, ThreadId?, ImageLoader, Notification?, Notification> = var createRoomMessageResult: LambdaSixParamsRecorder<
lambdaRecorder { _, _, _, _, _, _ -> A_NOTIFICATION } NotificationAccountParams, List<NotifiableMessageEvent>, RoomId, ThreadId?, ImageLoader, Notification?, Notification
> = lambdaRecorder { _, _, _, _, _, _ -> A_NOTIFICATION }
) : RoomGroupMessageCreator { ) : RoomGroupMessageCreator {
override suspend fun createRoomMessage( override suspend fun createRoomMessage(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
events: List<NotifiableMessageEvent>, events: List<NotifiableMessageEvent>,
roomId: RoomId, roomId: RoomId,
threadId: ThreadId?, threadId: ThreadId?,
imageLoader: ImageLoader, imageLoader: ImageLoader,
existingNotification: Notification?, existingNotification: Notification?,
@ColorInt color: Int,
): Notification { ): Notification {
return createRoomMessageResult(currentUser, events, roomId, threadId, imageLoader, existingNotification) return createRoomMessageResult(notificationAccountParams, events, roomId, threadId, imageLoader, existingNotification)
} }
} }

View file

@ -8,30 +8,28 @@
package io.element.android.libraries.push.impl.notifications.fake package io.element.android.libraries.push.impl.notifications.fake
import android.app.Notification import android.app.Notification
import androidx.annotation.ColorInt
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.push.impl.notifications.OneShotNotification import io.element.android.libraries.push.impl.notifications.OneShotNotification
import io.element.android.libraries.push.impl.notifications.RoomNotification import io.element.android.libraries.push.impl.notifications.RoomNotification
import io.element.android.libraries.push.impl.notifications.SummaryGroupMessageCreator import io.element.android.libraries.push.impl.notifications.SummaryGroupMessageCreator
import io.element.android.libraries.push.impl.notifications.factories.NotificationAccountParams
import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION import io.element.android.libraries.push.impl.notifications.fixtures.A_NOTIFICATION
import io.element.android.tests.testutils.lambda.LambdaFiveParamsRecorder import io.element.android.tests.testutils.lambda.LambdaFiveParamsRecorder
import io.element.android.tests.testutils.lambda.lambdaRecorder import io.element.android.tests.testutils.lambda.lambdaRecorder
class FakeSummaryGroupMessageCreator( class FakeSummaryGroupMessageCreator(
var createSummaryNotificationResult: LambdaFiveParamsRecorder< var createSummaryNotificationResult: LambdaFiveParamsRecorder<
MatrixUser, List<RoomNotification>, List<OneShotNotification>, List<OneShotNotification>, List<OneShotNotification>, Notification> = NotificationAccountParams, List<RoomNotification>, List<OneShotNotification>, List<OneShotNotification>, List<OneShotNotification>, Notification> =
lambdaRecorder { _, _, _, _, _ -> A_NOTIFICATION } lambdaRecorder { _, _, _, _, _ -> A_NOTIFICATION }
) : SummaryGroupMessageCreator { ) : SummaryGroupMessageCreator {
override fun createSummaryNotification( override fun createSummaryNotification(
currentUser: MatrixUser, notificationAccountParams: NotificationAccountParams,
roomNotifications: List<RoomNotification>, roomNotifications: List<RoomNotification>,
invitationNotifications: List<OneShotNotification>, invitationNotifications: List<OneShotNotification>,
simpleNotifications: List<OneShotNotification>, simpleNotifications: List<OneShotNotification>,
fallbackNotifications: List<OneShotNotification>, fallbackNotifications: List<OneShotNotification>,
@ColorInt color: Int,
): Notification { ): Notification {
return createSummaryNotificationResult( return createSummaryNotificationResult(
currentUser, notificationAccountParams,
roomNotifications, roomNotifications,
invitationNotifications, invitationNotifications,
simpleNotifications, simpleNotifications,