Timeline: try to optimise a bit the loading
This commit is contained in:
parent
76eddef840
commit
014da84ba6
|
@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.room.timeline
|
||||||
|
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import io.realm.RealmResults
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
@ -26,13 +25,11 @@ import kotlinx.coroutines.android.asCoroutineDispatcher
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.internal.closeQuietly
|
import okhttp3.internal.closeQuietly
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
import org.matrix.android.sdk.internal.database.mapper.EventMapper
|
|
||||||
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
|
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
|
||||||
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
|
import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
|
||||||
import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler
|
import org.matrix.android.sdk.internal.session.sync.handler.room.ReadReceiptHandler
|
||||||
|
@ -47,16 +44,16 @@ import java.util.concurrent.atomic.AtomicReference
|
||||||
|
|
||||||
internal class DefaultTimeline internal constructor(private val roomId: String,
|
internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
private val initialEventId: String?,
|
private val initialEventId: String?,
|
||||||
private val settings: TimelineSettings,
|
|
||||||
private val realmConfiguration: RealmConfiguration,
|
private val realmConfiguration: RealmConfiguration,
|
||||||
private val loadRoomMembersTask: LoadRoomMembersTask,
|
private val loadRoomMembersTask: LoadRoomMembersTask,
|
||||||
private val readReceiptHandler: ReadReceiptHandler,
|
private val readReceiptHandler: ReadReceiptHandler,
|
||||||
|
settings: TimelineSettings,
|
||||||
paginationTask: PaginationTask,
|
paginationTask: PaginationTask,
|
||||||
getEventTask: GetContextOfEventTask,
|
getEventTask: GetContextOfEventTask,
|
||||||
fetchTokenAndPaginateTask: FetchTokenAndPaginateTask,
|
fetchTokenAndPaginateTask: FetchTokenAndPaginateTask,
|
||||||
timelineEventMapper: TimelineEventMapper,
|
timelineEventMapper: TimelineEventMapper,
|
||||||
timelineInput: TimelineInput,
|
timelineInput: TimelineInput,
|
||||||
private val threadsAwarenessHandler: ThreadsAwarenessHandler,
|
threadsAwarenessHandler: ThreadsAwarenessHandler,
|
||||||
eventDecryptor: TimelineEventDecryptor) : Timeline {
|
eventDecryptor: TimelineEventDecryptor) : Timeline {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -76,6 +73,7 @@ internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
private val sequencer = SemaphoreCoroutineSequencer()
|
private val sequencer = SemaphoreCoroutineSequencer()
|
||||||
|
|
||||||
private val strategyDependencies = LoadTimelineStrategy.Dependencies(
|
private val strategyDependencies = LoadTimelineStrategy.Dependencies(
|
||||||
|
timelineScope = timelineScope,
|
||||||
eventDecryptor = eventDecryptor,
|
eventDecryptor = eventDecryptor,
|
||||||
timelineSettings = settings,
|
timelineSettings = settings,
|
||||||
paginationTask = paginationTask,
|
paginationTask = paginationTask,
|
||||||
|
@ -139,6 +137,7 @@ internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
override fun restartWithEventId(eventId: String?) {
|
override fun restartWithEventId(eventId: String?) {
|
||||||
timelineScope.launch {
|
timelineScope.launch {
|
||||||
openAround(eventId)
|
openAround(eventId)
|
||||||
|
postSnapshot()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +164,7 @@ internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
}.get()
|
}.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun loadMore(count: Long, direction: Timeline.Direction) = withContext(timelineDispatcher) {
|
private suspend fun loadMore(count: Long, direction: Timeline.Direction) {
|
||||||
val baseLogMessage = "loadMore(count: $count, direction: $direction, roomId: $roomId)"
|
val baseLogMessage = "loadMore(count: $count, direction: $direction, roomId: $roomId)"
|
||||||
Timber.v("$baseLogMessage started")
|
Timber.v("$baseLogMessage started")
|
||||||
if (!isStarted.get()) {
|
if (!isStarted.get()) {
|
||||||
|
@ -174,21 +173,21 @@ internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
val currentState = getPaginationState(direction)
|
val currentState = getPaginationState(direction)
|
||||||
if (!currentState.hasMoreToLoad) {
|
if (!currentState.hasMoreToLoad) {
|
||||||
Timber.v("$baseLogMessage : nothing more to load")
|
Timber.v("$baseLogMessage : nothing more to load")
|
||||||
return@withContext
|
return
|
||||||
}
|
}
|
||||||
if (currentState.loading) {
|
if (currentState.loading) {
|
||||||
Timber.v("$baseLogMessage : already loading")
|
Timber.v("$baseLogMessage : already loading")
|
||||||
return@withContext
|
return
|
||||||
}
|
}
|
||||||
updateState(direction) {
|
updateState(direction) {
|
||||||
it.copy(loading = true)
|
it.copy(loading = true)
|
||||||
}
|
}
|
||||||
val loadMoreResult = strategy.loadMore(count, direction)
|
val loadMoreResult = strategy.loadMore(count, direction)
|
||||||
|
Timber.v("$baseLogMessage: result $loadMoreResult")
|
||||||
val hasMoreToLoad = loadMoreResult != LoadMoreResult.REACHED_END
|
val hasMoreToLoad = loadMoreResult != LoadMoreResult.REACHED_END
|
||||||
updateState(direction) {
|
updateState(direction) {
|
||||||
it.copy(loading = false, hasMoreToLoad = hasMoreToLoad)
|
it.copy(loading = false, hasMoreToLoad = hasMoreToLoad)
|
||||||
}
|
}
|
||||||
postSnapshot()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun openAround(eventId: String?) = withContext(timelineDispatcher) {
|
private suspend fun openAround(eventId: String?) = withContext(timelineDispatcher) {
|
||||||
|
@ -210,12 +209,12 @@ internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
it.copy(loading = false, hasMoreToLoad = true)
|
it.copy(loading = false, hasMoreToLoad = true)
|
||||||
}
|
}
|
||||||
strategy.onStart()
|
strategy.onStart()
|
||||||
postSnapshot()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun postSnapshot() {
|
private fun postSnapshot() {
|
||||||
timelineScope.launch {
|
timelineScope.launch {
|
||||||
val snapshot = strategy.buildSnapshot()
|
val snapshot = strategy.buildSnapshot()
|
||||||
|
Timber.v("Post snapshot of ${snapshot.size} items")
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
tryOrNull { it.onTimelineUpdated(snapshot) }
|
tryOrNull { it.onTimelineUpdated(snapshot) }
|
||||||
|
@ -242,7 +241,7 @@ internal class DefaultTimeline internal constructor(private val roomId: String,
|
||||||
stateReference.set(newValue)
|
stateReference.set(newValue)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
listeners.forEach {
|
listeners.forEach {
|
||||||
tryOrNull { it.onStateUpdated() }
|
tryOrNull { it.onStateUpdated(direction, newValue) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import io.realm.OrderedCollectionChangeSet
|
||||||
import io.realm.OrderedRealmCollectionChangeListener
|
import io.realm.OrderedRealmCollectionChangeListener
|
||||||
import io.realm.Realm
|
import io.realm.Realm
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
|
@ -62,6 +63,7 @@ internal class LoadTimelineStrategy(
|
||||||
|
|
||||||
data class Dependencies(
|
data class Dependencies(
|
||||||
val timelineSettings: TimelineSettings,
|
val timelineSettings: TimelineSettings,
|
||||||
|
val timelineScope: CoroutineScope,
|
||||||
val realm: AtomicReference<Realm>,
|
val realm: AtomicReference<Realm>,
|
||||||
val eventDecryptor: TimelineEventDecryptor,
|
val eventDecryptor: TimelineEventDecryptor,
|
||||||
val paginationTask: PaginationTask,
|
val paginationTask: PaginationTask,
|
||||||
|
@ -214,7 +216,8 @@ internal class LoadTimelineStrategy(
|
||||||
uiEchoManager = uiEchoManager,
|
uiEchoManager = uiEchoManager,
|
||||||
threadsAwarenessHandler = dependencies.threadsAwarenessHandler,
|
threadsAwarenessHandler = dependencies.threadsAwarenessHandler,
|
||||||
initialEventId = mode.originEventId(),
|
initialEventId = mode.originEventId(),
|
||||||
onBuiltEvents = dependencies.onEventsUpdated
|
onBuiltEvents = dependencies.onEventsUpdated,
|
||||||
|
timelineScope = dependencies.timelineScope
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,8 @@ import io.realm.RealmObjectChangeListener
|
||||||
import io.realm.RealmQuery
|
import io.realm.RealmQuery
|
||||||
import io.realm.RealmResults
|
import io.realm.RealmResults
|
||||||
import io.realm.Sort
|
import io.realm.Sort
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import org.matrix.android.sdk.api.extensions.orFalse
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
import org.matrix.android.sdk.api.session.room.timeline.Timeline
|
||||||
|
@ -50,6 +51,7 @@ private const val PAGINATION_COUNT = 50
|
||||||
* It also triggers pagination to the server when needed, or dispatch to the prev or next chunk if any.
|
* It also triggers pagination to the server when needed, or dispatch to the prev or next chunk if any.
|
||||||
*/
|
*/
|
||||||
internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
|
private val timelineScope: CoroutineScope,
|
||||||
private val timelineSettings: TimelineSettings,
|
private val timelineSettings: TimelineSettings,
|
||||||
private val roomId: String,
|
private val roomId: String,
|
||||||
private val timelineId: String,
|
private val timelineId: String,
|
||||||
|
@ -65,18 +67,30 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
private val isLastForward = AtomicBoolean(chunkEntity.isLastForward)
|
private val isLastForward = AtomicBoolean(chunkEntity.isLastForward)
|
||||||
|
|
||||||
private val chunkObjectListener = RealmObjectChangeListener<ChunkEntity> { _, changeSet ->
|
private val chunkObjectListener = RealmObjectChangeListener<ChunkEntity> { _, changeSet ->
|
||||||
if(changeSet?.isDeleted.orFalse()){
|
if (changeSet == null) return@RealmObjectChangeListener
|
||||||
|
if (changeSet.isDeleted.orFalse()) {
|
||||||
return@RealmObjectChangeListener
|
return@RealmObjectChangeListener
|
||||||
}
|
}
|
||||||
Timber.v("on chunk (${chunkEntity.identifier()}) changed: ${changeSet?.changedFields?.joinToString(",")}")
|
Timber.v("on chunk (${chunkEntity.identifier()}) changed: ${changeSet.changedFields?.joinToString(",")}")
|
||||||
if(changeSet?.isFieldChanged(ChunkEntityFields.IS_LAST_FORWARD).orFalse()){
|
if (changeSet.isFieldChanged(ChunkEntityFields.IS_LAST_FORWARD)) {
|
||||||
isLastForward.set(chunkEntity.isLastForward)
|
isLastForward.set(chunkEntity.isLastForward)
|
||||||
}
|
}
|
||||||
|
if (changeSet.isFieldChanged(ChunkEntityFields.NEXT_CHUNK.`$`)) {
|
||||||
|
nextChunk = createTimelineChunk(chunkEntity.nextChunk)
|
||||||
|
timelineScope.launch {
|
||||||
|
nextChunk?.loadMore(PAGINATION_COUNT.toLong(), Timeline.Direction.FORWARDS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changeSet.isFieldChanged(ChunkEntityFields.PREV_CHUNK.`$`)) {
|
||||||
|
prevChunk = createTimelineChunk(chunkEntity.prevChunk)
|
||||||
|
timelineScope.launch {
|
||||||
|
prevChunk?.loadMore(PAGINATION_COUNT.toLong(), Timeline.Direction.BACKWARDS)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val timelineEventCollectionListener = OrderedRealmCollectionChangeListener { results: RealmResults<TimelineEventEntity>, changeSet: OrderedCollectionChangeSet ->
|
private val timelineEventCollectionListener = OrderedRealmCollectionChangeListener { results: RealmResults<TimelineEventEntity>, changeSet: OrderedCollectionChangeSet ->
|
||||||
val frozenResults = results.freeze()
|
val frozenResults = results.freeze()
|
||||||
Timber.v("on timeline event changed: $changeSet")
|
|
||||||
handleDatabaseChangeSet(frozenResults, changeSet)
|
handleDatabaseChangeSet(frozenResults, changeSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,18 +130,22 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
|
|
||||||
suspend fun loadMore(count: Long, direction: Timeline.Direction): LoadMoreResult {
|
suspend fun loadMore(count: Long, direction: Timeline.Direction): LoadMoreResult {
|
||||||
val loadFromDbCount = loadFromDb(count, direction)
|
val loadFromDbCount = loadFromDb(count, direction)
|
||||||
|
Timber.v("Has loaded $loadFromDbCount items from db")
|
||||||
val offsetCount = count - loadFromDbCount
|
val offsetCount = count - loadFromDbCount
|
||||||
// We have built the right amount of data
|
// We have built the right amount of data
|
||||||
if (offsetCount == 0L) {
|
return if (offsetCount == 0L) {
|
||||||
onBuiltEvents()
|
LoadMoreResult.SUCCESS
|
||||||
return LoadMoreResult.SUCCESS
|
} else {
|
||||||
|
delegateLoadMore(offsetCount, direction)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun delegateLoadMore(offsetCount: Long, direction: Timeline.Direction): LoadMoreResult {
|
||||||
return if (direction == Timeline.Direction.FORWARDS) {
|
return if (direction == Timeline.Direction.FORWARDS) {
|
||||||
val nextChunkEntity = chunkEntity.nextChunk
|
val nextChunkEntity = chunkEntity.nextChunk
|
||||||
if (nextChunkEntity == null) {
|
if (nextChunkEntity == null) {
|
||||||
// Fetch next chunk from server if not in the db
|
// Fetch next chunk from server if not in the db
|
||||||
val token = chunkEntity.nextToken
|
fetchFromServer(chunkEntity.nextToken, direction)
|
||||||
fetchFromServer(token, direction)
|
|
||||||
} else {
|
} else {
|
||||||
// otherwise we delegate to the next chunk
|
// otherwise we delegate to the next chunk
|
||||||
if (nextChunk == null) {
|
if (nextChunk == null) {
|
||||||
|
@ -139,8 +157,7 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
val prevChunkEntity = chunkEntity.prevChunk
|
val prevChunkEntity = chunkEntity.prevChunk
|
||||||
if (prevChunkEntity == null) {
|
if (prevChunkEntity == null) {
|
||||||
// Fetch prev chunk from server if not in the db
|
// Fetch prev chunk from server if not in the db
|
||||||
val token = chunkEntity.prevToken
|
fetchFromServer(chunkEntity.prevToken, direction)
|
||||||
fetchFromServer(token, direction)
|
|
||||||
} else {
|
} else {
|
||||||
// otherwise we delegate to the prev chunk
|
// otherwise we delegate to the prev chunk
|
||||||
if (prevChunk == null) {
|
if (prevChunk == null) {
|
||||||
|
@ -227,6 +244,9 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
timelineEventEntities.removeChangeListener(timelineEventCollectionListener)
|
timelineEventEntities.removeChangeListener(timelineEventCollectionListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method tries to read events from the current chunk.
|
||||||
|
*/
|
||||||
private suspend fun loadFromDb(count: Long, direction: Timeline.Direction): Long {
|
private suspend fun loadFromDb(count: Long, direction: Timeline.Direction): Long {
|
||||||
val displayIndex = getNextDisplayIndex(direction) ?: return 0
|
val displayIndex = getNextDisplayIndex(direction) ?: return 0
|
||||||
val baseQuery = timelineEventEntities.where()
|
val baseQuery = timelineEventEntities.where()
|
||||||
|
@ -247,6 +267,7 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
builtEvents.add(timelineEvent)
|
builtEvents.add(timelineEvent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
onBuiltEvents()
|
||||||
return timelineEvents.size.toLong()
|
return timelineEvents.size.toLong()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,7 +285,6 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
threadsAwarenessHandler.fetchRootThreadEventsIfNeeded(eventEntityList)
|
threadsAwarenessHandler.fetchRootThreadEventsIfNeeded(eventEntityList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun TimelineEventEntity.buildAndDecryptIfNeeded(): TimelineEvent {
|
private fun TimelineEventEntity.buildAndDecryptIfNeeded(): TimelineEvent {
|
||||||
val timelineEvent = buildTimelineEvent(this)
|
val timelineEvent = buildTimelineEvent(this)
|
||||||
val transactionId = timelineEvent.root.unsignedData?.transactionId
|
val transactionId = timelineEvent.root.unsignedData?.transactionId
|
||||||
|
@ -284,23 +304,11 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
(uiEchoManager?.decorateEventWithReactionUiEcho(it) ?: it)
|
(uiEchoManager?.decorateEventWithReactionUiEcho(it) ?: it)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTimelineChunk(chunkEntity: ChunkEntity): TimelineChunk {
|
/**
|
||||||
return TimelineChunk(
|
* Will try to fetch a new chunk on the home server.
|
||||||
chunkEntity = chunkEntity,
|
* It will take care to update the database by inserting new events and linking new chunk
|
||||||
timelineSettings = timelineSettings,
|
* with this one.
|
||||||
timelineId = timelineId,
|
*/
|
||||||
eventDecryptor = eventDecryptor,
|
|
||||||
roomId = roomId,
|
|
||||||
paginationTask = paginationTask,
|
|
||||||
fetchTokenAndPaginateTask = fetchTokenAndPaginateTask,
|
|
||||||
timelineEventMapper = timelineEventMapper,
|
|
||||||
uiEchoManager = uiEchoManager,
|
|
||||||
threadsAwarenessHandler = threadsAwarenessHandler,
|
|
||||||
initialEventId = null,
|
|
||||||
onBuiltEvents = onBuiltEvents
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun fetchFromServer(token: String?, direction: Timeline.Direction): LoadMoreResult {
|
private suspend fun fetchFromServer(token: String?, direction: Timeline.Direction): LoadMoreResult {
|
||||||
val paginationResult = try {
|
val paginationResult = try {
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
|
@ -309,6 +317,7 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
val taskParams = FetchTokenAndPaginateTask.Params(roomId, lastKnownEventId, direction.toPaginationDirection(), PAGINATION_COUNT)
|
val taskParams = FetchTokenAndPaginateTask.Params(roomId, lastKnownEventId, direction.toPaginationDirection(), PAGINATION_COUNT)
|
||||||
fetchTokenAndPaginateTask.execute(taskParams)
|
fetchTokenAndPaginateTask.execute(taskParams)
|
||||||
} else {
|
} else {
|
||||||
|
Timber.v("Fetch more events on server")
|
||||||
val taskParams = PaginationTask.Params(roomId, token, direction.toPaginationDirection(), PAGINATION_COUNT)
|
val taskParams = PaginationTask.Params(roomId, token, direction.toPaginationDirection(), PAGINATION_COUNT)
|
||||||
paginationTask.execute(taskParams)
|
paginationTask.execute(taskParams)
|
||||||
}
|
}
|
||||||
|
@ -337,6 +346,10 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is responsible for managing insertions and updates of events on this chunk.
|
||||||
|
*
|
||||||
|
*/
|
||||||
private fun handleDatabaseChangeSet(frozenResults: RealmResults<TimelineEventEntity>, changeSet: OrderedCollectionChangeSet) {
|
private fun handleDatabaseChangeSet(frozenResults: RealmResults<TimelineEventEntity>, changeSet: OrderedCollectionChangeSet) {
|
||||||
val insertions = changeSet.insertionRanges
|
val insertions = changeSet.insertionRanges
|
||||||
for (range in insertions) {
|
for (range in insertions) {
|
||||||
|
@ -385,6 +398,25 @@ internal class TimelineChunk constructor(private val chunkEntity: ChunkEntity,
|
||||||
builtEvents.last().displayIndex - 1
|
builtEvents.last().displayIndex - 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun createTimelineChunk(chunkEntity: ChunkEntity?): TimelineChunk? {
|
||||||
|
if (chunkEntity == null) return null
|
||||||
|
return TimelineChunk(
|
||||||
|
chunkEntity = chunkEntity,
|
||||||
|
timelineScope = timelineScope,
|
||||||
|
timelineSettings = timelineSettings,
|
||||||
|
timelineId = timelineId,
|
||||||
|
eventDecryptor = eventDecryptor,
|
||||||
|
roomId = roomId,
|
||||||
|
paginationTask = paginationTask,
|
||||||
|
fetchTokenAndPaginateTask = fetchTokenAndPaginateTask,
|
||||||
|
timelineEventMapper = timelineEventMapper,
|
||||||
|
uiEchoManager = uiEchoManager,
|
||||||
|
threadsAwarenessHandler = threadsAwarenessHandler,
|
||||||
|
initialEventId = null,
|
||||||
|
onBuiltEvents = this.onBuiltEvents
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun RealmQuery<TimelineEventEntity>.offsets(
|
private fun RealmQuery<TimelineEventEntity>.offsets(
|
||||||
|
|
|
@ -310,9 +310,9 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStateUpdated(direction: Timeline.Direction, state: Timeline.PaginationState) {
|
override fun onStateUpdated(direction: Timeline.Direction, state: Timeline.PaginationState) {
|
||||||
if(!state.hasMoreToLoad) {
|
if (!state.hasMoreToLoad) {
|
||||||
backgroundHandler.post {
|
backgroundHandler.post {
|
||||||
requestModelBuild()
|
requestDelayedModelBuild(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
|
||||||
currentSnapshot = newSnapshot
|
currentSnapshot = newSnapshot
|
||||||
val diffResult = DiffUtil.calculateDiff(diffCallback)
|
val diffResult = DiffUtil.calculateDiff(diffCallback)
|
||||||
diffResult.dispatchUpdatesTo(listUpdateCallback)
|
diffResult.dispatchUpdatesTo(listUpdateCallback)
|
||||||
requestModelBuild()
|
requestDelayedModelBuild(0)
|
||||||
inSubmitList = false
|
inSubmitList = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue