Use PageLoader for thumbnails
This commit is contained in:
@@ -2,13 +2,13 @@ package org.koitharu.kotatsu.local.data
|
||||
|
||||
import android.content.Context
|
||||
import com.tomclaw.cache.DiskLruCache
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.koitharu.kotatsu.parsers.util.longHashCode
|
||||
import org.koitharu.kotatsu.utils.FileSize
|
||||
import org.koitharu.kotatsu.utils.ext.subdir
|
||||
import org.koitharu.kotatsu.utils.ext.takeIfReadable
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
|
||||
class PagesCache(context: Context) {
|
||||
|
||||
@@ -60,4 +60,4 @@ class PagesCache(context: Context) {
|
||||
progress.value = (bytesCopied.toDouble() / contentLength.toDouble()).toFloat()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,6 @@ import android.graphics.BitmapFactory
|
||||
import android.net.Uri
|
||||
import androidx.collection.LongSparseArray
|
||||
import androidx.collection.set
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.zip.ZipFile
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -31,6 +27,10 @@ import org.koitharu.kotatsu.parsers.util.await
|
||||
import org.koitharu.kotatsu.reader.ui.pager.ReaderPage
|
||||
import org.koitharu.kotatsu.utils.ext.connectivityManager
|
||||
import org.koitharu.kotatsu.utils.progress.ProgressDeferred
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
private const val PROGRESS_UNDEFINED = -1f
|
||||
private const val PREFETCH_LIMIT_DEFAULT = 10
|
||||
@@ -115,8 +115,13 @@ class PageLoader : KoinComponent, Closeable {
|
||||
|
||||
private fun onIdle() {
|
||||
synchronized(prefetchQueue) {
|
||||
val page = prefetchQueue.pollFirst() ?: return
|
||||
tasks[page.id] = loadPageAsyncImpl(page)
|
||||
while (prefetchQueue.isNotEmpty()) {
|
||||
val page = prefetchQueue.pollFirst() ?: return
|
||||
if (cache[page.url] == null) {
|
||||
tasks[page.id] = loadPageAsyncImpl(page)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,17 +19,20 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.databinding.SheetPagesBinding
|
||||
import org.koitharu.kotatsu.list.ui.MangaListSpanResolver
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.thumbnails.adapter.PageThumbnailAdapter
|
||||
import org.koitharu.kotatsu.utils.BottomSheetToolbarController
|
||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||
|
||||
class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
||||
class PagesThumbnailsSheet :
|
||||
BaseBottomSheet<SheetPagesBinding>(),
|
||||
OnListItemClickListener<MangaPage> {
|
||||
|
||||
private lateinit var thumbnails: List<PageThumbnail>
|
||||
private val spanResolver = MangaListSpanResolver()
|
||||
private var currentPageIndex = -1
|
||||
private var pageLoader: PageLoader? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -75,11 +78,11 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
||||
SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing))
|
||||
)
|
||||
adapter = PageThumbnailAdapter(
|
||||
thumbnails,
|
||||
get(),
|
||||
viewLifecycleScope,
|
||||
get(),
|
||||
this@PagesThumbnailsSheet
|
||||
dataSet = thumbnails,
|
||||
coil = get(),
|
||||
scope = viewLifecycleScope,
|
||||
loader = PageLoader().also { pageLoader = it },
|
||||
clickListener = this@PagesThumbnailsSheet
|
||||
)
|
||||
addOnLayoutChangeListener(spanResolver)
|
||||
spanResolver.setGridSize(get<AppSettings>().gridSize / 100f, this)
|
||||
@@ -90,9 +93,17 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
pageLoader?.close()
|
||||
pageLoader = null
|
||||
}
|
||||
|
||||
override fun onItemClick(item: MangaPage, view: View) {
|
||||
((parentFragment as? OnPageSelectListener)
|
||||
?: (activity as? OnPageSelectListener))?.run {
|
||||
(
|
||||
(parentFragment as? OnPageSelectListener)
|
||||
?: (activity as? OnPageSelectListener)
|
||||
)?.run {
|
||||
onPageSelected(item)
|
||||
dismiss()
|
||||
}
|
||||
@@ -127,6 +138,5 @@ class PagesThumbnailsSheet : BaseBottomSheet<SheetPagesBinding>(),
|
||||
putString(ARG_TITLE, title)
|
||||
putInt(ARG_CURRENT, currentPage)
|
||||
}.show(fm, TAG)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
package org.koitharu.kotatsu.reader.ui.thumbnails.adapter
|
||||
|
||||
import androidx.core.net.toUri
|
||||
import android.graphics.drawable.Drawable
|
||||
import coil.ImageLoader
|
||||
import coil.request.ImageRequest
|
||||
import coil.size.PixelSize
|
||||
import com.google.android.material.R as materialR
|
||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||
import kotlinx.coroutines.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.databinding.ItemPageThumbBinding
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail
|
||||
import org.koitharu.kotatsu.utils.ext.IgnoreErrors
|
||||
import org.koitharu.kotatsu.utils.ext.referer
|
||||
import org.koitharu.kotatsu.utils.ext.setTextColorAttr
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
fun pageThumbnailAD(
|
||||
coil: ImageLoader,
|
||||
scope: CoroutineScope,
|
||||
cache: PagesCache,
|
||||
clickListener: OnListItemClickListener<MangaPage>
|
||||
loader: PageLoader,
|
||||
clickListener: OnListItemClickListener<MangaPage>,
|
||||
) = adapterDelegateViewBinding<PageThumbnail, PageThumbnail, ItemPageThumbBinding>(
|
||||
{ inflater, parent -> ItemPageThumbBinding.inflate(inflater, parent, false) }
|
||||
) {
|
||||
@@ -33,6 +32,29 @@ fun pageThumbnailAD(
|
||||
height = (gridWidth * 13f / 18f).toInt()
|
||||
)
|
||||
|
||||
suspend fun loadPageThumbnail(item: PageThumbnail): Drawable? = withContext(Dispatchers.Default) {
|
||||
item.page.preview?.let { url ->
|
||||
coil.execute(
|
||||
ImageRequest.Builder(context)
|
||||
.data(url)
|
||||
.referer(item.page.referer)
|
||||
.size(thumbSize)
|
||||
.allowRgb565(true)
|
||||
.build()
|
||||
).drawable
|
||||
}?.let { drawable ->
|
||||
return@withContext drawable
|
||||
}
|
||||
val file = loader.loadPage(item.page, force = false)
|
||||
coil.execute(
|
||||
ImageRequest.Builder(context)
|
||||
.data(file)
|
||||
.size(thumbSize)
|
||||
.allowRgb565(true)
|
||||
.build()
|
||||
).drawable
|
||||
}
|
||||
|
||||
binding.root.setOnClickListener {
|
||||
clickListener.onItemClick(item.page, itemView)
|
||||
}
|
||||
@@ -45,22 +67,11 @@ fun pageThumbnailAD(
|
||||
setTextColorAttr(if (item.isCurrent) materialR.attr.colorOnTertiary else android.R.attr.textColorPrimary)
|
||||
text = (item.number).toString()
|
||||
}
|
||||
job = scope.launch(Dispatchers.Default + IgnoreErrors) {
|
||||
val url = item.page.preview ?: item.page.url.let {
|
||||
val pageUrl = item.repository.getPageUrl(item.page)
|
||||
cache[pageUrl]?.toUri()?.toString() ?: pageUrl
|
||||
}
|
||||
val drawable = coil.execute(
|
||||
ImageRequest.Builder(context)
|
||||
.data(url)
|
||||
.referer(item.page.referer)
|
||||
.size(thumbSize)
|
||||
.allowRgb565(true)
|
||||
.build()
|
||||
).drawable
|
||||
withContext(Dispatchers.Main) {
|
||||
binding.imageViewThumb.setImageDrawable(drawable)
|
||||
}
|
||||
job = scope.launch {
|
||||
val drawable = runCatching {
|
||||
loadPageThumbnail(item)
|
||||
}.getOrNull()
|
||||
binding.imageViewThumb.setImageDrawable(drawable)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,20 +4,20 @@ import coil.ImageLoader
|
||||
import com.hannesdorfmann.adapterdelegates4.ListDelegationAdapter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||
import org.koitharu.kotatsu.local.data.PagesCache
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
import org.koitharu.kotatsu.reader.ui.thumbnails.PageThumbnail
|
||||
|
||||
class PageThumbnailAdapter(
|
||||
dataSet: List<PageThumbnail>,
|
||||
coil: ImageLoader,
|
||||
scope: CoroutineScope,
|
||||
cache: PagesCache,
|
||||
loader: PageLoader,
|
||||
clickListener: OnListItemClickListener<MangaPage>
|
||||
) : ListDelegationAdapter<List<PageThumbnail>>() {
|
||||
|
||||
init {
|
||||
delegatesManager.addDelegate(pageThumbnailAD(coil, scope, cache, clickListener))
|
||||
delegatesManager.addDelegate(pageThumbnailAD(coil, scope, loader, clickListener))
|
||||
setItems(dataSet)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user