Timeline event: handle displayName/avatar [WIP]

This commit is contained in:
ganfra 2019-07-05 19:07:33 +02:00
parent c503445092
commit 78951b9155
6 changed files with 92 additions and 74 deletions

View File

@ -18,17 +18,28 @@ 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
@ -64,11 +75,11 @@ internal fun ChunkEntity.merge(roomId: String,
this.isLastBackward = chunkToMerge.isLastBackward
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.ROOT.DISPLAY_INDEX, Sort.DESCENDING)
}
eventsToMerge.forEach {
it.root?.let { root ->
add(roomId, root.asDomain(), direction, isUnlinked = isUnlinked)
}
val events = eventsToMerge.mapNotNull { it.root?.asDomain() }
events.forEach { event ->
add(roomId, event, direction, isUnlinked = isUnlinked)
}
updateSenderDataFor(roomId, isUnlinked, events)
}

internal fun ChunkEntity.addAll(roomId: String,
@ -81,13 +92,35 @@ internal fun ChunkEntity.addAll(roomId: String,
events.forEach { event ->
add(roomId, event, direction, stateIndexOffset, isUnlinked)
}
updateSenderDataFor(roomId, isUnlinked, events)
}

internal fun ChunkEntity.add(roomId: String,
event: Event,
direction: PaginationDirection,
stateIndexOffset: Int = 0,
isUnlinked: Boolean = false) {
private fun ChunkEntity.updateSenderDataFor(roomId: String, isUnlinked: Boolean, events: List<Event>) {
for (event in events) {
val eventId = event.eventId ?: continue
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)
}
}

private fun ChunkEntity.add(roomId: String,
event: Event,
direction: PaginationDirection,
stateIndexOffset: Int = 0,
isUnlinked: Boolean = false) {

assertIsManaged()
if (event.eventId != null && timelineEvents.find(event.eventId) != null) {
@ -128,6 +161,19 @@ internal fun ChunkEntity.add(roomId: String,
timelineEvents.add(position, eventEntity)
}

private fun RealmList<TimelineEventEntity>.build(sender: String, isUnlinked: Boolean): RealmQuery<TimelineEventEntity> {
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<EventEntity>.build(sender: String): RealmQuery<EventEntity> {
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

View File

@ -24,6 +24,7 @@ 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.query.fastContains
import im.vector.matrix.android.internal.extensions.assertIsManaged
import im.vector.matrix.android.internal.session.room.membership.RoomMembers


internal fun RoomEntity.deleteOnCascade(chunkEntity: ChunkEntity) {
@ -58,13 +59,19 @@ internal fun RoomEntity.addStateEvents(stateEvents: List<Event>,

internal fun RoomEntity.addSendingEvent(event: Event) {
assertIsManaged()
val senderId = event.senderId ?: return
val eventEntity = event.toEntity(roomId).apply {
this.sendState = SendState.UNSENT
}
val roomMembers = RoomMembers(realm, roomId)
val myUser = roomMembers.get(senderId)
val timelineEventEntity = TimelineEventEntity().also {
it.root = eventEntity
it.eventId = event.eventId ?: ""
it.roomId = roomId
it.senderName = myUser?.displayName
it.senderAvatar = myUser?.avatarUrl
it.isUniqueDisplayName = roomMembers.isUniqueDisplayName(myUser?.displayName)
}
sendingTimelineEvents.add(0, timelineEventEntity)
}

View File

@ -16,13 +16,9 @@

package im.vector.matrix.android.internal.database.query

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.EventEntity.LinkFilterMode.*
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 io.realm.Realm
import io.realm.RealmList
import io.realm.RealmQuery

View File

@ -19,7 +19,6 @@ package im.vector.matrix.android.internal.database.query
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.EventEntity.LinkFilterMode.*
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
@ -38,9 +37,9 @@ internal fun TimelineEventEntity.Companion.where(realm: Realm, eventIds: List<St
}

internal fun TimelineEventEntity.Companion.where(realm: Realm,
roomId: String? = null,
type: String? = null,
linkFilterMode: EventEntity.LinkFilterMode = LINKED_ONLY): RealmQuery<TimelineEventEntity> {
roomId: String? = null,
type: String? = null,
linkFilterMode: EventEntity.LinkFilterMode = LINKED_ONLY): RealmQuery<TimelineEventEntity> {
val query = realm.where<TimelineEventEntity>()
if (roomId != null) {
query.equalTo(TimelineEventEntityFields.ROOM_ID, roomId)
@ -78,6 +77,33 @@ internal fun TimelineEventEntity.Companion.latestEvent(realm: Realm,
?.findFirst()
}

internal fun RealmQuery<TimelineEventEntity>.next(from: Int? = null, strict: Boolean = true): TimelineEventEntity? {
if (from != null) {
if (strict) {
this.greaterThan(TimelineEventEntityFields.ROOT.STATE_INDEX, from)
} else {
this.greaterThanOrEqualTo(TimelineEventEntityFields.ROOT.STATE_INDEX, from)
}
}
return this
.sort(TimelineEventEntityFields.ROOT.STATE_INDEX, Sort.ASCENDING)
.findFirst()
}

internal fun RealmQuery<TimelineEventEntity>.prev(since: Int? = null, strict: Boolean = false): TimelineEventEntity? {
if (since != null) {
if (strict) {
this.lessThan(TimelineEventEntityFields.ROOT.STATE_INDEX, since)
} else {
this.lessThanOrEqualTo(TimelineEventEntityFields.ROOT.STATE_INDEX, since)
}
}
return this
.sort(TimelineEventEntityFields.ROOT.STATE_INDEX, Sort.DESCENDING)
.findFirst()
}


internal fun RealmList<TimelineEventEntity>.find(eventId: String): TimelineEventEntity? {
return this.where().equalTo(TimelineEventEntityFields.ROOT.EVENT_ID, eventId).findFirst()
}

View File

@ -24,7 +24,6 @@ import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.internal.database.mapper.RoomSummaryMapper
import im.vector.matrix.android.internal.session.room.membership.DefaultMembershipService
import im.vector.matrix.android.internal.session.room.membership.LoadRoomMembersTask
import im.vector.matrix.android.internal.session.room.membership.SenderRoomMemberExtractor
import im.vector.matrix.android.internal.session.room.membership.joining.InviteTask
import im.vector.matrix.android.internal.session.room.membership.joining.JoinRoomTask
import im.vector.matrix.android.internal.session.room.membership.leaving.LeaveRoomTask

View File

@ -1,56 +0,0 @@
/*
* 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.membership

internal object SenderRoomMemberExtractor {

/*
fun extractFrom(event: Event, realm: Realm): RoomMember? {
val roomId = event.roomId
val sender = event.senderId ?: return null
// If the event is unlinked we want to fetch unlinked state events
val unlinked = event.isUnlinked
val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst() ?: return null

// When not synced, we should grab the live RoomMember event
return if (event.sendState != SendState.SYNCED) {
RoomMembers(realm, roomId).get(sender)
} else {
val chunkEntity = ChunkEntity.findIncludingEvent(realm, event.eventId)
val content = when {
chunkEntity == null -> null
event.stateIndex <= 0 -> baseQuery(chunkEntity.events, sender, unlinked).next(from = event.stateIndex)?.prevContent
else -> baseQuery(chunkEntity.events, sender, unlinked).prev(since = event.stateIndex)?.content
}
val fallbackContent = content
?: baseQuery(roomEntity.untimelinedStateEvents, sender, unlinked).prev(since = event.stateIndex)?.content
ContentMapper.map(fallbackContent).toModel()
}
}

private fun baseQuery(list: RealmList<EventEntity>,
sender: String,
isUnlinked: Boolean): RealmQuery<EventEntity> {
return list
.where()
.equalTo(EventEntityFields.STATE_KEY, sender)
.equalTo(EventEntityFields.TYPE, EventType.STATE_ROOM_MEMBER)
.equalTo(EventEntityFields.IS_UNLINKED, isUnlinked)
}

*/
}