Fix concurrent chapters loading in reader
This commit is contained in:
@@ -8,19 +8,22 @@ abstract class BoundsScrollListener(private val offsetTop: Int, private val offs
|
||||
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
if (recyclerView.hasPendingAdapterUpdates()) {
|
||||
return
|
||||
}
|
||||
val layoutManager = (recyclerView.layoutManager as? LinearLayoutManager) ?: return
|
||||
val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()
|
||||
if (firstVisibleItemPosition == RecyclerView.NO_POSITION) {
|
||||
return
|
||||
}
|
||||
if (firstVisibleItemPosition <= offsetTop) {
|
||||
onScrolledToStart(recyclerView)
|
||||
}
|
||||
val visibleItemCount = layoutManager.childCount
|
||||
val totalItemCount = layoutManager.itemCount
|
||||
if (visibleItemCount + firstVisibleItemPosition >= totalItemCount - offsetBottom) {
|
||||
onScrolledToEnd(recyclerView)
|
||||
}
|
||||
if (firstVisibleItemPosition <= offsetTop) {
|
||||
onScrolledToStart(recyclerView)
|
||||
}
|
||||
}
|
||||
|
||||
abstract fun onScrolledToStart(recyclerView: RecyclerView)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.koitharu.kotatsu.base.ui.list
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
class ScrollListenerInvalidationObserver(
|
||||
private val recyclerView: RecyclerView,
|
||||
private val scrollListener: RecyclerView.OnScrollListener,
|
||||
) : RecyclerView.AdapterDataObserver() {
|
||||
|
||||
override fun onChanged() {
|
||||
super.onChanged()
|
||||
invalidateScroll()
|
||||
}
|
||||
|
||||
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
|
||||
super.onItemRangeInserted(positionStart, itemCount)
|
||||
invalidateScroll()
|
||||
}
|
||||
|
||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||
super.onItemRangeRemoved(positionStart, itemCount)
|
||||
invalidateScroll()
|
||||
}
|
||||
|
||||
private fun invalidateScroll() {
|
||||
recyclerView.post {
|
||||
scrollListener.onScrolled(recyclerView, 0, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,6 +252,7 @@ class ReaderViewModel @Inject constructor(
|
||||
val prevJob = stateChangeJob
|
||||
stateChangeJob = launchJob(Dispatchers.Default) {
|
||||
prevJob?.cancelAndJoin()
|
||||
loadingJob?.join()
|
||||
val pages = content.value?.pages ?: return@launchJob
|
||||
pages.getOrNull(position)?.let { page ->
|
||||
currentState.update { cs ->
|
||||
@@ -263,12 +264,12 @@ class ReaderViewModel @Inject constructor(
|
||||
return@launchJob
|
||||
}
|
||||
ensureActive()
|
||||
if (position <= BOUNDS_PAGE_OFFSET) {
|
||||
loadPrevNextChapter(pages.first().chapterId, isNext = false)
|
||||
}
|
||||
if (position >= pages.lastIndex - BOUNDS_PAGE_OFFSET) {
|
||||
loadPrevNextChapter(pages.last().chapterId, isNext = true)
|
||||
}
|
||||
if (position <= BOUNDS_PAGE_OFFSET) {
|
||||
loadPrevNextChapter(pages.first().chapterId, isNext = false)
|
||||
}
|
||||
if (pageLoader.isPrefetchApplicable()) {
|
||||
pageLoader.prefetch(pages.trySublist(position + 1, position + PREFETCH_LIMIT))
|
||||
}
|
||||
@@ -348,7 +349,9 @@ class ReaderViewModel @Inject constructor(
|
||||
|
||||
@AnyThread
|
||||
private fun loadPrevNextChapter(currentId: Long, isNext: Boolean) {
|
||||
val prevJob = loadingJob
|
||||
loadingJob = launchLoadingJob(Dispatchers.Default) {
|
||||
prevJob?.join()
|
||||
chaptersLoader.loadPrevNextChapter(mangaData.requireValue(), currentId, isNext)
|
||||
content.emitValue(ReaderContent(chaptersLoader.snapshot(), null))
|
||||
}
|
||||
|
||||
@@ -54,6 +54,11 @@ var RecyclerView.firstVisibleItemPosition: Int
|
||||
}
|
||||
}
|
||||
|
||||
val RecyclerView.visibleItemCount: Int
|
||||
get() = (layoutManager as? LinearLayoutManager)?.run {
|
||||
findLastVisibleItemPosition() - findFirstVisibleItemPosition()
|
||||
} ?: 0
|
||||
|
||||
fun View.hasGlobalPoint(x: Int, y: Int): Boolean {
|
||||
if (visibility != View.VISIBLE) {
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user