forked from GitHub-Mirror/riotX-android
Timeline : try to get a better PagedList/Epoxy integration. Still need to be refined.
This commit is contained in:
@ -37,6 +37,10 @@ internal fun ChunkEntity.Companion.findAllIncludingEvents(realm: Realm, eventIds
|
||||
.findAll()
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.Companion.findIncludingEvent(realm: Realm, eventId: String): ChunkEntity? {
|
||||
return findAllIncludingEvents(realm, listOf(eventId)).firstOrNull()
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.Companion.create(realm: Realm, prevToken: String?, nextToken: String?): ChunkEntity {
|
||||
return realm.createObject<ChunkEntity>().apply {
|
||||
this.prevToken = prevToken
|
||||
|
@ -15,7 +15,12 @@ import io.realm.RealmQuery
|
||||
internal class RoomMemberExtractor(private val monarchy: Monarchy,
|
||||
private val roomId: String) {
|
||||
|
||||
private val cached = HashMap<String, RoomMember?>()
|
||||
|
||||
fun extractFrom(event: EventEntity): RoomMember? {
|
||||
if (cached.containsKey(event.eventId)) {
|
||||
return cached[event.eventId]
|
||||
}
|
||||
val sender = event.sender ?: return null
|
||||
// If the event is unlinked we want to fetch unlinked state events
|
||||
val unlinked = event.isUnlinked
|
||||
@ -23,11 +28,13 @@ internal class RoomMemberExtractor(private val monarchy: Monarchy,
|
||||
// If prevContent is null we fallback to the Int.MIN state events content()
|
||||
val content = if (event.stateIndex <= 0) {
|
||||
baseQuery(monarchy, roomId, sender, unlinked).next(from = event.stateIndex)?.prevContent
|
||||
?: baseQuery(monarchy, roomId, sender, unlinked).last(since = event.stateIndex)?.content
|
||||
?: baseQuery(monarchy, roomId, sender, unlinked).last(since = event.stateIndex)?.content
|
||||
} else {
|
||||
baseQuery(monarchy, roomId, sender, unlinked).last(since = event.stateIndex)?.content
|
||||
}
|
||||
return ContentMapper.map(content).toModel()
|
||||
val roomMember: RoomMember? = ContentMapper.map(content).toModel()
|
||||
cached[event.eventId] = roomMember
|
||||
return roomMember
|
||||
}
|
||||
|
||||
private fun baseQuery(monarchy: Monarchy,
|
||||
|
@ -7,7 +7,7 @@ import im.vector.matrix.android.internal.task.Task
|
||||
import im.vector.matrix.android.internal.util.FilterUtil
|
||||
|
||||
|
||||
internal interface PaginationTask : Task<PaginationTask.Params, TokenChunkEvent> {
|
||||
internal interface PaginationTask : Task<PaginationTask.Params, Boolean> {
|
||||
|
||||
data class Params(
|
||||
val roomId: String,
|
||||
@ -22,14 +22,13 @@ internal class DefaultPaginationTask(private val roomAPI: RoomAPI,
|
||||
private val tokenChunkEventPersistor: TokenChunkEventPersistor
|
||||
) : PaginationTask {
|
||||
|
||||
override fun execute(params: PaginationTask.Params): Try<TokenChunkEvent> {
|
||||
override fun execute(params: PaginationTask.Params): Try<Boolean> {
|
||||
val filter = FilterUtil.createRoomEventFilter(true)?.toJSONString()
|
||||
return executeRequest<PaginationResponse> {
|
||||
apiCall = roomAPI.getRoomMessagesFrom(params.roomId, params.from, params.direction.value, params.limit, filter)
|
||||
}.flatMap { chunk ->
|
||||
tokenChunkEventPersistor
|
||||
.insertInDb(chunk, params.roomId, params.direction)
|
||||
.map { chunk }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,8 @@ import im.vector.matrix.android.internal.util.tryTransactionAsync
|
||||
import io.realm.Realm
|
||||
import io.realm.RealmQuery
|
||||
|
||||
private const val PAGE_SIZE = 30
|
||||
private const val PAGE_SIZE = 50
|
||||
private const val PREFETCH_DISTANCE = 20
|
||||
|
||||
internal class DefaultTimelineService(private val roomId: String,
|
||||
private val monarchy: Monarchy,
|
||||
@ -51,6 +52,7 @@ internal class DefaultTimelineService(private val roomId: String,
|
||||
val pagedListConfig = PagedList.Config.Builder()
|
||||
.setEnablePlaceholders(false)
|
||||
.setPageSize(PAGE_SIZE)
|
||||
.setPrefetchDistance(PREFETCH_DISTANCE)
|
||||
.build()
|
||||
|
||||
val livePagedListBuilder = LivePagedListBuilder(domainSourceFactory, pagedListConfig).setBoundaryCallback(boundaryCallback)
|
||||
|
@ -6,11 +6,11 @@ import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
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.database.query.findIncludingEvent
|
||||
import im.vector.matrix.android.internal.task.TaskExecutor
|
||||
import im.vector.matrix.android.internal.task.configureWith
|
||||
import im.vector.matrix.android.internal.util.PagingRequestHelper
|
||||
import java.util.*
|
||||
import timber.log.Timber
|
||||
|
||||
internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
private val taskExecutor: TaskExecutor,
|
||||
@ -43,8 +43,9 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
}
|
||||
|
||||
override fun onItemAtEndLoaded(itemAtEnd: EnrichedEvent) {
|
||||
Timber.v("On item at end loaded")
|
||||
val token = itemAtEnd.root.eventId?.let { getToken(it, PaginationDirection.BACKWARDS) }
|
||||
?: return
|
||||
?: return
|
||||
|
||||
helper.runIfNotRunning(PagingRequestHelper.RequestType.AFTER) {
|
||||
runPaginationRequest(it, token, PaginationDirection.BACKWARDS)
|
||||
@ -52,8 +53,9 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
}
|
||||
|
||||
override fun onItemAtFrontLoaded(itemAtFront: EnrichedEvent) {
|
||||
Timber.v("On item at front loaded")
|
||||
val token = itemAtFront.root.eventId?.let { getToken(it, PaginationDirection.FORWARDS) }
|
||||
?: return
|
||||
?: return
|
||||
|
||||
helper.runIfNotRunning(PagingRequestHelper.RequestType.BEFORE) {
|
||||
runPaginationRequest(it, token, PaginationDirection.FORWARDS)
|
||||
@ -63,7 +65,7 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
private fun getToken(eventId: String, direction: PaginationDirection): String? {
|
||||
var token: String? = null
|
||||
monarchy.doWithRealm { realm ->
|
||||
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(eventId)).firstOrNull()
|
||||
val chunkEntity = ChunkEntity.findIncludingEvent(realm, eventId)
|
||||
token = if (direction == PaginationDirection.FORWARDS) chunkEntity?.nextToken else chunkEntity?.prevToken
|
||||
}
|
||||
return token
|
||||
@ -74,14 +76,14 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
direction: PaginationDirection) {
|
||||
|
||||
val params = PaginationTask.Params(roomId = roomId,
|
||||
from = from,
|
||||
direction = direction,
|
||||
limit = limit)
|
||||
from = from,
|
||||
direction = direction,
|
||||
limit = limit)
|
||||
|
||||
paginationTask.configureWith(params)
|
||||
.enableRetry()
|
||||
.dispatchTo(object : MatrixCallback<TokenChunkEvent> {
|
||||
override fun onSuccess(data: TokenChunkEvent) {
|
||||
.dispatchTo(object : MatrixCallback<Boolean> {
|
||||
override fun onSuccess(data: Boolean) {
|
||||
requestCallback.recordSuccess()
|
||||
}
|
||||
|
||||
|
@ -2,12 +2,7 @@ package im.vector.matrix.android.internal.session.room.timeline
|
||||
|
||||
import arrow.core.Try
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.internal.database.helper.addAll
|
||||
import im.vector.matrix.android.internal.database.helper.addOrUpdate
|
||||
import im.vector.matrix.android.internal.database.helper.addStateEvents
|
||||
import im.vector.matrix.android.internal.database.helper.deleteOnCascade
|
||||
import im.vector.matrix.android.internal.database.helper.isUnlinked
|
||||
import im.vector.matrix.android.internal.database.helper.merge
|
||||
import im.vector.matrix.android.internal.database.helper.*
|
||||
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.query.create
|
||||
@ -21,12 +16,15 @@ internal class TokenChunkEventPersistor(private val monarchy: Monarchy) {
|
||||
|
||||
fun insertInDb(receivedChunk: TokenChunkEvent,
|
||||
roomId: String,
|
||||
direction: PaginationDirection): Try<Unit> {
|
||||
direction: PaginationDirection): Try<Boolean> {
|
||||
|
||||
if (receivedChunk.events.isEmpty() && receivedChunk.stateEvents.isEmpty()) {
|
||||
return Try.just(false)
|
||||
}
|
||||
return monarchy
|
||||
.tryTransactionSync { realm ->
|
||||
val roomEntity = RoomEntity.where(realm, roomId).findFirst()
|
||||
?: throw IllegalStateException("You shouldn't use this method without a room")
|
||||
?: throw IllegalStateException("You shouldn't use this method without a room")
|
||||
|
||||
val nextToken: String?
|
||||
val prevToken: String?
|
||||
@ -46,10 +44,10 @@ internal class TokenChunkEventPersistor(private val monarchy: Monarchy) {
|
||||
|
||||
var currentChunk = if (direction == PaginationDirection.FORWARDS) {
|
||||
prevChunk?.apply { this.nextToken = nextToken }
|
||||
?: ChunkEntity.create(realm, prevToken, nextToken)
|
||||
?: ChunkEntity.create(realm, prevToken, nextToken)
|
||||
} else {
|
||||
nextChunk?.apply { this.prevToken = prevToken }
|
||||
?: ChunkEntity.create(realm, prevToken, nextToken)
|
||||
?: ChunkEntity.create(realm, prevToken, nextToken)
|
||||
}
|
||||
|
||||
currentChunk.addAll(roomId, receivedChunk.events, direction, isUnlinked = currentChunk.isUnlinked())
|
||||
@ -71,6 +69,7 @@ internal class TokenChunkEventPersistor(private val monarchy: Monarchy) {
|
||||
roomEntity.addOrUpdate(currentChunk)
|
||||
roomEntity.addStateEvents(receivedChunk.stateEvents, isUnlinked = currentChunk.isUnlinked())
|
||||
}
|
||||
.map { true }
|
||||
}
|
||||
|
||||
private fun handleMerge(roomEntity: RoomEntity,
|
||||
|
Reference in New Issue
Block a user