diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/AsyncTransaction.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/AsyncTransaction.kt index 36e68e5cf3..af98f94146 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/AsyncTransaction.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/AsyncTransaction.kt @@ -20,14 +20,20 @@ import io.realm.RealmConfiguration import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.isActive import kotlinx.coroutines.withContext +import timber.log.Timber +import java.lang.RuntimeException suspend fun awaitTransaction(config: RealmConfiguration, transaction: suspend (realm: Realm) -> Unit) = withContext(Dispatchers.IO) { Realm.getInstance(config).use { bgRealm -> bgRealm.beginTransaction() try { + val start = System.currentTimeMillis() transaction(bgRealm) if (isActive) { bgRealm.commitTransaction() + val end = System.currentTimeMillis() + val time = end - start + Timber.v("Execute transaction in $time millis") } } finally { if (bgRealm.isInTransaction) { @@ -35,4 +41,5 @@ suspend fun awaitTransaction(config: RealmConfiguration, transaction: suspend (r } } } + } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt index 0b18279aa8..070960fb91 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomAvatarResolver.kt @@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.RoomAvatarContent import im.vector.matrix.android.api.session.room.model.RoomMember +import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntityFields @@ -41,8 +42,8 @@ internal class RoomAvatarResolver @Inject constructor(private val monarchy: Mona fun resolve(roomId: String): String? { var res: String? = null monarchy.doWithRealm { realm -> - val roomName = EventEntity.where(realm, roomId, EventType.STATE_ROOM_AVATAR).prev()?.asDomain() - res = roomName?.content.toModel()?.avatarUrl + val roomName = EventEntity.where(realm, roomId, EventType.STATE_ROOM_AVATAR).prev() + res = ContentMapper.map(roomName?.content).toModel()?.avatarUrl if (!res.isNullOrEmpty()) { return@doWithRealm } @@ -60,6 +61,6 @@ internal class RoomAvatarResolver @Inject constructor(private val monarchy: Mona } private fun EventEntity?.toRoomMember(): RoomMember? { - return this?.asDomain()?.content?.toModel() + return ContentMapper.map(this?.content).toModel() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt index 0d28720ec6..44794e307e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryUpdater.kt @@ -21,6 +21,7 @@ import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.RoomTopicContent +import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntityFields @@ -65,8 +66,10 @@ internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId roomId: String, membership: Membership? = null, roomSummary: RoomSyncSummary? = null, - unreadNotifications: RoomSyncUnreadNotifications? = null) { - val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) + unreadNotifications: RoomSyncUnreadNotifications? = null, + updateMembers: Boolean = false) { + val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst() + ?: realm.createObject(roomId) if (roomSummary != null) { if (roomSummary.heroes.isNotEmpty()) { @@ -88,24 +91,30 @@ internal class RoomSummaryUpdater @Inject constructor(@UserId private val userId } val latestPreviewableEvent = TimelineEventEntity.latestEvent(realm, roomId, includesSending = true, filterTypes = PREVIEWABLE_TYPES) - val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev()?.asDomain() + val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev() roomSummaryEntity.hasUnreadMessages = roomSummaryEntity.notificationCount > 0 - // avoid this call if we are sure there are unread events - || !isEventRead(monarchy, userId, roomId, latestPreviewableEvent?.eventId) + // avoid this call if we are sure there are unread events + || !isEventRead(monarchy, userId, roomId, latestPreviewableEvent?.eventId) - val otherRoomMembers = RoomMembers(realm, roomId) - .queryRoomMembersEvent() - .notEqualTo(EventEntityFields.STATE_KEY, userId) - .findAll() - .asSequence() - .map { it.stateKey } roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(roomId).toString() roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(roomId) - roomSummaryEntity.topic = lastTopicEvent?.content.toModel()?.topic + roomSummaryEntity.topic = ContentMapper.map(lastTopicEvent?.content).toModel()?.topic roomSummaryEntity.latestPreviewableEvent = latestPreviewableEvent - roomSummaryEntity.otherMemberIds.clear() - roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers) + + if (updateMembers) { + val otherRoomMembers = RoomMembers(realm, roomId) + .queryRoomMembersEvent() + .notEqualTo(EventEntityFields.STATE_KEY, userId) + .findAll() + .asSequence() + .map { it.stateKey } + + roomSummaryEntity.otherMemberIds.clear() + roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers) + } + + } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt index d952915d2c..7d9332ee84 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/LoadRoomMembersTask.kt @@ -74,7 +74,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(private val roomAP it.updateSenderData() } roomEntity.areAllMembersLoaded = true - roomSummaryUpdater.update(realm, roomId) + roomSummaryUpdater.update(realm, roomId, updateMembers = true) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomDisplayNameResolver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomDisplayNameResolver.kt index 965bd21cf4..365bde749a 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomDisplayNameResolver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomDisplayNameResolver.kt @@ -22,6 +22,7 @@ import im.vector.matrix.android.R import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel import im.vector.matrix.android.api.session.room.model.* +import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntityFields @@ -56,20 +57,20 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context: var name: CharSequence? = null monarchy.doWithRealm { realm -> val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() - val roomName = EventEntity.where(realm, roomId, EventType.STATE_ROOM_NAME).prev()?.asDomain() - name = roomName?.content.toModel()?.name + val roomName = EventEntity.where(realm, roomId, EventType.STATE_ROOM_NAME).prev() + name = ContentMapper.map(roomName?.content).toModel()?.name if (!name.isNullOrEmpty()) { return@doWithRealm } - val canonicalAlias = EventEntity.where(realm, roomId, EventType.STATE_CANONICAL_ALIAS).prev()?.asDomain() - name = canonicalAlias?.content.toModel()?.canonicalAlias + val canonicalAlias = EventEntity.where(realm, roomId, EventType.STATE_CANONICAL_ALIAS).prev() + name = ContentMapper.map(canonicalAlias?.content).toModel()?.canonicalAlias if (!name.isNullOrEmpty()) { return@doWithRealm } - val aliases = EventEntity.where(realm, roomId, EventType.STATE_ROOM_ALIASES).prev()?.asDomain() - name = aliases?.content.toModel()?.aliases?.firstOrNull() + val aliases = EventEntity.where(realm, roomId, EventType.STATE_ROOM_ALIASES).prev() + name = ContentMapper.map(aliases?.content).toModel()?.aliases?.firstOrNull() if (!name.isNullOrEmpty()) { return@doWithRealm } @@ -132,6 +133,6 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context: } private fun EventEntity?.toRoomMember(): RoomMember? { - return this?.asDomain()?.content?.toModel() + return ContentMapper.map(this?.content).toModel() } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index 5fb25834c0..4a003eb7d9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -67,6 +67,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch } suspend fun handle(roomsSyncResponse: RoomsSyncResponse, isInitialSync: Boolean, reporter: DefaultInitialSyncProgressService? = null) { + Timber.v("Execute transaction from $this") monarchy.awaitTransaction { realm -> handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), isInitialSync, reporter) handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), isInitialSync, reporter) @@ -133,6 +134,7 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch roomEntity.membership = Membership.JOIN // State event + if (roomSync.state != null && roomSync.state.events.isNotEmpty()) { val minStateIndex = roomEntity.untimelinedStateEvents.where().min(EventEntityFields.STATE_INDEX)?.toInt() ?: Int.MIN_VALUE @@ -146,7 +148,6 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch } } } - if (roomSync.timeline != null && roomSync.timeline.events.isNotEmpty()) { val chunkEntity = handleTimelineEvents( realm, @@ -157,14 +158,19 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch ) roomEntity.addOrUpdate(chunkEntity) } - roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications) + val hasRoomMember = roomSync.state?.events?.firstOrNull { + it.type == EventType.STATE_ROOM_MEMBER + } != null || roomSync.timeline?.events?.firstOrNull { + it.type == EventType.STATE_ROOM_MEMBER + } != null + + roomSummaryUpdater.update(realm, roomId, Membership.JOIN, roomSync.summary, roomSync.unreadNotifications, updateMembers = hasRoomMember) return roomEntity } private fun handleInvitedRoom(realm: Realm, roomId: String, - roomSync: - InvitedRoomSync): RoomEntity { + roomSync: InvitedRoomSync): RoomEntity { Timber.v("Handle invited sync for room $roomId") val roomEntity = RoomEntity.where(realm, roomId).findFirst() ?: realm.createObject(roomId) roomEntity.membership = Membership.INVITE @@ -172,7 +178,10 @@ internal class RoomSyncHandler @Inject constructor(private val monarchy: Monarch val chunkEntity = handleTimelineEvents(realm, roomEntity, roomSync.inviteState.events) roomEntity.addOrUpdate(chunkEntity) } - roomSummaryUpdater.update(realm, roomId, Membership.INVITE) + val hasRoomMember = roomSync.inviteState?.events?.firstOrNull { + it.type == EventType.STATE_ROOM_MEMBER + } != null + roomSummaryUpdater.update(realm, roomId, Membership.INVITE, updateMembers = hasRoomMember) return roomEntity }