Merge pull request #7945 from vector-im/feature/fre/vb_notification_on_first_chunk

Voice Broadcast - only send a notification on the first chunk
This commit is contained in:
Florian Renaud 2023-01-13 14:26:04 +01:00 committed by GitHub
commit 1b192ea45c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 79 additions and 4 deletions

1
changelog.d/7845.wip Normal file
View File

@ -0,0 +1 @@
[Voice Broadcast] Only display a notification on the first voice chunk

View File

@ -2295,6 +2295,7 @@
<string name="sent_verification_conclusion">Verification Conclusion</string> <string name="sent_verification_conclusion">Verification Conclusion</string>
<string name="sent_location">Shared their location</string> <string name="sent_location">Shared their location</string>
<string name="sent_live_location">Shared their live location</string> <string name="sent_live_location">Shared their live location</string>
<string name="started_a_voice_broadcast">Started a voice broadcast</string>
<string name="verification_request_waiting">Waiting…</string> <string name="verification_request_waiting">Waiting…</string>
<string name="verification_request_other_cancelled">%s canceled</string> <string name="verification_request_other_cancelled">%s canceled</string>

View File

@ -27,6 +27,7 @@ import im.vector.app.core.resources.StringProvider
import im.vector.app.features.html.EventHtmlRenderer import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
import im.vector.app.features.voicebroadcast.isLive import im.vector.app.features.voicebroadcast.isLive
import im.vector.app.features.voicebroadcast.isVoiceBroadcast
import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent import im.vector.app.features.voicebroadcast.model.asVoiceBroadcastEvent
import me.gujun.android.span.image import me.gujun.android.span.image
import me.gujun.android.span.span 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.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent 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.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.model.relation.ReactionContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import org.matrix.android.sdk.api.session.room.timeline.getTextDisplayableContent 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) simpleFormat(senderName, stringProvider.getString(R.string.sent_an_image), appendAuthor)
} }
MessageType.MSGTYPE_AUDIO -> { MessageType.MSGTYPE_AUDIO -> {
if ((messageContent as? MessageAudioContent)?.voiceMessageIndicator != null) { when {
simpleFormat(senderName, stringProvider.getString(R.string.sent_a_voice_message), appendAuthor) (messageContent as? MessageAudioContent)?.voiceMessageIndicator == null -> {
} else { simpleFormat(senderName, stringProvider.getString(R.string.sent_an_audio_file), appendAuthor)
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 -> { MessageType.MSGTYPE_VIDEO -> {

View File

@ -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
}
}

View File

@ -47,6 +47,7 @@ class NotificationDrawerManager @Inject constructor(
private val notifiableEventProcessor: NotifiableEventProcessor, private val notifiableEventProcessor: NotifiableEventProcessor,
private val notificationRenderer: NotificationRenderer, private val notificationRenderer: NotificationRenderer,
private val notificationEventPersistence: NotificationEventPersistence, private val notificationEventPersistence: NotificationEventPersistence,
private val filteredEventDetector: FilteredEventDetector,
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
) { ) {
@ -100,6 +101,11 @@ class NotificationDrawerManager @Inject constructor(
Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}") Timber.d("onNotifiableEventReceived(): is push: ${notifiableEvent.canBeReplaced}")
} }
if (filteredEventDetector.shouldBeIgnored(notifiableEvent)) {
Timber.d("onNotifiableEventReceived(): ignore the event")
return
}
add(notifiableEvent) add(notifiableEvent)
} }