From 279241974af3c71d841444d77066f21074a15bcc Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 22 Oct 2018 19:36:29 +0200 Subject: [PATCH] Add a way to enrich event with useful data to be displayed. --- .../features/home/EventDiffUtilCallback.kt | 16 +++++---- .../features/home/RoomDetailFragment.kt | 6 ++-- .../features/home/TimelineEventAdapter.kt | 29 +++++++++------ .../features/home/TimelineEventController.kt | 2 +- .../interceptor/EnrichedEventInterceptor.kt | 12 +++++++ .../interceptor/MessageEventInterceptor.kt | 29 +++++++++++++++ .../api/session/events/model/EnrichedEvent.kt | 35 +++++++++++++++++++ .../matrix/android/api/session/room/Room.kt | 4 +-- .../api/session/room/model/MessageContent.kt | 14 ++++++++ .../api/session/room/model/MessageType.kt | 17 +++++++++ .../api/session/room/model/RoomMember.kt | 4 +-- .../database/query/EventEntityQueries.kt | 32 +++++++---------- .../internal/session/room/DefaultRoom.kt | 27 +++++++++++--- .../session/room/RoomSummaryObserver.kt | 9 +++-- .../room/timeline/PaginationRequest.kt | 18 +++------- .../room/timeline/TimelineBoundaryCallback.kt | 16 ++++----- .../internal/session/sync/RoomSyncHandler.kt | 19 +++++----- .../session/sync/StateEventsChunkHandler.kt | 28 +++++++++++++++ 18 files changed, 232 insertions(+), 85 deletions(-) create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/EnrichedEventInterceptor.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/MessageEventInterceptor.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EnrichedEvent.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageContent.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageType.kt create mode 100644 matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt diff --git a/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt b/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt index fa5adb2be9..1a54f399f6 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/EventDiffUtilCallback.kt @@ -1,14 +1,18 @@ package im.vector.riotredesign.features.home import android.support.v7.util.DiffUtil -import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.model.EnrichedEvent -class EventDiffUtilCallback : DiffUtil.ItemCallback() { - override fun areItemsTheSame(p0: Event, p1: Event): Boolean { - return p0.eventId == p1.eventId +class EventDiffUtilCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(p0: EnrichedEvent, p1: EnrichedEvent): Boolean { + return p0.core.eventId == p1.core.eventId } - override fun areContentsTheSame(p0: Event, p1: Event): Boolean { - return p0 == p1 + override fun areContentsTheSame(p0: EnrichedEvent, p1: EnrichedEvent): Boolean { + return p0.core == p1.core + && p0.getMetaEvents() + .zip(p1.getMetaEvents()) { a, b -> + a.eventId == b.eventId + }.none { !it } } } \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt b/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt index 81b95dc3b8..9912ec1a74 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/RoomDetailFragment.kt @@ -9,7 +9,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import im.vector.matrix.android.api.Matrix -import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.api.session.room.Room import im.vector.riotredesign.R import im.vector.riotredesign.core.platform.RiotFragment @@ -46,7 +46,7 @@ class RoomDetailFragment : RiotFragment(), TimelineEventAdapter.Callback { room.liveTimeline().observe(this, Observer { renderEvents(it) }) } - private fun renderEvents(events: PagedList?) { + private fun renderEvents(events: PagedList?) { timelineAdapter.submitList(events) } @@ -65,7 +65,7 @@ class RoomDetailFragment : RiotFragment(), TimelineEventAdapter.Callback { //recyclerView.setController(timelineEventController) } - override fun onEventsListChanged(oldList: List?, newList: List?) { + override fun onEventsListChanged(oldList: List?, newList: List?) { if (oldList == null && newList != null) { recyclerView.scrollToPosition(0) } diff --git a/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventAdapter.kt b/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventAdapter.kt index a3c1b9d018..750256e3a9 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventAdapter.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventAdapter.kt @@ -7,7 +7,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.TextView -import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.model.EnrichedEvent +import im.vector.matrix.android.api.session.events.model.EventType +import im.vector.matrix.android.api.session.room.model.MessageContent +import im.vector.matrix.android.api.session.room.model.RoomMember import im.vector.riotredesign.R /** @@ -15,10 +18,10 @@ import im.vector.riotredesign.R */ class TimelineEventAdapter(private val callback: Callback? = null) - : PagedListAdapter(EventDiffUtilCallback()) { + : PagedListAdapter(EventDiffUtilCallback()) { - private var currentList: List? = null + private var currentList: List? = null override fun onCreateViewHolder(parent: ViewGroup, position: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_event, parent, false) @@ -30,27 +33,33 @@ class TimelineEventAdapter(private val callback: Callback? = null) viewHolder.bind(event) } - class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { val titleView = view.findViewById(R.id.titleView)!! - fun bind(event: Event?) { - if (event == null) { - + fun bind(event: EnrichedEvent?) { + if (event == null || event.core.type != EventType.MESSAGE) { + titleView.text = null } else { - titleView.text = event.toString() + val messageContent = event.core.content() + val roomMember = event.getMetaEvents(EventType.STATE_ROOM_MEMBER).firstOrNull()?.content() + if (messageContent == null || roomMember == null) { + titleView.text = null + } else { + val text = "${roomMember.displayName} : ${messageContent.body}" + titleView.text = text + } } } } - override fun onCurrentListChanged(newList: PagedList?) { + override fun onCurrentListChanged(newList: PagedList?) { callback?.onEventsListChanged(currentList, newList) currentList = newList } interface Callback { - fun onEventsListChanged(oldList: List?, newList: List?) + fun onEventsListChanged(oldList: List?, newList: List?) } } diff --git a/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt b/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt index bb19f9a295..e536d10136 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/TimelineEventController.kt @@ -13,7 +13,7 @@ class TimelineEventController : PagedListEpoxyController( return if (item == null) { LoadingItemModel_().id(-currentPosition) } else { - TimelineEventItem(item.toString()).id(currentPosition) + TimelineEventItem(item.toString()).id(item.eventId) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/EnrichedEventInterceptor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/EnrichedEventInterceptor.kt new file mode 100644 index 0000000000..8a640fa61b --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/EnrichedEventInterceptor.kt @@ -0,0 +1,12 @@ +package im.vector.matrix.android.api.session.events.interceptor + +import im.vector.matrix.android.api.session.events.model.EnrichedEvent + +interface EnrichedEventInterceptor { + + fun enrich(roomId: String, event: EnrichedEvent) + + fun canEnrich(event: EnrichedEvent): Boolean + +} + diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/MessageEventInterceptor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/MessageEventInterceptor.kt new file mode 100644 index 0000000000..86ae000ca7 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/interceptor/MessageEventInterceptor.kt @@ -0,0 +1,29 @@ +package im.vector.matrix.android.api.session.events.interceptor + +import com.zhuinden.monarchy.Monarchy +import im.vector.matrix.android.api.session.events.model.EnrichedEvent +import im.vector.matrix.android.api.session.events.model.EventType +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.query.last +import im.vector.matrix.android.internal.database.query.where + +class MessageEventInterceptor(val monarchy: Monarchy) : EnrichedEventInterceptor { + + override fun canEnrich(event: EnrichedEvent): Boolean { + return event.core.type == EventType.MESSAGE + } + + override fun enrich(roomId: String, event: EnrichedEvent) { + monarchy.doWithRealm { realm -> + val roomMember = EventEntity + .where(realm, roomId, EventType.STATE_ROOM_MEMBER) + .equalTo("stateKey", event.core.sender) + .last(from = event.core.originServerTs) + ?.asDomain() + event.enrichWith(roomMember) + } + } + + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EnrichedEvent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EnrichedEvent.kt new file mode 100644 index 0000000000..5318421992 --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/events/model/EnrichedEvent.kt @@ -0,0 +1,35 @@ +package im.vector.matrix.android.api.session.events.model + +data class EnrichedEvent(val core: Event) { + + private val metaEventsByType = HashMap>() + + fun enrichWith(events: List) { + events.forEach { enrichWith(it) } + } + + fun enrichWith(event: Event?) { + if (event == null) { + return + } + var currentEventsForType = metaEventsByType[event.type] + if (currentEventsForType == null) { + currentEventsForType = ArrayList() + metaEventsByType[event.type] = currentEventsForType + } + currentEventsForType.add(event) + } + + fun getMetaEvents(type: String): List { + return metaEventsByType[type] ?: emptyList() + } + + fun getMetaEvents(): List { + return metaEventsByType.values.flatten() + } + + override fun toString(): String { + return super.toString() + } + +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt index 3e2a539677..1ca2497f21 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/Room.kt @@ -2,12 +2,12 @@ package im.vector.matrix.android.api.session.room import android.arch.lifecycle.LiveData import android.arch.paging.PagedList -import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.model.EnrichedEvent interface Room { val roomId: String - fun liveTimeline(): LiveData> + fun liveTimeline(): LiveData> } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageContent.kt new file mode 100644 index 0000000000..49a3ad6a6a --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageContent.kt @@ -0,0 +1,14 @@ +package im.vector.matrix.android.api.session.room.model + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class MessageContent( + + @Json(name = "msgtype") val type: String? = null, + @Json(name = "body") val body: String? = null, + @Json(name = "format") val format: String? = null, + @Json(name = "formatted_body") val formattedBody: String? = null + +) \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageType.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageType.kt new file mode 100644 index 0000000000..6ffebca66d --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/MessageType.kt @@ -0,0 +1,17 @@ +package im.vector.matrix.android.api.session.room.model + +object MessageType { + + val MSGTYPE_TEXT = "m.text" + val MSGTYPE_EMOTE = "m.emote" + val MSGTYPE_NOTICE = "m.notice" + val MSGTYPE_IMAGE = "m.image" + val MSGTYPE_AUDIO = "m.audio" + val MSGTYPE_VIDEO = "m.video" + val MSGTYPE_LOCATION = "m.location" + val MSGTYPE_FILE = "m.file" + val FORMAT_MATRIX_HTML = "org.matrix.custom.html" + // Add, in local, a fake message type in order to StickerMessage can inherit Message class + // Because sticker isn't a message type but a event type without msgtype field + val MSGTYPE_STICKER_LOCAL = "org.matrix.android.sdk.sticker" +} \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMember.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMember.kt index d292206226..9d610d4f24 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMember.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/room/model/RoomMember.kt @@ -7,9 +7,9 @@ import im.vector.matrix.android.api.session.events.model.UnsignedData @JsonClass(generateAdapter = true) data class RoomMember( @Json(name = "membership") val membership: Membership, - @Json(name = "display_name") val displayDame: String? = null, + @Json(name = "displayname") val displayName: String? = null, @Json(name = "avatar_url") val avatarUrl: String? = null, @Json(name = "is_direct") val isDirect: Boolean = false, @Json(name = "third_party_invite") val thirdPartyInvite: Invite? = null, - @Json(name = "unsigned_data") val unsignedData: UnsignedData? = null + @Json(name = "unsigned") val unsignedData: UnsignedData? = null ) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt index 66ed29f447..0752b386d9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/database/query/EventEntityQueries.kt @@ -1,32 +1,26 @@ 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 io.realm.Realm import io.realm.RealmQuery -import io.realm.RealmResults import io.realm.Sort -fun EventEntity.Companion.where(realm: Realm, roomId: String): RealmQuery { - return realm.where(EventEntity::class.java) - .equalTo("chunk.room.roomId", roomId) -} - -fun EventEntity.Companion.where(realm: Realm, chunk: ChunkEntity?): RealmQuery { +fun EventEntity.Companion.where(realm: Realm, roomId: String, type: String? = null): RealmQuery { var query = realm.where(EventEntity::class.java) - if (chunk?.prevToken != null) { - query = query.equalTo("chunk.prevToken", chunk.prevToken) - } - if (chunk?.nextToken != null) { - query = query.equalTo("chunk.nextToken", chunk.nextToken) + .equalTo("chunk.room.roomId", roomId) + if (type != null) { + query = query.equalTo("type", type) } return query } -fun RealmResults.getLast(type: String? = null): EventEntity? { - var query = this.where().sort("originServerTs", Sort.DESCENDING) - if (type != null) { - query = query.equalTo("type", type) + +fun RealmQuery.last(from: Long? = null): EventEntity? { + var query = this + if (from != null) { + query = query.lessThanOrEqualTo("originServerTs", from) } - return query.findFirst() -} \ No newline at end of file + return query + .sort("originServerTs", Sort.DESCENDING) + .findFirst() +} diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt index 19c8b5f0e8..bbb9921b20 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/DefaultRoom.kt @@ -4,9 +4,11 @@ import android.arch.lifecycle.LiveData import android.arch.paging.LivePagedListBuilder import android.arch.paging.PagedList import com.zhuinden.monarchy.Monarchy -import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.interceptor.EnrichedEventInterceptor +import im.vector.matrix.android.api.session.events.interceptor.MessageEventInterceptor +import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.api.session.room.Room -import im.vector.matrix.android.internal.database.mapper.EventMapper +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.query.where import im.vector.matrix.android.internal.session.room.timeline.PaginationRequest @@ -23,8 +25,13 @@ data class DefaultRoom( private val paginationRequest by inject() private val monarchy by inject() private val boundaryCallback = TimelineBoundaryCallback(paginationRequest, roomId, monarchy, Executors.newSingleThreadExecutor()) + private val eventInterceptors = ArrayList() - override fun liveTimeline(): LiveData> { + init { + eventInterceptors.add(MessageEventInterceptor(monarchy)) + } + + override fun liveTimeline(): LiveData> { val realmDataSourceFactory = monarchy.createDataSourceFactory { realm -> ChunkEntity.where(realm, roomId) .findAll() @@ -33,7 +40,18 @@ data class DefaultRoom( it.events.where().sort("originServerTs", Sort.DESCENDING) } } - val domainSourceFactory = realmDataSourceFactory.map { EventMapper.map(it) } + val domainSourceFactory = realmDataSourceFactory + .map { it.asDomain() } + .map { event -> + val enrichedEvent = EnrichedEvent(event) + eventInterceptors + .filter { + it.canEnrich(enrichedEvent) + }.forEach { + it.enrich(roomId, enrichedEvent) + } + enrichedEvent + } val pagedListConfig = PagedList.Config.Builder() .setEnablePlaceholders(false) @@ -45,5 +63,4 @@ data class DefaultRoom( return monarchy.findAllPagedWithChanges(realmDataSourceFactory, livePagedListBuilder) } - } \ No newline at end of file diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt index 89ca01e0de..c719596209 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/RoomSummaryObserver.kt @@ -8,7 +8,7 @@ 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.RoomEntity import im.vector.matrix.android.internal.database.model.RoomSummaryEntity -import im.vector.matrix.android.internal.database.query.getLast +import im.vector.matrix.android.internal.database.query.last import im.vector.matrix.android.internal.database.query.where import io.realm.RealmResults import java.util.concurrent.atomic.AtomicBoolean @@ -49,10 +49,9 @@ internal class RoomSummaryObserver(private val monarchy: Monarchy) { private fun manageRoom(roomId: String) { monarchy.writeAsync { realm -> - val roomEvents = EventEntity.where(realm, roomId).findAll() - val lastNameEvent = roomEvents.getLast(EventType.STATE_ROOM_NAME)?.asDomain() - val lastTopicEvent = roomEvents.getLast(EventType.STATE_ROOM_TOPIC)?.asDomain() - val lastMessageEvent = roomEvents.getLast(EventType.MESSAGE) + val lastNameEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_NAME).last()?.asDomain() + val lastTopicEvent = EventEntity.where(realm, roomId, EventType.STATE_ROOM_TOPIC).last()?.asDomain() + val lastMessageEvent = EventEntity.where(realm, roomId, EventType.MESSAGE).last() val roomSummary = realm.copyToRealmOrUpdate(RoomSummaryEntity(roomId)) roomSummary.displayName = lastNameEvent?.content()?.name diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt index 74f2118279..a48304b3de 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/PaginationRequest.kt @@ -7,7 +7,6 @@ import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.failure.Failure import im.vector.matrix.android.api.util.Cancelable -import im.vector.matrix.android.internal.database.DBConstants import im.vector.matrix.android.internal.database.mapper.asEntity import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.RoomEntity @@ -20,6 +19,7 @@ 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.model.PaginationDirection import im.vector.matrix.android.internal.session.room.model.TokenChunkEvent +import im.vector.matrix.android.internal.session.sync.StateEventsChunkHandler import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import kotlinx.coroutines.GlobalScope @@ -89,19 +89,9 @@ class PaginationRequest(private val roomAPI: RoomAPI, currentChunk.prevToken = chunkEvent.prevToken - val stateEventsChunk = ChunkEntity.findWithNextToken(realm, roomId, DBConstants.STATE_EVENTS_CHUNK_TOKEN) - ?: ChunkEntity().apply { - this.prevToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN - this.nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN - } - - chunkEvent.stateEvents.forEach { stateEvent -> - val eventEntity = stateEvent.asEntity().let { - realm.copyToRealmOrUpdate(it) - } - if (!stateEventsChunk.events.contains(eventEntity)) { - stateEventsChunk.events.add(0, eventEntity) - } + val stateEventsChunk = StateEventsChunkHandler().handle(realm, roomId, chunkEvent.stateEvents) + if (!roomEntity.chunks.contains(stateEventsChunk)) { + roomEntity.chunks.add(stateEventsChunk) } chunkEvent.chunk.forEach { event -> diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt index f62756d7b7..eab31a3635 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineBoundaryCallback.kt @@ -4,7 +4,7 @@ import android.arch.paging.PagedList import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.MatrixCallback import im.vector.matrix.android.api.failure.Failure -import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.api.session.events.model.EnrichedEvent import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.query.findAllIncludingEvents import im.vector.matrix.android.internal.session.room.model.PaginationDirection @@ -17,7 +17,7 @@ class TimelineBoundaryCallback(private val paginationRequest: PaginationRequest, private val roomId: String, private val monarchy: Monarchy, ioExecutor: Executor -) : PagedList.BoundaryCallback() { +) : PagedList.BoundaryCallback() { private val helper = PagingRequestHelper(ioExecutor) @@ -25,25 +25,25 @@ class TimelineBoundaryCallback(private val paginationRequest: PaginationRequest, // actually, it's not possible } - override fun onItemAtEndLoaded(itemAtEnd: Event) { + override fun onItemAtEndLoaded(itemAtEnd: EnrichedEvent) { helper.runIfNotRunning(PagingRequestHelper.RequestType.AFTER) { monarchy.doWithRealm { realm -> - if (itemAtEnd.eventId == null) { + if (itemAtEnd.core.eventId == null) { return@doWithRealm } - val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtEnd.eventId)).firstOrNull() + val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtEnd.core.eventId)).firstOrNull() paginationRequest.execute(roomId, chunkEntity?.prevToken, PaginationDirection.BACKWARDS, callback = createCallback(it)) } } } - override fun onItemAtFrontLoaded(itemAtFront: Event) { + override fun onItemAtFrontLoaded(itemAtFront: EnrichedEvent) { helper.runIfNotRunning(PagingRequestHelper.RequestType.BEFORE) { monarchy.doWithRealm { realm -> - if (itemAtFront.eventId == null) { + if (itemAtFront.core.eventId == null) { return@doWithRealm } - val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtFront.eventId)).firstOrNull() + val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtFront.core.eventId)).firstOrNull() paginationRequest.execute(roomId, chunkEntity?.nextToken, PaginationDirection.FORWARDS, callback = createCallback(it)) } } diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt index 1bdd7f1ca9..de8049bce9 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/RoomSyncHandler.kt @@ -2,7 +2,6 @@ package im.vector.matrix.android.internal.session.sync import com.zhuinden.monarchy.Monarchy import im.vector.matrix.android.api.session.events.model.Event -import im.vector.matrix.android.internal.database.DBConstants import im.vector.matrix.android.internal.database.mapper.asEntity import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.RoomEntity @@ -48,13 +47,13 @@ class RoomSyncHandler(private val monarchy: Monarchy) { roomEntity.membership = RoomEntity.Membership.JOINED if (roomSync.state != null && roomSync.state.events.isNotEmpty()) { - val chunkEntity = eventListToChunk(realm, roomId, roomSync.state.events, DBConstants.STATE_EVENTS_CHUNK_TOKEN, DBConstants.STATE_EVENTS_CHUNK_TOKEN) + val chunkEntity = StateEventsChunkHandler().handle(realm, roomId, roomSync.state.events) if (!roomEntity.chunks.contains(chunkEntity)) { roomEntity.chunks.add(chunkEntity) } } if (roomSync.timeline != null && roomSync.timeline.events.isNotEmpty()) { - val chunkEntity = eventListToChunk(realm, roomId, roomSync.timeline.events, roomSync.timeline.prevToken, isLimited = roomSync.timeline.limited) + val chunkEntity = handleListOfEvent(realm, roomId, roomSync.timeline.events, roomSync.timeline.prevToken, isLimited = roomSync.timeline.limited) if (!roomEntity.chunks.contains(chunkEntity)) { roomEntity.chunks.add(chunkEntity) } @@ -70,7 +69,7 @@ class RoomSyncHandler(private val monarchy: Monarchy) { roomEntity.roomId = roomId roomEntity.membership = RoomEntity.Membership.INVITED if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) { - val chunkEntity = eventListToChunk(realm, roomId, roomSync.inviteState.events) + val chunkEntity = handleListOfEvent(realm, roomId, roomSync.inviteState.events) if (!roomEntity.chunks.contains(chunkEntity)) { roomEntity.chunks.add(chunkEntity) } @@ -87,12 +86,12 @@ class RoomSyncHandler(private val monarchy: Monarchy) { } } - private fun eventListToChunk(realm: Realm, - roomId: String, - eventList: List, - prevToken: String? = null, - nextToken: String? = null, - isLimited: Boolean = true): ChunkEntity { + private fun handleListOfEvent(realm: Realm, + roomId: String, + eventList: List, + prevToken: String? = null, + nextToken: String? = null, + isLimited: Boolean = true): ChunkEntity { val chunkEntity = if (!isLimited) { ChunkEntity.findLastLiveChunkFromRoom(realm, roomId) diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt new file mode 100644 index 0000000000..aeb9a86e5a --- /dev/null +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/sync/StateEventsChunkHandler.kt @@ -0,0 +1,28 @@ +package im.vector.matrix.android.internal.session.sync + +import im.vector.matrix.android.api.session.events.model.Event +import im.vector.matrix.android.internal.database.DBConstants +import im.vector.matrix.android.internal.database.mapper.asEntity +import im.vector.matrix.android.internal.database.model.ChunkEntity +import im.vector.matrix.android.internal.database.query.findWithNextToken +import io.realm.Realm + +class StateEventsChunkHandler { + + fun handle(realm: Realm, roomId: String, stateEvents: List): ChunkEntity { + val chunkEntity = ChunkEntity.findWithNextToken(realm, roomId, DBConstants.STATE_EVENTS_CHUNK_TOKEN) + ?: ChunkEntity(prevToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN, nextToken = DBConstants.STATE_EVENTS_CHUNK_TOKEN) + + stateEvents.forEach { event -> + val eventEntity = event.asEntity().let { + realm.copyToRealmOrUpdate(it) + } + if (!chunkEntity.events.contains(eventEntity)) { + chunkEntity.events.add(eventEntity) + } + } + return chunkEntity + } + + +} \ No newline at end of file