Fix pages bottom sheet scroll
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user