mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-16 02:05:06 +08:00
Add state events to chunks
This commit is contained in:
parent
bf7c53ecab
commit
a8f783bbfa
@ -16,12 +16,14 @@
|
|||||||
|
|
||||||
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.events.model.toModel
|
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.EventAnnotationsSummaryEntity
|
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.EventEntity
|
||||||
|
import im.vector.matrix.android.internal.database.model.EventEntityFields
|
||||||
import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
|
import im.vector.matrix.android.internal.database.model.ReadReceiptEntity
|
||||||
import im.vector.matrix.android.internal.database.model.ReadReceiptsSummaryEntity
|
import im.vector.matrix.android.internal.database.model.ReadReceiptsSummaryEntity
|
||||||
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
import im.vector.matrix.android.internal.database.model.TimelineEventEntity
|
||||||
@ -33,6 +35,7 @@ import im.vector.matrix.android.internal.extensions.assertIsManaged
|
|||||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import io.realm.kotlin.createObject
|
import io.realm.kotlin.createObject
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
internal fun ChunkEntity.deleteOnCascade() {
|
internal fun ChunkEntity.deleteOnCascade() {
|
||||||
assertIsManaged()
|
assertIsManaged()
|
||||||
@ -40,7 +43,7 @@ internal fun ChunkEntity.deleteOnCascade() {
|
|||||||
this.deleteFromRealm()
|
this.deleteFromRealm()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun ChunkEntity.merge(chunkToMerge: ChunkEntity, direction: PaginationDirection) {
|
internal fun ChunkEntity.merge(roomId: String, chunkToMerge: ChunkEntity, direction: PaginationDirection) {
|
||||||
assertIsManaged()
|
assertIsManaged()
|
||||||
val eventsToMerge: List<TimelineEventEntity>
|
val eventsToMerge: List<TimelineEventEntity>
|
||||||
if (direction == PaginationDirection.FORWARDS) {
|
if (direction == PaginationDirection.FORWARDS) {
|
||||||
@ -52,6 +55,9 @@ internal fun ChunkEntity.merge(chunkToMerge: ChunkEntity, direction: PaginationD
|
|||||||
this.isLastBackward = chunkToMerge.isLastBackward
|
this.isLastBackward = chunkToMerge.isLastBackward
|
||||||
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
|
eventsToMerge = chunkToMerge.timelineEvents.sort(TimelineEventEntityFields.DISPLAY_INDEX, Sort.DESCENDING)
|
||||||
}
|
}
|
||||||
|
chunkToMerge.stateEvents.forEach { stateEvent ->
|
||||||
|
addStateEvent(roomId, stateEvent, direction)
|
||||||
|
}
|
||||||
return eventsToMerge
|
return eventsToMerge
|
||||||
.forEach {
|
.forEach {
|
||||||
if (timelineEvents.find(it.eventId) == null) {
|
if (timelineEvents.find(it.eventId) == null) {
|
||||||
@ -61,10 +67,29 @@ internal fun ChunkEntity.merge(chunkToMerge: ChunkEntity, direction: PaginationD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun ChunkEntity.addStateEvent(roomId: String, stateEvent: EventEntity, direction: PaginationDirection) {
|
||||||
|
if (direction == PaginationDirection.FORWARDS) {
|
||||||
|
Timber.v("We don't keep chunk state events when paginating forward")
|
||||||
|
} else {
|
||||||
|
val stateKey = stateEvent.stateKey ?: return
|
||||||
|
val type = stateEvent.type
|
||||||
|
val pastStateEvent = stateEvents.where()
|
||||||
|
.equalTo(EventEntityFields.ROOM_ID, roomId)
|
||||||
|
.equalTo(EventEntityFields.STATE_KEY, stateKey)
|
||||||
|
.equalTo(CurrentStateEventEntityFields.TYPE, type)
|
||||||
|
.findFirst()
|
||||||
|
|
||||||
|
if (pastStateEvent != null) {
|
||||||
|
stateEvents.remove(pastStateEvent)
|
||||||
|
}
|
||||||
|
stateEvents.add(stateEvent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun ChunkEntity.addTimelineEvent(roomId: String,
|
internal fun ChunkEntity.addTimelineEvent(roomId: String,
|
||||||
eventEntity: EventEntity,
|
eventEntity: EventEntity,
|
||||||
direction: PaginationDirection,
|
direction: PaginationDirection,
|
||||||
roomMemberEvent: Event?) {
|
roomMemberEvent: EventEntity?) {
|
||||||
|
|
||||||
val eventId = eventEntity.eventId
|
val eventId = eventEntity.eventId
|
||||||
if (timelineEvents.find(eventId) != null) {
|
if (timelineEvents.find(eventId) != null) {
|
||||||
@ -104,10 +129,9 @@ internal fun ChunkEntity.addTimelineEvent(roomId: String,
|
|||||||
this.readReceipts = readReceiptsSummaryEntity
|
this.readReceipts = readReceiptsSummaryEntity
|
||||||
this.displayIndex = displayIndex
|
this.displayIndex = displayIndex
|
||||||
if (roomMemberEvent != null) {
|
if (roomMemberEvent != null) {
|
||||||
val roomMemberContent = roomMemberEvent.content.toModel<RoomMemberContent>()
|
val roomMemberContent = ContentMapper.map(roomMemberEvent.content).toModel<RoomMemberContent>()
|
||||||
this.senderAvatar = roomMemberContent?.avatarUrl
|
this.senderAvatar = roomMemberContent?.avatarUrl
|
||||||
this.senderName = roomMemberContent?.displayName
|
this.senderName = roomMemberContent?.displayName
|
||||||
this.isUniqueDisplayName = false
|
|
||||||
this.senderMembershipEventId = roomMemberEvent.eventId
|
this.senderMembershipEventId = roomMemberEvent.eventId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import io.realm.annotations.LinkingObjects
|
|||||||
|
|
||||||
internal open class ChunkEntity(@Index var prevToken: String? = null,
|
internal open class ChunkEntity(@Index var prevToken: String? = null,
|
||||||
@Index var nextToken: String? = null,
|
@Index var nextToken: String? = null,
|
||||||
|
var stateEvents: RealmList<EventEntity> = RealmList(),
|
||||||
var timelineEvents: RealmList<TimelineEventEntity> = RealmList(),
|
var timelineEvents: RealmList<TimelineEventEntity> = RealmList(),
|
||||||
@Index var isLastForward: Boolean = false,
|
@Index var isLastForward: Boolean = false,
|
||||||
@Index var isLastBackward: Boolean = false
|
@Index var isLastBackward: Boolean = false
|
||||||
|
@ -21,6 +21,7 @@ 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.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.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
|
||||||
@ -192,7 +193,7 @@ 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, Event?>()
|
val roomMemberEventsByUser = HashMap<String, EventEntity?>()
|
||||||
val eventList = if (direction == PaginationDirection.FORWARDS) {
|
val eventList = if (direction == PaginationDirection.FORWARDS) {
|
||||||
receivedChunk.events
|
receivedChunk.events
|
||||||
} else {
|
} else {
|
||||||
@ -200,8 +201,12 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||||||
}
|
}
|
||||||
val stateEvents = receivedChunk.stateEvents
|
val stateEvents = receivedChunk.stateEvents
|
||||||
for (stateEvent in stateEvents) {
|
for (stateEvent in stateEvents) {
|
||||||
|
val stateEventEntity = stateEvent.toEntity(roomId, SendState.SYNCED).let {
|
||||||
|
realm.copyToRealmOrUpdate(it)
|
||||||
|
}
|
||||||
|
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] = stateEvent
|
roomMemberEventsByUser[stateEvent.stateKey] = stateEventEntity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val eventIds = ArrayList<String>(eventList.size)
|
val eventIds = ArrayList<String>(eventList.size)
|
||||||
@ -220,13 +225,13 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||||||
eventEntities.add(0, eventEntity)
|
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] = event
|
roomMemberEventsByUser[event.stateKey] = eventEntity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (eventEntity in eventEntities) {
|
for (eventEntity in eventEntities) {
|
||||||
val senderId = eventEntity.sender ?: continue
|
val senderId = eventEntity.sender ?: continue
|
||||||
val roomMemberEvent = roomMemberEventsByUser.getOrPut(senderId) {
|
val roomMemberEvent = roomMemberEventsByUser.getOrPut(senderId) {
|
||||||
CurrentStateEventEntity.getOrNull(realm, roomId, senderId, EventType.STATE_ROOM_MEMBER)?.root?.asDomain()
|
CurrentStateEventEntity.getOrNull(realm, roomId, senderId, EventType.STATE_ROOM_MEMBER)?.root
|
||||||
}
|
}
|
||||||
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberEvent)
|
currentChunk.addTimelineEvent(roomId, eventEntity, direction, roomMemberEvent)
|
||||||
}
|
}
|
||||||
@ -235,7 +240,7 @@ internal class TokenChunkEventPersistor @Inject constructor(private val monarchy
|
|||||||
val chunksToDelete = ArrayList<ChunkEntity>()
|
val chunksToDelete = ArrayList<ChunkEntity>()
|
||||||
chunks.forEach {
|
chunks.forEach {
|
||||||
if (it != currentChunk) {
|
if (it != currentChunk) {
|
||||||
currentChunk.merge(it, direction)
|
currentChunk.merge(roomId, it, direction)
|
||||||
chunksToDelete.add(it)
|
chunksToDelete.add(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ 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.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.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
|
||||||
@ -210,7 +211,7 @@ 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, Event?>()
|
val roomMemberEventsByUser = HashMap<String, EventEntity?>()
|
||||||
|
|
||||||
for (event in eventList) {
|
for (event in eventList) {
|
||||||
if (event.eventId == null || event.senderId == null) {
|
if (event.eventId == null || event.senderId == null) {
|
||||||
@ -226,12 +227,12 @@ 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] = event
|
roomMemberEventsByUser[event.stateKey] = eventEntity
|
||||||
roomMemberEventHandler.handle(realm, roomEntity.roomId, event)
|
roomMemberEventHandler.handle(realm, roomEntity.roomId, event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val roomMemberEvent = roomMemberEventsByUser.getOrPut(event.senderId) {
|
val roomMemberEvent = roomMemberEventsByUser.getOrPut(event.senderId) {
|
||||||
CurrentStateEventEntity.getOrNull(realm, roomId, event.senderId, EventType.STATE_ROOM_MEMBER)?.root?.asDomain()
|
CurrentStateEventEntity.getOrNull(realm, roomId, event.senderId, EventType.STATE_ROOM_MEMBER)?.root
|
||||||
}
|
}
|
||||||
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberEvent)
|
chunkEntity.addTimelineEvent(roomId, eventEntity, PaginationDirection.FORWARDS, roomMemberEvent)
|
||||||
// Give info to crypto module
|
// Give info to crypto module
|
||||||
|
Loading…
Reference in New Issue
Block a user