From 21595b21554608b2715ebfc6b00d33fc8f15065e Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 10 Feb 2026 17:40:20 +0100 Subject: [PATCH 1/6] Format file. --- .../factories/NotificationCreator.kt | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt index 9533f6b0ac..1102c7c9f6 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt @@ -240,11 +240,13 @@ class DefaultNotificationCreator( .addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent)) .addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent)) // Build the pending intent for when the notification is clicked - .setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent( - sessionId = inviteNotifiableEvent.sessionId, - roomId = inviteNotifiableEvent.roomId, - eventId = null, - )) + .setContentIntent( + pendingIntentFactory.createOpenRoomPendingIntent( + sessionId = inviteNotifiableEvent.sessionId, + roomId = inviteNotifiableEvent.roomId, + eventId = null, + ) + ) .apply { if (inviteNotifiableEvent.noisy) { // Compat @@ -276,12 +278,14 @@ class DefaultNotificationCreator( .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .configureWith(notificationAccountParams) .setAutoCancel(true) - .setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent( - sessionId = simpleNotifiableEvent.sessionId, - roomId = simpleNotifiableEvent.roomId, - eventId = null, - extras = bundleOf(ROOM_OPENED_FROM_NOTIFICATION to true), - )) + .setContentIntent( + pendingIntentFactory.createOpenRoomPendingIntent( + sessionId = simpleNotifiableEvent.sessionId, + roomId = simpleNotifiableEvent.roomId, + eventId = null, + extras = bundleOf(ROOM_OPENED_FROM_NOTIFICATION to true), + ) + ) .apply { if (simpleNotifiableEvent.noisy) { // Compat From 7535258bae214c3c9c16f1ce814cb4c11446e4ba Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 10 Feb 2026 18:13:09 +0100 Subject: [PATCH 2/6] Remove file sound (it is the same file than the file in the `main` scope). --- .../push/impl/src/debug/res/raw/message.mp3 | Bin 8685 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 libraries/push/impl/src/debug/res/raw/message.mp3 diff --git a/libraries/push/impl/src/debug/res/raw/message.mp3 b/libraries/push/impl/src/debug/res/raw/message.mp3 deleted file mode 100644 index abc056786c8504a9441ed74e955d9dcfa6bac927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8685 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

q)t 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 From 6e958f31327cfaf0a2a85f9758be3eb7391c6d6f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 11 Feb 2026 09:59:45 +0100 Subject: [PATCH 3/6] Let enterprise build be able to use a different notification channel for noisy notification. --- enterprise | 2 +- .../enterprise/api/EnterpriseService.kt | 5 +++ .../impl/DefaultEnterpriseService.kt | 2 ++ .../impl/DefaultEnterpriseServiceTest.kt | 6 ++++ .../enterprise/test/FakeEnterpriseService.kt | 5 +++ .../messages/impl/MessagesPresenterTest.kt | 2 +- .../channels/NotificationChannels.kt | 17 +++++++--- .../factories/NotificationCreator.kt | 25 +++++++++++--- .../DefaultBaseRoomGroupMessageCreatorTest.kt | 14 ++++++-- .../channels/FakeNotificationChannels.kt | 8 +++-- .../channels/NotificationChannelsTest.kt | 29 ++++++++++++++-- .../DefaultNotificationCreatorTest.kt | 34 +++++++++++++++---- .../wellknown/api/ElementWellKnown.kt | 1 + .../impl/InternalElementWellKnown.kt | 2 ++ .../libraries/wellknown/impl/Mapper.kt | 1 + .../DefaultSessionWellknownRetrieverTest.kt | 6 +++- .../features/wellknown/test/Fixtures.kt | 2 ++ 17 files changed, 135 insertions(+), 26 deletions(-) diff --git a/enterprise b/enterprise index 6207ddc1cb..6c63bfa2d2 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 6207ddc1cb7dac7fdb6212c0158497a1d9752c75 +Subproject commit 6c63bfa2d2147dd1667b644b9d4fc3bebcd31c4c diff --git a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt index ecf1ba6b64..65fe3fe087 100644 --- a/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt +++ b/features/enterprise/api/src/main/kotlin/io/element/android/features/enterprise/api/EnterpriseService.kt @@ -35,6 +35,11 @@ interface EnterpriseService { fun bugReportUrlFlow(sessionId: SessionId?): Flow + /** + * Gets Notification Channel to use for the noisy notifications of the provided session. + */ + fun getNoisyNotificationChannelId(sessionId: SessionId): String? + companion object { const val ANY_ACCOUNT_PROVIDER = "*" } diff --git a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt index b154d78afa..932d082fd9 100644 --- a/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt +++ b/features/enterprise/impl-foss/src/main/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseService.kt @@ -43,4 +43,6 @@ class DefaultEnterpriseService : EnterpriseService { override fun bugReportUrlFlow(sessionId: SessionId?): Flow { return flowOf(BugReportUrl.UseDefault) } + + override fun getNoisyNotificationChannelId(sessionId: SessionId): String? = null } diff --git a/features/enterprise/impl-foss/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt b/features/enterprise/impl-foss/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt index ff95fd8721..2bee3f8b4d 100644 --- a/features/enterprise/impl-foss/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt +++ b/features/enterprise/impl-foss/src/test/kotlin/io/element/android/features/enterprise/impl/DefaultEnterpriseServiceTest.kt @@ -98,4 +98,10 @@ class DefaultEnterpriseServiceTest { awaitComplete() } } + + @Test + fun `getNoisyNotificationChannelId returns null`() = runTest { + val defaultEnterpriseService = DefaultEnterpriseService() + assertThat(defaultEnterpriseService.getNoisyNotificationChannelId(A_SESSION_ID)).isNull() + } } diff --git a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt index b2c386267a..3c17a4de7c 100644 --- a/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt +++ b/features/enterprise/test/src/main/kotlin/io/element/android/features/enterprise/test/FakeEnterpriseService.kt @@ -29,6 +29,7 @@ class FakeEnterpriseService( private val overrideBrandColorResult: (SessionId?, String?) -> Unit = { _, _ -> lambdaError() }, private val firebasePushGatewayResult: () -> String? = { lambdaError() }, private val unifiedPushDefaultPushGatewayResult: () -> String? = { lambdaError() }, + private val getNoisyNotificationChannelIdResult: (SessionId?) -> String? = { lambdaError() }, ) : EnterpriseService { private val brandColorState = MutableStateFlow(initialBrandColor) private val semanticColorsState = MutableStateFlow(initialSemanticColors) @@ -69,4 +70,8 @@ class FakeEnterpriseService( override fun bugReportUrlFlow(sessionId: SessionId?): Flow { return bugReportUrlMutableFlow.asStateFlow() } + + override fun getNoisyNotificationChannelId(sessionId: SessionId): String? { + return getNoisyNotificationChannelIdResult(sessionId) + } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index d52179f3ef..f6967de0e5 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -1238,7 +1238,7 @@ class MessagesPresenterTest { } @Test - fun `present - shows a "world_readable" icon if the room is encrypted and history is world_readable`() = runTest { + fun `present - shows a 'world_readable' icon if the room is encrypted and history is world_readable`() = runTest { val presenter = createMessagesPresenter( joinedRoom = FakeJoinedRoom( baseRoom = FakeBaseRoom( diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt index 9d1452fdae..120d48cf4b 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannels.kt @@ -23,7 +23,9 @@ import dev.zacsweers.metro.AppScope import dev.zacsweers.metro.ContributesBinding import dev.zacsweers.metro.SingleIn import io.element.android.appconfig.NotificationConfig +import io.element.android.features.enterprise.api.EnterpriseService import io.element.android.libraries.di.annotations.ApplicationContext +import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.push.impl.R import io.element.android.services.toolbox.api.strings.StringProvider @@ -47,9 +49,10 @@ interface NotificationChannels { /** * Get the channel for messages. + * @param sessionId the session the message belongs to. * @param noisy true if the notification should have sound and vibration. */ - fun getChannelIdForMessage(noisy: Boolean): String + fun getChannelIdForMessage(sessionId: SessionId, noisy: Boolean): String /** * Get the channel for test notifications. @@ -67,6 +70,7 @@ class DefaultNotificationChannels( private val stringProvider: StringProvider, @ApplicationContext private val context: Context, + private val enterpriseService: EnterpriseService, ) : NotificationChannels { init { createNotificationChannels() @@ -115,7 +119,7 @@ class DefaultNotificationChannels( .setSound( Uri.Builder() .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) - // Strangely wwe have to provide a "//" before the package name + // Strangely we have to provide a "//" before the package name .path("//" + context.packageName + "/" + R.raw.message) .build(), AudioAttributes.Builder() @@ -186,8 +190,13 @@ class DefaultNotificationChannels( return if (ring) RINGING_CALL_NOTIFICATION_CHANNEL_ID else CALL_NOTIFICATION_CHANNEL_ID } - override fun getChannelIdForMessage(noisy: Boolean): String { - return if (noisy) NOISY_NOTIFICATION_CHANNEL_ID else SILENT_NOTIFICATION_CHANNEL_ID + override fun getChannelIdForMessage(sessionId: SessionId, noisy: Boolean): String { + return if (noisy) { + enterpriseService.getNoisyNotificationChannelId(sessionId) + ?: NOISY_NOTIFICATION_CHANNEL_ID + } else { + SILENT_NOTIFICATION_CHANNEL_ID + } } override fun getChannelIdForTest(): String = NOISY_NOTIFICATION_CHANNEL_ID diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt index 1102c7c9f6..4249c5653c 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt @@ -151,7 +151,10 @@ class DefaultNotificationCreator( val channelId = if (containsMissedCall) { notificationChannels.getChannelForIncomingCall(false) } else { - notificationChannels.getChannelIdForMessage(noisy = roomInfo.shouldBing) + notificationChannels.getChannelIdForMessage( + sessionId = roomInfo.sessionId, + noisy = roomInfo.shouldBing, + ) } // A category allows groups of notifications to be ranked and filtered – per user or system settings. // For example, alarm notifications should display before promo notifications, or message from known contact @@ -230,7 +233,10 @@ class DefaultNotificationCreator( notificationAccountParams: NotificationAccountParams, inviteNotifiableEvent: InviteNotifiableEvent, ): Notification { - val channelId = notificationChannels.getChannelIdForMessage(inviteNotifiableEvent.noisy) + val channelId = notificationChannels.getChannelIdForMessage( + sessionId = inviteNotifiableEvent.sessionId, + noisy = inviteNotifiableEvent.noisy, + ) return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) .setContentTitle((inviteNotifiableEvent.roomName ?: buildMeta.applicationName).annotateForDebug(5)) @@ -270,7 +276,10 @@ class DefaultNotificationCreator( notificationAccountParams: NotificationAccountParams, simpleNotifiableEvent: SimpleNotifiableEvent, ): Notification { - val channelId = notificationChannels.getChannelIdForMessage(simpleNotifiableEvent.noisy) + val channelId = notificationChannels.getChannelIdForMessage( + sessionId = simpleNotifiableEvent.sessionId, + noisy = simpleNotifiableEvent.noisy, + ) return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) .setContentTitle(buildMeta.applicationName.annotateForDebug(7)) @@ -302,7 +311,10 @@ class DefaultNotificationCreator( notificationAccountParams: NotificationAccountParams, fallbackNotifiableEvent: FallbackNotifiableEvent, ): Notification { - val channelId = notificationChannels.getChannelIdForMessage(false) + val channelId = notificationChannels.getChannelIdForMessage( + sessionId = fallbackNotifiableEvent.sessionId, + noisy = false, + ) return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) .setContentTitle(buildMeta.applicationName.annotateForDebug(7)) @@ -334,8 +346,11 @@ class DefaultNotificationCreator( noisy: Boolean, lastMessageTimestamp: Long, ): Notification { - val channelId = notificationChannels.getChannelIdForMessage(noisy) val userId = notificationAccountParams.user.userId + val channelId = notificationChannels.getChannelIdForMessage( + sessionId = userId, + noisy = noisy, + ) return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) // used in compat < N, after summary is built based on child notifications diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultBaseRoomGroupMessageCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultBaseRoomGroupMessageCreatorTest.kt index 542608254a..3caec04add 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultBaseRoomGroupMessageCreatorTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultBaseRoomGroupMessageCreatorTest.kt @@ -13,6 +13,8 @@ import android.os.Build import androidx.core.app.NotificationCompat import com.google.common.truth.Truth.assertThat import io.element.android.appconfig.NotificationConfig +import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.test.A_ROOM_ID import io.element.android.libraries.matrix.test.A_TIMESTAMP @@ -66,7 +68,11 @@ class DefaultBaseRoomGroupMessageCreatorTest { @Test fun `test createRoomMessage with one noisy Event`() = runTest { - val sut = createRoomGroupMessageCreator() + val sut = createRoomGroupMessageCreator( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { null } + ) + ) val fakeImageLoader = FakeImageLoader() val result = sut.createRoomMessage( notificationAccountParams = aNotificationAccountParams(), @@ -228,6 +234,7 @@ class DefaultBaseRoomGroupMessageCreatorTest { fun createRoomGroupMessageCreator( sdkIntProvider: BuildVersionSdkIntProvider = FakeBuildVersionSdkIntProvider(Build.VERSION_CODES.O), + enterpriseService: EnterpriseService = FakeEnterpriseService(), ): RoomGroupMessageCreator { val context = RuntimeEnvironment.getApplication() as Context val bitmapLoader = DefaultNotificationBitmapLoader( @@ -236,7 +243,10 @@ fun createRoomGroupMessageCreator( initialsAvatarBitmapGenerator = FakeInitialsAvatarBitmapGenerator(), ) return DefaultRoomGroupMessageCreator( - notificationCreator = createNotificationCreator(bitmapLoader = bitmapLoader), + notificationCreator = createNotificationCreator( + bitmapLoader = bitmapLoader, + enterpriseService = enterpriseService, + ), bitmapLoader = bitmapLoader, stringProvider = AndroidStringProvider(context.resources) ) diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt index 6caf02b41b..194caf7287 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/FakeNotificationChannels.kt @@ -8,17 +8,19 @@ package io.element.android.libraries.push.impl.notifications.channels +import io.element.android.libraries.matrix.api.core.SessionId + class FakeNotificationChannels( var channelForIncomingCall: (ring: Boolean) -> String = { _ -> "" }, - var channelIdForMessage: (noisy: Boolean) -> String = { _ -> "" }, + var channelIdForMessage: (sessionId: SessionId, noisy: Boolean) -> String = { _, _ -> "" }, var channelIdForTest: () -> String = { "" } ) : NotificationChannels { override fun getChannelForIncomingCall(ring: Boolean): String { return channelForIncomingCall(ring) } - override fun getChannelIdForMessage(noisy: Boolean): String { - return channelIdForMessage(noisy) + override fun getChannelIdForMessage(sessionId: SessionId, noisy: Boolean): String { + return channelIdForMessage(sessionId, noisy) } override fun getChannelIdForTest(): String { diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt index e6b28831bd..b004c35537 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/channels/NotificationChannelsTest.kt @@ -12,6 +12,9 @@ import android.os.Build import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationManagerCompat 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.libraries.matrix.test.A_SESSION_ID import io.element.android.services.toolbox.test.strings.FakeStringProvider import io.mockk.every import io.mockk.mockk @@ -50,10 +53,28 @@ class NotificationChannelsTest { @Test fun `getChannelIdForMessage - returns the right channel`() { - val notificationChannels = createNotificationChannels() + val notificationChannels = createNotificationChannels( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { null } + ), + ) + assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = true)) + .isEqualTo(NOISY_NOTIFICATION_CHANNEL_ID) + assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = false)) + .isEqualTo(SILENT_NOTIFICATION_CHANNEL_ID) + } - assertThat(notificationChannels.getChannelIdForMessage(noisy = true)).isEqualTo(NOISY_NOTIFICATION_CHANNEL_ID) - assertThat(notificationChannels.getChannelIdForMessage(noisy = false)).isEqualTo(SILENT_NOTIFICATION_CHANNEL_ID) + @Test + fun `getChannelIdForMessage - returns the right channel when enterprise service override the result`() { + val notificationChannels = createNotificationChannels( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { "A_CHANNEL_ID" } + ), + ) + assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = true)) + .isEqualTo("A_CHANNEL_ID") + assertThat(notificationChannels.getChannelIdForMessage(sessionId = A_SESSION_ID, noisy = false)) + .isEqualTo(SILENT_NOTIFICATION_CHANNEL_ID) } @Test @@ -65,9 +86,11 @@ class NotificationChannelsTest { private fun createNotificationChannels( notificationManager: NotificationManagerCompat = mockk(relaxed = true), + enterpriseService: EnterpriseService = FakeEnterpriseService(), ) = DefaultNotificationChannels( notificationManager = notificationManager, stringProvider = FakeStringProvider(), context = RuntimeEnvironment.getApplication(), + enterpriseService = enterpriseService, ) } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt index 0504ae433b..f2649ec32e 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/factories/DefaultNotificationCreatorTest.kt @@ -15,6 +15,8 @@ import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.google.common.truth.Truth.assertThat import io.element.android.appconfig.NotificationConfig +import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.features.enterprise.test.FakeEnterpriseService import io.element.android.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_COLOR_INT @@ -129,7 +131,11 @@ class DefaultNotificationCreatorTest { @Test fun `test createSimpleEventNotification noisy`() { - val sut = createNotificationCreator() + val sut = createNotificationCreator( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { null }, + ), + ) val result = sut.createSimpleEventNotification( notificationAccountParams = aNotificationAccountParams(), SimpleNotifiableEvent( @@ -189,7 +195,11 @@ class DefaultNotificationCreatorTest { @Test fun `test createRoomInvitationNotification noisy`() { - val sut = createNotificationCreator() + val sut = createNotificationCreator( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { null }, + ), + ) val result = sut.createRoomInvitationNotification( notificationAccountParams = aNotificationAccountParams(), InviteNotifiableEvent( @@ -231,7 +241,11 @@ class DefaultNotificationCreatorTest { @Test fun `test createSummaryListNotification noisy`() { - val sut = createNotificationCreator() + val sut = createNotificationCreator( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { null }, + ), + ) val matrixUser = aMatrixUser() val result = sut.createSummaryListNotification( notificationAccountParams = aNotificationAccountParams(user = matrixUser), @@ -271,7 +285,11 @@ class DefaultNotificationCreatorTest { @Test fun `test createMessagesListNotification should bing and thread`() = runTest { - val sut = createNotificationCreator() + val sut = createNotificationCreator( + enterpriseService = FakeEnterpriseService( + getNoisyNotificationChannelIdResult = { null }, + ), + ) val result = sut.createMessagesListNotification( notificationAccountParams = aNotificationAccountParams(), roomInfo = RoomEventGroupInfo( @@ -312,7 +330,8 @@ const val REJECT_INVITATION_ACTION_TITLE = "RejectInvitationAction" fun createNotificationCreator( context: Context = RuntimeEnvironment.getApplication(), buildMeta: BuildMeta = aBuildMeta(), - notificationChannels: NotificationChannels = createNotificationChannels(), + enterpriseService: EnterpriseService = FakeEnterpriseService(), + notificationChannels: NotificationChannels = createNotificationChannels(enterpriseService), bitmapLoader: NotificationBitmapLoader = DefaultNotificationBitmapLoader( context = context, sdkIntProvider = FakeBuildVersionSdkIntProvider(Build.VERSION_CODES.R), @@ -358,11 +377,14 @@ fun createNotificationCreator( ) } -fun createNotificationChannels(): NotificationChannels { +fun createNotificationChannels( + enterpriseService: EnterpriseService = FakeEnterpriseService(), +): NotificationChannels { val context = RuntimeEnvironment.getApplication() return DefaultNotificationChannels( notificationManager = NotificationManagerCompat.from(context), stringProvider = FakeStringProvider(""), context = context, + enterpriseService = enterpriseService, ) } diff --git a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt index 7dc230d2e1..134a9bcdb5 100644 --- a/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt +++ b/libraries/wellknown/api/src/main/kotlin/io/element/android/libraries/wellknown/api/ElementWellKnown.kt @@ -13,4 +13,5 @@ data class ElementWellKnown( val enforceElementPro: Boolean?, val rageshakeUrl: String?, val brandColor: String?, + val notificationSound: String?, ) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt index c79d8fa4c3..d4661d1be0 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/InternalElementWellKnown.kt @@ -30,4 +30,6 @@ data class InternalElementWellKnown( val rageshakeUrl: String? = null, @SerialName("brand_color") val brandColor: String? = null, + @SerialName("notification_sound") + val notificationSound: String? = null, ) diff --git a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt index d3f57806b3..c7ca088e68 100644 --- a/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt +++ b/libraries/wellknown/impl/src/main/kotlin/io/element/android/libraries/wellknown/impl/Mapper.kt @@ -15,4 +15,5 @@ internal fun InternalElementWellKnown.map() = ElementWellKnown( enforceElementPro = enforceElementPro, rageshakeUrl = rageshakeUrl, brandColor = brandColor, + notificationSound = notificationSound, ) diff --git a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt index 4e384dbc0d..faad139a36 100644 --- a/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt +++ b/libraries/wellknown/impl/src/test/kotlin/io/element/android/libraries/wellknown/impl/DefaultSessionWellknownRetrieverTest.kt @@ -35,6 +35,7 @@ class DefaultSessionWellknownRetrieverTest { enforceElementPro = null, rageshakeUrl = null, brandColor = null, + notificationSound = null, ) ) ) @@ -51,7 +52,8 @@ class DefaultSessionWellknownRetrieverTest { "registration_helper_url": "a_registration_url", "enforce_element_pro": true, "rageshake_url": "a_rageshake_url", - "brand_color": "#FF0000" + "brand_color": "#FF0000", + "notification_sound": "a_notification_sound.flac" }""".trimIndent().toByteArray() ) } @@ -63,6 +65,7 @@ class DefaultSessionWellknownRetrieverTest { enforceElementPro = true, rageshakeUrl = "a_rageshake_url", brandColor = "#FF0000", + notificationSound = "a_notification_sound.flac", ) ) ) @@ -89,6 +92,7 @@ class DefaultSessionWellknownRetrieverTest { enforceElementPro = true, rageshakeUrl = "a_rageshake_url", brandColor = null, + notificationSound = null, ) ) ) diff --git a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt index b5fd9f6020..7457aafc98 100644 --- a/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt +++ b/libraries/wellknown/test/src/main/kotlin/io/element/android/features/wellknown/test/Fixtures.kt @@ -15,9 +15,11 @@ fun anElementWellKnown( enforceElementPro: Boolean? = null, rageshakeUrl: String? = null, brandColor: String? = null, + notificationSound: String? = null, ) = ElementWellKnown( registrationHelperUrl = registrationHelperUrl, enforceElementPro = enforceElementPro, rageshakeUrl = rageshakeUrl, brandColor = brandColor, + notificationSound = notificationSound, ) From 52141c64b650db68342420dd071b04587b7a7c0f Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 12 Feb 2026 14:37:34 +0100 Subject: [PATCH 4/6] Update ref. --- enterprise | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise b/enterprise index 6c63bfa2d2..01a907643a 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 6c63bfa2d2147dd1667b644b9d4fc3bebcd31c4c +Subproject commit 01a907643af79d8b99c305b6ac60a6973ac0571f From d2ca80e7e8f20ce408e38f8664f137fdd1f07e10 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 13 Feb 2026 16:44:42 +0100 Subject: [PATCH 5/6] Fix compilation issue after merging develop. --- .../push/impl/notifications/factories/NotificationCreator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt index 9db65ebfb2..459389e8f1 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationCreator.kt @@ -313,6 +313,7 @@ class DefaultNotificationCreator( notificationAccountParams: NotificationAccountParams, fallbackNotifiableEvents: List, ): Notification { + val fallbackNotifiableEvent = fallbackNotifiableEvents.first() val channelId = notificationChannels.getChannelIdForMessage( sessionId = fallbackNotifiableEvent.sessionId, noisy = false, @@ -322,7 +323,6 @@ class DefaultNotificationCreator( ?.getInt(FALLBACK_COUNTER_EXTRA) ?: 0 val counter = existingCounter + fallbackNotifiableEvents.size - val fallbackNotifiableEvent = fallbackNotifiableEvents.first() return NotificationCompat.Builder(context, channelId) .setOnlyAlertOnce(true) .setContentTitle(buildMeta.applicationName.annotateForDebug(7)) From 5729e834b6d09d483e38b66117d660045e827302 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Fri, 13 Feb 2026 17:09:14 +0100 Subject: [PATCH 6/6] Update ref. --- enterprise | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/enterprise b/enterprise index 01a907643a..1fd0d297d9 160000 --- a/enterprise +++ b/enterprise @@ -1 +1 @@ -Subproject commit 01a907643af79d8b99c305b6ac60a6973ac0571f +Subproject commit 1fd0d297d944186e3af2773e1c5db2938d60f74b