Extract from_notification extra to a constant in IntentNavigationExtras
Allow `IntentProvider` to receive extras and `PendingIntentFactory` to send them.
This commit is contained in:
parent
71bfffe58f
commit
884c547123
7 changed files with 54 additions and 15 deletions
|
|
@ -10,6 +10,7 @@ package io.element.android.x.intent
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
import dev.zacsweers.metro.ContributesBinding
|
||||||
|
|
@ -32,11 +33,12 @@ class DefaultIntentProvider(
|
||||||
roomId: RoomId?,
|
roomId: RoomId?,
|
||||||
threadId: ThreadId?,
|
threadId: ThreadId?,
|
||||||
eventId: EventId?,
|
eventId: EventId?,
|
||||||
|
extras: Bundle?,
|
||||||
): Intent {
|
): Intent {
|
||||||
return Intent(context, MainActivity::class.java).apply {
|
return Intent(context, MainActivity::class.java).apply {
|
||||||
action = Intent.ACTION_VIEW
|
action = Intent.ACTION_VIEW
|
||||||
data = deepLinkCreator.create(sessionId, roomId, threadId, eventId).toUri()
|
data = deepLinkCreator.create(sessionId, roomId, threadId, eventId).toUri()
|
||||||
putExtra("from_notification", true)
|
extras?.let(::putExtras)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ import dev.zacsweers.metro.Assisted
|
||||||
import dev.zacsweers.metro.AssistedInject
|
import dev.zacsweers.metro.AssistedInject
|
||||||
import im.vector.app.features.analytics.plan.JoinedRoom
|
import im.vector.app.features.analytics.plan.JoinedRoom
|
||||||
import io.element.android.annotations.ContributesNode
|
import io.element.android.annotations.ContributesNode
|
||||||
import io.element.android.appnav.analytics.AnalyticsColdStartWatcher
|
|
||||||
import io.element.android.appnav.di.MatrixSessionCache
|
import io.element.android.appnav.di.MatrixSessionCache
|
||||||
import io.element.android.appnav.intent.IntentResolver
|
import io.element.android.appnav.intent.IntentResolver
|
||||||
import io.element.android.appnav.intent.ResolvedIntent
|
import io.element.android.appnav.intent.ResolvedIntent
|
||||||
|
|
@ -66,6 +65,7 @@ import io.element.android.libraries.ui.common.nodes.emptyNode
|
||||||
import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction
|
import io.element.android.services.analytics.api.AnalyticsLongRunningTransaction
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher
|
import io.element.android.services.analytics.api.watchers.AnalyticsColdStartWatcher
|
||||||
|
import io.element.android.services.appnavstate.api.ROOM_OPENED_FROM_NOTIFICATION
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
@ -318,7 +318,8 @@ class RootFlowNode(
|
||||||
val resolvedIntent = intentResolver.resolve(intent) ?: return
|
val resolvedIntent = intentResolver.resolve(intent) ?: return
|
||||||
when (resolvedIntent) {
|
when (resolvedIntent) {
|
||||||
is ResolvedIntent.Navigation -> {
|
is ResolvedIntent.Navigation -> {
|
||||||
if (intent.getBooleanExtra("from_notification", false) && resolvedIntent.deeplinkData is DeeplinkData.Room) {
|
val openingRoomFromNotification = intent.getBooleanExtra(ROOM_OPENED_FROM_NOTIFICATION, false)
|
||||||
|
if (openingRoomFromNotification && resolvedIntent.deeplinkData is DeeplinkData.Room) {
|
||||||
analyticsService.startLongRunningTransaction(AnalyticsLongRunningTransaction.NotificationTapOpensTimeline)
|
analyticsService.startLongRunningTransaction(AnalyticsLongRunningTransaction.NotificationTapOpensTimeline)
|
||||||
}
|
}
|
||||||
navigateTo(resolvedIntent.deeplinkData)
|
navigateTo(resolvedIntent.deeplinkData)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
package io.element.android.libraries.push.impl.intent
|
package io.element.android.libraries.push.impl.intent
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
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.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
|
@ -23,5 +24,6 @@ interface IntentProvider {
|
||||||
roomId: RoomId?,
|
roomId: RoomId?,
|
||||||
threadId: ThreadId?,
|
threadId: ThreadId?,
|
||||||
eventId: EventId?,
|
eventId: EventId?,
|
||||||
|
extras: Bundle? = null,
|
||||||
): Intent
|
): Intent
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import androidx.annotation.ColorInt
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationCompat.MessagingStyle
|
import androidx.core.app.NotificationCompat.MessagingStyle
|
||||||
import androidx.core.app.Person
|
import androidx.core.app.Person
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
import coil3.ImageLoader
|
import coil3.ImageLoader
|
||||||
import dev.zacsweers.metro.AppScope
|
import dev.zacsweers.metro.AppScope
|
||||||
import dev.zacsweers.metro.ContributesBinding
|
import dev.zacsweers.metro.ContributesBinding
|
||||||
|
|
@ -44,6 +45,7 @@ import io.element.android.libraries.push.impl.notifications.model.NotifiableMess
|
||||||
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
|
import io.element.android.libraries.push.impl.notifications.model.SimpleNotifiableEvent
|
||||||
import io.element.android.libraries.push.impl.notifications.shortcut.createShortcutId
|
import io.element.android.libraries.push.impl.notifications.shortcut.createShortcutId
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
import io.element.android.services.appnavstate.api.ROOM_OPENED_FROM_NOTIFICATION
|
||||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
|
||||||
interface NotificationCreator {
|
interface NotificationCreator {
|
||||||
|
|
@ -138,7 +140,12 @@ class DefaultNotificationCreator(
|
||||||
val eventId = events.firstOrNull()?.eventId
|
val eventId = events.firstOrNull()?.eventId
|
||||||
val openIntent = when {
|
val openIntent = when {
|
||||||
threadId != null -> pendingIntentFactory.createOpenThreadPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId, threadId)
|
threadId != null -> pendingIntentFactory.createOpenThreadPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId, threadId)
|
||||||
else -> pendingIntentFactory.createOpenRoomPendingIntent(roomInfo.sessionId, roomInfo.roomId, eventId)
|
else -> pendingIntentFactory.createOpenRoomPendingIntent(
|
||||||
|
sessionId = roomInfo.sessionId,
|
||||||
|
roomId = roomInfo.roomId,
|
||||||
|
eventId = eventId,
|
||||||
|
extras = bundleOf(ROOM_OPENED_FROM_NOTIFICATION to true),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
val containsMissedCall = events.any { it.type == EventType.RTC_NOTIFICATION }
|
val containsMissedCall = events.any { it.type == EventType.RTC_NOTIFICATION }
|
||||||
val channelId = if (containsMissedCall) {
|
val channelId = if (containsMissedCall) {
|
||||||
|
|
@ -233,7 +240,11 @@ class DefaultNotificationCreator(
|
||||||
.addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent))
|
.addAction(rejectInvitationActionFactory.create(inviteNotifiableEvent))
|
||||||
.addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent))
|
.addAction(acceptInvitationActionFactory.create(inviteNotifiableEvent))
|
||||||
// Build the pending intent for when the notification is clicked
|
// Build the pending intent for when the notification is clicked
|
||||||
.setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(inviteNotifiableEvent.sessionId, inviteNotifiableEvent.roomId, null))
|
.setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(
|
||||||
|
sessionId = inviteNotifiableEvent.sessionId,
|
||||||
|
roomId = inviteNotifiableEvent.roomId,
|
||||||
|
eventId = null,
|
||||||
|
))
|
||||||
.apply {
|
.apply {
|
||||||
if (inviteNotifiableEvent.noisy) {
|
if (inviteNotifiableEvent.noisy) {
|
||||||
// Compat
|
// Compat
|
||||||
|
|
@ -265,7 +276,12 @@ class DefaultNotificationCreator(
|
||||||
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL)
|
.setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_ALL)
|
||||||
.configureWith(notificationAccountParams)
|
.configureWith(notificationAccountParams)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(simpleNotifiableEvent.sessionId, simpleNotifiableEvent.roomId, null))
|
.setContentIntent(pendingIntentFactory.createOpenRoomPendingIntent(
|
||||||
|
sessionId = simpleNotifiableEvent.sessionId,
|
||||||
|
roomId = simpleNotifiableEvent.roomId,
|
||||||
|
eventId = null,
|
||||||
|
extras = bundleOf(ROOM_OPENED_FROM_NOTIFICATION to true),
|
||||||
|
))
|
||||||
.apply {
|
.apply {
|
||||||
if (simpleNotifiableEvent.noisy) {
|
if (simpleNotifiableEvent.noisy) {
|
||||||
// Compat
|
// Compat
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ package io.element.android.libraries.push.impl.notifications.factories
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import dev.zacsweers.metro.Inject
|
import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.libraries.androidutils.uri.createIgnoredUri
|
import io.element.android.libraries.androidutils.uri.createIgnoredUri
|
||||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||||
|
|
@ -31,20 +32,20 @@ class PendingIntentFactory(
|
||||||
private val clock: SystemClock,
|
private val clock: SystemClock,
|
||||||
private val actionIds: NotificationActionIds,
|
private val actionIds: NotificationActionIds,
|
||||||
) {
|
) {
|
||||||
fun createOpenSessionPendingIntent(sessionId: SessionId): PendingIntent? {
|
fun createOpenSessionPendingIntent(sessionId: SessionId, extras: Bundle? = null): PendingIntent? {
|
||||||
return createRoomPendingIntent(sessionId = sessionId, roomId = null, eventId = null, threadId = null)
|
return createRoomPendingIntent(sessionId = sessionId, roomId = null, eventId = null, threadId = null, extras = extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createOpenRoomPendingIntent(sessionId: SessionId, roomId: RoomId, eventId: EventId?): PendingIntent? {
|
fun createOpenRoomPendingIntent(sessionId: SessionId, roomId: RoomId, eventId: EventId?, extras: Bundle? = null): PendingIntent? {
|
||||||
return createRoomPendingIntent(sessionId = sessionId, roomId = roomId, eventId = eventId, threadId = null)
|
return createRoomPendingIntent(sessionId = sessionId, roomId = roomId, eventId = eventId, threadId = null, extras = extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createOpenThreadPendingIntent(sessionId: SessionId, roomId: RoomId, eventId: EventId?, threadId: ThreadId): PendingIntent? {
|
fun createOpenThreadPendingIntent(sessionId: SessionId, roomId: RoomId, eventId: EventId?, threadId: ThreadId, extras: Bundle? = null): PendingIntent? {
|
||||||
return createRoomPendingIntent(sessionId = sessionId, roomId = roomId, eventId = eventId, threadId = threadId)
|
return createRoomPendingIntent(sessionId = sessionId, roomId = roomId, eventId = eventId, threadId = threadId, extras = extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createRoomPendingIntent(sessionId: SessionId, roomId: RoomId?, eventId: EventId?, threadId: ThreadId?): PendingIntent? {
|
private fun createRoomPendingIntent(sessionId: SessionId, roomId: RoomId?, eventId: EventId?, threadId: ThreadId?, extras: Bundle? = null): PendingIntent? {
|
||||||
val intent = intentProvider.getViewRoomIntent(sessionId = sessionId, roomId = roomId, eventId = eventId, threadId = threadId)
|
val intent = intentProvider.getViewRoomIntent(sessionId = sessionId, roomId = roomId, eventId = eventId, threadId = threadId, extras = extras)
|
||||||
return PendingIntent.getActivity(
|
return PendingIntent.getActivity(
|
||||||
context,
|
context,
|
||||||
clock.epochMillis().toInt(),
|
clock.epochMillis().toInt(),
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
package io.element.android.libraries.push.impl.notifications.factories
|
package io.element.android.libraries.push.impl.notifications.factories
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
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.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
|
|
@ -16,5 +17,11 @@ import io.element.android.libraries.matrix.api.core.ThreadId
|
||||||
import io.element.android.libraries.push.impl.intent.IntentProvider
|
import io.element.android.libraries.push.impl.intent.IntentProvider
|
||||||
|
|
||||||
class FakeIntentProvider : IntentProvider {
|
class FakeIntentProvider : IntentProvider {
|
||||||
override fun getViewRoomIntent(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?, eventId: EventId?) = Intent(Intent.ACTION_VIEW)
|
override fun getViewRoomIntent(
|
||||||
|
sessionId: SessionId,
|
||||||
|
roomId: RoomId?,
|
||||||
|
threadId: ThreadId?,
|
||||||
|
eventId: EventId?,
|
||||||
|
extras: Bundle?,
|
||||||
|
) = Intent(Intent.ACTION_VIEW)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Element Creations Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||||
|
* Please see LICENSE files in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.services.appnavstate.api
|
||||||
|
|
||||||
|
const val ROOM_OPENED_FROM_NOTIFICATION = "opened_from_notification"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue