Fix room summary not being updated when room members are loaded

This commit is contained in:
ganfra 2019-03-29 11:15:27 +01:00
parent 2e2d5b9f86
commit 94db36d6c4
6 changed files with 103 additions and 88 deletions

View File

@ -29,6 +29,7 @@ import im.vector.matrix.android.internal.session.group.DefaultGroupService
import im.vector.matrix.android.internal.session.group.GroupSummaryUpdater
import im.vector.matrix.android.internal.session.room.DefaultRoomService
import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
import im.vector.matrix.android.internal.session.room.prune.EventsPruner
@ -89,6 +90,10 @@ internal class SessionModule(private val sessionParams: SessionParams) {
RoomAvatarResolver(get(), sessionParams.credentials)
}

scope(DefaultSession.SCOPE) {
RoomSummaryUpdater(get(), get(), get())
}

scope(DefaultSession.SCOPE) {
DefaultRoomService(get(), get()) as RoomService
}

View File

@ -22,11 +22,7 @@ import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersTas
import im.vector.matrix.android.internal.session.room.read.DefaultSetReadMarkersTask
import im.vector.matrix.android.internal.session.room.read.SetReadMarkersTask
import im.vector.matrix.android.internal.session.room.send.EventFactory
import im.vector.matrix.android.internal.session.room.timeline.DefaultGetContextOfEventTask
import im.vector.matrix.android.internal.session.room.timeline.DefaultPaginationTask
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
import im.vector.matrix.android.internal.session.room.timeline.*
import org.koin.dsl.module.module
import retrofit2.Retrofit

@ -41,7 +37,7 @@ class RoomModule {
}

scope(DefaultSession.SCOPE) {
DefaultLoadRoomMembersTask(get(), get(), get()) as LoadRoomMembersTask
DefaultLoadRoomMembersTask(get(), get(), get(), get()) as LoadRoomMembersTask
}

scope(DefaultSession.SCOPE) {
@ -57,7 +53,7 @@ class RoomModule {
}

scope(DefaultSession.SCOPE) {
DefaultSetReadMarkersTask(get(), get(),get()) as SetReadMarkersTask
DefaultSetReadMarkersTask(get(), get(), get()) as SetReadMarkersTask
}

scope(DefaultSession.SCOPE) {

View File

@ -0,0 +1,79 @@
/*
*
* * 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.session.room

import im.vector.matrix.android.api.auth.data.Credentials
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.RoomTopicContent
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.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.prev
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.members.RoomMembers
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
import io.realm.Realm
import io.realm.kotlin.createObject

internal class RoomSummaryUpdater(private val credentials: Credentials,
private val roomDisplayNameResolver: RoomDisplayNameResolver,
private val roomAvatarResolver: RoomAvatarResolver) {

fun update(realm: Realm,
roomId: String,
roomSummary: RoomSyncSummary? = null,
unreadNotifications: RoomSyncUnreadNotifications? = null) {

val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)

if (roomSummary != null) {
if (roomSummary.heroes.isNotEmpty()) {
roomSummaryEntity.heroes.clear()
roomSummaryEntity.heroes.addAll(roomSummary.heroes)
}
if (roomSummary.invitedMembersCount != null) {
roomSummaryEntity.invitedMembersCount = roomSummary.invitedMembersCount
}
if (roomSummary.joinedMembersCount != null) {
roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount
}
}
if (unreadNotifications?.highlightCount != null) {
roomSummaryEntity.highlightCount = unreadNotifications.highlightCount
}
if (unreadNotifications?.notificationCount != null) {
roomSummaryEntity.notificationCount = unreadNotifications.notificationCount
}

val lastEvent = EventEntity.latestEvent(realm, roomId, includedTypes = listOf(EventType.MESSAGE))
val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev()?.asDomain()
val otherRoomMembers = RoomMembers(realm, roomId).getLoaded().filterKeys { it != credentials.userId }
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(roomId).toString()
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(roomId)
roomSummaryEntity.topic = lastTopicEvent?.content.toModel<RoomTopicContent>()?.topic
roomSummaryEntity.lastMessage = lastEvent
roomSummaryEntity.otherMemberIds.clear()
roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers.keys)
}
}

View File

@ -24,6 +24,7 @@ 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.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
@ -39,7 +40,8 @@ internal interface LoadRoomMembersTask : Task<LoadRoomMembersTask.Params, Boolea

internal class DefaultLoadRoomMembersTask(private val roomAPI: RoomAPI,
private val monarchy: Monarchy,
private val syncTokenStore: SyncTokenStore
private val syncTokenStore: SyncTokenStore,
private val roomSummaryUpdater: RoomSummaryUpdater
) : LoadRoomMembersTask {

override fun execute(params: LoadRoomMembersTask.Params): Try<Boolean> {
@ -49,7 +51,7 @@ internal class DefaultLoadRoomMembersTask(private val roomAPI: RoomAPI,
//TODO use this token
val lastToken = syncTokenStore.getLastToken()
executeRequest<RoomMembersResponse> {
apiCall = roomAPI.getMembers(params.roomId, null, null, params.excludeMembership?.value)
apiCall = roomAPI.getMembers(params.roomId, lastToken, null, params.excludeMembership?.value)
}.flatMap { response ->
insertInDb(response, params.roomId)
}.map { true }
@ -61,22 +63,24 @@ internal class DefaultLoadRoomMembersTask(private val roomAPI: RoomAPI,
.tryTransactionSync { realm ->
// We ignore all the already known members
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
?: realm.createObject(roomId)

val roomMembers = RoomMembers(realm, roomId).getLoaded()
val eventsToInsert = response.roomMemberEvents.filter { !roomMembers.containsKey(it.stateKey) }

roomEntity.addStateEvents(eventsToInsert)
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
.fetchAllCopiedSync { RoomEntity.where(it, roomId) }
.firstOrNull()
?.areAllMembersLoaded ?: false
}

}

View File

@ -17,45 +17,28 @@
package im.vector.matrix.android.internal.session.sync

import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.auth.data.Credentials
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.MyMembership
import im.vector.matrix.android.api.session.room.model.RoomTopicContent
import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent
import im.vector.matrix.android.internal.database.helper.addAll
import im.vector.matrix.android.internal.database.helper.addOrUpdate
import im.vector.matrix.android.internal.database.helper.addStateEvents
import im.vector.matrix.android.internal.database.helper.lastStateIndex
import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.prev
import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
import im.vector.matrix.android.internal.session.room.members.RoomMembers
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import im.vector.matrix.android.internal.session.sync.model.InvitedRoomSync
import im.vector.matrix.android.internal.session.sync.model.RoomSync
import im.vector.matrix.android.internal.session.sync.model.RoomSyncAccountData
import im.vector.matrix.android.internal.session.sync.model.RoomSyncEphemeral
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
import im.vector.matrix.android.internal.session.sync.model.RoomSyncUnreadNotifications
import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
import im.vector.matrix.android.internal.session.sync.model.*
import io.realm.Realm
import io.realm.kotlin.createObject

internal class RoomSyncHandler(private val monarchy: Monarchy,
private val readReceiptHandler: ReadReceiptHandler,
private val roomDisplayNameResolver: RoomDisplayNameResolver,
private val roomAvatarResolver: RoomAvatarResolver,
private val credentials: Credentials,
private val roomSummaryUpdater: RoomSummaryUpdater,
private val roomTagHandler: RoomTagHandler) {

sealed class HandlingStrategy {
@ -88,7 +71,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
roomSync: RoomSync): RoomEntity {

val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: realm.createObject(roomId)
?: realm.createObject(roomId)

if (roomEntity.membership == MyMembership.INVITED) {
roomEntity.chunks.deleteAllFromRealm()
@ -119,12 +102,7 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
)
roomEntity.addOrUpdate(chunkEntity)
}

handleRoomSummary(realm, roomId, roomSync.summary)

if (roomSync.unreadNotifications != null) {
handleUnreadNotifications(realm, roomId, roomSync.unreadNotifications)
}
roomSummaryUpdater.update(realm, roomId, roomSync.summary, roomSync.unreadNotifications)

if (roomSync.ephemeral != null && roomSync.ephemeral.events.isNotEmpty()) {
handleEphemeral(realm, roomId, roomSync.ephemeral)
@ -180,39 +158,6 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
return chunkEntity
}

private fun handleRoomSummary(realm: Realm,
roomId: String,
roomSummary: RoomSyncSummary?) {

val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
?: RoomSummaryEntity(roomId)

val lastEvent = EventEntity.latestEvent(realm, roomId, includedTypes = listOf(EventType.MESSAGE))
val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).prev()?.asDomain()

val otherRoomMembers = RoomMembers(realm, roomId).getLoaded().filterKeys { it != credentials.userId }
roomSummaryEntity.displayName = roomDisplayNameResolver.resolve(roomId).toString()
roomSummaryEntity.avatarUrl = roomAvatarResolver.resolve(roomId)
roomSummaryEntity.topic = lastTopicEvent?.content.toModel<RoomTopicContent>()?.topic
roomSummaryEntity.lastMessage = lastEvent
roomSummaryEntity.otherMemberIds.clear()
roomSummaryEntity.otherMemberIds.addAll(otherRoomMembers.keys)

if (roomSummary != null) {
if (roomSummary.heroes.isNotEmpty()) {
roomSummaryEntity.heroes.clear()
roomSummaryEntity.heroes.addAll(roomSummary.heroes)
}
if (roomSummary.invitedMembersCount != null) {
roomSummaryEntity.invitedMembersCount = roomSummary.invitedMembersCount
}
if (roomSummary.joinedMembersCount != null) {
roomSummaryEntity.joinedMembersCount = roomSummary.joinedMembersCount
}
}
realm.insertOrUpdate(roomSummaryEntity)
}

private fun handleEphemeral(realm: Realm,
roomId: String,
ephemeral: RoomSyncEphemeral) {
@ -222,20 +167,6 @@ internal class RoomSyncHandler(private val monarchy: Monarchy,
.flatMap { readReceiptHandler.handle(realm, roomId, it) }
}

private fun handleUnreadNotifications(realm: Realm, roomId: String, unreadNotifications: RoomSyncUnreadNotifications) {
val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
?: RoomSummaryEntity(roomId)

if (unreadNotifications.highlightCount != null) {
roomSummaryEntity.highlightCount = unreadNotifications.highlightCount
}
if (unreadNotifications.notificationCount != null) {
roomSummaryEntity.notificationCount = unreadNotifications.notificationCount
}
realm.insertOrUpdate(roomSummaryEntity)

}

private fun handleRoomAccountDataEvents(realm: Realm, roomId: String, accountData: RoomSyncAccountData) {
accountData.events
.filter { it.type == EventType.TAG }

View File

@ -40,7 +40,7 @@ internal class SyncModule {
}

scope(DefaultSession.SCOPE) {
RoomSyncHandler(get(), get(), get(),get(),get(),get())
RoomSyncHandler(get(), get(), get(), get())
}

scope(DefaultSession.SCOPE) {