archive-97f2350/app/src/main/java/uk/orllewin/sianel/data/VideoPagingSource.kt 1.5 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
package uk.orllewin.sianel.data

import androidx.paging.PagingSource
import androidx.paging.PagingState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * Offset-keyed paging over [SianelService.listPage]. The key is the row offset into
 * the newest-first list; [SianelService.Page.total] tells us when to stop.
 */
class VideoPagingSource(
    private val client: SianelService,
) : PagingSource<Int, SianelService.VideoItem>() {

    override suspend fun load(
        params: LoadParams<Int>,
    ): LoadResult<Int, SianelService.VideoItem> {
        val offset = params.key ?: 0
        val count = params.loadSize
        return try {
            val page = withContext(Dispatchers.IO) { client.listPage(offset, count) }
            val nextOffset = offset + page.items.size
            LoadResult.Page(
                data = page.items,
                prevKey = if (offset == 0) null else (offset - count).coerceAtLeast(0),
                nextKey = if (nextOffset >= page.total || page.items.isEmpty()) null else nextOffset,
            )
        } catch (e: Throwable) {
            LoadResult.Error(e)
        }
    }

    // Recompute a sensible reload key around the user's current position.
    override fun getRefreshKey(state: PagingState<Int, SianelService.VideoItem>): Int? {
        val anchor = state.anchorPosition ?: return null
        val page = state.closestPageToPosition(anchor) ?: return null
        return page.prevKey?.plus(state.config.pageSize) ?: page.nextKey?.minus(state.config.pageSize)
    }
}