Skip to content

Commit fe9dde5

Browse files
authored
Merge pull request #4274 from vector-im/feature/adm/notification-redesign
Notifications redesign
2 parents 109a5a6 + 124061e commit fe9dde5

35 files changed

+1777
-650
lines changed

changelog.d/1491.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Stops showing a dedicated redacted event notification, the message notifications will update accordingly

changelog.d/3395.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes marking individual notifications as read causing other notifications to be dismissed

changelog.d/4152.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Tentatively fixing the doubled notifications by updating the group summary at specific points in the notification rendering cycle

changelog.d/582.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Adding the room name to the invitation notification (if the room summary is available)

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import org.json.JSONObject
2222
import org.matrix.android.sdk.api.extensions.tryOrNull
2323
import org.matrix.android.sdk.api.failure.MatrixError
2424
import org.matrix.android.sdk.api.session.crypto.MXCryptoError
25+
import org.matrix.android.sdk.api.session.room.model.Membership
26+
import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
2527
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
2628
import org.matrix.android.sdk.api.session.room.model.message.MessageType
2729
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
@@ -310,3 +312,6 @@ fun Event.isEdition(): Boolean {
310312
fun Event.getPresenceContent(): PresenceContent? {
311313
return content.toModel<PresenceContent>()
312314
}
315+
316+
fun Event.isInvitation(): Boolean = type == EventType.STATE_ROOM_MEMBER &&
317+
content?.toModel<RoomMemberContent>()?.membership == Membership.INVITE

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.notification
1818

1919
import org.matrix.android.sdk.api.pushrules.rest.PushRule
2020
import org.matrix.android.sdk.api.session.events.model.EventType
21+
import org.matrix.android.sdk.api.session.events.model.isInvitation
2122
import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
2223
import org.matrix.android.sdk.internal.di.UserId
2324
import org.matrix.android.sdk.internal.task.Task
@@ -48,14 +49,18 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
4849
}
4950
val newJoinEvents = params.syncResponse.join
5051
.mapNotNull { (key, value) ->
51-
value.timeline?.events?.map { it.copy(roomId = key) }
52+
value.timeline?.events?.mapNotNull {
53+
it.takeIf { !it.isInvitation() }?.copy(roomId = key)
54+
}
5255
}
5356
.flatten()
57+
5458
val inviteEvents = params.syncResponse.invite
5559
.mapNotNull { (key, value) ->
5660
value.inviteState?.events?.map { it.copy(roomId = key) }
5761
}
5862
.flatten()
63+
5964
val allEvents = (newJoinEvents + inviteEvents).filter { event ->
6065
when (event.type) {
6166
EventType.MESSAGE,

tools/check/forbidden_strings_in_code.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Formatter\.formatShortFileSize===1
160160
# android\.text\.TextUtils
161161

162162
### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt
163-
enum class===106
163+
enum class===107
164164

165165
### Do not import temporary legacy classes
166166
import org.matrix.android.sdk.internal.legacy.riot===3

vector/src/gplay/java/im/vector/app/gplay/push/fcm/VectorFirebaseMessagingService.kt

Lines changed: 1 addition & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,13 @@ import com.google.firebase.messaging.FirebaseMessagingService
2929
import com.google.firebase.messaging.RemoteMessage
3030
import dagger.hilt.android.AndroidEntryPoint
3131
import im.vector.app.BuildConfig
32-
import im.vector.app.R
3332
import im.vector.app.core.di.ActiveSessionHolder
3433
import im.vector.app.core.network.WifiDetector
3534
import im.vector.app.core.pushers.PushersManager
3635
import im.vector.app.features.badge.BadgeProxy
3736
import im.vector.app.features.notifications.NotifiableEventResolver
38-
import im.vector.app.features.notifications.NotifiableMessageEvent
3937
import im.vector.app.features.notifications.NotificationDrawerManager
4038
import im.vector.app.features.notifications.NotificationUtils
41-
import im.vector.app.features.notifications.SimpleNotifiableEvent
4239
import im.vector.app.features.settings.VectorDataStore
4340
import im.vector.app.features.settings.VectorPreferences
4441
import im.vector.app.push.fcm.FcmHelper
@@ -48,9 +45,7 @@ import kotlinx.coroutines.launch
4845
import kotlinx.coroutines.runBlocking
4946
import org.matrix.android.sdk.api.extensions.tryOrNull
5047
import org.matrix.android.sdk.api.logger.LoggerTag
51-
import org.matrix.android.sdk.api.pushrules.Action
5248
import org.matrix.android.sdk.api.session.Session
53-
import org.matrix.android.sdk.api.session.events.model.Event
5449
import timber.log.Timber
5550
import javax.inject.Inject
5651

@@ -201,12 +196,11 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
201196
Timber.tag(loggerTag.value).d("Fast lane: start request")
202197
val event = tryOrNull { session.getEvent(roomId, eventId) } ?: return@launch
203198

204-
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event)
199+
val resolvedEvent = notifiableEventResolver.resolveInMemoryEvent(session, event, canBeReplaced = true)
205200

206201
resolvedEvent
207202
?.also { Timber.tag(loggerTag.value).d("Fast lane: notify drawer") }
208203
?.let {
209-
it.isPushGatewayEvent = true
210204
notificationDrawerManager.onNotifiableEventReceived(it)
211205
notificationDrawerManager.refreshNotificationDrawer()
212206
}
@@ -227,87 +221,4 @@ class VectorFirebaseMessagingService : FirebaseMessagingService() {
227221
}
228222
return false
229223
}
230-
231-
private fun handleNotificationWithoutSyncingMode(data: Map<String, String>, session: Session?) {
232-
if (session == null) {
233-
Timber.tag(loggerTag.value).e("## handleNotificationWithoutSyncingMode cannot find session")
234-
return
235-
}
236-
237-
// The Matrix event ID of the event being notified about.
238-
// This is required if the notification is about a particular Matrix event.
239-
// It may be omitted for notifications that only contain updated badge counts.
240-
// This ID can and should be used to detect duplicate notification requests.
241-
val eventId = data["event_id"] ?: return // Just ignore
242-
243-
val eventType = data["type"]
244-
if (eventType == null) {
245-
// Just add a generic unknown event
246-
val simpleNotifiableEvent = SimpleNotifiableEvent(
247-
session.myUserId,
248-
eventId,
249-
null,
250-
true, // It's an issue in this case, all event will bing even if expected to be silent.
251-
title = getString(R.string.notification_unknown_new_event),
252-
description = "",
253-
type = null,
254-
timestamp = System.currentTimeMillis(),
255-
soundName = Action.ACTION_OBJECT_VALUE_VALUE_DEFAULT,
256-
isPushGatewayEvent = true
257-
)
258-
notificationDrawerManager.onNotifiableEventReceived(simpleNotifiableEvent)
259-
notificationDrawerManager.refreshNotificationDrawer()
260-
} else {
261-
val event = parseEvent(data) ?: return
262-
263-
val notifiableEvent = notifiableEventResolver.resolveEvent(event, session)
264-
265-
if (notifiableEvent == null) {
266-
Timber.tag(loggerTag.value).e("Unsupported notifiable event $eventId")
267-
if (BuildConfig.LOW_PRIVACY_LOG_ENABLE) {
268-
Timber.tag(loggerTag.value).e("--> $event")
269-
}
270-
} else {
271-
if (notifiableEvent is NotifiableMessageEvent) {
272-
if (notifiableEvent.senderName.isNullOrEmpty()) {
273-
notifiableEvent.senderName = data["sender_display_name"] ?: data["sender"] ?: ""
274-
}
275-
if (notifiableEvent.roomName.isNullOrEmpty()) {
276-
notifiableEvent.roomName = findRoomNameBestEffort(data, session) ?: ""
277-
}
278-
}
279-
280-
notifiableEvent.isPushGatewayEvent = true
281-
notifiableEvent.matrixID = session.myUserId
282-
notificationDrawerManager.onNotifiableEventReceived(notifiableEvent)
283-
notificationDrawerManager.refreshNotificationDrawer()
284-
}
285-
}
286-
}
287-
288-
private fun findRoomNameBestEffort(data: Map<String, String>, session: Session?): String? {
289-
var roomName: String? = data["room_name"]
290-
val roomId = data["room_id"]
291-
if (null == roomName && null != roomId) {
292-
// Try to get the room name from our store
293-
roomName = session?.getRoom(roomId)?.roomSummary()?.displayName
294-
}
295-
return roomName
296-
}
297-
298-
/**
299-
* Try to create an event from the FCM data
300-
*
301-
* @param data the FCM data
302-
* @return the event or null if required data are missing
303-
*/
304-
private fun parseEvent(data: Map<String, String>?): Event? {
305-
return Event(
306-
eventId = data?.get("event_id") ?: return null,
307-
senderId = data["sender"],
308-
roomId = data["room_id"] ?: return null,
309-
type = data["type"] ?: return null,
310-
originServerTs = System.currentTimeMillis()
311-
)
312-
}
313224
}

vector/src/main/java/im/vector/app/features/notifications/InviteNotifiableEvent.kt

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,18 @@
1515
*/
1616
package im.vector.app.features.notifications
1717

18-
import androidx.core.app.NotificationCompat
19-
2018
data class InviteNotifiableEvent(
21-
override var matrixID: String?,
19+
val matrixID: String?,
2220
override val eventId: String,
2321
override val editedEventId: String?,
24-
var roomId: String,
25-
override var noisy: Boolean,
26-
override val title: String,
27-
override val description: String,
28-
override val type: String?,
29-
override val timestamp: Long,
30-
override var soundName: String?,
31-
override var isPushGatewayEvent: Boolean = false) : NotifiableEvent {
32-
33-
override var hasBeenDisplayed: Boolean = false
34-
override var isRedacted: Boolean = false
35-
override var lockScreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
36-
}
22+
override val canBeReplaced: Boolean,
23+
val roomId: String,
24+
val roomName: String?,
25+
val noisy: Boolean,
26+
val title: String,
27+
val description: String,
28+
val type: String?,
29+
val timestamp: Long,
30+
val soundName: String?,
31+
override val isRedacted: Boolean = false
32+
) : NotifiableEvent

vector/src/main/java/im/vector/app/features/notifications/NotifiableEvent.kt

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,11 @@ import java.io.Serializable
2020
/**
2121
* Parent interface for all events which can be displayed as a Notification
2222
*/
23-
interface NotifiableEvent : Serializable {
24-
var matrixID: String?
23+
sealed interface NotifiableEvent : Serializable {
2524
val eventId: String
2625
val editedEventId: String?
27-
var noisy: Boolean
28-
val title: String
29-
val description: String?
30-
val type: String?
31-
val timestamp: Long
32-
33-
// NotificationCompat.VISIBILITY_PUBLIC , VISIBILITY_PRIVATE , VISIBILITY_SECRET
34-
var lockScreenVisibility: Int
35-
36-
// Compat: Only for android <7, for newer version the sound is defined in the channel
37-
var soundName: String?
38-
var hasBeenDisplayed: Boolean
39-
var isRedacted: Boolean
4026

4127
// Used to know if event should be replaced with the one coming from eventstream
42-
var isPushGatewayEvent: Boolean
28+
val canBeReplaced: Boolean
29+
val isRedacted: Boolean
4330
}

0 commit comments

Comments
 (0)