BayernMessenger/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt

165 lines
7.2 KiB
Kotlin
Raw Normal View History

2018-10-17 16:21:09 +00:00
package im.vector.matrix.android.internal.session.sync
2018-10-18 09:16:02 +00:00
import com.zhuinden.monarchy.Monarchy
2018-10-17 16:21:09 +00:00
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.room.model.MyMembership
import im.vector.matrix.android.internal.database.helper.addManagedToChunk
2018-10-12 17:26:22 +00:00
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.RoomSummaryEntity
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.where
2018-10-17 16:21:09 +00:00
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.RoomSyncEphemeral
import im.vector.matrix.android.internal.session.sync.model.RoomSyncSummary
2018-10-30 17:22:29 +00:00
import im.vector.matrix.android.internal.session.sync.model.RoomsSyncResponse
2018-10-15 17:42:13 +00:00
import io.realm.Realm
import io.realm.kotlin.createObject
internal class RoomSyncHandler(private val monarchy: Monarchy,
private val stateEventsChunkHandler: StateEventsChunkHandler,
private val readReceiptHandler: ReadReceiptHandler) {
2018-10-15 17:42:13 +00:00
sealed class HandlingStrategy {
data class JOINED(val data: Map<String, RoomSync>) : HandlingStrategy()
data class INVITED(val data: Map<String, InvitedRoomSync>) : HandlingStrategy()
data class LEFT(val data: Map<String, RoomSync>) : HandlingStrategy()
}
2018-10-30 17:22:29 +00:00
fun handle(roomsSyncResponse: RoomsSyncResponse) {
handleRoomSync(RoomSyncHandler.HandlingStrategy.JOINED(roomsSyncResponse.join))
handleRoomSync(RoomSyncHandler.HandlingStrategy.INVITED(roomsSyncResponse.invite))
handleRoomSync(RoomSyncHandler.HandlingStrategy.LEFT(roomsSyncResponse.leave))
monarchy.runTransactionSync { realm ->
roomsSyncResponse.join.forEach { (roomId, roomSync) ->
handleEphemeral(realm, roomId, roomSync.ephemeral)
}
}
}
// PRIVATE METHODS *****************************************************************************
private fun handleRoomSync(handlingStrategy: HandlingStrategy) {
monarchy.runTransactionSync { realm ->
val rooms = when (handlingStrategy) {
is HandlingStrategy.JOINED -> handlingStrategy.data.map { handleJoinedRoom(realm, it.key, it.value) }
2018-10-15 17:42:13 +00:00
is HandlingStrategy.INVITED -> handlingStrategy.data.map { handleInvitedRoom(realm, it.key, it.value) }
is HandlingStrategy.LEFT -> handlingStrategy.data.map { handleLeftRoom(it.key, it.value) }
2018-10-15 17:42:13 +00:00
}
realm.insertOrUpdate(rooms)
2018-10-12 17:26:22 +00:00
}
}
2018-10-15 17:42:13 +00:00
private fun handleJoinedRoom(realm: Realm,
roomId: String,
roomSync: RoomSync): RoomEntity {
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: RoomEntity(roomId)
2018-10-15 17:42:13 +00:00
if (roomEntity.membership == MyMembership.INVITED) {
2018-10-15 17:42:13 +00:00
roomEntity.chunks.deleteAllFromRealm()
2018-10-12 17:26:22 +00:00
}
2018-10-15 17:42:13 +00:00
roomEntity.membership = MyMembership.JOINED
2018-10-15 17:42:13 +00:00
if (roomSync.state != null && roomSync.state.events.isNotEmpty()) {
val chunkEntity = stateEventsChunkHandler.handle(realm, roomId, roomSync.state.events)
2018-10-15 17:42:13 +00:00
if (!roomEntity.chunks.contains(chunkEntity)) {
roomEntity.chunks.add(chunkEntity)
}
}
if (roomSync.timeline != null && roomSync.timeline.events.isNotEmpty()) {
val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.timeline.events, roomSync.timeline.prevToken, isLimited = roomSync.timeline.limited)
2018-10-15 17:42:13 +00:00
if (!roomEntity.chunks.contains(chunkEntity)) {
roomEntity.chunks.add(chunkEntity)
}
2018-10-12 17:26:22 +00:00
}
if (roomSync.summary != null) {
handleRoomSummary(realm, roomId, roomSync.summary)
}
2018-10-15 17:42:13 +00:00
return roomEntity
}
2018-10-12 17:26:22 +00:00
2018-10-15 17:42:13 +00:00
private fun handleInvitedRoom(realm: Realm,
roomId: String,
roomSync:
InvitedRoomSync): RoomEntity {
val roomEntity = RoomEntity()
roomEntity.roomId = roomId
roomEntity.membership = MyMembership.INVITED
2018-10-15 17:42:13 +00:00
if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
val chunkEntity = handleTimelineEvents(realm, roomId, roomSync.inviteState.events)
2018-10-15 17:42:13 +00:00
if (!roomEntity.chunks.contains(chunkEntity)) {
roomEntity.chunks.add(chunkEntity)
}
2018-10-12 17:26:22 +00:00
}
return roomEntity
}
2018-10-15 17:42:13 +00:00
// TODO : handle it
private fun handleLeftRoom(roomId: String,
roomSync: RoomSync): RoomEntity {
return RoomEntity().apply {
this.roomId = roomId
this.membership = MyMembership.LEFT
}
}
private fun handleRoomSummary(realm: Realm,
roomId: String,
roomSummary: RoomSyncSummary) {
val roomSummaryEntity = RoomSummaryEntity.where(realm, roomId).findFirst()
?: RoomSummaryEntity(roomId)
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
2018-10-15 17:42:13 +00:00
}
realm.insertOrUpdate(roomSummaryEntity)
2018-10-15 17:42:13 +00:00
}
private fun handleTimelineEvents(realm: Realm,
roomId: String,
eventList: List<Event>,
prevToken: String? = null,
nextToken: String? = null,
isLimited: Boolean = true): ChunkEntity {
2018-10-15 17:42:13 +00:00
val chunkEntity = if (!isLimited) {
ChunkEntity.findLastLiveChunkFromRoom(realm, roomId)
2018-10-15 17:42:13 +00:00
} else {
val eventIds = eventList.filter { it.eventId != null }.map { it.eventId!! }
ChunkEntity.findAllIncludingEvents(realm, eventIds).firstOrNull()
} ?: realm.createObject<ChunkEntity>().apply { this.prevToken = prevToken }
2018-10-15 17:42:13 +00:00
2018-10-13 09:18:49 +00:00
chunkEntity.nextToken = nextToken
eventList.addManagedToChunk(chunkEntity)
2018-10-13 09:18:49 +00:00
return chunkEntity
}
private fun handleEphemeral(realm: Realm,
roomId: String,
ephemeral: RoomSyncEphemeral?) {
if (ephemeral == null || ephemeral.events.isNullOrEmpty()) {
return
}
ephemeral.events
.filter { it.type == EventType.RECEIPT }
.map { it.content<ReadReceiptContent>() }
.flatMap { readReceiptHandler.handle(realm, roomId, it) }
}
}