forked from GitHub-Mirror/riotX-android
Start to add a flag (isUnlinked) to work with permalink. Still in progress (break state index at the moment)
This commit is contained in:
parent
b6728ce9be
commit
b3ba542e09
@ -17,6 +17,10 @@ class TimelineEventController(private val roomId: String,
|
||||
EpoxyAsyncUtil.getAsyncBackgroundHandler()
|
||||
) {
|
||||
|
||||
init {
|
||||
setFilterDuplicates(true)
|
||||
}
|
||||
|
||||
private val pagedListCallback = object : PagedList.Callback() {
|
||||
override fun onChanged(position: Int, count: Int) {
|
||||
buildSnapshotList()
|
||||
|
@ -3,35 +3,51 @@ 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.EventType
|
||||
import im.vector.matrix.android.internal.database.mapper.asDomain
|
||||
import im.vector.matrix.android.internal.database.mapper.asEntity
|
||||
import im.vector.matrix.android.internal.database.mapper.fillWith
|
||||
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.EventEntityFields
|
||||
import im.vector.matrix.android.internal.database.query.fastContains
|
||||
import im.vector.matrix.android.internal.database.query.find
|
||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||
import io.realm.Sort
|
||||
import io.realm.kotlin.createObject
|
||||
|
||||
internal fun ChunkEntity.isUnlinked(): Boolean {
|
||||
return events.where().equalTo(EventEntityFields.IS_UNLINKED, true).findAll().isNotEmpty()
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.merge(chunkEntity: ChunkEntity,
|
||||
internal fun ChunkEntity.merge(chunkToMerge: ChunkEntity,
|
||||
direction: PaginationDirection) {
|
||||
|
||||
val isChunkToMergeUnlinked = chunkToMerge.isUnlinked()
|
||||
val isCurrentChunkUnlinked = this.isUnlinked()
|
||||
val isUnlinked = isCurrentChunkUnlinked && isChunkToMergeUnlinked
|
||||
|
||||
chunkEntity.events.forEach {
|
||||
addOrUpdate(it.asDomain(), direction)
|
||||
if (isCurrentChunkUnlinked && !isChunkToMergeUnlinked) {
|
||||
this.events.forEach { it.isUnlinked = false }
|
||||
}
|
||||
val eventsToMerge: List<EventEntity>
|
||||
if (direction == PaginationDirection.FORWARDS) {
|
||||
nextToken = chunkEntity.nextToken
|
||||
this.nextToken = chunkToMerge.nextToken
|
||||
this.isLast = chunkToMerge.isLast
|
||||
eventsToMerge = chunkToMerge.events.reversed()
|
||||
} else {
|
||||
prevToken = chunkEntity.prevToken
|
||||
this.prevToken = chunkToMerge.prevToken
|
||||
eventsToMerge = chunkToMerge.events
|
||||
}
|
||||
eventsToMerge.forEach {
|
||||
addOrUpdate(it.asDomain(), direction, isUnlinked = isUnlinked)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.addAll(events: List<Event>,
|
||||
direction: PaginationDirection,
|
||||
stateIndexOffset: Int = 0) {
|
||||
stateIndexOffset: Int = 0,
|
||||
isUnlinked: Boolean = false) {
|
||||
|
||||
events.forEach { event ->
|
||||
addOrUpdate(event, direction, stateIndexOffset)
|
||||
addOrUpdate(event, direction, stateIndexOffset, isUnlinked)
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +57,8 @@ internal fun ChunkEntity.updateDisplayIndexes() {
|
||||
|
||||
internal fun ChunkEntity.addOrUpdate(event: Event,
|
||||
direction: PaginationDirection,
|
||||
stateIndexOffset: Int = 0) {
|
||||
stateIndexOffset: Int = 0,
|
||||
isUnlinked: Boolean = false) {
|
||||
if (!isManaged) {
|
||||
throw IllegalStateException("Chunk entity should be managed to use fast contains")
|
||||
}
|
||||
@ -60,15 +77,17 @@ internal fun ChunkEntity.addOrUpdate(event: Event,
|
||||
}
|
||||
}
|
||||
|
||||
val eventEntity: EventEntity?
|
||||
if (!events.fastContains(event.eventId)) {
|
||||
val eventEntity = event.asEntity()
|
||||
eventEntity.stateIndex = currentStateIndex
|
||||
eventEntity = realm.createObject()
|
||||
eventEntity.fillWith(event)
|
||||
val position = if (direction == PaginationDirection.FORWARDS) 0 else this.events.size
|
||||
events.add(position, eventEntity)
|
||||
} else {
|
||||
val eventEntity = events.find(event.eventId)
|
||||
eventEntity?.stateIndex = currentStateIndex
|
||||
eventEntity = events.find(event.eventId)
|
||||
}
|
||||
eventEntity?.stateIndex = currentStateIndex
|
||||
eventEntity?.isUnlinked = isUnlinked
|
||||
}
|
||||
|
||||
internal fun ChunkEntity.lastStateIndex(direction: PaginationDirection, defaultValue: Int = 0): Int {
|
||||
|
@ -19,7 +19,9 @@ internal fun RoomEntity.addOrUpdate(chunkEntity: ChunkEntity) {
|
||||
}
|
||||
}
|
||||
|
||||
internal fun RoomEntity.addStateEvents(stateEvents: List<Event>, stateIndex: Int = Int.MIN_VALUE) {
|
||||
internal fun RoomEntity.addStateEvents(stateEvents: List<Event>,
|
||||
stateIndex: Int = Int.MIN_VALUE,
|
||||
isUnlinked: Boolean = false) {
|
||||
if (!isManaged) {
|
||||
throw IllegalStateException("Chunk entity should be managed to use fast contains")
|
||||
}
|
||||
@ -29,6 +31,7 @@ internal fun RoomEntity.addStateEvents(stateEvents: List<Event>, stateIndex: Int
|
||||
}
|
||||
val eventEntity = event.asEntity()
|
||||
eventEntity.stateIndex = stateIndex
|
||||
eventEntity.isUnlinked = isUnlinked
|
||||
untimelinedStateEvents.add(eventEntity)
|
||||
}
|
||||
}
|
@ -14,7 +14,8 @@ internal open class EventEntity(var eventId: String = "",
|
||||
var age: Long? = 0,
|
||||
var redacts: String? = null,
|
||||
var stateIndex: Int = 0,
|
||||
var displayIndex: Int = 0
|
||||
var displayIndex: Int = 0,
|
||||
var isUnlinked: Boolean = false
|
||||
) : RealmObject() {
|
||||
|
||||
companion object {
|
||||
|
@ -27,6 +27,7 @@ internal fun EventEntity.Companion.where(realm: Realm, roomId: String? = null, t
|
||||
if (type != null) {
|
||||
query.equalTo(EventEntityFields.TYPE, type)
|
||||
}
|
||||
query.notEqualTo(EventEntityFields.IS_UNLINKED, true)
|
||||
return query
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import im.vector.matrix.android.internal.session.room.RoomAvatarResolver
|
||||
import im.vector.matrix.android.internal.session.room.RoomSummaryUpdater
|
||||
import im.vector.matrix.android.internal.session.room.members.RoomDisplayNameResolver
|
||||
import im.vector.matrix.android.internal.session.room.members.RoomMemberDisplayNameResolver
|
||||
import im.vector.matrix.android.internal.util.md5
|
||||
import io.realm.RealmConfiguration
|
||||
import org.koin.dsl.context.ModuleDefinition
|
||||
import org.koin.dsl.module.Module
|
||||
@ -31,7 +32,8 @@ internal class SessionModule(private val sessionParams: SessionParams) : Module
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
val context = get<Context>()
|
||||
val directory = File(context.filesDir, sessionParams.credentials.userId)
|
||||
val childPath = sessionParams.credentials.userId.md5()
|
||||
val directory = File(context.filesDir, childPath)
|
||||
|
||||
RealmConfiguration.Builder()
|
||||
.directory(directory)
|
||||
@ -47,7 +49,7 @@ internal class SessionModule(private val sessionParams: SessionParams) : Module
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
val retrofitBuilder = get() as Retrofit.Builder
|
||||
val retrofitBuilder = get<Retrofit.Builder>()
|
||||
retrofitBuilder
|
||||
.baseUrl(sessionParams.homeServerConnectionConfig.homeServerUri.toString())
|
||||
.build()
|
||||
|
@ -8,6 +8,7 @@ import im.vector.matrix.android.internal.session.DefaultSession
|
||||
import im.vector.matrix.android.internal.session.room.members.LoadRoomMembersRequest
|
||||
import im.vector.matrix.android.internal.session.room.send.DefaultSendService
|
||||
import im.vector.matrix.android.internal.session.room.timeline.DefaultTimelineHolder
|
||||
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventRequest
|
||||
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.util.PagingRequestHelper
|
||||
@ -35,6 +36,10 @@ class RoomModule : Module {
|
||||
PaginationRequest(get(), get(), get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
GetContextOfEventRequest(get(), get(), get())
|
||||
}
|
||||
|
||||
scope(DefaultSession.SCOPE) {
|
||||
val sessionParams = get<SessionParams>()
|
||||
EventFactory(sessionParams.credentials)
|
||||
@ -43,10 +48,9 @@ class RoomModule : Module {
|
||||
factory { (roomId: String) ->
|
||||
val helper = PagingRequestHelper(Executors.newSingleThreadExecutor())
|
||||
val timelineBoundaryCallback = TimelineBoundaryCallback(roomId, get(), get(), helper)
|
||||
DefaultTimelineHolder(roomId, get(), timelineBoundaryCallback) as TimelineHolder
|
||||
DefaultTimelineHolder(roomId, get(), timelineBoundaryCallback, get()) as TimelineHolder
|
||||
}
|
||||
|
||||
|
||||
factory { (roomId: String) ->
|
||||
DefaultSendService(roomId, get(), get()) as SendService
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ 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.MatrixCallback
|
||||
import im.vector.matrix.android.api.session.events.interceptor.EnrichedEventInterceptor
|
||||
import im.vector.matrix.android.api.session.events.model.EnrichedEvent
|
||||
import im.vector.matrix.android.api.session.room.TimelineHolder
|
||||
@ -20,7 +21,8 @@ private const val PAGE_SIZE = 30
|
||||
|
||||
internal class DefaultTimelineHolder(private val roomId: String,
|
||||
private val monarchy: Monarchy,
|
||||
private val boundaryCallback: TimelineBoundaryCallback
|
||||
private val boundaryCallback: TimelineBoundaryCallback,
|
||||
private val contextOfEventRequest: GetContextOfEventRequest
|
||||
) : TimelineHolder {
|
||||
|
||||
private val eventInterceptors = ArrayList<EnrichedEventInterceptor>()
|
||||
@ -32,7 +34,7 @@ internal class DefaultTimelineHolder(private val roomId: String,
|
||||
|
||||
override fun timeline(eventId: String?): LiveData<PagedList<EnrichedEvent>> {
|
||||
if (eventId != null) {
|
||||
fetchEventIfNeeded()
|
||||
fetchEventIfNeeded(eventId)
|
||||
}
|
||||
val realmDataSourceFactory = monarchy.createDataSourceFactory {
|
||||
buildDataSourceFactoryQuery(it, eventId)
|
||||
@ -60,8 +62,18 @@ internal class DefaultTimelineHolder(private val roomId: String,
|
||||
return monarchy.findAllPagedWithChanges(realmDataSourceFactory, livePagedListBuilder)
|
||||
}
|
||||
|
||||
private fun fetchEventIfNeeded() {
|
||||
private fun fetchEventIfNeeded(eventId: String) {
|
||||
if (!isEventPersisted(eventId)) {
|
||||
contextOfEventRequest.execute(roomId, eventId, object : MatrixCallback<EventContextResponse> {})
|
||||
}
|
||||
}
|
||||
|
||||
private fun isEventPersisted(eventId: String): Boolean {
|
||||
var isEventPersisted = false
|
||||
monarchy.doWithRealm {
|
||||
isEventPersisted = EventEntity.where(it, eventId = eventId).findFirst() != null
|
||||
}
|
||||
return isEventPersisted
|
||||
}
|
||||
|
||||
private fun buildDataSourceFactoryQuery(realm: Realm, eventId: String?): RealmQuery<EventEntity> {
|
||||
|
@ -12,11 +12,4 @@ data class EventContextResponse(
|
||||
@Json(name = "events_after") val eventsAfter: List<Event> = emptyList(),
|
||||
@Json(name = "end") val nextToken: String? = null,
|
||||
@Json(name = "state") val stateEvents: List<Event> = emptyList()
|
||||
) {
|
||||
|
||||
val timelineEvents: List<Event> by lazy {
|
||||
eventsBefore + event + eventsAfter
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
)
|
||||
|
@ -4,7 +4,6 @@ import arrow.core.Try
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
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
|
||||
@ -46,7 +45,7 @@ internal class GetContextOfEventRequest(private val roomAPI: RoomAPI,
|
||||
filter: String?) = withContext(coroutineDispatchers.io) {
|
||||
|
||||
executeRequest<EventContextResponse> {
|
||||
apiCall = roomAPI.getContextOfEvent(roomId, eventId, 1, filter)
|
||||
apiCall = roomAPI.getContextOfEvent(roomId, eventId, 0, filter)
|
||||
}.flatMap { response ->
|
||||
insertInDb(response, roomId)
|
||||
}
|
||||
@ -56,17 +55,14 @@ internal class GetContextOfEventRequest(private val roomAPI: RoomAPI,
|
||||
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 currentChunk = realm.createObject<ChunkEntity>().apply {
|
||||
prevToken = response.prevToken
|
||||
nextToken = response.nextToken
|
||||
}
|
||||
|
||||
currentChunk.addOrUpdate(response.event, PaginationDirection.FORWARDS)
|
||||
currentChunk.addAll(response.eventsAfter, PaginationDirection.FORWARDS)
|
||||
currentChunk.addAll(response.eventsBefore, PaginationDirection.BACKWARDS)
|
||||
|
||||
currentChunk.addOrUpdate(response.event, PaginationDirection.FORWARDS, isUnlinked = true)
|
||||
// Now, handles chunk merge
|
||||
val prevChunk = ChunkEntity.find(realm, roomId, nextToken = response.prevToken)
|
||||
val nextChunk = ChunkEntity.find(realm, roomId, prevToken = response.nextToken)
|
||||
@ -79,18 +75,8 @@ internal class GetContextOfEventRequest(private val roomAPI: RoomAPI,
|
||||
currentChunk.merge(nextChunk, PaginationDirection.FORWARDS)
|
||||
roomEntity.deleteOnCascade(nextChunk)
|
||||
}
|
||||
/*
|
||||
val eventIds = response.timelineEvents.mapNotNull { it.eventId }
|
||||
ChunkEntity
|
||||
.findAllIncludingEvents(realm, eventIds)
|
||||
.filter { it != currentChunk }
|
||||
.forEach { overlapped ->
|
||||
currentChunk.merge(overlapped, direction)
|
||||
roomEntity.deleteOnCascade(overlapped)
|
||||
}
|
||||
*/
|
||||
roomEntity.addOrUpdate(currentChunk)
|
||||
roomEntity.addStateEvents(response.stateEvents)
|
||||
roomEntity.addStateEvents(response.stateEvents, stateIndex = Int.MIN_VALUE, isUnlinked = true)
|
||||
}
|
||||
.map { response }
|
||||
}
|
||||
|
@ -5,11 +5,7 @@ import arrow.core.failure
|
||||
import com.zhuinden.monarchy.Monarchy
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.util.Cancelable
|
||||
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.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.find
|
||||
@ -34,7 +30,7 @@ internal class PaginationRequest(private val roomAPI: RoomAPI,
|
||||
fun execute(roomId: String,
|
||||
from: String?,
|
||||
direction: PaginationDirection,
|
||||
limit: Int = 10,
|
||||
limit: Int,
|
||||
callback: MatrixCallback<TokenChunkEvent>
|
||||
): Cancelable {
|
||||
val job = GlobalScope.launch(coroutineDispatchers.main) {
|
||||
@ -48,7 +44,7 @@ internal class PaginationRequest(private val roomAPI: RoomAPI,
|
||||
private suspend fun execute(roomId: String,
|
||||
from: String?,
|
||||
direction: PaginationDirection,
|
||||
limit: Int = 10,
|
||||
limit: Int,
|
||||
filter: String?) = withContext(coroutineDispatchers.io) {
|
||||
|
||||
if (from == null) {
|
||||
@ -61,38 +57,45 @@ internal class PaginationRequest(private val roomAPI: RoomAPI,
|
||||
}
|
||||
}
|
||||
|
||||
private fun insertInDb(receivedChunk: TokenChunkEvent, roomId: String, direction: PaginationDirection): Try<TokenChunkEvent> {
|
||||
private fun insertInDb(receivedChunk: TokenChunkEvent,
|
||||
roomId: String,
|
||||
direction: PaginationDirection): Try<TokenChunkEvent> {
|
||||
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 currentChunk = ChunkEntity.find(realm, roomId, prevToken = receivedChunk.nextToken)
|
||||
?: realm.createObject()
|
||||
|
||||
currentChunk.prevToken = receivedChunk.prevToken
|
||||
currentChunk.addAll(receivedChunk.events, direction)
|
||||
val currentChunk = realm.createObject<ChunkEntity>().apply {
|
||||
prevToken = receivedChunk.prevToken
|
||||
nextToken = receivedChunk.nextToken
|
||||
}
|
||||
currentChunk.addAll(receivedChunk.events, direction, isUnlinked = true)
|
||||
|
||||
// Now, handles chunk merge
|
||||
|
||||
val prevChunk = ChunkEntity.find(realm, roomId, nextToken = receivedChunk.prevToken)
|
||||
val nextChunk = ChunkEntity.find(realm, roomId, prevToken = receivedChunk.nextToken)
|
||||
|
||||
if (prevChunk != null) {
|
||||
currentChunk.merge(prevChunk, direction)
|
||||
currentChunk.merge(prevChunk, PaginationDirection.BACKWARDS)
|
||||
roomEntity.deleteOnCascade(prevChunk)
|
||||
} else {
|
||||
val eventIds = receivedChunk.events.mapNotNull { it.eventId }
|
||||
ChunkEntity
|
||||
.findAllIncludingEvents(realm, eventIds)
|
||||
.filter { it != currentChunk }
|
||||
.forEach { overlapped ->
|
||||
currentChunk.merge(overlapped, direction)
|
||||
roomEntity.deleteOnCascade(overlapped)
|
||||
}
|
||||
}
|
||||
if (nextChunk != null) {
|
||||
currentChunk.merge(nextChunk, PaginationDirection.FORWARDS)
|
||||
roomEntity.deleteOnCascade(nextChunk)
|
||||
}
|
||||
val eventIds = receivedChunk.events.mapNotNull { it.eventId }
|
||||
ChunkEntity
|
||||
.findAllIncludingEvents(realm, eventIds)
|
||||
.filter { it != currentChunk }
|
||||
.forEach { overlapped ->
|
||||
currentChunk.merge(overlapped, direction)
|
||||
roomEntity.deleteOnCascade(overlapped)
|
||||
}
|
||||
|
||||
roomEntity.addOrUpdate(currentChunk)
|
||||
// TODO : there is an issue with the pagination sending unwanted room member events
|
||||
roomEntity.addStateEvents(receivedChunk.stateEvents)
|
||||
val isUnlinked = currentChunk.isUnlinked()
|
||||
roomEntity.addStateEvents(receivedChunk.stateEvents, isUnlinked = isUnlinked)
|
||||
}
|
||||
.map { receivedChunk }
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||
import im.vector.matrix.android.internal.database.query.findAllIncludingEvents
|
||||
import im.vector.matrix.android.internal.util.PagingRequestHelper
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
private val paginationRequest: PaginationRequest,
|
||||
@ -24,28 +23,37 @@ internal class TimelineBoundaryCallback(private val roomId: String,
|
||||
|
||||
override fun onItemAtEndLoaded(itemAtEnd: EnrichedEvent) {
|
||||
helper.runIfNotRunning(PagingRequestHelper.RequestType.AFTER) {
|
||||
monarchy.doWithRealm { realm ->
|
||||
if (itemAtEnd.root.eventId == null) {
|
||||
return@doWithRealm
|
||||
}
|
||||
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtEnd.root.eventId)).firstOrNull()
|
||||
paginationRequest.execute(roomId, chunkEntity?.prevToken, PaginationDirection.BACKWARDS, limit, callback = createCallback(it))
|
||||
}
|
||||
runPaginationRequest(it, itemAtEnd, PaginationDirection.BACKWARDS)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onItemAtFrontLoaded(itemAtFront: EnrichedEvent) {
|
||||
helper.runIfNotRunning(PagingRequestHelper.RequestType.BEFORE) {
|
||||
monarchy.doWithRealm { realm ->
|
||||
if (itemAtFront.root.eventId == null) {
|
||||
return@doWithRealm
|
||||
}
|
||||
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(itemAtFront.root.eventId)).firstOrNull()
|
||||
paginationRequest.execute(roomId, chunkEntity?.nextToken, PaginationDirection.FORWARDS, limit, callback = createCallback(it))
|
||||
}
|
||||
runPaginationRequest(it, itemAtFront, PaginationDirection.FORWARDS)
|
||||
}
|
||||
}
|
||||
|
||||
private fun runPaginationRequest(requestCallback: PagingRequestHelper.Request.Callback,
|
||||
item: EnrichedEvent,
|
||||
direction: PaginationDirection) {
|
||||
var token: String? = null
|
||||
monarchy.doWithRealm { realm ->
|
||||
if (item.root.eventId == null) {
|
||||
return@doWithRealm
|
||||
}
|
||||
val chunkEntity = ChunkEntity.findAllIncludingEvents(realm, Collections.singletonList(item.root.eventId)).firstOrNull()
|
||||
token = if (direction == PaginationDirection.FORWARDS) chunkEntity?.nextToken else chunkEntity?.prevToken
|
||||
}
|
||||
paginationRequest.execute(
|
||||
roomId = roomId,
|
||||
from = token,
|
||||
direction = direction,
|
||||
limit = limit,
|
||||
callback = createCallback(requestCallback)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun createCallback(pagingRequestCallback: PagingRequestHelper.Request.Callback) = object : MatrixCallback<TokenChunkEvent> {
|
||||
override fun onSuccess(data: TokenChunkEvent) {
|
||||
pagingRequestCallback.recordSuccess()
|
||||
|
@ -0,0 +1,17 @@
|
||||
package im.vector.matrix.android.internal.util
|
||||
|
||||
import java.security.MessageDigest
|
||||
|
||||
fun String.md5() = try {
|
||||
val digest = MessageDigest.getInstance("md5")
|
||||
digest.update(toByteArray())
|
||||
val bytes = digest.digest()
|
||||
val sb = StringBuilder()
|
||||
for (i in bytes.indices) {
|
||||
sb.append(String.format("%02X", bytes[i]))
|
||||
}
|
||||
sb.toString().toLowerCase()
|
||||
} catch (exc: Exception) {
|
||||
// Should not happen, but just in case
|
||||
hashCode().toString()
|
||||
}
|
Loading…
Reference in New Issue
Block a user