Misc fixes
This commit is contained in:
@@ -16,4 +16,8 @@ class PagerLifecycleDispatcher(
|
||||
(wh as? LifecycleAwareViewHolder)?.setIsCurrent(wh.absoluteAdapterPosition == position)
|
||||
}
|
||||
}
|
||||
|
||||
fun invalidate() {
|
||||
onPageSelected(pager.currentItem)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,10 @@ class RecyclerViewLifecycleDispatcher : RecyclerView.OnScrollListener() {
|
||||
|
||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||
super.onScrolled(recyclerView, dx, dy)
|
||||
invalidate(recyclerView)
|
||||
}
|
||||
|
||||
fun invalidate(recyclerView: RecyclerView) {
|
||||
val lm = recyclerView.layoutManager as? LinearLayoutManager ?: return
|
||||
val first = lm.findFirstVisibleItemPosition()
|
||||
val last = lm.findLastVisibleItemPosition()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.koitharu.kotatsu.local.data
|
||||
|
||||
import android.net.Uri
|
||||
import org.koitharu.kotatsu.core.util.ext.URI_SCHEME_ZIP
|
||||
import java.io.File
|
||||
|
||||
private fun isCbzExtension(ext: String?): Boolean {
|
||||
@@ -12,6 +13,8 @@ fun hasCbzExtension(string: String): Boolean {
|
||||
return isCbzExtension(ext)
|
||||
}
|
||||
|
||||
fun hasCbzExtension(file: File) = isCbzExtension(file.extension)
|
||||
fun File.hasCbzExtension() = isCbzExtension(extension)
|
||||
|
||||
fun isCbzUri(uri: Uri) = isCbzExtension(uri.scheme)
|
||||
fun Uri.isZipUri() = scheme.let {
|
||||
it == URI_SCHEME_ZIP || it == "cbz" || it == "zip"
|
||||
}
|
||||
|
||||
@@ -121,13 +121,13 @@ class LocalMangaDirInput(root: File) : LocalMangaInput(root) {
|
||||
private fun String.toHumanReadable() = replace("_", " ").toCamelCase()
|
||||
|
||||
private fun getChaptersFiles(): List<File> = root.walkCompat()
|
||||
.filter { hasCbzExtension(it) }
|
||||
.filter { it.hasCbzExtension() }
|
||||
.toListSorted(compareBy(AlphanumComparator()) { it.name })
|
||||
|
||||
private fun findFirstImageEntry(): String? {
|
||||
return root.walkCompat().firstOrNull { hasImageExtension(it) }?.toUri()?.toString()
|
||||
?: run {
|
||||
val cbz = root.walkCompat().firstOrNull { hasCbzExtension(it) } ?: return null
|
||||
val cbz = root.walkCompat().firstOrNull { it.hasCbzExtension() } ?: return null
|
||||
ZipFile(cbz).use { zip ->
|
||||
zip.entries().asSequence()
|
||||
.firstOrNull { !it.isDirectory && hasImageExtension(it.name) }
|
||||
|
||||
@@ -45,7 +45,7 @@ import org.koitharu.kotatsu.core.util.ext.ramAvailable
|
||||
import org.koitharu.kotatsu.core.util.ext.withProgress
|
||||
import org.koitharu.kotatsu.core.util.progress.ProgressDeferred
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.local.data.isCbzUri
|
||||
import org.koitharu.kotatsu.local.data.isZipUri
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
||||
@@ -199,8 +199,12 @@ class PageLoader @Inject constructor(
|
||||
val pageUrl = getPageUrl(page)
|
||||
check(pageUrl.isNotBlank()) { "Cannot obtain full image url" }
|
||||
val uri = Uri.parse(pageUrl)
|
||||
return if (isCbzUri(uri)) {
|
||||
uri.buildUpon().scheme(URI_SCHEME_ZIP).build()
|
||||
return if (uri.isZipUri()) {
|
||||
if (uri.scheme == URI_SCHEME_ZIP) {
|
||||
uri
|
||||
} else { // legacy uri
|
||||
uri.buildUpon().scheme(URI_SCHEME_ZIP).build()
|
||||
}
|
||||
} else {
|
||||
val request = createPageRequest(page, pageUrl)
|
||||
imageProxyInterceptor.interceptPageRequest(request, okHttp).ensureSuccess().use { response ->
|
||||
|
||||
@@ -11,12 +11,13 @@ import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.yield
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
import org.koitharu.kotatsu.core.prefs.ReaderAnimation
|
||||
import org.koitharu.kotatsu.core.ui.list.lifecycle.PagerLifecycleDispatcher
|
||||
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
||||
import org.koitharu.kotatsu.core.util.ext.findCurrentViewHolder
|
||||
import org.koitharu.kotatsu.core.util.ext.observe
|
||||
@@ -46,6 +47,8 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
@Inject
|
||||
lateinit var pageLoader: PageLoader
|
||||
|
||||
private var pagerLifecycleDispatcher: PagerLifecycleDispatcher? = null
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -62,6 +65,9 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
recyclerView?.defaultFocusHighlightEnabled = false
|
||||
}
|
||||
PagerEventSupplier(this).attach()
|
||||
pagerLifecycleDispatcher = PagerLifecycleDispatcher(this).also {
|
||||
registerOnPageChangeCallback(it)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.pageAnimation.observe(viewLifecycleOwner) {
|
||||
@@ -80,6 +86,7 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
pagerLifecycleDispatcher = null
|
||||
requireViewBinding().pager.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
@@ -132,15 +139,16 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
|
||||
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
|
||||
val reversedPages = pages.asReversed()
|
||||
val items = async {
|
||||
val items = launch {
|
||||
requireAdapter().setItems(reversedPages)
|
||||
yield()
|
||||
pagerLifecycleDispatcher?.invalidate()
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = reversedPages.indexOfLast {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
items.await()
|
||||
items.join()
|
||||
if (position != -1) {
|
||||
requireViewBinding().pager.setCurrentItem(position, false)
|
||||
notifyPageChanged(position)
|
||||
@@ -149,7 +157,7 @@ class ReversedReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
items.await()
|
||||
items.join()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import android.view.ViewGroup
|
||||
import androidx.core.view.children
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.yield
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
@@ -43,6 +43,8 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>(),
|
||||
@Inject
|
||||
lateinit var pageLoader: PageLoader
|
||||
|
||||
private var pagerLifecycleDispatcher: PagerLifecycleDispatcher? = null
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -62,7 +64,9 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>(),
|
||||
recyclerView?.defaultFocusHighlightEnabled = false
|
||||
}
|
||||
PagerEventSupplier(this).attach()
|
||||
registerOnPageChangeCallback(PagerLifecycleDispatcher(this))
|
||||
pagerLifecycleDispatcher = PagerLifecycleDispatcher(this).also {
|
||||
registerOnPageChangeCallback(it)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.pageAnimation.observe(viewLifecycleOwner) {
|
||||
@@ -81,6 +85,7 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>(),
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
pagerLifecycleDispatcher = null
|
||||
requireViewBinding().pager.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
@@ -109,15 +114,16 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>(),
|
||||
|
||||
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) =
|
||||
coroutineScope {
|
||||
val items = async {
|
||||
val items = launch {
|
||||
requireAdapter().setItems(pages)
|
||||
yield()
|
||||
pagerLifecycleDispatcher?.invalidate()
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = pages.indexOfFirst {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
items.await()
|
||||
items.join()
|
||||
if (position != -1) {
|
||||
requireViewBinding().pager.setCurrentItem(position, false)
|
||||
notifyPageChanged(position)
|
||||
@@ -126,7 +132,7 @@ class PagerReaderFragment : BaseReaderFragment<FragmentReaderStandardBinding>(),
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
items.await()
|
||||
items.join()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ import android.view.ViewGroup
|
||||
import android.view.animation.DecelerateInterpolator
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.yield
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.os.NetworkState
|
||||
@@ -34,6 +34,8 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
|
||||
private val scrollInterpolator = DecelerateInterpolator()
|
||||
|
||||
private var recyclerLifecycleDispatcher: RecyclerViewLifecycleDispatcher? = null
|
||||
|
||||
override fun onCreateViewBinding(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
@@ -45,7 +47,9 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
setHasFixedSize(true)
|
||||
adapter = readerAdapter
|
||||
addOnPageScrollListener(PageScrollListener())
|
||||
addOnScrollListener(RecyclerViewLifecycleDispatcher())
|
||||
recyclerLifecycleDispatcher = RecyclerViewLifecycleDispatcher().also {
|
||||
addOnScrollListener(it)
|
||||
}
|
||||
}
|
||||
viewModel.isWebtoonZooEnabled.observe(viewLifecycleOwner) {
|
||||
binding.frame.isZoomEnable = it
|
||||
@@ -53,6 +57,7 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
recyclerLifecycleDispatcher = null
|
||||
requireViewBinding().recyclerView.adapter = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
@@ -66,15 +71,18 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
)
|
||||
|
||||
override suspend fun onPagesChanged(pages: List<ReaderPage>, pendingState: ReaderState?) = coroutineScope {
|
||||
val setItems = async {
|
||||
val setItems = launch {
|
||||
requireAdapter().setItems(pages)
|
||||
yield()
|
||||
viewBinding?.recyclerView?.let { rv ->
|
||||
recyclerLifecycleDispatcher?.invalidate(rv)
|
||||
}
|
||||
}
|
||||
if (pendingState != null) {
|
||||
val position = pages.indexOfFirst {
|
||||
it.chapterId == pendingState.chapterId && it.index == pendingState.page
|
||||
}
|
||||
setItems.await()
|
||||
setItems.join()
|
||||
if (position != -1) {
|
||||
with(requireViewBinding().recyclerView) {
|
||||
firstVisibleItemPosition = position
|
||||
@@ -89,7 +97,7 @@ class WebtoonReaderFragment : BaseReaderFragment<FragmentReaderWebtoonBinding>()
|
||||
.show()
|
||||
}
|
||||
} else {
|
||||
setItems.await()
|
||||
setItems.join()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.koitharu.kotatsu.core.network.ImageProxyInterceptor
|
||||
import org.koitharu.kotatsu.core.network.MangaHttpClient
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.local.data.isCbzUri
|
||||
import org.koitharu.kotatsu.local.data.isZipUri
|
||||
import org.koitharu.kotatsu.local.data.util.withExtraCloseable
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.util.mimeType
|
||||
@@ -56,7 +56,7 @@ class MangaPageFetcher(
|
||||
|
||||
private suspend fun loadPage(pageUrl: String): SourceResult {
|
||||
val uri = pageUrl.toUri()
|
||||
return if (isCbzUri(uri)) {
|
||||
return if (uri.isZipUri()) {
|
||||
runInterruptible(Dispatchers.IO) {
|
||||
val zip = ZipFile(uri.schemeSpecificPart)
|
||||
val entry = zip.getEntry(uri.fragment)
|
||||
|
||||
Reference in New Issue
Block a user