diff --git a/changelog.d/7845.wip b/changelog.d/7845.wip
new file mode 100644
index 0000000000..8bce21499a
--- /dev/null
+++ b/changelog.d/7845.wip
@@ -0,0 +1 @@
+[Voice Broadcast] Only display a notification on the first voice chunk
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index f1c2eb2c6d..6731248f83 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -2295,6 +2295,7 @@
Verification Conclusion
Shared their location
Shared their live location
+ Started a voice broadcast
Waiting…
%s canceled
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
index ef4846d822..eaa0bbb51a 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
@@ -27,6 +27,7 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
import im.vector.app.features.voicebroadcast.isLive
+import im.vector.app.features.voicebroadcast.isVoiceBroadcast
import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent
import me.gujun.android.span.image
import me.gujun.android.span.span
@@ -39,6 +40,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
+import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.getTextDisplayableContent
@@ -86,10 +88,16 @@ class DisplayableEventFormatter @Inject constructor(
simpleFormat(senderName, stringProvider.getString(R.string.sent_an_image), appendAuthor)
}
MessageType.MSGTYPE_AUDIO -> {
- if ((messageContent as? MessageAudioContent)?.voiceMessageIndicator != null) {
- simpleFormat(senderName, stringProvider.getString(R.string.sent_a_voice_message), appendAuthor)
- } else {
- simpleFormat(senderName, stringProvider.getString(R.string.sent_an_audio_file), appendAuthor)
+ when {
+ (messageContent as? MessageAudioContent)?.voiceMessageIndicator == null -> {
+ simpleFormat(senderName, stringProvider.getString(R.string.sent_an_audio_file), appendAuthor)
+ }
+ timelineEvent.root.asMessageAudioEvent().isVoiceBroadcast() -> {
+ simpleFormat(senderName, stringProvider.getString(R.string.started_a_voice_broadcast), appendAuthor)
+ }
+ else -> {
+ simpleFormat(senderName, stringProvider.getString(R.string.sent_a_voice_message), appendAuthor)
+ }
}
}
MessageType.MSGTYPE_VIDEO -> {
diff --git a/vector/src/main/java/im/vector/app/features/notifications/FilteredEventDetector.kt b/vector/src/main/java/im/vector/app/features/notifications/FilteredEventDetector.kt
new file mode 100644
index 0000000000..e21462b182
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/notifications/FilteredEventDetector.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright 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 im.vector.app.features.notifications
+
+import im.vector.app.ActiveSessionDataSource
+import im.vector.app.features.voicebroadcast.isVoiceBroadcast
+import im.vector.app.features.voicebroadcast.sequence
+import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
+import org.matrix.android.sdk.api.session.getRoom
+import org.matrix.android.sdk.api.session.room.getTimelineEvent
+import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
+import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
+import javax.inject.Inject
+
+class FilteredEventDetector @Inject constructor(
+ private val activeSessionDataSource: ActiveSessionDataSource
+) {
+
+ /**
+ * Returns true if the given event should be ignored.
+ * Used to skip notifications if a non expected message is received.
+ */
+ fun shouldBeIgnored(notifiableEvent: NotifiableEvent): Boolean {
+ val session = activeSessionDataSource.currentValue?.orNull() ?: return false
+
+ if (notifiableEvent is NotifiableMessageEvent) {
+ val room = session.getRoom(notifiableEvent.roomId) ?: return false
+ val timelineEvent = room.getTimelineEvent(notifiableEvent.eventId) ?: return false
+ return timelineEvent.shouldBeIgnored()
+ }
+ return false
+ }
+
+ /**
+ * Whether the timeline event should be ignored.
+ */
+ private fun TimelineEvent.shouldBeIgnored(): Boolean {
+ if (root.isVoiceMessage()) {
+ val audioEvent = root.asMessageAudioEvent()
+ // if the event is a voice message related to a voice broadcast, only show the event on the first chunk.
+ return audioEvent.isVoiceBroadcast() && audioEvent?.sequence != 1
+ }
+
+ return false
+ }
+}
diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
index 4f05e83bd4..2d799034d9 100644
--- a/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
+++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationDrawerManager.kt
@@ -47,6 +47,7 @@ class NotificationDrawerManager @Inject constructor(
private val notifiableEventProcessor: NotifiableEventProcessor,
private val notificationRenderer: NotificationRenderer,
private val notificationEventPersistence: NotificationEventPersistence,
+ private val filteredEventDetector: FilteredEventDetector,
private val buildMeta: BuildMeta,
) {
@@ -100,6 +101,11 @@ class NotificationDrawerManager @Inject constructor(
Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}")
}
+ if (filteredEventDetector.shouldBeIgnored(notifiableEvent)) {
+ Timber.d("onNotifiableEventReceived(): ignore the event")
+ return
+ }
+
add(notifiableEvent)
}