Use custom QueryPagingSource (#7321)
* Use custom QueryPagingSource - Adds placeholder to make the list jump around less - Fixes issue where SQLDelight QueryPagingSource would throw IndexOutOfBounds * Review Changes
This commit is contained in:
@@ -2,8 +2,6 @@ package eu.kanade.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import com.squareup.sqldelight.Query
|
||||
import com.squareup.sqldelight.Transacter
|
||||
import com.squareup.sqldelight.android.paging3.QueryPagingSource
|
||||
import com.squareup.sqldelight.db.SqlDriver
|
||||
import com.squareup.sqldelight.runtime.coroutines.asFlow
|
||||
import com.squareup.sqldelight.runtime.coroutines.mapToList
|
||||
@@ -63,13 +61,11 @@ class AndroidDatabaseHandler(
|
||||
|
||||
override fun <T : Any> subscribeToPagingSource(
|
||||
countQuery: Database.() -> Query<Long>,
|
||||
transacter: Database.() -> Transacter,
|
||||
queryProvider: Database.(Long, Long) -> Query<T>,
|
||||
): PagingSource<Long, T> {
|
||||
return QueryPagingSource(
|
||||
countQuery = countQuery(db),
|
||||
transacter = transacter(db),
|
||||
dispatcher = queryDispatcher,
|
||||
handler = this,
|
||||
countQuery = countQuery,
|
||||
queryProvider = { limit, offset ->
|
||||
queryProvider.invoke(db, limit, offset)
|
||||
},
|
||||
|
||||
@@ -2,7 +2,6 @@ package eu.kanade.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import com.squareup.sqldelight.Query
|
||||
import com.squareup.sqldelight.Transacter
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@@ -33,7 +32,6 @@ interface DatabaseHandler {
|
||||
|
||||
fun <T : Any> subscribeToPagingSource(
|
||||
countQuery: Database.() -> Query<Long>,
|
||||
transacter: Database.() -> Transacter,
|
||||
queryProvider: Database.(Long, Long) -> Query<T>,
|
||||
): PagingSource<Long, T>
|
||||
}
|
||||
|
||||
72
app/src/main/java/eu/kanade/data/QueryPagingSource.kt
Normal file
72
app/src/main/java/eu/kanade/data/QueryPagingSource.kt
Normal file
@@ -0,0 +1,72 @@
|
||||
package eu.kanade.data
|
||||
|
||||
import androidx.paging.PagingSource
|
||||
import androidx.paging.PagingState
|
||||
import com.squareup.sqldelight.Query
|
||||
import eu.kanade.tachiyomi.Database
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
class QueryPagingSource<RowType : Any>(
|
||||
val handler: DatabaseHandler,
|
||||
val countQuery: Database.() -> Query<Long>,
|
||||
val queryProvider: Database.(Long, Long) -> Query<RowType>,
|
||||
) : PagingSource<Long, RowType>(), Query.Listener {
|
||||
|
||||
override val jumpingSupported: Boolean = true
|
||||
|
||||
private var currentQuery: Query<RowType>? by Delegates.observable(null) { _, old, new ->
|
||||
old?.removeListener(this)
|
||||
new?.addListener(this)
|
||||
}
|
||||
|
||||
init {
|
||||
registerInvalidatedCallback {
|
||||
currentQuery?.removeListener(this)
|
||||
currentQuery = null
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(params: LoadParams<Long>): LoadResult<Long, RowType> {
|
||||
try {
|
||||
val key = params.key ?: 0L
|
||||
val loadSize = params.loadSize
|
||||
val count = handler.awaitOne { countQuery() }
|
||||
|
||||
val (offset, limit) = when (params) {
|
||||
is LoadParams.Prepend -> key - loadSize to loadSize.toLong()
|
||||
else -> key to loadSize.toLong()
|
||||
}
|
||||
|
||||
val data = handler.awaitList {
|
||||
queryProvider(limit, offset)
|
||||
.also { currentQuery = it }
|
||||
}
|
||||
|
||||
val (prevKey, nextKey) = when (params) {
|
||||
is LoadParams.Append -> { offset - loadSize to offset + loadSize }
|
||||
else -> { offset to offset + loadSize }
|
||||
}
|
||||
|
||||
return LoadResult.Page(
|
||||
data = data,
|
||||
prevKey = if (offset <= 0L || prevKey < 0L) null else prevKey,
|
||||
nextKey = if (offset + loadSize >= count) null else nextKey,
|
||||
itemsBefore = maxOf(0L, offset).toInt(),
|
||||
itemsAfter = maxOf(0L, count - (offset + loadSize)).toInt(),
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
return LoadResult.Error(throwable = e)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRefreshKey(state: PagingState<Long, RowType>): Long? {
|
||||
return state.anchorPosition?.let { anchorPosition ->
|
||||
val anchorPage = state.closestPageToPosition(anchorPosition)
|
||||
anchorPage?.prevKey ?: anchorPage?.nextKey
|
||||
}
|
||||
}
|
||||
|
||||
override fun queryResultsChanged() {
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ class HistoryRepositoryImpl(
|
||||
override fun getHistory(query: String): PagingSource<Long, HistoryWithRelations> {
|
||||
return handler.subscribeToPagingSource(
|
||||
countQuery = { historyViewQueries.countHistory(query) },
|
||||
transacter = { historyViewQueries },
|
||||
queryProvider = { limit, offset ->
|
||||
historyViewQueries.history(query, limit, offset, historyWithRelationsMapper)
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user