Browse Source

Notifications: add prefix to debug notification display.

feature/fga/small_timeline_improvements
Benoit Marty 1 year ago committed by Benoit Marty
parent
commit
fee97ff735
  1. 2
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt
  2. 8
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBitmapLoader.kt
  3. 13
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt
  4. 16
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/SummaryGroupMessageCreator.kt
  5. 21
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/debug/DebugNotification.kt
  6. 21
      libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationFactory.kt

2
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotifiableEventResolver.kt

@ -86,7 +86,7 @@ class NotifiableEventResolver @Inject constructor(
imageUriString = event.contentUrl, imageUriString = event.contentUrl,
threadId = null, threadId = null,
roomName = roomDisplayName, roomName = roomDisplayName,
roomIsDirect = false, roomIsDirect = isDirect,
roomAvatarPath = roomAvatarUrl, roomAvatarPath = roomAvatarUrl,
senderAvatarPath = senderAvatarUrl, senderAvatarPath = senderAvatarUrl,
soundName = null, soundName = null,

8
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationBitmapLoader.kt

@ -51,13 +51,13 @@ class NotificationBitmapLoader @Inject constructor(
private fun loadRoomBitmap(path: String): Bitmap? { private fun loadRoomBitmap(path: String): Bitmap? {
return try { return try {
val imageRequest = ImageRequest.Builder(context) val imageRequest = ImageRequest.Builder(context)
.data(MediaResolver.Meta(path, MediaResolver.Kind.Thumbnail(128))) .data(MediaResolver.Meta(path, MediaResolver.Kind.Thumbnail(512)))
.build() .build()
runBlocking { runBlocking {
val result = context.imageLoader.execute(imageRequest) val result = context.imageLoader.execute(imageRequest)
result.drawable?.toBitmap() result.drawable?.toBitmap()
} }
} catch (e: Exception) { } catch (e: Throwable) {
Timber.e(e, "Unable to load room bitmap") Timber.e(e, "Unable to load room bitmap")
null null
} }
@ -81,7 +81,7 @@ class NotificationBitmapLoader @Inject constructor(
private fun loadUserIcon(path: String): IconCompat? { private fun loadUserIcon(path: String): IconCompat? {
return try { return try {
val imageRequest = ImageRequest.Builder(context) val imageRequest = ImageRequest.Builder(context)
.data(MediaResolver.Meta(path, MediaResolver.Kind.Thumbnail(128))) .data(MediaResolver.Meta(path, MediaResolver.Kind.Thumbnail(512)))
.transformations(CircleCropTransformation()) .transformations(CircleCropTransformation())
.build() .build()
val bitmap = runBlocking { val bitmap = runBlocking {
@ -89,7 +89,7 @@ class NotificationBitmapLoader @Inject constructor(
result.drawable?.toBitmap() result.drawable?.toBitmap()
} }
return bitmap?.let { IconCompat.createWithBitmap(it) } return bitmap?.let { IconCompat.createWithBitmap(it) }
} catch (e: Exception) { } catch (e: Throwable) {
Timber.e(e, "Unable to load user bitmap") Timber.e(e, "Unable to load user bitmap")
null null
} }

13
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt

@ -22,6 +22,7 @@ import androidx.core.app.Person
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.user.MatrixUser 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.debug.annotateForDebug
import io.element.android.libraries.push.impl.notifications.factories.NotificationFactory import io.element.android.libraries.push.impl.notifications.factories.NotificationFactory
import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent import io.element.android.libraries.push.impl.notifications.model.NotifiableMessageEvent
import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.strings.StringProvider
@ -46,12 +47,12 @@ class RoomGroupMessageCreator @Inject constructor(
val roomIsGroup = !lastKnownRoomEvent.roomIsDirect val roomIsGroup = !lastKnownRoomEvent.roomIsDirect
val style = NotificationCompat.MessagingStyle( val style = NotificationCompat.MessagingStyle(
Person.Builder() Person.Builder()
.setName(currentUser.displayName) .setName(currentUser.displayName?.annotateForDebug(50))
.setIcon(bitmapLoader.getUserIcon(currentUser.avatarUrl)) .setIcon(bitmapLoader.getUserIcon(currentUser.avatarUrl))
.setKey(lastKnownRoomEvent.sessionId.value) .setKey(lastKnownRoomEvent.sessionId.value)
.build() .build()
).also { ).also {
it.conversationTitle = roomName.takeIf { roomIsGroup } it.conversationTitle = roomName.takeIf { roomIsGroup }?.annotateForDebug(51)
it.isGroupConversation = roomIsGroup it.isGroupConversation = roomIsGroup
it.addMessagesFromEvents(events) it.addMessagesFromEvents(events)
} }
@ -103,7 +104,7 @@ class RoomGroupMessageCreator @Inject constructor(
null null
} else { } else {
Person.Builder() Person.Builder()
.setName(event.senderName) .setName(event.senderName?.annotateForDebug(70))
.setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath)) .setIcon(bitmapLoader.getUserIcon(event.senderAvatarPath))
.setKey(event.senderId) .setKey(event.senderId)
.build() .build()
@ -115,7 +116,11 @@ class RoomGroupMessageCreator @Inject constructor(
senderPerson senderPerson
) )
else -> { else -> {
val message = NotificationCompat.MessagingStyle.Message(event.body, event.timestamp, senderPerson).also { message -> val message = NotificationCompat.MessagingStyle.Message(
event.body?.annotateForDebug(71),
event.timestamp,
senderPerson
).also { message ->
event.imageUri?.let { event.imageUri?.let {
message.setData("image/", it) message.setData("image/", it)
} }

16
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/SummaryGroupMessageCreator.kt

@ -20,6 +20,7 @@ import android.app.Notification
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import io.element.android.libraries.matrix.api.user.MatrixUser 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.debug.annotateForDebug
import io.element.android.libraries.push.impl.notifications.factories.NotificationFactory import io.element.android.libraries.push.impl.notifications.factories.NotificationFactory
import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.strings.StringProvider
import javax.inject.Inject import javax.inject.Inject
@ -40,7 +41,7 @@ import javax.inject.Inject
*/ */
class SummaryGroupMessageCreator @Inject constructor( class SummaryGroupMessageCreator @Inject constructor(
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val notificationFactory: NotificationFactory private val notificationFactory: NotificationFactory,
) { ) {
fun createSummaryNotification( fun createSummaryNotification(
@ -51,9 +52,9 @@ class SummaryGroupMessageCreator @Inject constructor(
useCompleteNotificationFormat: Boolean useCompleteNotificationFormat: Boolean
): Notification { ): Notification {
val summaryInboxStyle = NotificationCompat.InboxStyle().also { style -> val summaryInboxStyle = NotificationCompat.InboxStyle().also { style ->
roomNotifications.forEach { style.addLine(it.summaryLine) } roomNotifications.forEach { style.addLine(it.summaryLine.annotateForDebug(40)) }
invitationNotifications.forEach { style.addLine(it.summaryLine) } invitationNotifications.forEach { style.addLine(it.summaryLine.annotateForDebug(41)) }
simpleNotifications.forEach { style.addLine(it.summaryLine) } simpleNotifications.forEach { style.addLine(it.summaryLine.annotateForDebug(42)) }
} }
val summaryIsNoisy = roomNotifications.any { it.shouldBing } || val summaryIsNoisy = roomNotifications.any { it.shouldBing } ||
@ -69,9 +70,10 @@ class SummaryGroupMessageCreator @Inject constructor(
// FIXME roomIdToEventMap.size is not correct, this is the number of rooms // FIXME roomIdToEventMap.size is not correct, this is the number of rooms
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)
summaryInboxStyle.setBigContentTitle(sumTitle) summaryInboxStyle.setBigContentTitle(sumTitle.annotateForDebug(43))
// TODO get latest event? //.setSummaryText(stringProvider.getQuantityString(R.plurals.notification_unread_notified_messages, nbEvents, nbEvents).annotateForDebug(44))
.setSummaryText(stringProvider.getQuantityString(R.plurals.notification_unread_notified_messages, nbEvents, nbEvents)) // Use account name now, for multi-session
.setSummaryText(currentUser.userId.value.annotateForDebug(44))
return if (useCompleteNotificationFormat) { return if (useCompleteNotificationFormat) {
notificationFactory.createSummaryListNotification( notificationFactory.createSummaryListNotification(
currentUser, currentUser,

21
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/debug/DebugNotification.kt

@ -0,0 +1,21 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.push.impl.notifications.debug
fun CharSequence.annotateForDebug(prefix: Int): CharSequence {
return "$prefix-$this"
}

21
libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/NotificationFactory.kt

@ -31,6 +31,7 @@ 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.RoomEventGroupInfo import io.element.android.libraries.push.impl.notifications.RoomEventGroupInfo
import io.element.android.libraries.push.impl.notifications.channels.NotificationChannels import io.element.android.libraries.push.impl.notifications.channels.NotificationChannels
import io.element.android.libraries.push.impl.notifications.debug.annotateForDebug
import io.element.android.libraries.push.impl.notifications.factories.action.AcceptInvitationActionFactory import io.element.android.libraries.push.impl.notifications.factories.action.AcceptInvitationActionFactory
import io.element.android.libraries.push.impl.notifications.factories.action.MarkAsReadActionFactory import io.element.android.libraries.push.impl.notifications.factories.action.MarkAsReadActionFactory
import io.element.android.libraries.push.impl.notifications.factories.action.QuickReplyActionFactory import io.element.android.libraries.push.impl.notifications.factories.action.QuickReplyActionFactory
@ -84,16 +85,16 @@ class NotificationFactory @Inject constructor(
// ID of the corresponding shortcut, for conversation features under API 30+ // ID of the corresponding shortcut, for conversation features under API 30+
.setShortcutId(roomInfo.roomId.value) .setShortcutId(roomInfo.roomId.value)
// Title for API < 16 devices. // Title for API < 16 devices.
.setContentTitle(roomInfo.roomDisplayName) .setContentTitle(roomInfo.roomDisplayName.annotateForDebug(1))
// Content for API < 16 devices. // Content for API < 16 devices.
.setContentText(stringProvider.getString(R.string.notification_new_messages)) .setContentText(stringProvider.getString(R.string.notification_new_messages).annotateForDebug(2))
// Number of new notifications for API <24 (M and below) devices. // Number of new notifications for API <24 (M and below) devices.
.setSubText( .setSubText(
stringProvider.getQuantityString( stringProvider.getQuantityString(
R.plurals.notification_new_messages_for_room, R.plurals.notification_new_messages_for_room,
messageStyle.messages.size, messageStyle.messages.size,
messageStyle.messages.size messageStyle.messages.size
) ).annotateForDebug(3)
) )
// Auto-bundling is enabled for 4 or more notifications on API 24+ (N+) // Auto-bundling is enabled for 4 or more notifications on API 24+ (N+)
// devices and all Wear devices. But we want a custom grouping, so we specify the groupID // devices and all Wear devices. But we want a custom grouping, so we specify the groupID
@ -135,7 +136,7 @@ class NotificationFactory @Inject constructor(
} }
setDeleteIntent(pendingIntentFactory.createDismissRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId)) setDeleteIntent(pendingIntentFactory.createDismissRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId))
} }
.setTicker(tickerText) .setTicker(tickerText.annotateForDebug(4))
.build() .build()
} }
@ -147,8 +148,8 @@ class NotificationFactory @Inject constructor(
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)
.setContentTitle(inviteNotifiableEvent.roomName ?: buildMeta.applicationName) .setContentTitle((inviteNotifiableEvent.roomName ?: buildMeta.applicationName).annotateForDebug(5))
.setContentText(inviteNotifiableEvent.description) .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) .setSmallIcon(smallIcon)
@ -196,8 +197,8 @@ class NotificationFactory @Inject constructor(
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)
.setContentTitle(buildMeta.applicationName) .setContentTitle(buildMeta.applicationName.annotateForDebug(7))
.setContentText(simpleNotifiableEvent.description) .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) .setSmallIcon(smallIcon)
@ -240,11 +241,11 @@ class NotificationFactory @Inject constructor(
// 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)
.setStyle(style) .setStyle(style)
.setContentTitle(currentUser.userId.value) .setContentTitle(currentUser.userId.value.annotateForDebug(9))
.setCategory(NotificationCompat.CATEGORY_MESSAGE) .setCategory(NotificationCompat.CATEGORY_MESSAGE)
.setSmallIcon(smallIcon) .setSmallIcon(smallIcon)
// set content text to support devices running API level < 24 // set content text to support devices running API level < 24
.setContentText(compatSummary) .setContentText(compatSummary.annotateForDebug(10))
.setGroup(currentUser.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)

Loading…
Cancel
Save