From 8edffc5167abf5c891cd8bcdfe6e608b667ed64d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Tue, 4 Feb 2025 16:09:15 +0100 Subject: [PATCH] =?UTF-8?q?Update=20incoming=20call=20notification=20conte?= =?UTF-8?q?nt=20to=20"=F0=9F=93=B9=20Incoming=20call"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../call/api/ElementCallEntryPoint.kt | 2 ++ .../call/impl/DefaultElementCallEntryPoint.kt | 2 ++ .../notifications/CallNotificationData.kt | 1 + .../RingingCallNotificationCreator.kt | 8 ++++- .../call/impl/ui/IncomingCallScreen.kt | 1 + .../call/impl/utils/ActiveCallManager.kt | 3 +- .../call/DefaultElementCallEntryPointTest.kt | 1 + .../RingingCallNotificationCreatorTest.kt | 1 + features/call/test/build.gradle.kts | 1 + .../call/test/CallNotificationData.kt | 2 ++ .../call/test/FakeElementCallEntryPoint.kt | 28 ++++++++++++--- .../push/impl/push/DefaultPushHandler.kt | 1 + .../push/impl/push/DefaultPushHandlerTest.kt | 36 +++++++++++++++++-- .../tests/testutils/lambda/LambdaRecorder.kt | 7 ++++ 14 files changed, 85 insertions(+), 9 deletions(-) diff --git a/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt b/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt index 239c960a39..9229681966 100644 --- a/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt +++ b/features/call/api/src/main/kotlin/io/element/android/features/call/api/ElementCallEntryPoint.kt @@ -30,6 +30,7 @@ interface ElementCallEntryPoint { * @param avatarUrl The avatar url of the room or DM. * @param timestamp The timestamp of the event that started the call. * @param notificationChannelId The id of the notification channel to use for the call notification. + * @param textContent The text content of the notification. If null the default content from the system will be used. */ fun handleIncomingCall( callType: CallType.RoomCall, @@ -40,5 +41,6 @@ interface ElementCallEntryPoint { avatarUrl: String?, timestamp: Long, notificationChannelId: String, + textContent: String?, ) } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt index 1e42cb972d..290bfe0824 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/DefaultElementCallEntryPoint.kt @@ -43,6 +43,7 @@ class DefaultElementCallEntryPoint @Inject constructor( avatarUrl: String?, timestamp: Long, notificationChannelId: String, + textContent: String?, ) { val incomingCallNotificationData = CallNotificationData( sessionId = callType.sessionId, @@ -54,6 +55,7 @@ class DefaultElementCallEntryPoint @Inject constructor( avatarUrl = avatarUrl, timestamp = timestamp, notificationChannelId = notificationChannelId, + textContent = textContent, ) activeCallManager.registerIncomingCall(notificationData = incomingCallNotificationData) } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt index cd9e4c2109..7c97cc8529 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/CallNotificationData.kt @@ -25,4 +25,5 @@ data class CallNotificationData( val avatarUrl: String?, val notificationChannelId: String, val timestamp: Long, + val textContent: String?, ) : Parcelable diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt index 5ccb4aa227..de869e089e 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/notifications/RingingCallNotificationCreator.kt @@ -63,6 +63,7 @@ class RingingCallNotificationCreator @Inject constructor( roomAvatarUrl: String?, notificationChannelId: String, timestamp: Long, + textContent: String?, ): Notification? { val matrixClient = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return null val imageLoader = imageLoaderHolder.get(matrixClient) @@ -84,7 +85,8 @@ class RingingCallNotificationCreator @Inject constructor( senderName = senderDisplayName, avatarUrl = roomAvatarUrl, notificationChannelId = notificationChannelId, - timestamp = timestamp + timestamp = timestamp, + textContent = textContent, ) val declineIntent = PendingIntentCompat.getBroadcast( @@ -120,6 +122,10 @@ class RingingCallNotificationCreator @Inject constructor( .setOngoing(true) .setShowWhen(false) .apply { + if (textContent != null) { + setContentText(textContent) + // Else the content text is set by the style (will be "Incoming call") + } if (ringtoneUri != null) { setSound(ringtoneUri, AudioManager.STREAM_RING) } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt index 5c9057a847..905bd89c86 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/IncomingCallScreen.kt @@ -173,6 +173,7 @@ internal fun IncomingCallScreenPreview() = ElementPreview { avatarUrl = null, notificationChannelId = "incoming_call", timestamp = 0L, + textContent = null, ), onAnswer = {}, onCancel = {}, diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt index 421403d34f..2a12117a48 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/ActiveCallManager.kt @@ -160,7 +160,8 @@ class DefaultActiveCallManager @Inject constructor( senderDisplayName = notificationData.senderName ?: notificationData.senderId.value, roomAvatarUrl = notificationData.avatarUrl, notificationChannelId = notificationData.notificationChannelId, - timestamp = notificationData.timestamp + timestamp = notificationData.timestamp, + textContent = notificationData.textContent, ) ?: return runCatching { notificationManagerCompat.notify( diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt index 56fac5fc3b..97d6dac427 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/DefaultElementCallEntryPointTest.kt @@ -54,6 +54,7 @@ class DefaultElementCallEntryPointTest { avatarUrl = "avatarUrl", timestamp = 0, notificationChannelId = "notificationChannelId", + textContent = "textContent", ) registerIncomingCallLambda.assertions().isCalledOnce() diff --git a/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt b/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt index 9160ae92d8..1c703e44fc 100644 --- a/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt +++ b/features/call/impl/src/test/kotlin/io/element/android/features/call/notifications/RingingCallNotificationCreatorTest.kt @@ -73,6 +73,7 @@ class RingingCallNotificationCreatorTest { roomAvatarUrl = "https://example.com/avatar.jpg", notificationChannelId = "channelId", timestamp = 0L, + textContent = "textContent", ) private fun createRingingCallNotificationCreator( diff --git a/features/call/test/build.gradle.kts b/features/call/test/build.gradle.kts index d40d5c8c8c..4fe9b95384 100644 --- a/features/call/test/build.gradle.kts +++ b/features/call/test/build.gradle.kts @@ -22,4 +22,5 @@ dependencies { implementation(projects.features.call.impl) implementation(projects.libraries.matrix.api) implementation(projects.libraries.matrix.test) + implementation(projects.tests.testutils) } diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt b/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt index 3514cf425d..8e6ee00a16 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt +++ b/features/call/test/src/main/kotlin/io/element/android/features/call/test/CallNotificationData.kt @@ -30,6 +30,7 @@ fun aCallNotificationData( avatarUrl: String? = AN_AVATAR_URL, notificationChannelId: String = "channel_id", timestamp: Long = 0L, + textContent: String? = null, ): CallNotificationData = CallNotificationData( sessionId = sessionId, roomId = roomId, @@ -40,4 +41,5 @@ fun aCallNotificationData( avatarUrl = avatarUrl, notificationChannelId = notificationChannelId, timestamp = timestamp, + textContent = textContent, ) diff --git a/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt b/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt index 9a720bd2e7..bbd990df27 100644 --- a/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt +++ b/features/call/test/src/main/kotlin/io/element/android/features/call/test/FakeElementCallEntryPoint.kt @@ -11,10 +11,20 @@ import io.element.android.features.call.api.CallType import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.tests.testutils.lambda.lambdaError class FakeElementCallEntryPoint( - var startCallResult: (CallType) -> Unit = {}, - var handleIncomingCallResult: (CallType.RoomCall, EventId, UserId, String?, String?, String?, String) -> Unit = { _, _, _, _, _, _, _ -> } + var startCallResult: (CallType) -> Unit = { lambdaError() }, + var handleIncomingCallResult: ( + CallType.RoomCall, + EventId, + UserId, + String?, + String?, + String?, + String, + String?, + ) -> Unit = { _, _, _, _, _, _, _, _ -> lambdaError() } ) : ElementCallEntryPoint { override fun startCall(callType: CallType) { startCallResult(callType) @@ -28,8 +38,18 @@ class FakeElementCallEntryPoint( senderName: String?, avatarUrl: String?, timestamp: Long, - notificationChannelId: String + notificationChannelId: String, + textContent: String?, ) { - handleIncomingCallResult(callType, eventId, senderId, roomName, senderName, avatarUrl, notificationChannelId) + handleIncomingCallResult( + callType, + eventId, + senderId, + roomName, + senderName, + avatarUrl, + notificationChannelId, + textContent, + ) } } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt index 1e5066a5c8..66742652bf 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandler.kt @@ -129,6 +129,7 @@ class DefaultPushHandler @Inject constructor( avatarUrl = notifiableEvent.roomAvatarUrl, timestamp = notifiableEvent.timestamp, notificationChannelId = notificationChannels.getChannelForIncomingCall(ring = true), + textContent = notifiableEvent.description, ) } } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt index b0ef3af9ff..a8f921da0d 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/push/DefaultPushHandlerTest.kt @@ -238,7 +238,17 @@ class DefaultPushHandlerTest { unread = 0, clientSecret = A_SECRET, ) - val handleIncomingCallLambda = lambdaRecorder { _, _, _, _, _, _, _ -> } + val handleIncomingCallLambda = lambdaRecorder< + CallType.RoomCall, + EventId, + UserId, + String?, + String?, + String?, + String, + String?, + Unit, + > { _, _, _, _, _, _, _, _ -> } val elementCallEntryPoint = FakeElementCallEntryPoint(handleIncomingCallResult = handleIncomingCallLambda) val onNotifiableEventReceived = lambdaRecorder {} val defaultPushHandler = createDefaultPushHandler( @@ -266,7 +276,17 @@ class DefaultPushHandlerTest { clientSecret = A_SECRET, ) val onNotifiableEventReceived = lambdaRecorder {} - val handleIncomingCallLambda = lambdaRecorder { _, _, _, _, _, _, _ -> } + val handleIncomingCallLambda = lambdaRecorder< + CallType.RoomCall, + EventId, + UserId, + String?, + String?, + String?, + String, + String?, + Unit, + > { _, _, _, _, _, _, _, _ -> } val elementCallEntryPoint = FakeElementCallEntryPoint(handleIncomingCallResult = handleIncomingCallLambda) val defaultPushHandler = createDefaultPushHandler( elementCallEntryPoint = elementCallEntryPoint, @@ -294,7 +314,17 @@ class DefaultPushHandlerTest { clientSecret = A_SECRET, ) val onNotifiableEventReceived = lambdaRecorder {} - val handleIncomingCallLambda = lambdaRecorder { _, _, _, _, _, _, _ -> } + val handleIncomingCallLambda = lambdaRecorder< + CallType.RoomCall, + EventId, + UserId, + String?, + String?, + String?, + String, + String?, + Unit, + > { _, _, _, _, _, _, _, _ -> } val elementCallEntryPoint = FakeElementCallEntryPoint(handleIncomingCallResult = handleIncomingCallLambda) val defaultPushHandler = createDefaultPushHandler( elementCallEntryPoint = elementCallEntryPoint, diff --git a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt index 1371384b51..0966dd1cb7 100644 --- a/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt +++ b/tests/testutils/src/main/kotlin/io/element/android/tests/testutils/lambda/LambdaRecorder.kt @@ -83,6 +83,13 @@ inline fun lambdaRecorder( + ensureNeverCalled: Boolean = false, + noinline block: (T1, T2, T3, T4, T5, T6, T7, T8) -> R +): LambdaEightParamsRecorder { + return LambdaEightParamsRecorder(ensureNeverCalled, block) +} + inline fun lambdaAnyRecorder( ensureNeverCalled: Boolean = false, noinline block: (List) -> R