Continue to work on timeline/pagination. WIP

This commit is contained in:
ganfra 2018-10-19 20:34:54 +02:00
parent 6e3992e70e
commit 702abccb38
15 changed files with 122 additions and 72 deletions

View File

@ -10,3 +10,7 @@ fun AppCompatActivity.addFragment(fragment: Fragment, frameId: Int) {
fun AppCompatActivity.replaceFragment(fragment: Fragment, frameId: Int) { fun AppCompatActivity.replaceFragment(fragment: Fragment, frameId: Int) {
supportFragmentManager.inTransaction { replace(frameId, fragment) } supportFragmentManager.inTransaction { replace(frameId, fragment) }
} }
fun AppCompatActivity.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
supportFragmentManager.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
}

View File

@ -17,3 +17,11 @@ fun Fragment.addChildFragment(fragment: Fragment, frameId: Int) {
fun Fragment.replaceChildFragment(fragment: Fragment, frameId: Int) { fun Fragment.replaceChildFragment(fragment: Fragment, frameId: Int) {
childFragmentManager.inTransaction { replace(frameId, fragment) } childFragmentManager.inTransaction { replace(frameId, fragment) }
} }
fun Fragment.addFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
fragmentManager?.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
}
fun Fragment.addChildFragmentToBackstack(fragment: Fragment, frameId: Int, tag: String? = null) {
childFragmentManager.inTransaction { replace(frameId, fragment).addToBackStack(tag) }
}

View File

@ -3,19 +3,21 @@ package im.vector.riotredesign.features.home
import android.arch.lifecycle.Observer import android.arch.lifecycle.Observer
import android.arch.paging.PagedList import android.arch.paging.PagedList
import android.os.Bundle import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import im.vector.matrix.android.api.Matrix 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.Event
import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.Room
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.platform.RiotFragment import im.vector.riotredesign.core.platform.RiotFragment
import im.vector.riotredesign.core.utils.FragmentArgumentDelegate import im.vector.riotredesign.core.utils.FragmentArgumentDelegate
import kotlinx.android.synthetic.main.fragment_room_list.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
class RoomDetailFragment : RiotFragment(), RoomController.Callback { class RoomDetailFragment : RiotFragment() {
companion object { companion object {
@ -29,11 +31,8 @@ class RoomDetailFragment : RiotFragment(), RoomController.Callback {
private val matrix by inject<Matrix>() private val matrix by inject<Matrix>()
private val currentSession = matrix.currentSession!! private val currentSession = matrix.currentSession!!
private var roomId by FragmentArgumentDelegate<String>() private var roomId by FragmentArgumentDelegate<String>()
private val timelineController = TimelineEventController() private val timelineController = TimelineEventController()
private val room: Room? by lazy { private lateinit var room: Room
currentSession.getRoom(roomId)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_room_detail, container, false) return inflater.inflate(R.layout.fragment_room_detail, container, false)
@ -41,19 +40,20 @@ class RoomDetailFragment : RiotFragment(), RoomController.Callback {
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
if (room == null) { setupRecyclerView()
activity?.onBackPressed() room = currentSession.getRoom(roomId)!!
return room.liveTimeline().observe(this, Observer { renderEvents(it) })
}
room?.liveTimeline()?.observe(this, Observer { renderEvents(it) })
} }
private fun renderEvents(events: PagedList<Event>?) { private fun renderEvents(events: PagedList<Event>?) {
timelineController.submitList(events) timelineController.submitList(events)
} }
override fun onRoomSelected(room: Room) { private fun setupRecyclerView() {
Toast.makeText(context, "Room ${room.roomId} clicked", Toast.LENGTH_SHORT).show() val linearLayoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
linearLayoutManager.stackFromEnd = true
epoxyRecyclerView.layoutManager = linearLayoutManager
epoxyRecyclerView.setController(timelineController)
} }

View File

@ -2,13 +2,14 @@ package im.vector.riotredesign.features.home
import android.arch.lifecycle.Observer import android.arch.lifecycle.Observer
import android.os.Bundle import android.os.Bundle
import android.support.v7.widget.LinearLayoutManager
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import im.vector.matrix.android.api.Matrix import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.session.room.Room import im.vector.matrix.android.api.session.room.Room
import im.vector.riotredesign.R import im.vector.riotredesign.R
import im.vector.riotredesign.core.extensions.replaceFragment import im.vector.riotredesign.core.extensions.addFragmentToBackstack
import im.vector.riotredesign.core.platform.RiotFragment import im.vector.riotredesign.core.platform.RiotFragment
import kotlinx.android.synthetic.main.fragment_room_list.* import kotlinx.android.synthetic.main.fragment_room_list.*
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
@ -43,7 +44,7 @@ class RoomListFragment : RiotFragment(), RoomController.Callback {
override fun onRoomSelected(room: Room) { override fun onRoomSelected(room: Room) {
val detailFragment = RoomDetailFragment.newInstance(room.roomId) val detailFragment = RoomDetailFragment.newInstance(room.roomId)
replaceFragment(detailFragment, R.id.homeFragmentContainer) addFragmentToBackstack(detailFragment, R.id.homeFragmentContainer)
} }

View File

@ -6,14 +6,15 @@ import com.airbnb.epoxy.paging.PagedListEpoxyController
import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.events.model.Event
class TimelineEventController : PagedListEpoxyController<Event>( class TimelineEventController : PagedListEpoxyController<Event>(
modelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler() modelBuildingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler(),
diffingHandler = EpoxyAsyncUtil.getAsyncBackgroundHandler()
) { ) {
override fun buildItemModel(currentPosition: Int, item: Event?): EpoxyModel<*> { override fun buildItemModel(currentPosition: Int, item: Event?): EpoxyModel<*> {
return if (item == null) { return if (item == null) {
LoadingItemModel_().id(-currentPosition) LoadingItemModel_().id(-currentPosition)
} else { } else {
TimelineEventItem(item.eventId ?: "$currentPosition").id(currentPosition) TimelineEventItem(item.toString()).id(currentPosition)
} }
} }

View File

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" <TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/titleView" android:id="@+id/titleView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="80dp" android:layout_height="wrap_content"
android:gravity="center_vertical" android:gravity="center_vertical"
android:minHeight="80dp"
android:padding="16dp" android:padding="16dp"
android:textSize="14sp" android:textSize="14sp" />
tools:text="Room name" />

View File

@ -1,5 +1,6 @@
package im.vector.matrix.android.internal.database.query package im.vector.matrix.android.internal.database.query
import im.vector.matrix.android.internal.database.DBConstants
import im.vector.matrix.android.internal.database.model.ChunkEntity import im.vector.matrix.android.internal.database.model.ChunkEntity
import io.realm.Realm import io.realm.Realm
import io.realm.RealmQuery import io.realm.RealmQuery
@ -40,5 +41,7 @@ fun ChunkEntity.Companion.findLastFromRoom(realm: Realm, roomId: String): ChunkE
fun ChunkEntity.Companion.findAllIncludingEvents(realm: Realm, eventIds: List<String>): RealmResults<ChunkEntity> { fun ChunkEntity.Companion.findAllIncludingEvents(realm: Realm, eventIds: List<String>): RealmResults<ChunkEntity> {
return realm.where(ChunkEntity::class.java) return realm.where(ChunkEntity::class.java)
.`in`("events.eventId", eventIds.toTypedArray()) .`in`("events.eventId", eventIds.toTypedArray())
.notEqualTo("prevToken", DBConstants.STATE_EVENTS_CHUNK_TOKEN)
.notEqualTo("nextToken", DBConstants.STATE_EVENTS_CHUNK_TOKEN)
.findAll() .findAll()
} }

View File

@ -11,11 +11,15 @@ fun EventEntity.Companion.where(realm: Realm, roomId: String): RealmQuery<EventE
.equalTo("chunk.room.roomId", roomId) .equalTo("chunk.room.roomId", roomId)
} }
fun EventEntity.Companion.where(realm: Realm, chunk: ChunkEntity): RealmQuery<EventEntity> { fun EventEntity.Companion.where(realm: Realm, chunk: ChunkEntity?): RealmQuery<EventEntity> {
return realm.where(EventEntity::class.java) var query = realm.where(EventEntity::class.java)
.equalTo("chunk.prevToken", chunk.prevToken) if (chunk?.prevToken != null) {
.and() query = query.equalTo("chunk.prevToken", chunk.prevToken)
.equalTo("chunk.nextToken", chunk.nextToken) }
if (chunk?.nextToken != null) {
query = query.equalTo("chunk.nextToken", chunk.nextToken)
}
return query
} }
fun RealmResults<EventEntity>.getLast(type: String? = null): EventEntity? { fun RealmResults<EventEntity>.getLast(type: String? = null): EventEntity? {
@ -23,5 +27,5 @@ fun RealmResults<EventEntity>.getLast(type: String? = null): EventEntity? {
if (type != null) { if (type != null) {
query = query.equalTo("type", type) query = query.equalTo("type", type)
} }
return query.findAll().sort("age").last(null) return query.findAll().last(null)
} }

View File

@ -5,7 +5,9 @@ import im.vector.matrix.android.internal.network.parsing.UriMoshiAdapter
object MoshiProvider { object MoshiProvider {
private val moshi: Moshi = Moshi.Builder().add(UriMoshiAdapter()).build() private val moshi: Moshi = Moshi.Builder()
.add(UriMoshiAdapter())
.build()
fun providesMoshi(): Moshi { fun providesMoshi(): Moshi {
return moshi return moshi

View File

@ -8,7 +8,6 @@ import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.Room 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.EventMapper
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.EventEntity
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.timeline.PaginationRequest import im.vector.matrix.android.internal.session.room.timeline.PaginationRequest
import im.vector.matrix.android.internal.session.room.timeline.TimelineBoundaryCallback import im.vector.matrix.android.internal.session.room.timeline.TimelineBoundaryCallback
@ -26,15 +25,17 @@ data class DefaultRoom(
override fun liveTimeline(): LiveData<PagedList<Event>> { override fun liveTimeline(): LiveData<PagedList<Event>> {
val realmDataSourceFactory = monarchy.createDataSourceFactory { realm -> val realmDataSourceFactory = monarchy.createDataSourceFactory { realm ->
val lastChunk = ChunkEntity.where(realm, roomId).findAll().last(null) ChunkEntity.where(realm, roomId).findAll().last(null).let { it?.events }?.where()
if (lastChunk == null) {
EventEntity.where(realm, roomId)
} else {
EventEntity.where(realm, lastChunk)
}
} }
val domainSourceFactory = realmDataSourceFactory.map { EventMapper.map(it) } val domainSourceFactory = realmDataSourceFactory.map { EventMapper.map(it) }
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, 20).setBoundaryCallback(boundaryCallback)
val pagedListConfig = PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPageSize(10)
.setPrefetchDistance(5)
.build()
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, pagedListConfig).setBoundaryCallback(boundaryCallback)
return monarchy.findAllPagedWithChanges(realmDataSourceFactory, livePagedListBuilder) return monarchy.findAllPagedWithChanges(realmDataSourceFactory, livePagedListBuilder)
} }

View File

@ -1,5 +1,6 @@
package im.vector.matrix.android.internal.session.room package im.vector.matrix.android.internal.session.room
import im.vector.matrix.android.internal.network.NetworkConstants
import im.vector.matrix.android.internal.session.room.model.TokenChunkEvent import im.vector.matrix.android.internal.session.room.model.TokenChunkEvent
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import retrofit2.Response import retrofit2.Response
@ -18,12 +19,13 @@ interface RoomAPI {
* @param limit the maximum number of messages to retrieve. Optional. * @param limit the maximum number of messages to retrieve. Optional.
* @param filter A JSON RoomEventFilter to filter returned events with. Optional. * @param filter A JSON RoomEventFilter to filter returned events with. Optional.
*/ */
@GET("rooms/{roomId}/messages") @GET(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/messages")
fun getRoomMessagesFrom(@Path("roomId") roomId: String, fun getRoomMessagesFrom(@Path("roomId") roomId: String,
@Query("from") from: String, @Query("from") from: String,
@Query("dir") dir: String, @Query("dir") dir: String,
@Query("limit") limit: Int, @Query("limit") limit: Int,
@Query("filter") filter: String?): Deferred<Response<TokenChunkEvent>> @Query("filter") filter: String?
): Deferred<Response<TokenChunkEvent>>
} }

View File

@ -0,0 +1,15 @@
package im.vector.matrix.android.internal.session.room.model
enum class PaginationDirection(val value: String) {
/**
* Forwards when the event is added to the end of the timeline.
* These events come from the /sync stream or from forwards pagination.
*/
FORWARDS("f"),
/**
* Backwards when the event is added to the start of the timeline.
* These events come from a back pagination.
*/
BACKWARDS("b")
}

View File

@ -6,8 +6,8 @@ import im.vector.matrix.android.api.session.events.model.Event
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class TokenChunkEvent( data class TokenChunkEvent(
@Json(name = "start") val prevToken: String? = null, @Json(name = "start") val nextToken: String? = null,
@Json(name = "end") val nextToken: String? = null, @Json(name = "end") val prevToken: String? = null,
@Json(name = "chunks") val chunk: List<Event> = emptyList(), @Json(name = "chunk") val chunk: List<Event> = emptyList(),
@Json(name = "state") val stateEvents: List<Event> = emptyList() @Json(name = "state") val stateEvents: List<Event> = emptyList()
) )

View File

@ -9,6 +9,7 @@ import im.vector.matrix.android.api.failure.Failure
import im.vector.matrix.android.api.util.Cancelable import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.internal.database.mapper.asEntity 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.ChunkEntity
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.findAllIncludingEvents import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
import im.vector.matrix.android.internal.database.query.findWithNextToken import im.vector.matrix.android.internal.database.query.findWithNextToken
@ -16,6 +17,7 @@ import im.vector.matrix.android.internal.database.query.findWithPrevToken
import im.vector.matrix.android.internal.database.query.where import im.vector.matrix.android.internal.database.query.where
import im.vector.matrix.android.internal.network.executeRequest 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.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.room.model.TokenChunkEvent
import im.vector.matrix.android.internal.util.CancelableCoroutine import im.vector.matrix.android.internal.util.CancelableCoroutine
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
@ -28,8 +30,8 @@ class PaginationRequest(private val roomAPI: RoomAPI,
private val coroutineDispatchers: MatrixCoroutineDispatchers) { private val coroutineDispatchers: MatrixCoroutineDispatchers) {
fun execute(roomId: String, fun execute(roomId: String,
from: String? = null, from: String?,
direction: String, direction: PaginationDirection,
limit: Int = 10, limit: Int = 10,
filter: String? = null, filter: String? = null,
callback: MatrixCallback<TokenChunkEvent> callback: MatrixCallback<TokenChunkEvent>
@ -42,22 +44,24 @@ class PaginationRequest(private val roomAPI: RoomAPI,
} }
private suspend fun execute(roomId: String, private suspend fun execute(roomId: String,
from: String? = null, from: String?,
direction: String, direction: PaginationDirection,
limit: Int = 10, limit: Int = 10,
filter: String? = null) = withContext(coroutineDispatchers.io) { filter: String?) = withContext(coroutineDispatchers.io) {
if (from == null) { if (from == null) {
return@withContext Either.left(Failure.Unknown(RuntimeException("From token can't be null"))) return@withContext Either.left(
Failure.Unknown(RuntimeException("From token shouldn't be null"))
)
} }
executeRequest<TokenChunkEvent> { return@withContext executeRequest<TokenChunkEvent> {
apiCall = roomAPI.getRoomMessagesFrom(roomId, from, direction, limit, filter) apiCall = roomAPI.getRoomMessagesFrom(roomId, from, direction.value, limit, filter)
}.leftIfNull { }.leftIfNull {
Failure.Unknown(RuntimeException("TokenChunkEvent shouldn't be null")) Failure.Unknown(RuntimeException("TokenChunkEvent shouldn't be null"))
}.flatMap { }.flatMap { chunk ->
try { try {
insertInDb(it, roomId) insertInDb(chunk, roomId)
Either.right(it) Either.right(chunk)
} catch (exception: Exception) { } catch (exception: Exception) {
Either.Left(Failure.Unknown(exception)) Either.Left(Failure.Unknown(exception))
} }
@ -67,7 +71,7 @@ class PaginationRequest(private val roomAPI: RoomAPI,
private fun insertInDb(chunkEvent: TokenChunkEvent, roomId: String) { private fun insertInDb(chunkEvent: TokenChunkEvent, roomId: String) {
monarchy.runTransactionSync { realm -> monarchy.runTransactionSync { realm ->
val roomEntity = RoomEntity.where(realm, roomId).findFirst() val roomEntity = RoomEntity.where(realm, roomId).findFirst()
?: return@runTransactionSync ?: return@runTransactionSync
val nextChunk = ChunkEntity.findWithPrevToken(realm, roomId, chunkEvent.nextToken) val nextChunk = ChunkEntity.findWithPrevToken(realm, roomId, chunkEvent.nextToken)
val prevChunk = ChunkEntity.findWithNextToken(realm, roomId, chunkEvent.prevToken) val prevChunk = ChunkEntity.findWithNextToken(realm, roomId, chunkEvent.prevToken)
@ -75,38 +79,42 @@ class PaginationRequest(private val roomAPI: RoomAPI,
val mergedEvents = chunkEvent.chunk + chunkEvent.stateEvents val mergedEvents = chunkEvent.chunk + chunkEvent.stateEvents
val mergedEventIds = mergedEvents.filter { it.eventId != null }.map { it.eventId!! } val mergedEventIds = mergedEvents.filter { it.eventId != null }.map { it.eventId!! }
val chunksOverlapped = ChunkEntity.findAllIncludingEvents(realm, mergedEventIds) val chunksOverlapped = ChunkEntity.findAllIncludingEvents(realm, mergedEventIds)
val hasOverlapped = chunksOverlapped.isNotEmpty()
val currentChunk: ChunkEntity val currentChunk = if (nextChunk != null) {
if (nextChunk != null) { nextChunk
currentChunk = nextChunk
} else { } else {
currentChunk = ChunkEntity() ChunkEntity()
} }
val eventsToAdd = ArrayList<EventEntity>()
currentChunk.prevToken = chunkEvent.prevToken currentChunk.prevToken = chunkEvent.prevToken
mergedEvents.forEach { event -> mergedEvents.forEach { event ->
val eventEntity = event.asEntity().let { val eventEntity = event.asEntity().let {
realm.copyToRealmOrUpdate(it) realm.copyToRealmOrUpdate(it)
} }
if (!currentChunk.events.contains(eventEntity)) { if (!currentChunk.events.contains(eventEntity)) {
currentChunk.events.add(eventEntity) eventsToAdd.add(0, eventEntity)
} }
} }
if (prevChunk != null) { if (prevChunk != null) {
currentChunk.events.addAll(prevChunk.events) eventsToAdd.addAll(0, prevChunk.events)
roomEntity.chunks.remove(prevChunk) roomEntity.chunks.remove(prevChunk)
} else if (chunksOverlapped.isNotEmpty()) { } else if (hasOverlapped) {
chunksOverlapped.forEach { chunk -> chunksOverlapped.forEach { chunk ->
chunk.events.forEach { event -> chunk.events.forEach { event ->
if (!currentChunk.events.contains(event)) { if (!currentChunk.events.contains(event)) {
currentChunk.events.add(event) eventsToAdd.add(0, event)
} }
} }
roomEntity.chunks.remove(chunk) roomEntity.chunks.remove(chunk)
} }
} }
currentChunk.events.addAll(0, eventsToAdd)
if (!roomEntity.chunks.contains(currentChunk)) { if (!roomEntity.chunks.contains(currentChunk)) {
roomEntity.chunks.add(currentChunk) roomEntity.chunks.add(currentChunk)
} }

View File

@ -7,6 +7,7 @@ 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.Event
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.query.findAllIncludingEvents import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
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.room.model.TokenChunkEvent
import im.vector.matrix.android.internal.util.PagingRequestHelper import im.vector.matrix.android.internal.util.PagingRequestHelper
import java.util.* import java.util.*
@ -25,19 +26,20 @@ class TimelineBoundaryCallback(private val paginationRequest: PaginationRequest,
} }
override fun onItemAtEndLoaded(itemAtEnd: Event) { override fun onItemAtEndLoaded(itemAtEnd: Event) {
helper.runIfNotRunning(PagingRequestHelper.RequestType.AFTER) { //Todo handle forward pagination
monarchy.doWithRealm { realm ->
if (itemAtEnd.eventId == null) {
return@doWithRealm
}
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtEnd.eventId)).firstOrNull()
paginationRequest.execute(roomId, chunkEntity?.prevToken, "forward", callback = createCallback(it))
}
}
} }
override fun onItemAtFrontLoaded(itemAtFront: Event) { override fun onItemAtFrontLoaded(itemAtFront: Event) {
//Todo handle forward pagination helper.runIfNotRunning(PagingRequestHelper.RequestType.BEFORE) {
monarchy.doWithRealm { realm ->
if (itemAtFront.eventId == null) {
return@doWithRealm
}
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtFront.eventId)).firstOrNull()
paginationRequest.execute(roomId, chunkEntity?.prevToken, PaginationDirection.BACKWARDS, callback = createCallback(it))
}
}
} }
private fun createCallback(pagingRequestCallback: PagingRequestHelper.Request.Callback) = object : MatrixCallback<TokenChunkEvent> { private fun createCallback(pagingRequestCallback: PagingRequestHelper.Request.Callback) = object : MatrixCallback<TokenChunkEvent> {