Sync with tachiyomi, support load progress

This commit is contained in:
tarsin committed 2022-12-20 19:03:57 +08:00
1 parent 60438ae1ed
commit f06167ba4b
5 files changed
+67 -38

No files matched your search

@@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.source.model
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
open class Page(val index: Int) {
@@ -9,7 +10,14 @@ open class Page(val index: Int) {
var status = MutableStateFlow(State.QUEUE)
var progress = MutableStateFlow(0f)
private val _progressFlow = MutableStateFlow(0)
val progressFlow = _progressFlow.asStateFlow()
var progress: Int
get() = _progressFlow.value
set(value) {
_progressFlow.value = value
}
enum class State {
QUEUE,
@@ -48,7 +48,7 @@ abstract class PageLoader {
fun notifyPagePercent(index: Int, percent: Float) {
mPages[index].status.compareAndSet(Page.State.QUEUE, Page.State.DOWNLOAD_IMAGE)
mPages[index].progress.value = percent
mPages[index].progress = (percent * 100).toInt()
}
fun notifyPageSucceed(index: Int, image: Image) {
@@ -11,10 +11,9 @@ import androidx.annotation.IntRange
import com.google.android.material.progressindicator.CircularProgressIndicator
/**
* A wrapper for [CircularProgressIndicator] that always rotates while being determinate.
* A wrapper for [CircularProgressIndicator] that always rotates.
*
* By always rotating we give the feedback to the user that the application isn't 'stuck',
* and by making it determinate the user also approximately knows how much the operation will take.
* By always rotating we give the feedback to the user that the application isn't 'stuck'.
*/
class ReaderProgressIndicator @JvmOverloads constructor(
context: Context,
@@ -39,19 +39,18 @@ class PagerPageHolder(
/**
* Loading progress bar to indicate the current progress.
*/
private val progressIndicator: ReaderProgressIndicator =
ReaderProgressIndicator(readerThemedContext).apply {
updateLayoutParams<LayoutParams> {
gravity = Gravity.CENTER
}
private val progressIndicator: ReaderProgressIndicator = ReaderProgressIndicator(readerThemedContext).apply {
updateLayoutParams<LayoutParams> {
gravity = Gravity.CENTER
}
}
/**
* Error layout to show when the image fails to load.
*/
private var errorLayout: ReaderErrorBinding? = null
private var scope = CoroutineScope(Dispatchers.IO)
private val scope = CoroutineScope(Dispatchers.IO)
/**
* Subscription for status changes of the page.
@@ -59,17 +58,12 @@ class PagerPageHolder(
private var statusJob: Job? = null
/**
* Subscription for progress changes of the page.
* Job for progress changes of the page.
*/
private var progressJob: Job? = null
init {
addView(progressIndicator)
progressJob = scope.launch(Dispatchers.Main) {
page.progress.collect {
progressIndicator.setProgress(it.toInt())
}
}
statusJob = scope.launch(Dispatchers.Main) {
page.status.collectLatest {
processStatus(it)
@@ -83,10 +77,17 @@ class PagerPageHolder(
@SuppressLint("ClickableViewAccessibility")
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
unsubscribeProgress()
cancelProgressJob()
unsubscribeStatus()
}
private fun launchProgressJob() {
progressJob?.cancel()
progressJob = scope.launch(Dispatchers.Main) {
page.progressFlow.collectLatest { value -> progressIndicator.setProgress(value) }
}
}
/**
* Called when the status of the page changes.
*
@@ -97,17 +98,16 @@ class PagerPageHolder(
Page.State.QUEUE -> setQueued()
Page.State.LOAD_PAGE -> setLoading()
Page.State.DOWNLOAD_IMAGE -> {
launchProgressJob()
setDownloading()
}
Page.State.READY -> {
page.image?.mObtainedDrawable?.let { setImage(it) }
unsubscribeProgress()
cancelProgressJob()
}
Page.State.ERROR -> {
setError()
unsubscribeProgress()
cancelProgressJob()
}
}
}
@@ -117,13 +117,12 @@ class PagerPageHolder(
*/
private fun unsubscribeStatus() {
statusJob?.cancel()
statusJob = null
}
/**
* Unsubscribes from the progress subscription.
*/
private fun unsubscribeProgress() {
private fun cancelProgressJob() {
progressJob?.cancel()
progressJob = null
}
/**
@@ -63,14 +63,21 @@ class WebtoonPageHolder(
*/
private var page: ReaderPage? = null
private var progressJob: Job? = null
private val scope = CoroutineScope(Dispatchers.IO)
/**
* Subscription for status changes of the page.
*/
private var statusJob: Job? = null
private var scope = CoroutineScope(Dispatchers.IO)
/**
* Job for progress changes of the page.
*/
private var progressJob: Job? = null
init {
refreshLayoutParams()
frame.onImageLoaded = { onImageDecoded() }
frame.onImageLoadError = { onImageDecodeError() }
frame.onScaleChanged = { viewer.activity.hideMenu() }
@@ -81,11 +88,6 @@ class WebtoonPageHolder(
*/
fun bind(page: ReaderPage) {
this.page = page
progressJob = scope.launch(Dispatchers.Main) {
page.progress.collect {
progressIndicator.setProgress(it.toInt())
}
}
statusJob = scope.launch(Dispatchers.Main) {
page.status.collectLatest {
processStatus(it)
@@ -111,13 +113,27 @@ class WebtoonPageHolder(
*/
override fun recycle() {
statusJob?.cancel()
progressJob?.cancel()
cancelProgressJob()
removeErrorLayout()
frame.recycle()
page?.image?.recycle()
progressIndicator.setProgress(0, animated = false)
}
/**
* Observes the progress of the page and updates view.
*/
private fun launchProgressJob() {
cancelProgressJob()
val page = page ?: return
progressJob = scope.launch(Dispatchers.Main) {
page.progressFlow.collectLatest { value -> progressIndicator.setProgress(value) }
}
}
/**
* Called when the status of the page changes.
*
@@ -128,21 +144,28 @@ class WebtoonPageHolder(
Page.State.QUEUE -> setQueued()
Page.State.LOAD_PAGE -> setLoading()
Page.State.DOWNLOAD_IMAGE -> {
launchProgressJob()
setDownloading()
}
Page.State.READY -> {
page?.image?.mObtainedDrawable?.let { setImage(it) }
progressJob?.cancel()
cancelProgressJob()
}
Page.State.ERROR -> {
setError()
progressJob?.cancel()
cancelProgressJob()
}
}
}
/**
* Unsubscribes from the progress subscription.
*/
private fun cancelProgressJob() {
progressJob?.cancel()
progressJob = null
}
/**
* Called when the page is queued.
*/