diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/Config.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/Config.kt new file mode 100644 index 0000000000..eb37332f8f --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/Config.kt @@ -0,0 +1,25 @@ +/* + * 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 + +object NotificationConfig { + // TODO EAx Implement and set to true at some point + const val supportMarkAsReadAction = false + + // TODO EAx Implement and set to true at some point + const val supportQuickReplyAction = false +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationUtils.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationUtils.kt index 34f27cb62a..ef4d4c7438 100755 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationUtils.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/NotificationUtils.kt @@ -36,7 +36,6 @@ import androidx.annotation.DrawableRes import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat -import androidx.core.app.RemoteInput import androidx.core.content.ContextCompat import androidx.core.content.getSystemService import androidx.core.content.res.ResourcesCompat @@ -51,6 +50,10 @@ import io.element.android.libraries.matrix.api.core.SessionId import io.element.android.libraries.matrix.api.core.ThreadId import io.element.android.libraries.push.impl.R import io.element.android.libraries.push.impl.intent.IntentProvider +import io.element.android.libraries.push.impl.notifications.actions.AcceptInvitationActionFactory +import io.element.android.libraries.push.impl.notifications.actions.MarkAsReadActionFactory +import io.element.android.libraries.push.impl.notifications.actions.QuickReplyActionFactory +import io.element.android.libraries.push.impl.notifications.actions.RejectInvitationActionFactory import io.element.android.libraries.push.impl.notifications.model.InviteNotifiableEvent import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent import io.element.android.services.toolbox.api.strings.StringProvider @@ -68,6 +71,10 @@ class NotificationUtils @Inject constructor( private val actionIds: NotificationActionIds, private val intentProvider: IntentProvider, private val buildMeta: BuildMeta, + private val markAsReadActionFactory: MarkAsReadActionFactory, + private val quickReplyActionFactory: QuickReplyActionFactory, + private val rejectInvitationActionFactory: RejectInvitationActionFactory, + private val acceptInvitationActionFactory: AcceptInvitationActionFactory, ) { companion object { @@ -222,7 +229,6 @@ class NotificationUtils @Inject constructor( threadId: ThreadId?, largeIcon: Bitmap?, lastMessageTimestamp: Long, - senderDisplayNameForReplyCompat: String?, tickerText: String ): Notification { val accentColor = ContextCompat.getColor(context, R.color.notification_accent_color) @@ -232,6 +238,7 @@ class NotificationUtils @Inject constructor( true /** TODO EAx vectorPreferences.areThreadMessagesEnabled() */ -> buildOpenThreadIntent(roomInfo, threadId) + else -> buildOpenRoomIntent(roomInfo.sessionId, roomInfo.roomId) } @@ -288,43 +295,10 @@ class NotificationUtils @Inject constructor( // Add actions and notification intents // Mark room as read - val markRoomReadIntent = Intent(context, NotificationBroadcastReceiver::class.java) - markRoomReadIntent.action = actionIds.markRoomRead - markRoomReadIntent.data = createIgnoredUri("markRead?${roomInfo.sessionId}&$${roomInfo.roomId}") - markRoomReadIntent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, roomInfo.sessionId) - markRoomReadIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomInfo.roomId) - val markRoomReadPendingIntent = PendingIntent.getBroadcast( - context, - clock.epochMillis().toInt(), - markRoomReadIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE - ) - - NotificationCompat.Action.Builder( - R.drawable.ic_material_done_all_white, - stringProvider.getString(R.string.notification_room_action_mark_as_read), markRoomReadPendingIntent - ) - .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) - .setShowsUserInterface(false) - .build() - .let { addAction(it) } - + addAction(markAsReadActionFactory.create(roomInfo)) // Quick reply if (!roomInfo.hasSmartReplyError) { - buildQuickReplyIntent(roomInfo.sessionId, roomInfo.roomId, threadId, senderDisplayNameForReplyCompat)?.let { replyPendingIntent -> - val remoteInput = RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY) - .setLabel(stringProvider.getString(R.string.notification_room_action_quick_reply)) - .build() - NotificationCompat.Action.Builder( - R.drawable.vector_notification_quick_reply, - stringProvider.getString(R.string.notification_room_action_quick_reply), replyPendingIntent - ) - .addRemoteInput(remoteInput) - .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) - .setShowsUserInterface(false) - .build() - .let { addAction(it) } - } + addAction(quickReplyActionFactory.create(roomInfo, threadId)) } if (openIntent != null) { @@ -366,45 +340,9 @@ class NotificationUtils @Inject constructor( .setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL) .setSmallIcon(smallIcon) .setColor(accentColor) + .addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent)) + .addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent)) .apply { - val roomId = inviteNotifiableEvent.roomId - // offer to type a quick reject button - val rejectIntent = Intent(context, NotificationBroadcastReceiver::class.java) - rejectIntent.action = actionIds.reject - rejectIntent.data = createIgnoredUri("rejectInvite?${inviteNotifiableEvent.sessionId}&$roomId") - rejectIntent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, inviteNotifiableEvent.sessionId) - rejectIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) - val rejectIntentPendingIntent = PendingIntent.getBroadcast( - context, - clock.epochMillis().toInt(), - rejectIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE - ) - - addAction( - R.drawable.vector_notification_reject_invitation, - stringProvider.getString(R.string.notification_invitation_action_reject), - rejectIntentPendingIntent - ) - - // offer to type a quick accept button - val joinIntent = Intent(context, NotificationBroadcastReceiver::class.java) - joinIntent.action = actionIds.join - joinIntent.data = createIgnoredUri("acceptInvite?${inviteNotifiableEvent.sessionId}&$roomId") - joinIntent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, inviteNotifiableEvent.sessionId) - joinIntent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) - val joinIntentPendingIntent = PendingIntent.getBroadcast( - context, - clock.epochMillis().toInt(), - joinIntent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE - ) - addAction( - R.drawable.vector_notification_accept_invitation, - stringProvider.getString(R.string.notification_invitation_action_join), - joinIntentPendingIntent - ) - /* // Build the pending intent for when the notification is clicked val contentIntent = HomeActivity.newIntent( @@ -496,60 +434,6 @@ class NotificationUtils @Inject constructor( ) } - /* - Direct reply is new in Android N, and Android already handles the UI, so the right pending intent - here will ideally be a Service/IntentService (for a long running background task) or a BroadcastReceiver, - which runs on the UI thread. It also works without unlocking, making the process really fluid for the user. - However, for Android devices running Marshmallow and below (API level 23 and below), - it will be more appropriate to use an activity. Since you have to provide your own UI. - */ - private fun buildQuickReplyIntent( - sessionId: SessionId, - roomId: RoomId, - threadId: ThreadId?, - senderName: String? - ): PendingIntent? { - val intent: Intent - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - intent = Intent(context, NotificationBroadcastReceiver::class.java) - intent.action = actionIds.smartReply - intent.data = createIgnoredUri("quickReply?$sessionId&$roomId") - intent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, sessionId) - intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) - threadId?.let { - intent.putExtra(NotificationBroadcastReceiver.KEY_THREAD_ID, it) - } - - return PendingIntent.getBroadcast( - context, - clock.epochMillis().toInt(), - intent, - // PendingIntents attached to actions with remote inputs must be mutable - PendingIntent.FLAG_UPDATE_CURRENT or if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - PendingIntent.FLAG_MUTABLE - } else { - 0 - } - ) - } else { - /* - TODO - if (!LockScreenActivity.isDisplayingALockScreenActivity()) { - // start your activity for Android M and below - val quickReplyIntent = Intent(context, LockScreenActivity::class.java) - quickReplyIntent.putExtra(LockScreenActivity.EXTRA_ROOM_ID, roomId) - quickReplyIntent.putExtra(LockScreenActivity.EXTRA_SENDER_NAME, senderName ?: "") - - // the action must be unique else the parameters are ignored - quickReplyIntent.action = QUICK_LAUNCH_ACTION - quickReplyIntent.data = createIgnoredUri($roomId") - return PendingIntent.getActivity(context, 0, quickReplyIntent, PendingIntentCompat.FLAG_IMMUTABLE) - } - */ - } - return null - } - /** * Build the summary notification. */ diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt index ab38ad9fb4..1f308a8d40 100644 --- a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/RoomGroupMessageCreator.kt @@ -92,7 +92,6 @@ class RoomGroupMessageCreator @Inject constructor( threadId = lastKnownRoomEvent.threadId, largeIcon = largeBitmap, lastMessageTimestamp, - userDisplayName, tickerText ), meta diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/AcceptInvitationActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/AcceptInvitationActionFactory.kt new file mode 100644 index 0000000000..00ea4e407d --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/AcceptInvitationActionFactory.kt @@ -0,0 +1,60 @@ +/* + * 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.actions + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationCompat +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.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.api.systemclock.SystemClock +import javax.inject.Inject + +class AcceptInvitationActionFactory @Inject constructor( + @ApplicationContext private val context: Context, + private val actionIds: NotificationActionIds, + private val stringProvider: StringProvider, + private val clock: SystemClock, +) { + // offer to type a quick accept button + fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action { + val sessionId = inviteNotifiableEvent.sessionId + val roomId = inviteNotifiableEvent.roomId + val intent = Intent(context, NotificationBroadcastReceiver::class.java) + intent.action = actionIds.join + intent.data = createIgnoredUri("acceptInvite?${sessionId.value}&${roomId.value}") + intent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, sessionId) + intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) + val pendingIntent = PendingIntent.getBroadcast( + context, + clock.epochMillis().toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + return NotificationCompat.Action.Builder( + R.drawable.vector_notification_accept_invitation, + stringProvider.getString(R.string.notification_invitation_action_join), + pendingIntent + ).build() + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/MarkAsReadActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/MarkAsReadActionFactory.kt new file mode 100644 index 0000000000..54159c23cc --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/MarkAsReadActionFactory.kt @@ -0,0 +1,65 @@ +/* + * 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.actions + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationCompat +import io.element.android.libraries.androidutils.uri.createIgnoredUri +import io.element.android.libraries.di.ApplicationContext +import io.element.android.libraries.push.impl.NotificationConfig +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.RoomEventGroupInfo +import io.element.android.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.api.systemclock.SystemClock +import javax.inject.Inject + +class MarkAsReadActionFactory @Inject constructor( + @ApplicationContext private val context: Context, + private val actionIds: NotificationActionIds, + private val stringProvider: StringProvider, + private val clock: SystemClock, +) { + fun create(roomInfo: RoomEventGroupInfo): NotificationCompat.Action? { + if (!NotificationConfig.supportMarkAsReadAction) return null + val sessionId = roomInfo.sessionId + val roomId = roomInfo.roomId + val intent = Intent(context, NotificationBroadcastReceiver::class.java) + intent.action = actionIds.markRoomRead + intent.data = createIgnoredUri("markRead?${sessionId.value}&$${roomId.value}") + intent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, sessionId) + intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) + val pendingIntent = PendingIntent.getBroadcast( + context, + clock.epochMillis().toInt(), + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE + ) + + return NotificationCompat.Action.Builder( + R.drawable.ic_material_done_all_white, + stringProvider.getString(R.string.notification_room_action_mark_as_read), + pendingIntent + ) + .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_MARK_AS_READ) + .setShowsUserInterface(false) + .build() + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/QuickReplyActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/QuickReplyActionFactory.kt new file mode 100644 index 0000000000..6139fab6bb --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/QuickReplyActionFactory.kt @@ -0,0 +1,103 @@ +/* + * 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.actions + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.os.Build +import androidx.core.app.NotificationCompat +import androidx.core.app.RemoteInput +import io.element.android.libraries.androidutils.uri.createIgnoredUri +import io.element.android.libraries.di.ApplicationContext +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.matrix.api.core.ThreadId +import io.element.android.libraries.push.impl.NotificationConfig +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.RoomEventGroupInfo +import io.element.android.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.api.systemclock.SystemClock +import javax.inject.Inject + +class QuickReplyActionFactory @Inject constructor( + @ApplicationContext private val context: Context, + private val actionIds: NotificationActionIds, + private val stringProvider: StringProvider, + private val clock: SystemClock, +) { + fun create(roomInfo: RoomEventGroupInfo, threadId: ThreadId?): NotificationCompat.Action? { + if (!NotificationConfig.supportQuickReplyAction) return null + val sessionId = roomInfo.sessionId + val roomId = roomInfo.roomId + return buildQuickReplyIntent(sessionId, roomId, threadId)?.let { replyPendingIntent -> + val remoteInput = RemoteInput.Builder(NotificationBroadcastReceiver.KEY_TEXT_REPLY) + .setLabel(stringProvider.getString(R.string.notification_room_action_quick_reply)) + .build() + + NotificationCompat.Action.Builder( + R.drawable.vector_notification_quick_reply, + stringProvider.getString(R.string.notification_room_action_quick_reply), + replyPendingIntent + ) + .addRemoteInput(remoteInput) + .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) + .setShowsUserInterface(false) + .build() + } + } + + /* + * Direct reply is new in Android N, and Android already handles the UI, so the right pending intent + * here will ideally be a Service/IntentService (for a long running background task) or a BroadcastReceiver, + * which runs on the UI thread. It also works without unlocking, making the process really fluid for the user. + * However, for Android devices running Marshmallow and below (API level 23 and below), + * it will be more appropriate to use an activity. Since you have to provide your own UI. + */ + private fun buildQuickReplyIntent( + sessionId: SessionId, + roomId: RoomId, + threadId: ThreadId?, + ): PendingIntent? { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + val intent = Intent(context, NotificationBroadcastReceiver::class.java) + intent.action = actionIds.smartReply + intent.data = createIgnoredUri("quickReply?${sessionId.value}&${roomId.value}" + threadId?.let { "&${it.value}" }.orEmpty()) + intent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, sessionId) + intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) + threadId?.let { + intent.putExtra(NotificationBroadcastReceiver.KEY_THREAD_ID, it) + } + + PendingIntent.getBroadcast( + context, + clock.epochMillis().toInt(), + intent, + // PendingIntents attached to actions with remote inputs must be mutable + PendingIntent.FLAG_UPDATE_CURRENT or if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + PendingIntent.FLAG_MUTABLE + } else { + 0 + } + ) + } else { + null + } + } +} diff --git a/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/RejectInvitationActionFactory.kt b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/RejectInvitationActionFactory.kt new file mode 100644 index 0000000000..8b571d3318 --- /dev/null +++ b/libraries/push/impl/src/main/kotlin/io/element/android/libraries/push/impl/notifications/actions/RejectInvitationActionFactory.kt @@ -0,0 +1,60 @@ +/* + * 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.actions + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import androidx.core.app.NotificationCompat +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.services.toolbox.api.strings.StringProvider +import io.element.android.services.toolbox.api.systemclock.SystemClock +import javax.inject.Inject + +class RejectInvitationActionFactory @Inject constructor( + @ApplicationContext private val context: Context, + private val actionIds: NotificationActionIds, + private val stringProvider: StringProvider, + private val clock: SystemClock, +) { + fun create(inviteNotifiableEvent: InviteNotifiableEvent): NotificationCompat.Action? { + val sessionId = inviteNotifiableEvent.sessionId + val roomId = inviteNotifiableEvent.roomId + val intent = Intent(context, NotificationBroadcastReceiver::class.java) + intent.action = actionIds.reject + intent.data = createIgnoredUri("rejectInvite?${sessionId.value}&${roomId.value}") + intent.putExtra(NotificationBroadcastReceiver.KEY_SESSION_ID, sessionId) + intent.putExtra(NotificationBroadcastReceiver.KEY_ROOM_ID, roomId) + val pendingIntent = PendingIntent.getBroadcast( + context, + clock.epochMillis().toInt(), + 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), + pendingIntent + ).build() + } +}