From 9b7e94ebab42111a4c47227ab0b2b3845990cc75 Mon Sep 17 00:00:00 2001 From: Eric Decanini Date: Wed, 13 Apr 2022 18:35:33 +0200 Subject: [PATCH] Fixes myroomnick changing Display Name (#5618) --- changelog.d/5618.bugfix | 1 + .../sdk/api/session/user/model/User.kt | 15 ++- .../matrix/android/sdk/api/util/MatrixItem.kt | 3 +- .../room/membership/LoadRoomMembersTask.kt | 2 +- .../room/membership/RoomMemberEventHandler.kt | 107 ++++++++++++++---- .../SyncResponsePostTreatmentAggregator.kt | 3 + ...cResponsePostTreatmentAggregatorHandler.kt | 41 ++++++- .../sync/handler/room/RoomSyncHandler.kt | 22 ++-- .../session/user/DefaultUserService.kt | 13 +-- .../session/user/UserEntityFactory.kt | 13 ++- .../RoomMemberProfileViewModel.kt | 17 +-- 11 files changed, 171 insertions(+), 66 deletions(-) create mode 100644 changelog.d/5618.bugfix diff --git a/changelog.d/5618.bugfix b/changelog.d/5618.bugfix new file mode 100644 index 0000000000..8a839a2b4e --- /dev/null +++ b/changelog.d/5618.bugfix @@ -0,0 +1 @@ +Fixes display name being changed when using /myroomnick diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt index 54ae9e54f6..79c86f3f23 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt @@ -16,6 +16,9 @@ package org.matrix.android.sdk.api.session.user.model +import org.matrix.android.sdk.api.session.profile.ProfileService +import org.matrix.android.sdk.api.util.JsonDict + /** * Data class which holds information about a user. * It can be retrieved with [org.matrix.android.sdk.api.session.user.UserService] @@ -27,4 +30,14 @@ data class User( */ val displayName: String? = null, val avatarUrl: String? = null -) +) { + + companion object { + + fun fromJson(userId: String, json: JsonDict) = User( + userId = userId, + displayName = json[ProfileService.DISPLAY_NAME_KEY] as? String, + avatarUrl = json[ProfileService.AVATAR_URL_KEY] as? String + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt index 650b8cc26d..4f5f4f82d9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt @@ -37,6 +37,7 @@ sealed class MatrixItem( override val displayName: String? = null, override val avatarUrl: String? = null) : MatrixItem(id, displayName?.removeSuffix(IRC_PATTERN), avatarUrl) { + init { if (BuildConfig.DEBUG) checkId() } @@ -200,7 +201,7 @@ fun RoomMemberSummary.toMatrixItem() = MatrixItem.UserItem(userId, displayName, fun SenderInfo.toMatrixItem() = MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl) -fun SenderInfo.toMatrixItemOrNull() = tryOrNull { MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl) } +fun SenderInfo.toMatrixItemOrNull() = tryOrNull { MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl) } fun SpaceChildInfo.toMatrixItem() = if (roomType == RoomType.SPACE) { MatrixItem.SpaceItem(childRoomId, name ?: canonicalAlias, avatarUrl) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt index 3d0f51b831..70ba9287a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt @@ -123,7 +123,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor( eventId = roomMemberEvent.eventId root = eventEntity } - roomMemberEventHandler.handle(realm, roomId, roomMemberEvent) + roomMemberEventHandler.handle(realm, roomId, roomMemberEvent, false) } roomEntity.membersLoadStatus = RoomMembersLoadStatusType.LOADED roomSummaryUpdater.update(realm, roomId, updateMembers = true) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt index 25c124bd6b..85300fa351 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.session.room.membership import io.realm.Realm +import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.room.model.RoomMemberContent @@ -33,23 +34,49 @@ internal class RoomMemberEventHandler @Inject constructor( @UserId private val myUserId: String ) { - fun handle(realm: Realm, roomId: String, event: Event, aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean { + fun handle(realm: Realm, + roomId: String, + event: Event, + isInitialSync: Boolean, + aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean { if (event.type != EventType.STATE_ROOM_MEMBER) { return false } - val userId = event.stateKey ?: return false - val roomMember = event.getFixedRoomMemberContent() - return handle(realm, roomId, userId, roomMember, aggregator) + val eventUserId = event.stateKey ?: return false + val roomMember = event.getFixedRoomMemberContent() ?: return false + + return if (isInitialSync) { + handleInitialSync(realm, roomId, myUserId, eventUserId, roomMember, aggregator) + } else { + handleIncrementalSync( + realm, + roomId, + eventUserId, + roomMember, + event.resolvedPrevContent(), + aggregator + ) + } } - fun handle(realm: Realm, - roomId: String, - userId: String, - roomMember: RoomMemberContent?, - aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean { - if (roomMember == null) { - return false + private fun handleInitialSync(realm: Realm, + roomId: String, + currentUserId: String, + eventUserId: String, + roomMember: RoomMemberContent, + aggregator: SyncResponsePostTreatmentAggregator?): Boolean { + if (currentUserId != eventUserId) { + saveUserEntityLocallyIfNecessary(realm, eventUserId, roomMember) } + saveRoomMemberEntityLocally(realm, roomId, eventUserId, roomMember) + updateDirectChatsIfNecessary(roomId, roomMember, aggregator) + return true + } + + private fun saveRoomMemberEntityLocally(realm: Realm, + roomId: String, + userId: String, + roomMember: RoomMemberContent) { val roomMemberEntity = RoomMemberEntityFactory.create( roomId, userId, @@ -58,26 +85,58 @@ internal class RoomMemberEventHandler @Inject constructor( // but we want to preserve presence record value and not replace it with null getExistingPresenceState(realm, roomId, userId)) realm.insertOrUpdate(roomMemberEntity) - if (roomMember.membership.isActive()) { - val userEntity = UserEntityFactory.create(userId, roomMember) - realm.insertOrUpdate(userEntity) - } - - // check whether this new room member event may be used to update the directs dictionary in account data - // this is required to handle correctly invite by email in DM - val mxId = roomMember.thirdPartyInvite?.signed?.mxid - if (mxId != null && mxId != myUserId) { - aggregator?.directChatsToCheck?.put(roomId, mxId) - } - return true } /** * Get the already existing presence state for a specific user & room in order NOT to be replaced in RoomMemberSummaryEntity * by NULL value. */ - private fun getExistingPresenceState(realm: Realm, roomId: String, userId: String): UserPresenceEntity? { return RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()?.userPresenceEntity } + + private fun saveUserEntityLocallyIfNecessary(realm: Realm, + userId: String, + roomMember: RoomMemberContent) { + if (roomMember.membership.isActive()) { + saveUserLocally(realm, userId, roomMember) + } + } + + private fun saveUserLocally(realm: Realm, userId: String, roomMember: RoomMemberContent) { + val userEntity = UserEntityFactory.create(userId, roomMember) + realm.insertOrUpdate(userEntity) + } + + private fun updateDirectChatsIfNecessary(roomId: String, + roomMember: RoomMemberContent, + aggregator: SyncResponsePostTreatmentAggregator?) { + // check whether this new room member event may be used to update the directs dictionary in account data + // this is required to handle correctly invite by email in DM + val mxId = roomMember.thirdPartyInvite?.signed?.mxid + if (mxId != null && mxId != myUserId) { + aggregator?.directChatsToCheck?.put(roomId, mxId) + } + } + + private fun handleIncrementalSync(realm: Realm, + roomId: String, + eventUserId: String, + roomMember: RoomMemberContent, + prevContent: Content?, + aggregator: SyncResponsePostTreatmentAggregator?): Boolean { + if (aggregator != null) { + val previousDisplayName = prevContent?.get("displayname") as? String + val previousAvatar = prevContent?.get("avatar_url") as? String + + if (previousDisplayName != roomMember.displayName || previousAvatar != roomMember.avatarUrl) { + aggregator.userIdsToFetch.add(eventUserId) + } + } + + saveRoomMemberEntityLocally(realm, roomId, eventUserId, roomMember) + // At the end of the sync, fetch all the profiles from the aggregator + updateDirectChatsIfNecessary(roomId, roomMember, aggregator) + return true + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt index fe44531390..e9452c59fc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt @@ -22,4 +22,7 @@ internal class SyncResponsePostTreatmentAggregator { // Map of roomId to directUserId val directChatsToCheck = mutableMapOf() + + // List of userIds to fetch and update at the end of incremental syncs + val userIdsToFetch = mutableListOf() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt index 1e0e87a450..25de05602a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt @@ -16,10 +16,16 @@ package org.matrix.android.sdk.internal.session.sync.handler +import com.zhuinden.monarchy.Monarchy import org.matrix.android.sdk.api.MatrixPatterns +import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.user.model.User +import org.matrix.android.sdk.internal.di.SessionDatabase +import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask import org.matrix.android.sdk.internal.session.sync.RoomSyncEphemeralTemporaryStore import org.matrix.android.sdk.internal.session.sync.SyncResponsePostTreatmentAggregator import org.matrix.android.sdk.internal.session.sync.model.accountdata.toMutable +import org.matrix.android.sdk.internal.session.user.UserEntityFactory import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask import javax.inject.Inject @@ -27,11 +33,14 @@ import javax.inject.Inject internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor( private val directChatsHelper: DirectChatsHelper, private val ephemeralTemporaryStore: RoomSyncEphemeralTemporaryStore, - private val updateUserAccountDataTask: UpdateUserAccountDataTask + private val updateUserAccountDataTask: UpdateUserAccountDataTask, + private val getProfileInfoTask: GetProfileInfoTask, + @SessionDatabase private val monarchy: Monarchy, ) { - suspend fun handle(synResHaResponsePostTreatmentAggregator: SyncResponsePostTreatmentAggregator) { - cleanupEphemeralFiles(synResHaResponsePostTreatmentAggregator.ephemeralFilesToDelete) - updateDirectUserIds(synResHaResponsePostTreatmentAggregator.directChatsToCheck) + suspend fun handle(aggregator: SyncResponsePostTreatmentAggregator) { + cleanupEphemeralFiles(aggregator.ephemeralFilesToDelete) + updateDirectUserIds(aggregator.directChatsToCheck) + fetchAndUpdateUsers(aggregator.userIdsToFetch) } private fun cleanupEphemeralFiles(ephemeralFilesToDelete: List) { @@ -59,13 +68,33 @@ internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor( } // remove roomId from currentDirectUserId entry - hasUpdate = hasUpdate or(directChats[currentDirectUserId]?.remove(roomId) == true) + hasUpdate = hasUpdate or (directChats[currentDirectUserId]?.remove(roomId) == true) // remove currentDirectUserId entry if there is no attached room anymore - hasUpdate = hasUpdate or(directChats.takeIf { it[currentDirectUserId].isNullOrEmpty() }?.remove(currentDirectUserId) != null) + hasUpdate = hasUpdate or (directChats.takeIf { it[currentDirectUserId].isNullOrEmpty() }?.remove(currentDirectUserId) != null) } } if (hasUpdate) { updateUserAccountDataTask.execute(UpdateUserAccountDataTask.DirectChatParams(directMessages = directChats)) } } + + private suspend fun fetchAndUpdateUsers(userIdsToFetch: List) { + fetchUsers(userIdsToFetch) + .takeIf { it.isNotEmpty() } + ?.saveLocally() + } + + private suspend fun fetchUsers(userIdsToFetch: List) = userIdsToFetch.mapNotNull { + tryOrNull { + val profileJson = getProfileInfoTask.execute(GetProfileInfoTask.Params(it)) + User.fromJson(it, profileJson) + } + } + + private fun List.saveLocally() { + val userEntities = map { user -> UserEntityFactory.create(user) } + monarchy.doWithRealm { + it.insertOrUpdate(userEntities) + } + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt index 3a18092c42..afd8e1bb99 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt @@ -206,6 +206,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle syncLocalTimestampMillis: Long, aggregator: SyncResponsePostTreatmentAggregator): RoomEntity { Timber.v("Handle join sync for room $roomId") + val isInitialSync = insertType == EventInsertType.INITIAL_SYNC val ephemeralResult = (roomSync.ephemeral as? LazyRoomSyncEphemeral.Parsed) ?._roomSyncEphemeral @@ -240,7 +241,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle } // Give info to crypto module cryptoService.onStateEvent(roomId, event) - roomMemberEventHandler.handle(realm, roomId, event, aggregator) + roomMemberEventHandler.handle(realm, roomId, event, isInitialSync, aggregator) } } if (roomSync.timeline?.events?.isNotEmpty() == true) { @@ -282,6 +283,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle insertType: EventInsertType, syncLocalTimestampMillis: Long): RoomEntity { Timber.v("Handle invited sync for room $roomId") + val isInitialSync = insertType == EventInsertType.INITIAL_SYNC val roomEntity = RoomEntity.getOrCreate(realm, roomId) roomEntity.membership = Membership.INVITE if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) { @@ -295,7 +297,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle eventId = eventEntity.eventId root = eventEntity } - roomMemberEventHandler.handle(realm, roomId, event) + roomMemberEventHandler.handle(realm, roomId, event, isInitialSync) } } val inviterEvent = roomSync.inviteState?.events?.lastOrNull { @@ -311,6 +313,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle roomSync: RoomSync, insertType: EventInsertType, syncLocalTimestampMillis: Long): RoomEntity { + val isInitialSync = insertType == EventInsertType.INITIAL_SYNC val roomEntity = RoomEntity.getOrCreate(realm, roomId) for (event in roomSync.state?.events.orEmpty()) { if (event.eventId == null || event.stateKey == null || event.type == null) { @@ -322,7 +325,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle eventId = event.eventId root = eventEntity } - roomMemberEventHandler.handle(realm, roomId, event) + roomMemberEventHandler.handle(realm, roomId, event, isInitialSync) } for (event in roomSync.timeline?.events.orEmpty()) { if (event.eventId == null || event.senderId == null || event.type == null) { @@ -336,7 +339,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle root = eventEntity } if (event.type == EventType.STATE_ROOM_MEMBER) { - roomMemberEventHandler.handle(realm, roomEntity.roomId, event) + roomMemberEventHandler.handle(realm, roomEntity.roomId, event, isInitialSync) } } } @@ -380,11 +383,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle continue } - eventIds.add(event.eventId) - liveEventService.get().dispatchLiveEventReceived(event, roomId, insertType == EventInsertType.INITIAL_SYNC) - val isInitialSync = insertType == EventInsertType.INITIAL_SYNC + eventIds.add(event.eventId) + liveEventService.get().dispatchLiveEventReceived(event, roomId, isInitialSync) + if (event.isEncrypted() && !isInitialSync) { runBlocking { decryptIfNeeded(event, roomId) @@ -403,9 +406,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle root = eventEntity } if (event.type == EventType.STATE_ROOM_MEMBER) { - val fixedContent = event.getFixedRoomMemberContent() - roomMemberContentsByUser[event.stateKey] = fixedContent - roomMemberEventHandler.handle(realm, roomEntity.roomId, event.stateKey, fixedContent, aggregator) + roomMemberContentsByUser[event.stateKey] = event.getFixedRoomMemberContent() + roomMemberEventHandler.handle(realm, roomEntity.roomId, event, isInitialSync, aggregator) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt index 52b8cc3689..4ffc42e714 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt @@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.user import androidx.lifecycle.LiveData import androidx.paging.PagedList -import org.matrix.android.sdk.api.session.profile.ProfileService import org.matrix.android.sdk.api.session.user.UserService import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.util.Optional @@ -37,16 +36,10 @@ internal class DefaultUserService @Inject constructor(private val userDataSource } override suspend fun resolveUser(userId: String): User { - val known = getUser(userId) - if (known != null) { - return known - } else { + return getUser(userId) ?: run { val params = GetProfileInfoTask.Params(userId) - val data = getProfileInfoTask.execute(params) - return User( - userId, - data[ProfileService.DISPLAY_NAME_KEY] as? String, - data[ProfileService.AVATAR_URL_KEY] as? String) + val json = getProfileInfoTask.execute(params) + User.fromJson(userId, json) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt index 9a9458e84b..46ea7547b0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.session.user import org.matrix.android.sdk.api.session.room.model.RoomMemberContent +import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.internal.database.model.UserEntity internal object UserEntityFactory { @@ -24,8 +25,16 @@ internal object UserEntityFactory { fun create(userId: String, roomMember: RoomMemberContent): UserEntity { return UserEntity( userId = userId, - displayName = roomMember.displayName ?: "", - avatarUrl = roomMember.avatarUrl ?: "" + displayName = roomMember.displayName.orEmpty(), + avatarUrl = roomMember.avatarUrl.orEmpty() + ) + } + + fun create(user: User): UserEntity { + return UserEntity( + userId = user.userId, + displayName = user.displayName.orEmpty(), + avatarUrl = user.avatarUrl.orEmpty() ) } } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index 1f23fec327..4bcf9ef55d 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -55,7 +55,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.api.session.room.powerlevels.Role -import org.matrix.android.sdk.api.util.MatrixItem +import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.flow.flow @@ -112,8 +112,8 @@ class RoomMemberProfileViewModel @AssistedInject constructor( session.flow().liveUserCryptoDevices(initialState.userId) .map { Pair( - it.fold(true, { prev, dev -> prev && dev.isVerified }), - it.fold(true, { prev, dev -> prev && (dev.trustLevel?.crossSigningVerified == true) }) + it.fold(true) { prev, dev -> prev && dev.isVerified }, + it.fold(true) { prev, dev -> prev && (dev.trustLevel?.crossSigningVerified == true) } ) } .execute { it -> @@ -327,14 +327,9 @@ class RoomMemberProfileViewModel @AssistedInject constructor( private suspend fun fetchProfileInfo() { val result = runCatchingToAsync { - session.getProfileAsUser(initialState.userId) - .let { - MatrixItem.UserItem( - id = initialState.userId, - displayName = it.displayName, - avatarUrl = it.avatarUrl - ) - } + session.getProfile(initialState.userId) + .let { User.fromJson(initialState.userId, it) } + .toMatrixItem() } setState {