Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Voice Broadcast - Update last message in the room list #7719

Merged
merged 11 commits into from
Dec 14, 2022
1 change: 1 addition & 0 deletions changelog.d/7719.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Voice Broadcast - Update last message in the room list
4 changes: 4 additions & 0 deletions library/ui-strings/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@
<string name="notice_crypto_unable_to_decrypt">** Unable to decrypt: %s **</string>
<string name="notice_crypto_error_unknown_inbound_session_id">The sender\'s device has not sent us the keys for this message.</string>

<string name="notice_voice_broadcast_ended">%1$s ended a voice broadcast.</string>
<string name="notice_voice_broadcast_ended_by_you">You ended a voice broadcast.</string>

<!-- Messages -->

<!-- Room Screen -->
Expand Down Expand Up @@ -3101,6 +3104,7 @@
<string name="audio_message_file_size">(%1$s)</string>

<string name="voice_broadcast_live">Live</string>
<string name="voice_broadcast_live_broadcast">Live broadcast</string>
<!-- TODO Rename id to voice_broadcast_buffering -->
<string name="a11y_voice_broadcast_buffering">Buffering…</string>
<string name="a11y_resume_voice_broadcast_record">Resume voice broadcast record</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package org.matrix.android.sdk.common

import org.matrix.android.sdk.api.RoomDisplayNameFallbackProvider
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider

class TestRoomDisplayNameFallbackProvider : RoomDisplayNameFallbackProvider {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import okhttp3.ConnectionSpec
import okhttp3.Interceptor
import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import org.matrix.android.sdk.api.metrics.MetricPlugin
import org.matrix.android.sdk.api.provider.CustomEventTypesProvider
import org.matrix.android.sdk.api.provider.MatrixItemDisplayNameFallbackProvider
import org.matrix.android.sdk.api.provider.RoomDisplayNameFallbackProvider
import java.net.Proxy

data class MatrixConfiguration(
Expand Down Expand Up @@ -75,9 +78,12 @@ data class MatrixConfiguration(
* Sync configuration.
*/
val syncConfig: SyncConfig = SyncConfig(),

/**
* Metrics plugin that can be used to capture metrics from matrix-sdk-android.
*/
val metricPlugins: List<MetricPlugin> = emptyList()
val metricPlugins: List<MetricPlugin> = emptyList(),
/**
* CustomEventTypesProvider to provide custom event types to the sdk which should be processed with internal events.
*/
val customEventTypesProvider: CustomEventTypesProvider? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright 2022 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.provider

import org.matrix.android.sdk.api.session.room.model.RoomSummary

/**
* Provide custom event types which should be processed with the internal event types.
*/
interface CustomEventTypesProvider {

/**
* Custom event types to include when computing [RoomSummary.latestPreviewableEvent].
*/
val customPreviewableEventTypes: List<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.matrix.android.sdk.api
package org.matrix.android.sdk.api.provider

import org.matrix.android.sdk.api.util.MatrixItem

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.matrix.android.sdk.api
package org.matrix.android.sdk.api.provider

/**
* This interface exists to let the implementation provide localized room display name fallback.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import io.realm.RealmQuery
import io.realm.RealmResults
import io.realm.Sort
import io.realm.kotlin.where
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.room.send.SendState
import org.matrix.android.sdk.api.session.room.timeline.TimelineEventFilters
import org.matrix.android.sdk.internal.database.model.ChunkEntity
Expand Down Expand Up @@ -94,14 +95,27 @@ internal fun RealmQuery<TimelineEventEntity>.filterEvents(filters: TimelineEvent
if (filters.filterTypes && filters.allowedTypes.isNotEmpty()) {
beginGroup()
filters.allowedTypes.forEachIndexed { index, filter ->
if (filter.stateKey == null) {
equalTo(TimelineEventEntityFields.ROOT.TYPE, filter.eventType)
if (filter.eventType == EventType.ENCRYPTED) {
val otherTypes = filters.allowedTypes.minus(filter).map { it.eventType }
if (filter.stateKey == null) {
filterEncryptedTypes(otherTypes)
} else {
beginGroup()
filterEncryptedTypes(otherTypes)
and()
equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, filter.stateKey)
endGroup()
}
} else {
beginGroup()
equalTo(TimelineEventEntityFields.ROOT.TYPE, filter.eventType)
and()
equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, filter.stateKey)
endGroup()
if (filter.stateKey == null) {
equalTo(TimelineEventEntityFields.ROOT.TYPE, filter.eventType)
} else {
beginGroup()
equalTo(TimelineEventEntityFields.ROOT.TYPE, filter.eventType)
and()
equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, filter.stateKey)
endGroup()
}
}
if (index != filters.allowedTypes.size - 1) {
or()
Expand All @@ -115,7 +129,6 @@ internal fun RealmQuery<TimelineEventEntity>.filterEvents(filters: TimelineEvent
if (filters.filterEdits) {
not().like(TimelineEventEntityFields.ROOT.CONTENT, TimelineEventFilter.Content.EDIT)
not().like(TimelineEventEntityFields.ROOT.CONTENT, TimelineEventFilter.Content.RESPONSE)
not().like(TimelineEventEntityFields.ROOT.CONTENT, TimelineEventFilter.Content.REFERENCE)
}
if (filters.filterRedacted) {
not().like(TimelineEventEntityFields.ROOT.UNSIGNED_DATA, TimelineEventFilter.Unsigned.REDACTED)
Expand All @@ -124,6 +137,21 @@ internal fun RealmQuery<TimelineEventEntity>.filterEvents(filters: TimelineEvent
return this
}

internal fun RealmQuery<TimelineEventEntity>.filterEncryptedTypes(allowedTypes: List<String>): RealmQuery<TimelineEventEntity> {
beginGroup()
equalTo(TimelineEventEntityFields.ROOT.TYPE, EventType.ENCRYPTED)
and()
beginGroup()
isNull(TimelineEventEntityFields.ROOT.DECRYPTION_RESULT_JSON)
allowedTypes.forEach { eventType ->
or()
like(TimelineEventEntityFields.ROOT.DECRYPTION_RESULT_JSON, TimelineEventFilter.DecryptedContent.type(eventType))
}
endGroup()
endGroup()
return this
}

internal fun RealmQuery<TimelineEventEntity>.filterTypes(filterTypes: List<String>): RealmQuery<TimelineEventEntity> {
return if (filterTypes.isEmpty()) {
this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ internal object TimelineEventFilter {
*/
internal object DecryptedContent {
internal const val URL = """{*"file":*"url":*}"""
fun type(type: String) = """{*"type":*"$type"*}"""
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,23 @@
package org.matrix.android.sdk.internal.session.room.summary

import io.realm.Realm
import org.matrix.android.sdk.api.MatrixConfiguration
import org.matrix.android.sdk.api.session.room.summary.RoomSummaryConstants
import org.matrix.android.sdk.api.session.room.timeline.EventTypeFilter
import org.matrix.android.sdk.api.session.room.timeline.TimelineEventFilters
import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
import org.matrix.android.sdk.internal.database.query.latestEvent
import javax.inject.Inject

internal object RoomSummaryEventsHelper {
internal class RoomSummaryEventsHelper @Inject constructor(
matrixConfiguration: MatrixConfiguration,
) {

private val previewFilters = TimelineEventFilters(
filterTypes = true,
allowedTypes = RoomSummaryConstants.PREVIEWABLE_TYPES.map { EventTypeFilter(eventType = it, stateKey = null) },
allowedTypes = RoomSummaryConstants.PREVIEWABLE_TYPES
.plus(matrixConfiguration.customEventTypesProvider?.customPreviewableEventTypes.orEmpty())
.map { EventTypeFilter(eventType = it, stateKey = null) },
filterUseless = true,
filterRedacted = false,
filterEdits = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ internal class RoomSummaryUpdater @Inject constructor(
private val crossSigningService: DefaultCrossSigningService,
private val roomAccountDataDataSource: RoomAccountDataDataSource,
private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
private val roomSummaryEventsHelper: RoomSummaryEventsHelper,
) {

fun refreshLatestPreviewContent(realm: Realm, roomId: String) {
val roomSummaryEntity = RoomSummaryEntity.getOrNull(realm, roomId)
if (roomSummaryEntity != null) {
val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
val latestPreviewableEvent = roomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
latestPreviewableEvent?.attemptToDecrypt()
}
}
Expand Down Expand Up @@ -145,7 +146,7 @@ internal class RoomSummaryUpdater @Inject constructor(
val encryptionEvent = CurrentStateEventEntity.getOrNull(realm, roomId, type = EventType.STATE_ROOM_ENCRYPTION, stateKey = "")?.root
Timber.d("## CRYPTO: currentEncryptionEvent is $encryptionEvent")

val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
val latestPreviewableEvent = roomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)

val lastActivityFromEvent = latestPreviewableEvent?.root?.originServerTs
if (lastActivityFromEvent != null) {
Expand Down Expand Up @@ -231,7 +232,7 @@ internal class RoomSummaryUpdater @Inject constructor(
fun updateSendingInformation(realm: Realm, roomId: String) {
val roomSummaryEntity = RoomSummaryEntity.getOrCreate(realm, roomId)
roomSummaryEntity.updateHasFailedSending()
roomSummaryEntity.latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
roomSummaryEntity.latestPreviewableEvent = roomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import im.vector.app.features.analytics.AnalyticsTracker
import im.vector.app.features.analytics.VectorAnalytics
import im.vector.app.features.analytics.impl.DefaultVectorAnalytics
import im.vector.app.features.analytics.metrics.VectorPlugins
import im.vector.app.features.configuration.VectorCustomEventTypesProvider
import im.vector.app.features.invite.AutoAcceptInvites
import im.vector.app.features.invite.CompileTimeAutoAcceptInvites
import im.vector.app.features.navigation.DefaultNavigator
Expand Down Expand Up @@ -141,6 +142,7 @@ import javax.inject.Singleton
vectorRoomDisplayNameFallbackProvider: VectorRoomDisplayNameFallbackProvider,
flipperProxy: FlipperProxy,
vectorPlugins: VectorPlugins,
vectorCustomEventTypesProvider: VectorCustomEventTypesProvider,
): MatrixConfiguration {
return MatrixConfiguration(
applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
Expand All @@ -150,6 +152,7 @@ import javax.inject.Singleton
flipperProxy.networkInterceptor(),
),
metricPlugins = vectorPlugins.plugins(),
customEventTypesProvider = vectorCustomEventTypesProvider,
)
}

Expand Down
6 changes: 3 additions & 3 deletions vector/src/main/java/im/vector/app/core/di/VoiceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import im.vector.app.features.voicebroadcast.listening.VoiceBroadcastPlayer
import im.vector.app.features.voicebroadcast.listening.VoiceBroadcastPlayerImpl
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder
import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorderQ
import im.vector.app.features.voicebroadcast.usecase.GetMostRecentVoiceBroadcastStateEventUseCase
import im.vector.app.features.voicebroadcast.usecase.GetVoiceBroadcastStateEventLiveUseCase
import javax.inject.Singleton

@InstallIn(SingletonComponent::class)
Expand All @@ -40,13 +40,13 @@ abstract class VoiceModule {
fun providesVoiceBroadcastRecorder(
context: Context,
sessionHolder: ActiveSessionHolder,
getMostRecentVoiceBroadcastStateEventUseCase: GetMostRecentVoiceBroadcastStateEventUseCase,
getVoiceBroadcastStateEventLiveUseCase: GetVoiceBroadcastStateEventLiveUseCase,
): VoiceBroadcastRecorder? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
VoiceBroadcastRecorderQ(
context = context,
sessionHolder = sessionHolder,
getVoiceBroadcastEventUseCase = getMostRecentVoiceBroadcastStateEventUseCase
getVoiceBroadcastEventUseCase = getVoiceBroadcastStateEventLiveUseCase
)
} else {
null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2022 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.configuration

import im.vector.app.features.voicebroadcast.VoiceBroadcastConstants
import org.matrix.android.sdk.api.provider.CustomEventTypesProvider
import javax.inject.Inject

class VectorCustomEventTypesProvider @Inject constructor() : CustomEventTypesProvider {

override val customPreviewableEventTypes = listOf(
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package im.vector.app.features.displayname

import org.matrix.android.sdk.api.MatrixItemDisplayNameFallbackProvider
import org.matrix.android.sdk.api.provider.MatrixItemDisplayNameFallbackProvider
import org.matrix.android.sdk.api.util.MatrixItem

// Used to provide the fallback to the MatrixSDK, in the MatrixConfiguration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ import dagger.Lazy
import im.vector.app.EmojiSpanify
import im.vector.app.R
import im.vector.app.core.extensions.getVectorLastMessageContent
import im.vector.app.core.extensions.orEmpty
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.resources.DrawableProvider
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.model.asVoiceBroadcastEvent
import me.gujun.android.span.image
import me.gujun.android.span.span
import org.commonmark.node.Document
import org.matrix.android.sdk.api.session.events.model.Event
Expand All @@ -41,6 +47,7 @@ import javax.inject.Inject
class DisplayableEventFormatter @Inject constructor(
private val stringProvider: StringProvider,
private val colorProvider: ColorProvider,
private val drawableProvider: DrawableProvider,
private val emojiSpanify: EmojiSpanify,
private val noticeEventFormatter: NoticeEventFormatter,
private val htmlRenderer: Lazy<EventHtmlRenderer>
Expand Down Expand Up @@ -135,6 +142,9 @@ class DisplayableEventFormatter @Inject constructor(
in EventType.STATE_ROOM_BEACON_INFO.values -> {
simpleFormat(senderName, stringProvider.getString(R.string.sent_live_location), appendAuthor)
}
VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO -> {
formatVoiceBroadcastEvent(timelineEvent.root, isDm, senderName)
}
else -> {
span {
text = noticeEventFormatter.format(timelineEvent, isDm) ?: ""
Expand Down Expand Up @@ -252,4 +262,20 @@ class DisplayableEventFormatter @Inject constructor(
body
}
}

private fun formatVoiceBroadcastEvent(event: Event, isDm: Boolean, senderName: String): CharSequence {
return if (event.asVoiceBroadcastEvent()?.isLive == true) {
span {
drawableProvider.getDrawable(R.drawable.ic_voice_broadcast, colorProvider.getColor(R.color.palette_vermilion))?.let {
image(it)
+" "
}
span(stringProvider.getString(R.string.voice_broadcast_live_broadcast)) {
textColor = colorProvider.getColor(R.color.palette_vermilion)
}
}
} else {
noticeEventFormatter.format(event, senderName, isDm).orEmpty()
}
}
}
Loading