updating the push gateway property to reflect that it mean the event can be replaced

- makes the property immutable as only the creation of the event knows if it can be replace eg it came from a push or the /sync event stream
This commit is contained in:
Adam Brown 2021-10-07 12:19:35 +01:00
parent b44a382893
commit 86b500445f
8 changed files with 22 additions and 22 deletions

View file

@ -29,16 +29,13 @@ import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage import com.google.firebase.messaging.RemoteMessage
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.BuildConfig import im.vector.app.BuildConfig
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.network.WifiDetector import im.vector.app.core.network.WifiDetector
import im.vector.app.core.pushers.PushersManager import im.vector.app.core.pushers.PushersManager
import im.vector.app.features.badge.BadgeProxy import im.vector.app.features.badge.BadgeProxy
import im.vector.app.features.notifications.NotifiableEventResolver import im.vector.app.features.notifications.NotifiableEventResolver
import im.vector.app.features.notifications.NotifiableMessageEvent
import im.vector.app.features.notifications.NotificationDrawerManager import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.notifications.NotificationUtils import im.vector.app.features.notifications.NotificationUtils
import im.vector.app.features.notifications.SimpleNotifiableEvent
import im.vector.app.features.settings.VectorDataStore import im.vector.app.features.settings.VectorDataStore
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import im.vector.app.push.fcm.FcmHelper import im.vector.app.push.fcm.FcmHelper
@ -48,9 +45,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.logger.LoggerTag
import org.matrix.android.sdk.api.pushrules.Action
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.Event
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -201,12 +196,11 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
Timber.tag(loggerTag.value).d("Fast lane: start request") Timber.tag(loggerTag.value).d("Fast lane: start request")
val event = tryOrNull { session.getEvent(roomId, eventId) } ?: return@launch val event = tryOrNull { session.getEvent(roomId, eventId) } ?: return@launch
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event) val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event, canBeReplaced = true)
resolvedEvent resolvedEvent
?.also { Timber.tag(loggerTag.value).d("Fast lane: notify drawer") } ?.also { Timber.tag(loggerTag.value).d("Fast lane: notify drawer") }
?.let { ?.let {
it.isPushGatewayEvent = true
notificationDrawerManager.onNotifiableEventReceived(it) notificationDrawerManager.onNotifiableEventReceived(it)
notificationDrawerManager.refreshNotificationDrawer() notificationDrawerManager.refreshNotificationDrawer()
} }

View file

@ -19,6 +19,7 @@ data class InviteNotifiableEvent(
val matrixID: String?, val matrixID: String?,
override val eventId: String, override val eventId: String,
override val editedEventId: String?, override val editedEventId: String?,
override val canBeReplaced: Boolean,
val roomId: String, val roomId: String,
val noisy: Boolean, val noisy: Boolean,
val title: String, val title: String,
@ -29,6 +30,5 @@ data class InviteNotifiableEvent(
override val isRedacted: Boolean = false override val isRedacted: Boolean = false
) : NotifiableEvent { ) : NotifiableEvent {
override var isPushGatewayEvent: Boolean = false
override var hasBeenDisplayed = false override var hasBeenDisplayed = false
} }

View file

@ -25,6 +25,6 @@ sealed interface NotifiableEvent : Serializable {
val editedEventId: String? val editedEventId: String?
var hasBeenDisplayed: Boolean var hasBeenDisplayed: Boolean
// Used to know if event should be replaced with the one coming from eventstream // Used to know if event should be replaced with the one coming from eventstream
var isPushGatewayEvent: Boolean val canBeReplaced: Boolean
val isRedacted: Boolean val isRedacted: Boolean
} }

View file

@ -57,15 +57,15 @@ class NotifiableEventResolver @Inject constructor(
val roomID = event.roomId ?: return null val roomID = event.roomId ?: return null
val eventId = event.eventId ?: return null val eventId = event.eventId ?: return null
if (event.getClearType() == EventType.STATE_ROOM_MEMBER) { if (event.getClearType() == EventType.STATE_ROOM_MEMBER) {
return resolveStateRoomEvent(event, session, isNoisy) return resolveStateRoomEvent(event, session, canBeReplaced = false, isNoisy = isNoisy)
} }
val timelineEvent = session.getRoom(roomID)?.getTimeLineEvent(eventId) ?: return null val timelineEvent = session.getRoom(roomID)?.getTimeLineEvent(eventId) ?: return null
when (event.getClearType()) { when (event.getClearType()) {
EventType.MESSAGE -> { EventType.MESSAGE -> {
return resolveMessageEvent(timelineEvent, session, isNoisy) return resolveMessageEvent(timelineEvent, session, canBeReplaced = false, isNoisy = isNoisy)
} }
EventType.ENCRYPTED -> { EventType.ENCRYPTED -> {
return resolveMessageEvent(timelineEvent, session, isNoisy) return resolveMessageEvent(timelineEvent, session, canBeReplaced = false, isNoisy = isNoisy)
} }
else -> { else -> {
// If the event can be displayed, display it as is // If the event can be displayed, display it as is
@ -82,12 +82,14 @@ class NotifiableEventResolver @Inject constructor(
description = bodyPreview, description = bodyPreview,
title = stringProvider.getString(R.string.notification_unknown_new_event), title = stringProvider.getString(R.string.notification_unknown_new_event),
soundName = null, soundName = null,
type = event.type) type = event.type,
canBeReplaced = false
)
} }
} }
} }
fun resolveInMemoryEvent(session: Session, event: Event): NotifiableEvent? { fun resolveInMemoryEvent(session: Session, event: Event, canBeReplaced: Boolean): NotifiableEvent? {
if (event.getClearType() != EventType.MESSAGE) return null if (event.getClearType() != EventType.MESSAGE) return null
// Ignore message edition // Ignore message edition
@ -111,14 +113,14 @@ class NotifiableEventResolver @Inject constructor(
avatarUrl = user.avatarUrl avatarUrl = user.avatarUrl
) )
) )
resolveMessageEvent(timelineEvent, session, isNoisy = !notificationAction.soundName.isNullOrBlank()) resolveMessageEvent(timelineEvent, session, canBeReplaced = canBeReplaced, isNoisy = !notificationAction.soundName.isNullOrBlank())
} else { } else {
Timber.d("Matched push rule is set to not notify") Timber.d("Matched push rule is set to not notify")
null null
} }
} }
private fun resolveMessageEvent(event: TimelineEvent, session: Session, isNoisy: Boolean): NotifiableEvent { private fun resolveMessageEvent(event: TimelineEvent, session: Session, canBeReplaced: Boolean, isNoisy: Boolean): NotifiableEvent {
// The event only contains an eventId, and roomId (type is m.room.*) , we need to get the displayable content (names, avatar, text, etc...) // The event only contains an eventId, and roomId (type is m.room.*) , we need to get the displayable content (names, avatar, text, etc...)
val room = session.getRoom(event.root.roomId!! /*roomID cannot be null*/) val room = session.getRoom(event.root.roomId!! /*roomID cannot be null*/)
@ -132,6 +134,7 @@ class NotifiableEventResolver @Inject constructor(
return NotifiableMessageEvent( return NotifiableMessageEvent(
eventId = event.root.eventId!!, eventId = event.root.eventId!!,
editedEventId = event.getEditedEventId(), editedEventId = event.getEditedEventId(),
canBeReplaced = canBeReplaced,
timestamp = event.root.originServerTs ?: 0, timestamp = event.root.originServerTs ?: 0,
noisy = isNoisy, noisy = isNoisy,
senderName = senderDisplayName, senderName = senderDisplayName,
@ -164,6 +167,7 @@ class NotifiableEventResolver @Inject constructor(
return NotifiableMessageEvent( return NotifiableMessageEvent(
eventId = event.root.eventId!!, eventId = event.root.eventId!!,
editedEventId = event.getEditedEventId(), editedEventId = event.getEditedEventId(),
canBeReplaced = canBeReplaced,
timestamp = event.root.originServerTs ?: 0, timestamp = event.root.originServerTs ?: 0,
noisy = isNoisy, noisy = isNoisy,
senderName = senderDisplayName, senderName = senderDisplayName,
@ -188,7 +192,7 @@ class NotifiableEventResolver @Inject constructor(
} }
} }
private fun resolveStateRoomEvent(event: Event, session: Session, isNoisy: Boolean): NotifiableEvent? { private fun resolveStateRoomEvent(event: Event, session: Session, canBeReplaced: Boolean, isNoisy: Boolean): NotifiableEvent? {
val content = event.content?.toModel<RoomMemberContent>() ?: return null val content = event.content?.toModel<RoomMemberContent>() ?: return null
val roomId = event.roomId ?: return null val roomId = event.roomId ?: return null
val dName = event.senderId?.let { session.getRoomMember(it, roomId)?.displayName } val dName = event.senderId?.let { session.getRoomMember(it, roomId)?.displayName }
@ -199,6 +203,7 @@ class NotifiableEventResolver @Inject constructor(
session.myUserId, session.myUserId,
eventId = event.eventId!!, eventId = event.eventId!!,
editedEventId = null, editedEventId = null,
canBeReplaced = canBeReplaced,
roomId = roomId, roomId = roomId,
timestamp = event.originServerTs ?: 0, timestamp = event.originServerTs ?: 0,
noisy = isNoisy, noisy = isNoisy,

View file

@ -20,6 +20,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
data class NotifiableMessageEvent( data class NotifiableMessageEvent(
override val eventId: String, override val eventId: String,
override val editedEventId: String?, override val editedEventId: String?,
override val canBeReplaced: Boolean,
val noisy: Boolean, val noisy: Boolean,
val timestamp: Long, val timestamp: Long,
val senderName: String?, val senderName: String?,
@ -38,7 +39,6 @@ data class NotifiableMessageEvent(
override val isRedacted: Boolean = false override val isRedacted: Boolean = false
) : NotifiableEvent { ) : NotifiableEvent {
override var isPushGatewayEvent: Boolean = false
override var hasBeenDisplayed: Boolean = false override var hasBeenDisplayed: Boolean = false
val type: String = EventType.MESSAGE val type: String = EventType.MESSAGE

View file

@ -141,7 +141,8 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
roomId = room.roomId, roomId = room.roomId,
roomName = room.roomSummary()?.displayName ?: room.roomId, roomName = room.roomSummary()?.displayName ?: room.roomId,
roomIsDirect = room.roomSummary()?.isDirect == true, roomIsDirect = room.roomSummary()?.isDirect == true,
outGoingMessage = true outGoingMessage = true,
canBeReplaced = false
) )
notificationDrawerManager.onNotifiableEventReceived(notifiableMessageEvent) notificationDrawerManager.onNotifiableEventReceived(notifiableMessageEvent)

View file

@ -107,12 +107,12 @@ class NotificationDrawerManager @Inject constructor(private val context: Context
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) { if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
Timber.d("onNotifiableEventReceived(): $notifiableEvent") Timber.d("onNotifiableEventReceived(): $notifiableEvent")
} else { } else {
Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.isPushGatewayEvent}") Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}")
} }
synchronized(eventList) { synchronized(eventList) {
val existing = eventList.firstOrNull { it.eventId == notifiableEvent.eventId } val existing = eventList.firstOrNull { it.eventId == notifiableEvent.eventId }
if (existing != null) { if (existing != null) {
if (existing.isPushGatewayEvent) { if (existing.canBeReplaced) {
// Use the event coming from the event stream as it may contains more info than // Use the event coming from the event stream as it may contains more info than
// the fcm one (like type/content/clear text) (e.g when an encrypted message from // the fcm one (like type/content/clear text) (e.g when an encrypted message from
// FCM should be update with clear text after a sync) // FCM should be update with clear text after a sync)

View file

@ -25,10 +25,10 @@ data class SimpleNotifiableEvent(
val type: String?, val type: String?,
val timestamp: Long, val timestamp: Long,
val soundName: String?, val soundName: String?,
override var canBeReplaced: Boolean,
override val isRedacted: Boolean = false override val isRedacted: Boolean = false
) : NotifiableEvent { ) : NotifiableEvent {
override var isPushGatewayEvent: Boolean = false
override var hasBeenDisplayed: Boolean = false override var hasBeenDisplayed: Boolean = false
} }