Media timeline: improve pagination logic.
This commit is contained in:
parent
d86430d56a
commit
a4a8fc2268
5 changed files with 23 additions and 73 deletions
|
|
@ -56,6 +56,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.getAndUpdate
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
|
|
@ -64,8 +65,6 @@ import kotlinx.coroutines.flow.onCompletion
|
|||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.onStart
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.matrix.rustcomponents.sdk.EditedContent
|
||||
import org.matrix.rustcomponents.sdk.FormattedBody
|
||||
|
|
@ -172,36 +171,26 @@ class RustTimeline(
|
|||
}
|
||||
}
|
||||
|
||||
private val backwardsPaginationMutex = Mutex()
|
||||
private val forwardsPaginationMutex = Mutex()
|
||||
|
||||
private fun getPaginationMutex(direction: Timeline.PaginationDirection) = when (direction) {
|
||||
Timeline.PaginationDirection.BACKWARDS -> backwardsPaginationMutex
|
||||
Timeline.PaginationDirection.FORWARDS -> forwardsPaginationMutex
|
||||
}
|
||||
|
||||
// Use NonCancellable to avoid breaking the timeline when the coroutine is cancelled.
|
||||
override suspend fun paginate(direction: Timeline.PaginationDirection): Result<Boolean> = withContext(NonCancellable) {
|
||||
withContext(dispatcher) {
|
||||
initLatch.await()
|
||||
getPaginationMutex(direction).withLock {
|
||||
runCatching {
|
||||
if (!canPaginate(direction)) throw TimelineException.CannotPaginate
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = true) }
|
||||
when (direction) {
|
||||
Timeline.PaginationDirection.BACKWARDS -> inner.paginateBackwards(PAGINATION_SIZE.toUShort())
|
||||
Timeline.PaginationDirection.FORWARDS -> inner.focusedPaginateForwards(PAGINATION_SIZE.toUShort())
|
||||
}
|
||||
}.onFailure { error ->
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = false) }
|
||||
if (error is TimelineException.CannotPaginate) {
|
||||
Timber.d("Can't paginate $direction on room ${matrixRoom.roomId} with paginationStatus: ${backPaginationStatus.value}")
|
||||
} else {
|
||||
Timber.e(error, "Error paginating $direction on room ${matrixRoom.roomId}")
|
||||
}
|
||||
}.onSuccess { hasReachedEnd ->
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = false, hasMoreToLoad = !hasReachedEnd) }
|
||||
runCatching {
|
||||
if (!canPaginate(direction)) throw TimelineException.CannotPaginate
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = true) }
|
||||
when (direction) {
|
||||
Timeline.PaginationDirection.BACKWARDS -> inner.paginateBackwards(PAGINATION_SIZE.toUShort())
|
||||
Timeline.PaginationDirection.FORWARDS -> inner.focusedPaginateForwards(PAGINATION_SIZE.toUShort())
|
||||
}
|
||||
}.onFailure { error ->
|
||||
if (error is TimelineException.CannotPaginate) {
|
||||
Timber.d("Can't paginate $direction on room ${matrixRoom.roomId} with paginationStatus: ${backPaginationStatus.value}")
|
||||
} else {
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = false) }
|
||||
Timber.e(error, "Error paginating $direction on room ${matrixRoom.roomId}")
|
||||
}
|
||||
}.onSuccess { hasReachedEnd ->
|
||||
updatePaginationStatus(direction) { it.copy(isPaginating = false, hasMoreToLoad = !hasReachedEnd) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -223,13 +212,13 @@ class RustTimeline(
|
|||
|
||||
override val timelineItems: Flow<List<MatrixTimelineItem>> = combine(
|
||||
_timelineItems,
|
||||
backPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(),
|
||||
forwardPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(),
|
||||
backPaginationStatus.filter { !it.isPaginating }.distinctUntilChanged(),
|
||||
forwardPaginationStatus.filter { !it.isPaginating }.distinctUntilChanged(),
|
||||
matrixRoom.roomInfoFlow.map { it.creator },
|
||||
isTimelineInitialized,
|
||||
) { timelineItems,
|
||||
hasMoreToLoadBackward,
|
||||
hasMoreToLoadForward,
|
||||
backwardPaginationStatus,
|
||||
forwardPaginationStatus,
|
||||
roomCreator,
|
||||
isTimelineInitialized ->
|
||||
withContext(dispatcher) {
|
||||
|
|
@ -239,15 +228,15 @@ class RustTimeline(
|
|||
items = items,
|
||||
isDm = matrixRoom.isDm,
|
||||
roomCreator = roomCreator,
|
||||
hasMoreToLoadBackwards = hasMoreToLoadBackward,
|
||||
hasMoreToLoadBackwards = backwardPaginationStatus.hasMoreToLoad,
|
||||
)
|
||||
}
|
||||
.let { items ->
|
||||
loadingIndicatorsPostProcessor.process(
|
||||
items = items,
|
||||
isTimelineInitialized = isTimelineInitialized,
|
||||
hasMoreToLoadBackward = hasMoreToLoadBackward,
|
||||
hasMoreToLoadForward = hasMoreToLoadForward
|
||||
hasMoreToLoadBackward = backwardPaginationStatus.hasMoreToLoad,
|
||||
hasMoreToLoadForward = forwardPaginationStatus.hasMoreToLoad,
|
||||
)
|
||||
}
|
||||
.let { items ->
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue