diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt index c5f605e5fe..83ea9e3b77 100644 --- a/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt +++ b/appconfig/src/main/kotlin/io/element/android/appconfig/NotificationConfig.kt @@ -11,14 +11,20 @@ import android.graphics.Color import androidx.annotation.ColorInt object NotificationConfig { - // TODO EAx Implement and set to true at some point - const val SUPPORT_MARK_AS_READ_ACTION = false + /** + * If set to true, the notification will have a "Mark as read" action. + */ + const val SHOW_MARK_AS_READ_ACTION = true - // TODO EAx Implement and set to true at some point - const val SUPPORT_JOIN_DECLINE_INVITE = false + /** + * If set to true, the notification for invitation will have two actions to accept or decline the invite. + */ + const val SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS = true - // TODO EAx Implement and set to true at some point - const val SUPPORT_QUICK_REPLY_ACTION = false + /** + * If set to true, the notification will have a "Quick reply" action, allow to compose and send a message to the room. + */ + const val SHOW_QUICK_REPLY_ACTION = true @ColorInt val NOTIFICATION_ACCENT_COLOR: Int = Color.parseColor("#FF0DBD8B") 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 559322eaae..6788410468 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 @@ -230,10 +230,8 @@ class DefaultNotificationCreator @Inject constructor( .setSmallIcon(smallIcon) .setColor(accentColor) .apply { - if (NotificationConfig.SUPPORT_JOIN_DECLINE_INVITE) { - addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent)) - addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent)) - } + addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent)) + addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent)) // Build the pending intent for when the notification is clicked setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(inviteNotifiableEvent.sessionId, inviteNotifiableEvent.roomId)) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt index ee3d392c1f..9b2cf64a7d 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/AcceptInvitationActionFactory.kt @@ -11,12 +11,14 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import androidx.core.app.NotificationCompat +import io.element.android.appconfig.NotificationConfig import io.element.android.libraries.androidutils.uri.createIgnoredUri import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.notifications.NotificationActionIds import io.element.android.libraries.push.impl.notifications.NotificationBroadcastReceiver import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.systemclock.SystemClock import javax.inject.Inject @@ -27,8 +29,8 @@ class AcceptInvitationActionFactory @Inject constructor( private val stringProvider: StringProvider, private val clock: SystemClock, ) { - // offer to type a quick accept button - fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action { + fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action? { + if (!NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS) return null val sessionId = inviteNotifiableEvent.sessionId.value val roomId = inviteNotifiableEvent.roomId.value val intent = Intent(context, NotificationBroadcastReceiver::class.java) @@ -44,7 +46,7 @@ class AcceptInvitationActionFactory @Inject constructor( ) return NotificationCompat.Action.Builder( R.drawable.vector_notification_accept_invitation, - stringProvider.getString(R.string.notification_invitation_action_join), + stringProvider.getString(CommonStrings.action_accept), pendingIntent ).build() } diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt index b77e36cfc0..e6a2594bb8 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/MarkAsReadActionFactory.kt @@ -29,7 +29,7 @@ class MarkAsReadActionFactory @Inject constructor( private val clock: SystemClock, ) { fun create(roomInfo: RoomEventGroupInfo): NotificationCompat.Action? { - if (!NotificationConfig.SUPPORT_MARK_AS_READ_ACTION) return null + if (!NotificationConfig.SHOW_MARK_AS_READ_ACTION) return null val sessionId = roomInfo.sessionId.value val roomId = roomInfo.roomId.value val intent = Intent(context, NotificationBroadcastReceiver::class.java) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt index 3ada849026..bced0abd90 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/QuickReplyActionFactory.kt @@ -34,7 +34,7 @@ class QuickReplyActionFactory @Inject constructor( private val clock: SystemClock, ) { fun create(roomInfo: RoomEventGroupInfo, threadId: ThreadId?): NotificationCompat.Action? { - if (!NotificationConfig.SUPPORT_QUICK_REPLY_ACTION) return null + if (!NotificationConfig.SHOW_QUICK_REPLY_ACTION) return null val sessionId = roomInfo.sessionId val roomId = roomInfo.roomId val replyPendingIntent = buildQuickReplyIntent(sessionId, roomId, threadId) diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt index 309acce44c..d4eb28f141 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/factories/action/RejectInvitationActionFactory.kt @@ -11,12 +11,14 @@ import android.app.PendingIntent import android.content.Context import android.content.Intent import androidx.core.app.NotificationCompat +import io.element.android.appconfig.NotificationConfig import io.element.android.libraries.androidutils.uri.createIgnoredUri import io.element.android.libraries.di.ApplicationContext import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.notifications.NotificationActionIds import io.element.android.libraries.push.impl.notifications.NotificationBroadcastReceiver import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent +import io.element.android.libraries.ui.strings.CommonStrings import io.element.android.services.toolbox.api.strings.StringProvider import io.element.android.services.toolbox.api.systemclock.SystemClock import javax.inject.Inject @@ -28,6 +30,7 @@ class RejectInvitationActionFactory @Inject constructor( private val clock: SystemClock, ) { fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action? { + if (!NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS) return null val sessionId = inviteNotifiableEvent.sessionId.value val roomId = inviteNotifiableEvent.roomId.value val intent = Intent(context, NotificationBroadcastReceiver::class.java) @@ -41,10 +44,9 @@ class RejectInvitationActionFactory @Inject constructor( intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) - return NotificationCompat.Action.Builder( R.drawable.vector_notification_reject_invitation, - stringProvider.getString(R.string.notification_invitation_action_reject), + stringProvider.getString(CommonStrings.action_reject), pendingIntent ).build() } diff --git a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt index d0255aa452..44846f8010 100644 --- a/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt +++ b/libraries/push/impl/src/test/kotlin/io/element/android/libraries/push/impl/notifications/DefaultRoomGroupMessageCreatorTest.kt @@ -11,12 +11,15 @@ import android.content.Context 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.libraries.matrix.api.media.MediaSource 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.ui.components.aMatrixUser import io.element.android.libraries.matrix.ui.media.AVATAR_THUMBNAIL_SIZE_IN_PIXEL 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.QUICK_REPLY_ACTION_TITLE 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.test.notifications.FakeImageLoader @@ -156,6 +159,13 @@ class DefaultRoomGroupMessageCreatorTest { ) assertThat(result.number).isEqualTo(2) assertThat(result.`when`).isEqualTo(A_TIMESTAMP + 10) + val actionTitles = result.actions?.map { it.title } + assertThat(actionTitles).isEqualTo( + listOfNotNull( + MARK_AS_READ_ACTION_TITLE.takeIf { NotificationConfig.SHOW_MARK_AS_READ_ACTION }, + QUICK_REPLY_ACTION_TITLE.takeIf { NotificationConfig.SHOW_QUICK_REPLY_ACTION }, + ) + ) assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0) } @@ -175,7 +185,12 @@ class DefaultRoomGroupMessageCreatorTest { imageLoader = fakeImageLoader.getImageLoader(), existingNotification = null, ) - assertThat(result.actions).isNull() + val actionTitles = result.actions?.map { it.title } + assertThat(actionTitles).isEqualTo( + listOfNotNull( + MARK_AS_READ_ACTION_TITLE.takeIf { NotificationConfig.SHOW_MARK_AS_READ_ACTION } + ) + ) assertThat(fakeImageLoader.getCoilRequests().size).isEqualTo(0) } 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 9e2f3c1038..9a25ad2a72 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 @@ -13,6 +13,7 @@ import android.os.Build 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.libraries.core.meta.BuildMeta import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.A_ROOM_ID @@ -151,6 +152,13 @@ class DefaultNotificationCreatorTest { result.commonAssertions( expectedCategory = null, ) + val actionTitles = result.actions?.map { it.title } + assertThat(actionTitles).isEqualTo( + listOfNotNull( + REJECT_INVITATION_ACTION_TITLE.takeIf { NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS }, + ACCEPT_INVITATION_ACTION_TITLE.takeIf { NotificationConfig.SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS }, + ) + ) } @Test @@ -271,6 +279,11 @@ class DefaultNotificationCreatorTest { } } +const val MARK_AS_READ_ACTION_TITLE = "MarkAsReadAction" +const val QUICK_REPLY_ACTION_TITLE = "QuickReplyAction" +const val ACCEPT_INVITATION_ACTION_TITLE = "AcceptInvitationAction" +const val REJECT_INVITATION_ACTION_TITLE = "RejectInvitationAction" + fun createNotificationCreator( context: Context = RuntimeEnvironment.getApplication(), buildMeta: BuildMeta = aBuildMeta(), @@ -291,26 +304,26 @@ fun createNotificationCreator( markAsReadActionFactory = MarkAsReadActionFactory( context = context, actionIds = NotificationActionIds(buildMeta), - stringProvider = FakeStringProvider("MarkAsReadActionFactory"), + stringProvider = FakeStringProvider(MARK_AS_READ_ACTION_TITLE), clock = FakeSystemClock(), ), quickReplyActionFactory = QuickReplyActionFactory( context = context, actionIds = NotificationActionIds(buildMeta), - stringProvider = FakeStringProvider("QuickReplyActionFactory"), + stringProvider = FakeStringProvider(QUICK_REPLY_ACTION_TITLE), clock = FakeSystemClock(), ), bitmapLoader = bitmapLoader, acceptInvitationActionFactory = AcceptInvitationActionFactory( context = context, actionIds = NotificationActionIds(buildMeta), - stringProvider = FakeStringProvider("AcceptInvitationActionFactory"), + stringProvider = FakeStringProvider(ACCEPT_INVITATION_ACTION_TITLE), clock = FakeSystemClock(), ), rejectInvitationActionFactory = RejectInvitationActionFactory( context = context, actionIds = NotificationActionIds(buildMeta), - stringProvider = FakeStringProvider("RejectInvitationActionFactory"), + stringProvider = FakeStringProvider(REJECT_INVITATION_ACTION_TITLE), clock = FakeSystemClock(), ), )