diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt index dbb94a91..2c9c7d8b 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxRoom.kt @@ -25,8 +25,8 @@ import io.reactivex.schedulers.Schedulers class RxRoom(private val room: Room) { - fun liveRoomSummary(fetchLastEvent: Boolean): Observable { - return room.liveRoomSummary(fetchLastEvent).asObservable().observeOn(Schedulers.computation()) + fun liveRoomSummary(): Observable { + return room.liveRoomSummary().asObservable().observeOn(Schedulers.computation()) } fun liveRoomMemberIds(): Observable> { diff --git a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt index 5fd76f0b..30d31f94 100644 --- a/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt +++ b/matrix-sdk-android-rx/src/main/java/im/vector/matrix/rx/RxSession.kt @@ -26,8 +26,8 @@ import io.reactivex.schedulers.Schedulers class RxSession(private val session: Session) { - fun liveRoomSummaries(fetchLastEvents: Boolean): Observable> { - return session.liveRoomSummaries(fetchLastEvents).asObservable().observeOn(Schedulers.computation()) + fun liveRoomSummaries(): Observable> { + return session.liveRoomSummaries().asObservable().observeOn(Schedulers.computation()) } fun liveGroupSummaries(): Observable> { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt index 35efa0fb..ec6b382f 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt @@ -47,8 +47,8 @@ interface Room : * A live [RoomSummary] associated with the room * You can observe this summary to get dynamic data from this room. */ - fun liveRoomSummary(fetchLastEvent: Boolean = false): LiveData + fun liveRoomSummary(): LiveData - fun roomSummary(fetchLastEvent: Boolean = false): RoomSummary? + fun roomSummary(): RoomSummary? } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt index 8fd6605f..fc0bf499 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/RoomService.kt @@ -43,6 +43,6 @@ interface RoomService { * Get a live list of room summaries. This list is refreshed as soon as the data changes. * @return the [LiveData] of [RoomSummary] */ - fun liveRoomSummaries(fetchLastEvents: Boolean = true): LiveData> + fun liveRoomSummaries(): LiveData> } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveData.kt index 238c0916..46a431a4 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveData.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/RealmLiveData.kt @@ -31,8 +31,7 @@ class RealmLiveData(private val realmConfiguration: RealmConfigu override fun onActive() { val realm = Realm.getInstance(realmConfiguration) - val results = query.invoke(realm).findAll() - value = results + val results = query.invoke(realm).findAllAsync() results.addChangeListener(listener) this.realm = realm this.results = results diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt index d5979723..b779ec08 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/ChunkEntityHelper.kt @@ -18,28 +18,17 @@ package im.vector.matrix.android.internal.database.helper import im.vector.matrix.android.api.session.events.model.Event 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.RoomMember import im.vector.matrix.android.api.session.room.send.SendState -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.mapper.toEntity import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity -import im.vector.matrix.android.internal.database.model.EventEntity -import im.vector.matrix.android.internal.database.model.EventEntityFields -import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.TimelineEventEntity import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields import im.vector.matrix.android.internal.database.query.find -import im.vector.matrix.android.internal.database.query.next -import im.vector.matrix.android.internal.database.query.prev import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.extensions.assertIsManaged -import im.vector.matrix.android.internal.session.room.membership.RoomMembers import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection -import io.realm.RealmList -import io.realm.RealmQuery import io.realm.Sort // By default if a chunk is empty we consider it unlinked @@ -76,10 +65,14 @@ internal fun ChunkEntity.merge(roomId: String, eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING) } val events = eventsToMerge.mapNotNull { it.root?.asDomain() } + val eventIds = ArrayList() events.forEach { event -> add(roomId, event, direction, isUnlinked = isUnlinked) + if (event.eventId != null) { + eventIds.add(event.eventId) + } } - updateSenderDataFor(roomId, isUnlinked, events) + updateSenderDataFor(eventIds) } internal fun ChunkEntity.addAll(roomId: String, @@ -89,30 +82,20 @@ internal fun ChunkEntity.addAll(roomId: String, // Set to true for Event retrieved from a Permalink (i.e. not linked to live Chunk) isUnlinked: Boolean = false) { assertIsManaged() + val eventIds = ArrayList() events.forEach { event -> add(roomId, event, direction, stateIndexOffset, isUnlinked) + if (event.eventId != null) { + eventIds.add(event.eventId) + } } - updateSenderDataFor(roomId, isUnlinked, events) + updateSenderDataFor(eventIds) } -private fun ChunkEntity.updateSenderDataFor(roomId: String, isUnlinked: Boolean, events: List) { - for (event in events) { - val eventId = event.eventId ?: continue +internal fun ChunkEntity.updateSenderDataFor(eventIds: List) { + for (eventId in eventIds) { val timelineEventEntity = timelineEvents.find(eventId) ?: continue - val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: continue - val stateIndex = timelineEventEntity.root?.stateIndex ?: continue - val senderId = timelineEventEntity.root?.sender ?: continue - - val senderRoomMemberContent = when { - stateIndex <= 0 -> timelineEvents.build(senderId, isUnlinked).next(from = stateIndex)?.root?.prevContent - else -> timelineEvents.build(senderId, isUnlinked).prev(since = stateIndex)?.root?.content - } - val fallbackContent = senderRoomMemberContent - ?: roomEntity.untimelinedStateEvents.build(senderId).prev(since = stateIndex)?.content - val senderRoomMember: RoomMember? = ContentMapper.map(fallbackContent).toModel() - timelineEventEntity.senderAvatar = senderRoomMember?.avatarUrl - timelineEventEntity.senderName = senderRoomMember?.displayName - timelineEventEntity.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(senderRoomMember?.displayName) + timelineEventEntity.updateSenderData() } } @@ -161,19 +144,6 @@ private fun ChunkEntity.add(roomId: String, timelineEvents.add(position, eventEntity) } -private fun RealmList.build(sender: String, isUnlinked: Boolean): RealmQuery { - return where() - .equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, sender) - .equalTo(TimelineEventEntityFields.ROOT.TYPE, EventType.STATE_ROOM_MEMBER) - .equalTo(TimelineEventEntityFields.ROOT.IS_UNLINKED, isUnlinked) -} - -private fun RealmList.build(sender: String): RealmQuery { - return where() - .equalTo(EventEntityFields.STATE_KEY, sender) - .equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER) -} - internal fun ChunkEntity.lastDisplayIndex(direction: PaginationDirection, defaultValue: Int = 0): Int { return when (direction) { PaginationDirection.FORWARDS -> forwardsDisplayIndex diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt index f694953e..c0d01ded 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/RoomEntityHelper.kt @@ -72,6 +72,7 @@ internal fun RoomEntity.addSendingEvent(event: Event) { it.senderName = myUser?.displayName it.senderAvatar = myUser?.avatarUrl it.isUniqueDisplayName = roomMembers.isUniqueDisplayName(myUser?.displayName) + it.senderMembershipEvent = roomMembers.queryRoomMemberEvent(senderId).findFirst() } sendingTimelineEvents.add(0, timelineEventEntity) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/TimelineEventEntityHelper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/TimelineEventEntityHelper.kt new file mode 100644 index 00000000..16a815b4 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/helper/TimelineEventEntityHelper.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2019 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.matrix.android.internal.database.helper + +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.RoomMember +import im.vector.matrix.android.internal.database.mapper.ContentMapper +import im.vector.matrix.android.internal.database.model.EventEntity +import im.vector.matrix.android.internal.database.model.EventEntityFields +import im.vector.matrix.android.internal.database.model.RoomEntity +import im.vector.matrix.android.internal.database.model.TimelineEventEntity +import im.vector.matrix.android.internal.database.model.TimelineEventEntityFields +import im.vector.matrix.android.internal.database.query.next +import im.vector.matrix.android.internal.database.query.prev +import im.vector.matrix.android.internal.database.query.where +import im.vector.matrix.android.internal.extensions.assertIsManaged +import im.vector.matrix.android.internal.session.room.membership.RoomMembers +import io.realm.RealmList +import io.realm.RealmQuery + +internal fun TimelineEventEntity.updateSenderData() { + assertIsManaged() + val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: return + val stateIndex = root?.stateIndex ?: return + val senderId = root?.sender ?: return + val chunkEntity = chunk?.firstOrNull() ?: return + val isUnlinked = chunkEntity.isUnlinked() + var senderMembershipEvent: EventEntity? + var senderRoomMemberContent: String? + when { + stateIndex <= 0 -> { + senderMembershipEvent = chunkEntity.timelineEvents.buildQuery(senderId, isUnlinked).next(from = stateIndex)?.root + senderRoomMemberContent = senderMembershipEvent?.prevContent + } + else -> { + senderMembershipEvent = chunkEntity.timelineEvents.buildQuery(senderId, isUnlinked).prev(since = stateIndex)?.root + senderRoomMemberContent = senderMembershipEvent?.content + } + } + + // We fallback to untimelinedStateEvents if we can't find membership events in timeline + if (senderMembershipEvent == null) { + senderMembershipEvent = roomEntity.untimelinedStateEvents + .where() + .equalTo(EventEntityFields.STATE_KEY, senderId) + .equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER) + .prev(since = stateIndex) + senderRoomMemberContent = senderMembershipEvent?.content + } + val senderRoomMember: RoomMember? = ContentMapper.map(senderRoomMemberContent).toModel() + this.senderAvatar = senderRoomMember?.avatarUrl + this.senderName = senderRoomMember?.displayName + this.isUniqueDisplayName = RoomMembers(realm, roomId).isUniqueDisplayName(senderRoomMember?.displayName) + this.senderMembershipEvent = senderMembershipEvent +} + +private fun RealmList.buildQuery(sender: String, isUnlinked: Boolean): RealmQuery { + return where() + .equalTo(TimelineEventEntityFields.ROOT.STATE_KEY, sender) + .equalTo(TimelineEventEntityFields.ROOT.TYPE, EventType.STATE_ROOM_MEMBER) + .equalTo(TimelineEventEntityFields.ROOT.IS_UNLINKED, isUnlinked) +} + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt index dba7d502..5f946e42 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/mapper/RoomSummaryMapper.kt @@ -29,7 +29,7 @@ internal class RoomSummaryMapper @Inject constructor( val cryptoService: CryptoService ) { - fun map(roomSummaryEntity: RoomSummaryEntity, getLatestEvent: Boolean = false): RoomSummary { + fun map(roomSummaryEntity: RoomSummaryEntity): RoomSummary { val tags = roomSummaryEntity.tags.map { RoomTag(it.tagName, it.tagOrder) } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/TimelineEventEntity.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/TimelineEventEntity.kt index 8c42e4c9..9a467f72 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/TimelineEventEntity.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/model/TimelineEventEntity.kt @@ -35,7 +35,8 @@ internal open class TimelineEventEntity(@PrimaryKey var localId: String = UUID.r var annotations: EventAnnotationsSummaryEntity? = null, var senderName: String? = null, var isUniqueDisplayName: Boolean = false, - var senderAvatar: String? = null + var senderAvatar: String? = null, + var senderMembershipEvent: EventEntity? = null ) : RealmObject() { @LinkingObjects("timelineEvents") diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt index 620f47be..5942118d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/TimelineEventEntityQueries.kt @@ -54,6 +54,12 @@ internal fun TimelineEventEntity.Companion.where(realm: Realm, } } +internal fun TimelineEventEntity.Companion.findWithSenderMembershipEvent(realm: Realm, senderMembershipEventId: String): List { + return realm.where() + .equalTo(TimelineEventEntityFields.SENDER_MEMBERSHIP_EVENT.EVENT_ID, senderMembershipEventId) + .findAll() +} + internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm, roomId: String, diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index b94ba769..492dd035 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -33,8 +33,6 @@ import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntityFields import im.vector.matrix.android.internal.database.query.where -import im.vector.matrix.android.internal.util.fetchCopied -import im.vector.matrix.android.internal.util.fetchCopyMap import javax.inject.Inject internal class DefaultRoom @Inject constructor(override val roomId: String, @@ -55,12 +53,12 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, RelationService by relationService, MembershipService by roomMembersService { - override fun liveRoomSummary(fetchLastEvent: Boolean): LiveData { + override fun liveRoomSummary(): LiveData { val liveRealmData = RealmLiveData(monarchy.realmConfiguration) { realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) } return Transformations.map(liveRealmData) { results -> - val roomSummaries = results.map { roomSummaryMapper.map(it, fetchLastEvent) } + val roomSummaries = results.map { roomSummaryMapper.map(it) } if (roomSummaries.isEmpty()) { // Create a dummy RoomSummary to avoid Crash during Sign Out or clear cache @@ -71,10 +69,10 @@ internal class DefaultRoom @Inject constructor(override val roomId: String, } } - override fun roomSummary(fetchLastEvent: Boolean): RoomSummary? { + override fun roomSummary(): RoomSummary? { return monarchy.fetchAllMappedSync( { realm -> RoomSummaryEntity.where(realm, roomId).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, - { roomSummaryMapper.map(it, fetchLastEvent) } + { roomSummaryMapper.map(it) } ).firstOrNull() } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt index d40184a0..2c0f1ce9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoomService.kt @@ -52,10 +52,10 @@ internal class DefaultRoomService @Inject constructor(private val monarchy: Mona return roomFactory.create(roomId) } - override fun liveRoomSummaries(fetchLastEvents: Boolean): LiveData> { + override fun liveRoomSummaries(): LiveData> { return monarchy.findAllMappedWithChanges( { realm -> RoomSummaryEntity.where(realm).isNotEmpty(RoomSummaryEntityFields.DISPLAY_NAME) }, - { roomSummaryMapper.map(it, fetchLastEvents) } + { roomSummaryMapper.map(it) } ) } } \ No newline at end of file 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 4dbb60b8..d98436a7 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 @@ -20,15 +20,16 @@ import arrow.core.Try import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.internal.database.helper.addStateEvents +import im.vector.matrix.android.internal.database.helper.updateSenderData import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.network.executeRequest -import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.session.room.RoomAPI import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater import im.vector.matrix.android.internal.session.sync.SyncTokenStore import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.tryTransactionSync +import io.realm.Realm import io.realm.kotlin.createObject import javax.inject.Inject @@ -41,9 +42,9 @@ internal interface LoadRoomMembersTask : Task { @@ -68,20 +69,20 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(private val roomAP val roomMembers = RoomMembers(realm, roomId).getLoaded() val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) } - roomEntity.addStateEvents(eventsToInsert) + roomEntity.chunks.flatMap { it.timelineEvents }.forEach { + it.updateSenderData() + } roomEntity.areAllMembersLoaded = true - roomSummaryUpdater.update(realm, roomId) } .map { response } } private fun areAllMembersAlreadyLoaded(roomId: String): Boolean { - return monarchy - .fetchAllCopiedSync { RoomEntity.where(it, roomId) } - .firstOrNull() - ?.areAllMembersLoaded ?: false + return Realm.getInstance(monarchy.realmConfiguration).use { + RoomEntity.where(it, roomId).findFirst()?.areAllMembersLoaded ?: false + } } } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt index 41d5879c..72b2695e 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/membership/RoomMembers.kt @@ -29,6 +29,10 @@ import io.realm.Realm import io.realm.RealmQuery import io.realm.Sort +/** + * This class is an helper around STATE_ROOM_MEMBER events. + * It allows to get the live membership of a user. + */ internal class RoomMembers(private val realm: Realm, private val roomId: String ) { diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt index 56b40f2d..8ea8c337 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/prune/PruneEventTask.kt @@ -21,12 +21,14 @@ import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.UnsignedData import im.vector.matrix.android.api.session.room.send.SendState +import im.vector.matrix.android.internal.database.helper.updateSenderData import im.vector.matrix.android.internal.database.mapper.ContentMapper import im.vector.matrix.android.internal.database.mapper.EventMapper import im.vector.matrix.android.internal.database.model.EventEntity +import im.vector.matrix.android.internal.database.model.TimelineEventEntity +import im.vector.matrix.android.internal.database.query.findWithSenderMembershipEvent import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.di.MoshiProvider -import im.vector.matrix.android.internal.session.SessionScope import im.vector.matrix.android.internal.task.Task import im.vector.matrix.android.internal.util.tryTransactionSync import io.realm.Realm @@ -59,13 +61,13 @@ internal class DefaultPruneEventTask @Inject constructor(private val monarchy: M } val redactionEventEntity = EventEntity.where(realm, eventId = redactionEvent.eventId - ?: "").findFirst() - ?: return + ?: "").findFirst() + ?: return val isLocalEcho = redactionEventEntity.sendState == SendState.UNSENT Timber.v("Redact event for ${redactionEvent.redacts} localEcho=$isLocalEcho") val eventToPrune = EventEntity.where(realm, eventId = redactionEvent.redacts).findFirst() - ?: return + ?: return val allowedKeys = computeAllowedKeys(eventToPrune.type) if (allowedKeys.isNotEmpty()) { @@ -76,7 +78,7 @@ internal class DefaultPruneEventTask @Inject constructor(private val monarchy: M EventType.MESSAGE -> { Timber.d("REDACTION for message ${eventToPrune.eventId}") val unsignedData = EventMapper.map(eventToPrune).unsignedData - ?: UnsignedData(null, null) + ?: UnsignedData(null, null) //was this event a m.replace // val contentModel = ContentMapper.map(eventToPrune.content)?.toModel() @@ -94,28 +96,34 @@ internal class DefaultPruneEventTask @Inject constructor(private val monarchy: M // } } } + if (eventToPrune.type == EventType.STATE_ROOM_MEMBER) { + val timelineEventsToUpdate = TimelineEventEntity.findWithSenderMembershipEvent(realm, eventToPrune.eventId) + for (timelineEvent in timelineEventsToUpdate) { + timelineEvent.updateSenderData() + } + } } private fun computeAllowedKeys(type: String): List { // Add filtered content, allowed keys in content depends on the event type return when (type) { - EventType.STATE_ROOM_MEMBER -> listOf("membership") - EventType.STATE_ROOM_CREATE -> listOf("creator") - EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule") + EventType.STATE_ROOM_MEMBER -> listOf("membership") + EventType.STATE_ROOM_CREATE -> listOf("creator") + EventType.STATE_ROOM_JOIN_RULES -> listOf("join_rule") EventType.STATE_ROOM_POWER_LEVELS -> listOf("users", - "users_default", - "events", - "events_default", - "state_default", - "ban", - "kick", - "redact", - "invite") - EventType.STATE_ROOM_ALIASES -> listOf("aliases") - EventType.STATE_CANONICAL_ALIAS -> listOf("alias") - EventType.FEEDBACK -> listOf("type", "target_event_id") - else -> emptyList() + "users_default", + "events", + "events_default", + "state_default", + "ban", + "kick", + "redact", + "invite") + EventType.STATE_ROOM_ALIASES -> listOf("aliases") + EventType.STATE_CANONICAL_ALIAS -> listOf("alias") + EventType.FEEDBACK -> listOf("type", "target_event_id") + else -> emptyList() } } } \ No newline at end of file diff --git a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt index 6c1ef646..17faee35 100644 --- a/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt +++ b/matrix-sdk-android/src/test/java/im/vector/matrix/android/api/pushrules/PushrulesConditionTest.kt @@ -179,7 +179,7 @@ class PushrulesConditionTest { } } - override fun liveRoomSummaries(fetchLastEvents: Boolean): LiveData> { + override fun liveRoomSummaries(): LiveData> { return MutableLiveData() } } @@ -194,11 +194,11 @@ class PushrulesConditionTest { return _numberOfJoinedMembers } - override fun liveRoomSummary(fetchLastEvent: Boolean): LiveData { + override fun liveRoomSummary(): LiveData { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } - override fun roomSummary(fetchLastEvent: Boolean): RoomSummary? { + override fun roomSummary(): RoomSummary? { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. } diff --git a/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt index d3b95f26..36d57255 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/HomeActivityViewModel.kt @@ -73,7 +73,7 @@ class HomeActivityViewModel @AssistedInject constructor(@Assisted initialState: private fun observeRoomAndGroup() { Observable .combineLatest, Option, List>( - session.rx().liveRoomSummaries(fetchLastEvents = true).throttleLast(300, TimeUnit.MILLISECONDS), + session.rx().liveRoomSummaries().throttleLast(300, TimeUnit.MILLISECONDS), selectedGroupStore.observe(), BiFunction { rooms, selectedGroupOption -> val selectedGroup = selectedGroupOption.orNull() diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index d5d5ffa3..83dcb415 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -500,17 +500,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } private fun observeRoomSummary() { - room.rx().liveRoomSummary(false) - .observeOn(AndroidSchedulers.mainThread()) - .flatMap { - if (it.membership != Membership.INVITE || it.latestEvent != null) { - // Not an invitation, or already fetching last event - Observable.just(it) - } else { - // We need the last event - room.rx().liveRoomSummary(true) - } - } + room.rx().liveRoomSummary() .execute { async -> copy( asyncRoomSummary = async, diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt index f7d6c2fb..b34618e2 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/RoomDirectoryViewModel.kt @@ -86,7 +86,7 @@ class RoomDirectoryViewModel @AssistedInject constructor(@Assisted initialState: private fun observeJoinedRooms() { session .rx() - .liveRoomSummaries(fetchLastEvents = false) + .liveRoomSummaries() .subscribe { list -> val joinedRoomIds = list // Keep only joined room diff --git a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt index e91b4b0f..bf5fa743 100644 --- a/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/roomdirectory/roompreview/RoomPreviewViewModel.kt @@ -54,7 +54,7 @@ class RoomPreviewViewModel @AssistedInject constructor(@Assisted initialState: R private fun observeJoinedRooms() { session .rx() - .liveRoomSummaries(fetchLastEvents = false) + .liveRoomSummaries() .subscribe { list -> withState { state -> val isRoomJoined = list