Timeline : try to get better forward pagination.
This commit is contained in:
parent
7ac6e4166a
commit
7b4fa146e5
8 changed files with 119 additions and 101 deletions
|
|
@ -45,12 +45,11 @@ import io.element.android.libraries.matrix.impl.timeline.item.event.EventMessage
|
|||
import io.element.android.libraries.matrix.impl.timeline.item.event.EventTimelineItemMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.event.TimelineEventContentMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.item.virtual.VirtualTimelineItemMapper
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.InvisibleIndicatorPostProcessor
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.LastForwardIndicatorsPostProcessor
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.LoadingIndicatorsPostProcessor
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.RoomBeginningPostProcessor
|
||||
import io.element.android.libraries.matrix.impl.timeline.postprocessor.TimelineEncryptedHistoryPostProcessor
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -116,7 +115,7 @@ class RustTimeline(
|
|||
|
||||
private val roomBeginningPostProcessor = RoomBeginningPostProcessor()
|
||||
private val loadingIndicatorsPostProcessor = LoadingIndicatorsPostProcessor(systemClock)
|
||||
private val invisibleIndicatorPostProcessor = InvisibleIndicatorPostProcessor(isLive)
|
||||
private val lastForwardIndicatorsPostProcessor = LastForwardIndicatorsPostProcessor(isLive)
|
||||
|
||||
private val timelineItemFactory = MatrixTimelineItemMapper(
|
||||
fetchDetailsForEvent = this::fetchDetailsForEvent,
|
||||
|
|
@ -225,7 +224,8 @@ class RustTimeline(
|
|||
hasMoreToLoadBackwards = hasMoreToLoadBackward
|
||||
)
|
||||
}.let { items -> loadingIndicatorsPostProcessor.process(items, hasMoreToLoadBackward, hasMoreToLoadForward) }
|
||||
.let { items -> invisibleIndicatorPostProcessor.process(items) }
|
||||
// Keep lastForwardIndicatorsPostProcessor last
|
||||
.let { items -> lastForwardIndicatorsPostProcessor.process(items) }
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.timeline.postprocessor
|
||||
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||
|
||||
class InvisibleIndicatorPostProcessor(
|
||||
private val isLive: Boolean,
|
||||
) {
|
||||
private val latestEventIdentifiers: MutableSet<String> = HashSet()
|
||||
|
||||
fun process(
|
||||
items: List<MatrixTimelineItem>,
|
||||
): List<MatrixTimelineItem> {
|
||||
if (isLive) {
|
||||
return items
|
||||
} else {
|
||||
return buildList {
|
||||
items.forEach { item ->
|
||||
add(item)
|
||||
if (item is MatrixTimelineItem.Event) {
|
||||
if (latestEventIdentifiers.contains(item.uniqueId)) {
|
||||
add(createLatestKnownEventIndicator(item.uniqueId))
|
||||
}
|
||||
}
|
||||
}
|
||||
items.latestEventIdentifier()?.let { latestEventIdentifier ->
|
||||
if (latestEventIdentifiers.add(latestEventIdentifier)) {
|
||||
add(createLatestKnownEventIndicator(latestEventIdentifier))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLatestKnownEventIndicator(identifier: String): MatrixTimelineItem {
|
||||
return MatrixTimelineItem.Virtual(
|
||||
uniqueId = "latest_known_event_$identifier",
|
||||
virtual = VirtualTimelineItem.LatestKnownEventIndicator
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<MatrixTimelineItem>.latestEventIdentifier(): String? {
|
||||
return findLast {
|
||||
when (it) {
|
||||
is MatrixTimelineItem.Event -> true
|
||||
else -> false
|
||||
}
|
||||
}?.let {
|
||||
(it as MatrixTimelineItem.Event).uniqueId
|
||||
}
|
||||
}
|
||||
|
||||
private fun List<MatrixTimelineItem>.indexOf(identifier: String): Int {
|
||||
return indexOfLast {
|
||||
when (it) {
|
||||
is MatrixTimelineItem.Event -> {
|
||||
it.uniqueId == identifier
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2024 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.timeline.postprocessor
|
||||
|
||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
|
||||
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
|
||||
|
||||
/**
|
||||
* This post processor is responsible for adding virtual items to indicate all the previous last forward item.
|
||||
*/
|
||||
class LastForwardIndicatorsPostProcessor(
|
||||
private val isTimelineLive: Boolean,
|
||||
) {
|
||||
|
||||
private val lastForwardIdentifiers = LinkedHashSet<String>()
|
||||
|
||||
fun process(
|
||||
items: List<MatrixTimelineItem>,
|
||||
): List<MatrixTimelineItem> {
|
||||
// If the timeline is live, we don't have any last forward indicator to display
|
||||
if (isTimelineLive) {
|
||||
return items
|
||||
} else {
|
||||
return buildList {
|
||||
val latestEventIdentifier = items.latestEventIdentifier()
|
||||
// Remove if it always exists (this should happen only when no new events are added)
|
||||
lastForwardIdentifiers.remove(latestEventIdentifier)
|
||||
|
||||
items.forEach { item ->
|
||||
add(item)
|
||||
|
||||
if (item is MatrixTimelineItem.Event) {
|
||||
if (lastForwardIdentifiers.contains(item.uniqueId)) {
|
||||
add(createLastForwardIndicator(item.uniqueId))
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is important to always add this one at the end of the list so it's used to keep the scroll position.
|
||||
add(createLastForwardIndicator(latestEventIdentifier))
|
||||
lastForwardIdentifiers.add(latestEventIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createLastForwardIndicator(identifier: String): MatrixTimelineItem {
|
||||
return MatrixTimelineItem.Virtual(
|
||||
uniqueId = "last_forward_indicator_$identifier",
|
||||
virtual = VirtualTimelineItem.LastForwardIndicator
|
||||
)
|
||||
}
|
||||
|
||||
private fun List<MatrixTimelineItem>.latestEventIdentifier(): String {
|
||||
return findLast {
|
||||
when (it) {
|
||||
is MatrixTimelineItem.Event -> true
|
||||
else -> false
|
||||
}
|
||||
}?.let {
|
||||
(it as MatrixTimelineItem.Event).uniqueId
|
||||
} ?: "fake_id"
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue