From ced621d46963a11ed1a702974af1907c52f0c6ea Mon Sep 17 00:00:00 2001 From: Adam Brown <adampsbrown@gmail.com> Date: Thu, 27 Jan 2022 11:30:53 +0000 Subject: [PATCH] refreshing the room summaries when new crypto sessions are recieved - matches the same flow as the timeline by starting observing in the ViewModel init --- .../sdk/api/session/crypto/CryptoService.kt | 1 - .../sdk/api/session/room/RoomService.kt | 8 ++++ .../crypto/crosssigning/UpdateTrustWorker.kt | 2 +- .../query/RoomSummaryEntityQueries.kt | 4 ++ .../session/room/DefaultRoomService.kt | 21 ++++++++++ .../room/summary/RoomSummaryUpdater.kt | 42 ++++++++++++------- .../app/features/home/HomeDetailViewModel.kt | 9 ++++ 7 files changed, 70 insertions(+), 17 deletions(-) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index 65f69e17c9..a5b442dc4a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -140,7 +140,6 @@ interface CryptoService { fun getLiveCryptoDeviceInfo(userIds: List<String>): LiveData<List<CryptoDeviceInfo>> fun addNewSessionListener(newSessionListener: NewSessionListener) - fun removeSessionListener(listener: NewSessionListener) fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest> diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index aec358218b..c1c1a385b5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -242,4 +242,12 @@ interface RoomService { */ fun getFlattenRoomSummaryChildrenOfLive(spaceId: String?, memberships: List<Membership> = Membership.activeMemberships()): LiveData<List<RoomSummary>> + + /** + * Refreshes the RoomSummary LatestPreviewContent for the given @param roomId + * If the roomId is null, all rooms are updated + * + * This is useful for refreshing summary content with encrypted messages after receiving new room keys + */ + fun refreshJoinedRoomSummaryPreviews(roomId: String?) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt index 9325355d28..794ab04533 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt @@ -52,7 +52,7 @@ import timber.log.Timber import javax.inject.Inject internal class UpdateTrustWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker<UpdateTrustWorker.Params>(context, params, sessionManager, Params::class.java) { + SessionSafeCoroutineWorker<UpdateTrustWorker.Params>(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RoomSummaryEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RoomSummaryEntityQueries.kt index d1b05a4932..8993c36a30 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RoomSummaryEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/RoomSummaryEntityQueries.kt @@ -49,6 +49,10 @@ internal fun RoomSummaryEntity.Companion.getOrCreate(realm: Realm, roomId: Strin return where(realm, roomId).findFirst() ?: realm.createObject(roomId) } +internal fun RoomSummaryEntity.Companion.getOrNull(realm: Realm, roomId: String): RoomSummaryEntity? { + return where(realm, roomId).findFirst() +} + internal fun RoomSummaryEntity.Companion.getDirectRooms(realm: Realm, excludeRoomIds: Set<String>? = null): RealmResults<RoomSummaryEntity> { return RoomSummaryEntity.where(realm) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt index 1bc98015aa..c79c41069b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt @@ -20,6 +20,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.Transformations import androidx.paging.PagedList import com.zhuinden.monarchy.Monarchy +import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.RoomService @@ -32,6 +33,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.peeking.PeekResult +import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional @@ -51,6 +53,7 @@ import org.matrix.android.sdk.internal.session.room.peeking.PeekRoomTask import org.matrix.android.sdk.internal.session.room.peeking.ResolveRoomStateTask import org.matrix.android.sdk.internal.session.room.read.MarkAllRoomsReadTask import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource +import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater import org.matrix.android.sdk.internal.session.user.accountdata.UpdateBreadcrumbsTask import org.matrix.android.sdk.internal.util.fetchCopied import javax.inject.Inject @@ -69,6 +72,7 @@ internal class DefaultRoomService @Inject constructor( private val roomSummaryDataSource: RoomSummaryDataSource, private val roomChangeMembershipStateDataSource: RoomChangeMembershipStateDataSource, private val leaveRoomTask: LeaveRoomTask, + private val roomSummaryUpdater: RoomSummaryUpdater ) : RoomService { override suspend fun createRoom(createRoomParams: CreateRoomParams): String { @@ -92,6 +96,23 @@ internal class DefaultRoomService @Inject constructor( return roomSummaryDataSource.getRoomSummaries(queryParams, sortOrder) } + override fun refreshJoinedRoomSummaryPreviews(roomId: String?) { + val roomSummaries = getRoomSummaries(roomSummaryQueryParams { + if (roomId != null) { + this.roomId = QueryStringValue.Equals(roomId) + } + memberships = listOf(Membership.JOIN) + }) + + if (roomSummaries.isNotEmpty()) { + monarchy.runTransactionSync { realm -> + roomSummaries.forEach { + roomSummaryUpdater.refreshLatestPreviewContent(realm, it.roomId) + } + } + } + } + override fun getRoomSummariesLive(queryParams: RoomSummaryQueryParams, sortOrder: RoomSortOrder): LiveData<List<RoomSummary>> { return roomSummaryDataSource.getRoomSummariesLive(queryParams, sortOrder) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt index c9712c5721..c9d84b1b93 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt @@ -64,7 +64,6 @@ import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataD import org.matrix.android.sdk.internal.session.room.membership.RoomDisplayNameResolver import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper import org.matrix.android.sdk.internal.session.room.relationship.RoomChildRelationInfo -import org.matrix.android.sdk.internal.util.Normalizer import timber.log.Timber import javax.inject.Inject import kotlin.system.measureTimeMillis @@ -75,8 +74,16 @@ internal class RoomSummaryUpdater @Inject constructor( private val roomAvatarResolver: RoomAvatarResolver, private val eventDecryptor: EventDecryptor, private val crossSigningService: DefaultCrossSigningService, - private val roomAccountDataDataSource: RoomAccountDataDataSource, - private val normalizer: Normalizer) { + private val roomAccountDataDataSource: RoomAccountDataDataSource +) { + + fun refreshLatestPreviewContent(realm: Realm, roomId: String) { + val roomSummaryEntity = RoomSummaryEntity.getOrNull(realm, roomId) + if (roomSummaryEntity != null) { + val latestPreviewableEvent = RoomSummaryEventsHelper.getLatestPreviewableEvent(realm, roomId) + latestPreviewableEvent?.attemptToDecrypt() + } + } fun update(realm: Realm, roomId: String, @@ -128,6 +135,7 @@ internal class RoomSummaryUpdater @Inject constructor( val lastActivityFromEvent = latestPreviewableEvent?.root?.originServerTs if (lastActivityFromEvent != null) { roomSummaryEntity.lastActivityTime = lastActivityFromEvent + latestPreviewableEvent.attemptToDecrypt() } roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0 || @@ -161,18 +169,6 @@ internal class RoomSummaryUpdater @Inject constructor( } roomSummaryEntity.updateHasFailedSending() - val root = latestPreviewableEvent?.root - if (root?.type == EventType.ENCRYPTED && root.decryptionResultJson == null) { - Timber.v("Should decrypt ${latestPreviewableEvent.eventId}") - // mmm i want to decrypt now or is it ok to do it async? - tryOrNull { - runBlocking { - eventDecryptor.decryptEvent(root.asDomain(), "") - } - } - ?.let { root.setDecryptionResult(it) } - } - if (updateMembers) { val otherRoomMembers = RoomMemberHelper(realm, roomId) .queryActiveRoomMembersEvent() @@ -189,6 +185,22 @@ internal class RoomSummaryUpdater @Inject constructor( } } + private fun TimelineEventEntity.attemptToDecrypt() { + when (val root = this.root) { + null -> { + Timber.v("Decryption skipped due to missing root event $eventId") + } + else -> { + if (root.type == EventType.ENCRYPTED && root.decryptionResultJson == null) { + Timber.v("Should decrypt $eventId") + tryOrNull { + runBlocking { eventDecryptor.decryptEvent(root.asDomain(), "") } + }?.let { root.setDecryptionResult(it) } + } + } + } + } + private fun RoomSummaryEntity.updateHasFailedSending() { hasFailedSending = TimelineEventEntity.findAllInRoomWithSendStates(realm, roomId, SendState.HAS_FAILED_STATES).isNotEmpty() } diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt index 01d91f3edc..e70e7b8acb 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt @@ -54,6 +54,7 @@ import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.flow.flow +import org.matrix.android.sdk.internal.crypto.NewSessionListener import timber.log.Timber /** @@ -88,9 +89,16 @@ class HomeDetailViewModel @AssistedInject constructor( } } + private val refreshRoomSummariesOnCryptoSessionChange = object : NewSessionListener { + override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) { + session.refreshJoinedRoomSummaryPreviews(roomId) + } + } + init { observeSyncState() observeRoomGroupingMethod() + session.cryptoService().addNewSessionListener(refreshRoomSummariesOnCryptoSessionChange) observeRoomSummaries() updatePstnSupportFlag() observeDataStore() @@ -150,6 +158,7 @@ class HomeDetailViewModel @AssistedInject constructor( override fun onCleared() { super.onCleared() callManager.removeProtocolsCheckerListener(this) + session.cryptoService().removeSessionListener(refreshRoomSummariesOnCryptoSessionChange) } override fun onPSTNSupportUpdated() {