Fix pages bottom sheet scroll

This commit is contained in:
Koitharu
2023-06-04 15:42:15 +03:00
parent da4aedca97
commit b48c6d7d38
7 changed files with 84 additions and 44 deletions

View File

@@ -16,23 +16,25 @@ import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.ui.list.BoundsScrollListener
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.core.ui.list.ScrollListenerInvalidationObserver
import org.koitharu.kotatsu.core.ui.list.decor.SpacingItemDecoration
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetBehavior
import org.koitharu.kotatsu.core.ui.sheet.AdaptiveSheetCallback
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
import org.koitharu.kotatsu.core.util.RecyclerViewScrollCallback
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.plus
import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
import org.koitharu.kotatsu.core.util.ext.withArgs
import org.koitharu.kotatsu.databinding.SheetPagesBinding
import org.koitharu.kotatsu.list.ui.MangaListSpanResolver
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.reader.ui.ReaderActivity
import org.koitharu.kotatsu.reader.ui.ReaderState
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.TargetScrollObserver
import javax.inject.Inject
import kotlin.math.roundToInt
@AndroidEntryPoint
class PagesThumbnailsSheet :
@@ -79,14 +81,8 @@ class PagesThumbnailsSheet :
spanResolver?.setGridSize(settings.gridSize / 100f, this)
addOnScrollListener(ScrollListener().also { scrollListener = it })
(layoutManager as GridLayoutManager).spanSizeLookup = spanSizeLookup
thumbnailsAdapter?.registerAdapterDataObserver(
ScrollListenerInvalidationObserver(this, checkNotNull(scrollListener)),
)
thumbnailsAdapter?.registerAdapterDataObserver(TargetScrollObserver(this))
}
viewModel.thumbnails.observe(viewLifecycleOwner) {
thumbnailsAdapter?.setItems(it, listCommitCallback)
}
viewModel.thumbnails.observe(viewLifecycleOwner, ::onThumbnailsChanged)
viewModel.branch.observe(viewLifecycleOwner, ::updateTitle)
viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.recyclerView, this))
}
@@ -124,6 +120,28 @@ class PagesThumbnailsSheet :
}
}
private fun onThumbnailsChanged(list: List<ListModel>) {
val adapter = thumbnailsAdapter ?: return
if (adapter.itemCount == 0) {
var position = list.indexOfFirst { it is PageThumbnail && it.isCurrent }
if (position > 0) {
val spanCount = spanResolver?.spanCount ?: 0
val offset = if (position > spanCount + 1) {
(resources.getDimensionPixelSize(R.dimen.manga_list_details_item_height) * 0.6).roundToInt()
} else {
position = 0
0
}
val scrollCallback = RecyclerViewScrollCallback(requireViewBinding().recyclerView, position, offset)
adapter.setItems(list, listCommitCallback + scrollCallback)
} else {
adapter.setItems(list, listCommitCallback)
}
} else {
adapter.setItems(list, listCommitCallback)
}
}
private inner class ScrollListener : BoundsScrollListener(3, 3) {
override fun onScrolledToStart(recyclerView: RecyclerView) {
@@ -133,6 +151,13 @@ class PagesThumbnailsSheet :
override fun onScrolledToEnd(recyclerView: RecyclerView) {
viewModel.loadNextChapter()
}
override fun onPostScrolled(recyclerView: RecyclerView, firstVisibleItemPosition: Int, visibleItemCount: Int) {
super.onPostScrolled(recyclerView, firstVisibleItemPosition, visibleItemCount)
if (firstVisibleItemPosition > offsetTop) {
viewModel.allowLoadAbove()
}
}
}
private inner class SpanSizeLookup : GridLayoutManager.SpanSizeLookup() {

View File

@@ -39,6 +39,7 @@ class PagesThumbnailsViewModel @Inject constructor(
private var loadingJob: Job? = null
private var loadingPrevJob: Job? = null
private var loadingNextJob: Job? = null
private var isLoadAboveAllowed = false
val thumbnails = MutableStateFlow<List<ListModel>>(emptyList())
val branch = MutableStateFlow<String?>(null)
@@ -51,8 +52,17 @@ class PagesThumbnailsViewModel @Inject constructor(
}
}
fun allowLoadAbove() {
if (!isLoadAboveAllowed) {
loadingJob = launchJob(Dispatchers.Default) {
isLoadAboveAllowed = true
updateList()
}
}
}
fun loadPrevChapter() {
if (loadingJob?.isActive == true || loadingPrevJob?.isActive == true) {
if (!isLoadAboveAllowed || loadingJob?.isActive == true || loadingPrevJob?.isActive == true) {
return
}
loadingPrevJob = loadPrevNextChapter(isNext = false)
@@ -74,7 +84,7 @@ class PagesThumbnailsViewModel @Inject constructor(
private suspend fun updateList() {
val snapshot = chaptersLoader.snapshot()
val mangaChapters = mangaDetails.tryGet().getOrNull()?.chapters.orEmpty()
val hasPrevChapter = snapshot.firstOrNull()?.chapterId != mangaChapters.firstOrNull()?.id
val hasPrevChapter = isLoadAboveAllowed && snapshot.firstOrNull()?.chapterId != mangaChapters.firstOrNull()?.id
val hasNextChapter = snapshot.lastOrNull()?.chapterId != mangaChapters.lastOrNull()?.id
val pages = buildList(snapshot.size + chaptersLoader.size + 2) {
if (hasPrevChapter) {