Sync/Timeline: handle displayName isUnique

This commit is contained in:
ganfra 2020-01-29 17:30:31 +01:00
parent 7f72af426b
commit 71a02a58af
14 changed files with 89 additions and 94 deletions

View File

@ -61,10 +61,10 @@ class RxRoom(private val room: Room) {
} }
} }
fun liveStateEvent(eventType: String): Observable<Optional<Event>> { fun liveStateEvent(eventType: String, stateKey: String): Observable<Optional<Event>> {
return room.getStateEventLive(eventType).asObservable() return room.getStateEventLive(eventType, stateKey).asObservable()
.startWithCallable { .startWithCallable {
room.getStateEvent(eventType).toOptional() room.getStateEvent(eventType, stateKey).toOptional()
} }
} }

View File

@ -33,7 +33,7 @@ interface StateService {
*/ */
fun enableEncryption(algorithm: String, callback: MatrixCallback<Unit>) fun enableEncryption(algorithm: String, callback: MatrixCallback<Unit>)
fun getStateEvent(eventType: String): Event? fun getStateEvent(eventType: String, stateKey: String): Event?
fun getStateEventLive(eventType: String): LiveData<Optional<Event>> fun getStateEventLive(eventType: String, stateKey: String): LiveData<Optional<Event>>
} }

View File

@ -16,9 +16,7 @@
package im.vector.matrix.android.internal.database.helper package im.vector.matrix.android.internal.database.helper
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.RoomMemberContent import im.vector.matrix.android.api.session.room.model.RoomMemberContent
import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntityFields import im.vector.matrix.android.internal.database.model.CurrentStateEventEntityFields
import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
@ -89,7 +87,7 @@ internal fun ChunkEntity.addStateEvent(roomId: String, stateEvent: EventEntity,
internal fun ChunkEntity.addTimelineEvent(roomId: String, internal fun ChunkEntity.addTimelineEvent(roomId: String,
eventEntity: EventEntity, eventEntity: EventEntity,
direction: PaginationDirection, direction: PaginationDirection,
roomMemberEvent: EventEntity?) { roomMemberContentsByUser: HashMap<String, RoomMemberContent?>) {
val eventId = eventEntity.eventId val eventId = eventEntity.eventId
if (timelineEvents.find(eventId) != null) { if (timelineEvents.find(eventId) != null) {
@ -128,12 +126,15 @@ internal fun ChunkEntity.addTimelineEvent(roomId: String,
this.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst() this.annotations = EventAnnotationsSummaryEntity.where(realm, eventId).findFirst()
this.readReceipts = readReceiptsSummaryEntity this.readReceipts = readReceiptsSummaryEntity
this.displayIndex = displayIndex this.displayIndex = displayIndex
if (roomMemberEvent != null) {
val roomMemberContent = ContentMapper.map(roomMemberEvent.content).toModel<RoomMemberContent>() val roomMemberContent = roomMemberContentsByUser[senderId]
this.senderAvatar = roomMemberContent?.avatarUrl val isUnique = roomMemberContentsByUser.values.find {
this.senderName = roomMemberContent?.displayName roomMemberContent != it &&
this.senderMembershipEventId = roomMemberEvent.eventId it?.displayName == roomMemberContent?.displayName
} } == null
this.senderAvatar = roomMemberContent?.avatarUrl
this.senderName = roomMemberContent?.displayName
this.isUniqueDisplayName = isUnique
} }
timelineEvents.add(timelineEventEntity) timelineEvents.add(timelineEventEntity)
} }

View File

@ -16,14 +16,8 @@
package im.vector.matrix.android.internal.database.helper 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.room.send.SendState
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.ChunkEntity
import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
import im.vector.matrix.android.internal.session.room.membership.RoomMemberHelper
import io.realm.Realm
internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) { internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
chunks.remove(chunkEntity) chunks.remove(chunkEntity)
@ -35,21 +29,3 @@ internal fun RoomEntity.addOrUpdate(chunkEntity: ChunkEntity) {
chunks.add(chunkEntity) chunks.add(chunkEntity)
} }
} }
internal fun RoomEntity.addSendingEvent(realm: Realm, event: Event) {
val senderId = event.senderId ?: return
val eventEntity = event.toEntity(roomId, SendState.UNSENT)
val roomMembers = RoomMemberHelper(realm, roomId)
val myUser = roomMembers.getLastRoomMember(senderId)
val localId = TimelineEventEntity.nextId(realm)
val timelineEventEntity = TimelineEventEntity(localId).also {
it.root = eventEntity
it.eventId = event.eventId ?: ""
it.roomId = roomId
it.senderName = myUser?.displayName
it.senderAvatar = myUser?.avatarUrl
it.isUniqueDisplayName = roomMembers.isUniqueDisplayName()
}
sendingTimelineEvents.add(0, timelineEventEntity)
}

View File

@ -23,19 +23,23 @@ import io.realm.Realm
import io.realm.RealmQuery import io.realm.RealmQuery
import io.realm.kotlin.createObject import io.realm.kotlin.createObject
internal fun CurrentStateEventEntity.Companion.where(realm: Realm, roomId: String, stateKey: String, type: String): RealmQuery<CurrentStateEventEntity> { internal fun CurrentStateEventEntity.Companion.where(realm: Realm, roomId: String, type: String): RealmQuery<CurrentStateEventEntity> {
return realm.where(CurrentStateEventEntity::class.java) return realm.where(CurrentStateEventEntity::class.java)
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId) .equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.equalTo(CurrentStateEventEntityFields.STATE_KEY, stateKey)
.equalTo(CurrentStateEventEntityFields.TYPE, type) .equalTo(CurrentStateEventEntityFields.TYPE, type)
} }
internal fun CurrentStateEventEntity.Companion.whereStateKey(realm: Realm, roomId: String, type: String, stateKey: String): RealmQuery<CurrentStateEventEntity> {
return where(realm = realm, roomId = roomId, type = type)
.equalTo(CurrentStateEventEntityFields.STATE_KEY, stateKey)
}
internal fun CurrentStateEventEntity.Companion.getOrNull(realm: Realm, roomId: String, stateKey: String, type: String): CurrentStateEventEntity? { internal fun CurrentStateEventEntity.Companion.getOrNull(realm: Realm, roomId: String, stateKey: String, type: String): CurrentStateEventEntity? {
return where(realm, roomId, stateKey, type).findFirst() return whereStateKey(realm = realm, roomId = roomId, type = type, stateKey = stateKey).findFirst()
} }
internal fun CurrentStateEventEntity.Companion.getOrCreate(realm: Realm, roomId: String, stateKey: String, type: String): CurrentStateEventEntity { internal fun CurrentStateEventEntity.Companion.getOrCreate(realm: Realm, roomId: String, stateKey: String, type: String): CurrentStateEventEntity {
return getOrNull(realm, roomId, stateKey, type) ?: create(realm, roomId, stateKey, type) return getOrNull(realm = realm, roomId = roomId, stateKey = stateKey, type = type) ?: create(realm, roomId, stateKey, type)
} }
private fun create(realm: Realm, roomId: String, stateKey: String, type: String): CurrentStateEventEntity { private fun create(realm: Realm, roomId: String, stateKey: String, type: String): CurrentStateEventEntity {

View File

@ -129,7 +129,7 @@ internal class RoomDisplayNameResolver @Inject constructor(private val context:
private fun resolveRoomMemberName(roomMemberSummary: RoomMemberSummaryEntity?, private fun resolveRoomMemberName(roomMemberSummary: RoomMemberSummaryEntity?,
roomMemberHelper: RoomMemberHelper): String? { roomMemberHelper: RoomMemberHelper): String? {
if (roomMemberSummary == null) return null if (roomMemberSummary == null) return null
val isUnique = roomMemberHelper.isUniqueDisplayName() val isUnique = roomMemberHelper.isUniqueDisplayName(roomMemberSummary.displayName)
return if (isUnique) { return if (isUnique) {
roomMemberSummary.displayName roomMemberSummary.displayName
} else { } else {

View File

@ -18,9 +18,10 @@ package im.vector.matrix.android.internal.session.room.membership
import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.internal.database.model.* import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.EventEntity
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntity
import im.vector.matrix.android.internal.database.model.RoomMemberSummaryEntityFields
import im.vector.matrix.android.internal.database.model.RoomSummaryEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.query.getOrNull import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
@ -50,8 +51,14 @@ internal class RoomMemberHelper(private val realm: Realm,
.findFirst() .findFirst()
} }
fun isUniqueDisplayName(): Boolean { fun isUniqueDisplayName(displayName: String?): Boolean {
return false if (displayName.isNullOrEmpty()) {
return true
}
return RoomMemberSummaryEntity.where(realm, roomId)
.equalTo(RoomMemberSummaryEntityFields.DISPLAY_NAME, displayName)
.findAll()
.size == 1
} }
fun queryRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> { fun queryRoomMembersEvent(): RealmQuery<RoomMemberSummaryEntity> {

View File

@ -62,7 +62,7 @@ internal class LocalEchoRepository @Inject constructor(private val monarchy: Mon
it.roomId = roomId it.roomId = roomId
it.senderName = myUser?.displayName it.senderName = myUser?.displayName
it.senderAvatar = myUser?.avatarUrl it.senderAvatar = myUser?.avatarUrl
it.isUniqueDisplayName = roomMemberHelper.isUniqueDisplayName() it.isUniqueDisplayName = roomMemberHelper.isUniqueDisplayName(myUser?.displayName)
} }
roomEntity.sendingTimelineEvents.add(0, timelineEventEntity) roomEntity.sendingTimelineEvents.add(0, timelineEventEntity)
roomSummaryUpdater.update(realm, roomId) roomSummaryUpdater.update(realm, roomId)

View File

@ -31,7 +31,7 @@ import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.mapper.asDomain
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
import im.vector.matrix.android.internal.database.query.getOrNull import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.whereStateKey
import im.vector.matrix.android.internal.task.TaskExecutor import im.vector.matrix.android.internal.task.TaskExecutor
import im.vector.matrix.android.internal.task.configureWith import im.vector.matrix.android.internal.task.configureWith
import io.realm.Realm import io.realm.Realm
@ -48,15 +48,15 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
fun create(roomId: String): StateService fun create(roomId: String): StateService
} }
override fun getStateEvent(eventType: String): Event? { override fun getStateEvent(eventType: String, stateKey: String): Event? {
return Realm.getInstance(monarchy.realmConfiguration).use { realm -> return Realm.getInstance(monarchy.realmConfiguration).use { realm ->
CurrentStateEventEntity.getOrNull(realm, roomId, type = eventType, stateKey = "")?.root?.asDomain() CurrentStateEventEntity.getOrNull(realm, roomId, type = eventType, stateKey = stateKey)?.root?.asDomain()
} }
} }
override fun getStateEventLive(eventType: String): LiveData<Optional<Event>> { override fun getStateEventLive(eventType: String, stateKey: String): LiveData<Optional<Event>> {
val liveData = monarchy.findAllMappedWithChanges( val liveData = monarchy.findAllMappedWithChanges(
{ realm -> CurrentStateEventEntity.where(realm, roomId, type = eventType, stateKey = "") }, { realm -> CurrentStateEventEntity.whereStateKey(realm, roomId, type = eventType, stateKey = "") },
{ it.root?.asDomain() } { it.root?.asDomain() }
) )
return Transformations.map(liveData) { results -> return Transformations.map(liveData) { results ->

View File

@ -17,19 +17,20 @@
package im.vector.matrix.android.internal.session.room.timeline package im.vector.matrix.android.internal.session.room.timeline
import com.zhuinden.monarchy.Monarchy import com.zhuinden.monarchy.Monarchy
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.EventType
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.internal.database.helper.addOrUpdate import im.vector.matrix.android.internal.database.helper.addOrUpdate
import im.vector.matrix.android.internal.database.helper.addStateEvent import im.vector.matrix.android.internal.database.helper.addStateEvent
import im.vector.matrix.android.internal.database.helper.addTimelineEvent import im.vector.matrix.android.internal.database.helper.addTimelineEvent
import im.vector.matrix.android.internal.database.helper.deleteOnCascade import im.vector.matrix.android.internal.database.helper.deleteOnCascade
import im.vector.matrix.android.internal.database.helper.merge import im.vector.matrix.android.internal.database.helper.merge
import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.mapper.toEntity 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.ChunkEntity
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.CurrentStateEventEntityFields
import im.vector.matrix.android.internal.database.model.RoomEntity 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.model.RoomSummaryEntity
import im.vector.matrix.android.internal.database.model.TimelineEventEntity import im.vector.matrix.android.internal.database.model.TimelineEventEntity
@ -37,14 +38,11 @@ import im.vector.matrix.android.internal.database.query.create
import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findAllIncludingEvents import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.latestEvent import im.vector.matrix.android.internal.database.query.latestEvent
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
import im.vector.matrix.android.internal.util.awaitTransaction import im.vector.matrix.android.internal.util.awaitTransaction
import io.realm.Realm import io.realm.Realm
import io.realm.RealmList
import io.realm.kotlin.createObject
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -193,24 +191,29 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
currentChunk: ChunkEntity currentChunk: ChunkEntity
) { ) {
Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}") Timber.v("Add ${receivedChunk.events.size} events in chunk(${currentChunk.nextToken} | ${currentChunk.prevToken}")
val roomMemberEventsByUser = HashMap<String, EventEntity?>() val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
val eventList = if (direction == PaginationDirection.FORWARDS) { val eventList = receivedChunk.events
receivedChunk.events
} else {
receivedChunk.events.asReversed()
}
val stateEvents = receivedChunk.stateEvents val stateEvents = receivedChunk.stateEvents
realm.where(CurrentStateEventEntity::class.java)
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
.findAll()
.forEach {
val roomMember = ContentMapper.map(it.root?.content).toModel<RoomMemberContent>()
roomMemberContentsByUser[it.stateKey] = roomMember
}
for (stateEvent in stateEvents) { for (stateEvent in stateEvents) {
val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).let { val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }
currentChunk.addStateEvent(roomId, stateEventEntity, direction) currentChunk.addStateEvent(roomId, stateEventEntity, direction)
if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null && !stateEvent.isRedacted()) { if (stateEvent.type == EventType.STATE_ROOM_MEMBER && stateEvent.stateKey != null && !stateEvent.isRedacted()) {
roomMemberEventsByUser[stateEvent.stateKey] = stateEventEntity roomMemberContentsByUser[stateEvent.stateKey] = stateEvent.content.toModel<RoomMemberContent>()
} }
} }
val eventIds = ArrayList<String>(eventList.size) val eventIds = ArrayList<String>(eventList.size)
val eventEntities = ArrayList<EventEntity>(eventList.size)
for (event in eventList) { for (event in eventList) {
if (event.eventId == null || event.senderId == null) { if (event.eventId == null || event.senderId == null) {
continue continue
@ -219,23 +222,16 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
val eventEntity = event.toEntity(roomId, SendState.SYNCED).let { val eventEntity = event.toEntity(roomId, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }
if (direction == PaginationDirection.FORWARDS) {
eventEntities.add(eventEntity)
} else {
eventEntities.add(0, eventEntity)
}
if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null && !event.isRedacted()) { if (event.type == EventType.STATE_ROOM_MEMBER && event.stateKey != null && !event.isRedacted()) {
roomMemberEventsByUser[event.stateKey] = eventEntity val contentToUse = if (direction == PaginationDirection.FORWARDS) {
event.content
} else {
event.prevContent
}
roomMemberContentsByUser[event.stateKey] = contentToUse.toModel<RoomMemberContent>()
} }
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberContentsByUser)
} }
for (eventEntity in eventEntities) {
val senderId = eventEntity.sender ?: continue
val roomMemberEvent = roomMemberEventsByUser.getOrPut(senderId) {
CurrentStateEventEntity.getOrNull(realm, roomId, senderId, EventType.STATE_ROOM_MEMBER)?.root
}
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberEvent)
}
val chunks = ChunkEntity.findAllIncludingEvents(realm, eventIds) val chunks = ChunkEntity.findAllIncludingEvents(realm, eventIds)
val chunksToDelete = ArrayList<ChunkEntity>() val chunksToDelete = ArrayList<ChunkEntity>()
chunks.forEach { chunks.forEach {

View File

@ -21,20 +21,21 @@ 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.EventType
import im.vector.matrix.android.api.session.events.model.toModel 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.Membership
import im.vector.matrix.android.api.session.room.model.RoomMemberContent
import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent import im.vector.matrix.android.api.session.room.model.tag.RoomTagContent
import im.vector.matrix.android.api.session.room.send.SendState import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.internal.crypto.DefaultCryptoService import im.vector.matrix.android.internal.crypto.DefaultCryptoService
import im.vector.matrix.android.internal.database.helper.* import im.vector.matrix.android.internal.database.helper.addOrUpdate
import im.vector.matrix.android.internal.database.mapper.asDomain import im.vector.matrix.android.internal.database.helper.addTimelineEvent
import im.vector.matrix.android.internal.database.mapper.ContentMapper
import im.vector.matrix.android.internal.database.mapper.toEntity 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.ChunkEntity
import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity import im.vector.matrix.android.internal.database.model.CurrentStateEventEntity
import im.vector.matrix.android.internal.database.model.EventEntity import im.vector.matrix.android.internal.database.model.CurrentStateEventEntityFields
import im.vector.matrix.android.internal.database.model.RoomEntity import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.database.query.find import im.vector.matrix.android.internal.database.query.find
import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom import im.vector.matrix.android.internal.database.query.findLastLiveChunkFromRoom
import im.vector.matrix.android.internal.database.query.getOrCreate import im.vector.matrix.android.internal.database.query.getOrCreate
import im.vector.matrix.android.internal.database.query.getOrNull
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService import im.vector.matrix.android.internal.session.DefaultInitialSyncProgressService
import im.vector.matrix.android.internal.session.mapWithProgress import im.vector.matrix.android.internal.session.mapWithProgress
@ -44,7 +45,11 @@ import im.vector.matrix.android.internal.session.room.read.FullyReadContent
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimeline import im.vector.matrix.android.internal.session.room.timeline.DefaultTimeline
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import im.vector.matrix.android.internal.session.room.typing.TypingEventContent import im.vector.matrix.android.internal.session.room.typing.TypingEventContent
import im.vector.matrix.android.internal.session.sync.model.* 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.RoomsSyncResponse
import io.realm.Realm import io.realm.Realm
import io.realm.kotlin.createObject import io.realm.kotlin.createObject
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
@ -211,7 +216,16 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
chunkEntity.isLastForward = true chunkEntity.isLastForward = true
val eventIds = ArrayList<String>(eventList.size) val eventIds = ArrayList<String>(eventList.size)
val roomMemberEventsByUser = HashMap<String, EventEntity?>() val roomMemberContentsByUser = HashMap<String, RoomMemberContent?>()
realm.where(CurrentStateEventEntity::class.java)
.equalTo(CurrentStateEventEntityFields.ROOM_ID, roomId)
.equalTo(CurrentStateEventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
.findAll()
.forEach {
val roomMember = ContentMapper.map(it.root?.content).toModel<RoomMemberContent>()
roomMemberContentsByUser[it.stateKey] = roomMember
}
for (event in eventList) { for (event in eventList) {
if (event.eventId == null || event.senderId == null) { if (event.eventId == null || event.senderId == null) {
@ -227,14 +241,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
root = eventEntity root = eventEntity
} }
if (event.type == EventType.STATE_ROOM_MEMBER) { if (event.type == EventType.STATE_ROOM_MEMBER) {
roomMemberEventsByUser[event.stateKey] = eventEntity roomMemberContentsByUser[event.stateKey] = event.content.toModel()
roomMemberEventHandler.handle(realm, roomEntity.roomId, event) roomMemberEventHandler.handle(realm, roomEntity.roomId, event)
} }
} }
val roomMemberEvent = roomMemberEventsByUser.getOrPut(event.senderId) { chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberContentsByUser)
CurrentStateEventEntity.getOrNull(realm, roomId, event.senderId, EventType.STATE_ROOM_MEMBER)?.root
}
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberEvent)
// Give info to crypto module // Give info to crypto module
cryptoService.onLiveEvent(roomEntity.roomId, event) cryptoService.onLiveEvent(roomEntity.roomId, event)
// Try to remove local echo // Try to remove local echo

View File

@ -901,7 +901,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
setState { copy(asyncInviter = Success(it)) } setState { copy(asyncInviter = Success(it)) }
} }
} }
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE)?.also { room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE, "")?.also {
setState { copy(tombstoneEvent = it) } setState { copy(tombstoneEvent = it) }
} }
} }

View File

@ -147,7 +147,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor(@Assisted private v
private fun observeRoomSummaryAndPowerLevels(room: Room) { private fun observeRoomSummaryAndPowerLevels(room: Room) {
val roomSummaryLive = room.rx().liveRoomSummary().unwrap() val roomSummaryLive = room.rx().liveRoomSummary().unwrap()
val powerLevelsContentLive = room.rx().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS) val powerLevelsContentLive = room.rx().liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "")
.mapOptional { it.content.toModel<PowerLevelsContent>() } .mapOptional { it.content.toModel<PowerLevelsContent>() }
.unwrap() .unwrap()

View File

@ -72,7 +72,7 @@ class RoomMemberListViewModel @AssistedInject constructor(@Assisted initialState
.combineLatest<List<RoomMemberSummary>, PowerLevelsContent, RoomMemberSummaries>( .combineLatest<List<RoomMemberSummary>, PowerLevelsContent, RoomMemberSummaries>(
room.rx().liveRoomMembers(roomMemberQueryParams), room.rx().liveRoomMembers(roomMemberQueryParams),
room.rx() room.rx()
.liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS) .liveStateEvent(EventType.STATE_ROOM_POWER_LEVELS, "")
.mapOptional { it.content.toModel<PowerLevelsContent>() } .mapOptional { it.content.toModel<PowerLevelsContent>() }
.unwrap(), .unwrap(),
BiFunction { roomMembers, powerLevelsContent -> BiFunction { roomMembers, powerLevelsContent ->