diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt index c691f7839b..2b575608f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt @@ -23,7 +23,9 @@ import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult +import org.matrix.android.sdk.api.session.events.model.EventType.IS_JITSI_CALL import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.room.model.JitsiEventContent import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent @@ -498,7 +500,7 @@ fun Event.getPollContent(): MessagePollContent? { return getClearContent().toModel() } -fun Event.isJitsiEvent() = this.getClearType() == EventType.STATE_ROOM_WIDGET_LEGACY +fun Event.isJitsiEvent() = content?.toModel()?.type == IS_JITSI_CALL && content.toModel()?.name == IS_JITSI_CALL fun Event.supportsNotification() = this.getClearType() in EventType.MESSAGE + EventType.POLL_START.values + EventType.POLL_END.values + EventType.STATE_ROOM_BEACON_INFO.values diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt index 170254078f..94e336679a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt @@ -108,6 +108,9 @@ object EventType { // Relation Events const val REACTION = "m.reaction" + // Jitsi call + const val IS_JITSI_CALL = "jitsi" + // Poll val POLL_START = StableUnstableId(stable = "m.poll.start", unstable = "org.matrix.msc3381.poll.start") val POLL_RESPONSE = StableUnstableId(stable = "m.poll.response", unstable = "org.matrix.msc3381.poll.response") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/JitsiEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/JitsiEventContent.kt new file mode 100644 index 0000000000..956c343ac9 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/JitsiEventContent.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * 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 org.matrix.android.sdk.api.session.room.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +/** + * Class representing the Jitsi call state event. + */ +@JsonClass(generateAdapter = true) +data class JitsiEventContent( + @Json(name = "type") val type: String? = null, + @Json(name = "name") val name: String? = null, +) diff --git a/vector-config/src/main/res/values/config-settings.xml b/vector-config/src/main/res/values/config-settings.xml index 90e24e71ff..6d83f32a04 100755 --- a/vector-config/src/main/res/values/config-settings.xml +++ b/vector-config/src/main/res/values/config-settings.xml @@ -51,7 +51,7 @@ false true false - true + false diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventProcessor.kt b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventProcessor.kt index 6e91ecef08..b63ec903a2 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventProcessor.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventProcessor.kt @@ -41,18 +41,29 @@ class NotifiableEventProcessor @Inject constructor( .also { Timber.d("notification message removed due to being read") } else -> KEEP } - is NotifiableJitsiEvent -> KEEP + is NotifiableJitsiEvent -> { + if (it.isReceived != true) { + KEEP + } else { + REMOVE + } + } is SimpleNotifiableEvent -> when (it.type) { EventType.REDACTION -> REMOVE else -> KEEP } } - ProcessedEvent(type, it) + + val updatedEvent = if (it is NotifiableJitsiEvent) it.updateReceivedStatus() else it + ProcessedEvent(type, updatedEvent) } val removedEventsDiff = renderedEvents.filter { renderedEvent -> queuedEvents.none { it.eventId == renderedEvent.event.eventId } - }.map { ProcessedEvent(REMOVE, it.event) } + }.map { + val updatedEvent = if (it.event is NotifiableJitsiEvent) it.event.updateReceivedStatus() else it.event + ProcessedEvent(REMOVE, updatedEvent) + } return removedEventsDiff + processedEvents } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt index cf63b946f7..e93411bc23 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt @@ -174,7 +174,8 @@ class NotifiableEventResolver @Inject constructor( ContentUrlResolver.ThumbnailMethod.SCALE ), matrixID = session.myUserId, - soundName = null + soundName = null, + isReceived = null, ) } else { null diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotifiableJitsiEvent.kt b/vector/src/main/java/im/vector/app/features/notifications/NotifiableJitsiEvent.kt index 90cf609105..ca43d31f31 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotifiableJitsiEvent.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotifiableJitsiEvent.kt @@ -37,6 +37,7 @@ data class NotifiableJitsiEvent( // This is used for >N notification, as the result of a smart reply val outGoingMessage: Boolean = false, val outGoingMessageFailed: Boolean = false, + var isReceived: Boolean? = null, override val isRedacted: Boolean = false, override val isUpdated: Boolean = false ) : NotifiableEvent { @@ -44,4 +45,12 @@ data class NotifiableJitsiEvent( val type: String = EventType.MESSAGE val description: String = body ?: "" val title: String = senderName ?: "" + + fun updateReceivedStatus() = this.copy( + isReceived = when (isReceived) { + null -> false + false -> true + true -> true + } + ) } diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationFactory.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationFactory.kt index 29851f6a62..5bef05bf75 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationFactory.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationFactory.kt @@ -30,14 +30,20 @@ class NotificationFactory @Inject constructor( fun Map.toNotifications(): List { return map { (roomId, events) -> + if (events.all { it.event.isReceived == true }) { + return emptyList() + } + + val eventToShow = events.first { it.event.isReceived == false } + JitsiNotification.IncomingCall( roomId = roomId, - eventId = events.firstOrNull()?.event?.eventId.orEmpty(), - roomName = events.firstOrNull()?.event?.roomName.orEmpty(), + eventId = eventToShow.event.eventId, + roomName = eventToShow.event.roomName.orEmpty(), notification = notificationUtils.buildIncomingJitsiCallNotification( - callId = events.firstOrNull()?.event?.eventId.orEmpty().ifEmpty { roomId }, + callId = eventToShow.event.eventId.ifEmpty { roomId }, signalingRoomId = roomId, - title = events.firstOrNull()?.event?.roomName.orEmpty(), + title = eventToShow.event.roomName.orEmpty(), fromBg = true, ) ) diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt b/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt index 0ab5e725ed..098d173413 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotificationRenderer.kt @@ -76,7 +76,7 @@ class NotificationRenderer @Inject constructor( jitsiNotifications.forEach { wrapper -> when (wrapper) { is JitsiNotification.IncomingCall -> { - Timber.d("Updating jitsi call notification ${wrapper.roomId} for room ${wrapper.roomName}") + Timber.d("Updating jitsi call notification ${wrapper.eventId} for room ${wrapper.roomName}") if (wrapper.eventId.isNotEmpty() || wrapper.roomId.isNotEmpty()) { val tag = wrapper.eventId.ifEmpty { wrapper.roomId } notificationDisplayer.showNotificationMessage(tag, JITSI_CALL_NOTIFICATION_ID, wrapper.notification) @@ -135,10 +135,7 @@ private fun List>.groupByType(): GroupedNotifica } is NotifiableJitsiEvent -> { val jitsiEvents = roomIdToJitsiEventMap.getOrPut(event.roomId) { ArrayList() } - val diffInMillis = System.currentTimeMillis() - (it.event as NotifiableJitsiEvent).timestamp - if (diffInMillis < 10000) { - jitsiEvents.add(it.castedToEventType()) - } + jitsiEvents.add(it.castedToEventType()) } is SimpleNotifiableEvent -> simpleEvents.add(it.castedToEventType()) }