Let enterprise build be able to use a different notification channel for noisy notification.
This commit is contained in:
parent
abae0314e2
commit
df4c719151
17 changed files with 135 additions and 26 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue