Replace RxJava in webtoonholder

This commit is contained in:
Jays2Kings 2023-03-02 01:45:48 -05:00
parent b7fc06d2ad
commit 9c521e23ce

View file

@ -23,14 +23,15 @@ import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.launchIO
import eu.kanade.tachiyomi.util.system.withIOContext
import eu.kanade.tachiyomi.util.system.withUIContext
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.suspendCancellableCoroutine
import java.io.BufferedInputStream
import java.io.InputStream
@ -85,22 +86,11 @@ class WebtoonPageHolder(
*/
private var loadJob: Job? = null
/**
* Job for status changes of the page.
*/
private var statusJob: Job? = null
/**
* Job for progress changes of the page.
*/
private var progressJob: Job? = null
/**
* Subscription used to read the header of the image. This is needed in order to instantiate
* the appropriate image view depending if the image is animated (GIF).
*/
private var readImageHeaderSubscription: Subscription? = null
init {
refreshLayoutParams()
frame.setBackgroundColor(Color.BLACK)
@ -136,7 +126,6 @@ class WebtoonPageHolder(
override fun recycle() {
cancelLoadJob()
cancelProgressJob()
unsubscribeReadImageHeader()
removeDecodeErrorLayout()
frame.recycle()
@ -150,13 +139,14 @@ class WebtoonPageHolder(
*/
private fun launchLoadJob() {
cancelLoadJob()
loadJob = scope.launch { loadPageAndProcessStatus() }
}
private suspend fun loadPageAndProcessStatus() {
val page = page ?: return
val loader = page.chapter.pageLoader ?: return
loadJob = scope.launch {
loader.loadPage(page)
}
statusJob = scope.launch {
supervisorScope {
launchIO { loader.loadPage(page) }
page.statusFlow.collectLatest { processStatus(it) }
}
}
@ -168,7 +158,6 @@ class WebtoonPageHolder(
cancelProgressJob()
val page = page ?: return
progressJob = scope.launch {
page.progressFlow.collectLatest { value -> progressBar.setProgress(value) }
}
@ -179,7 +168,7 @@ class WebtoonPageHolder(
*
* @param status the new status of the page.
*/
private fun processStatus(status: Page.State) {
private suspend fun processStatus(status: Page.State) {
when (status) {
Page.State.QUEUE -> setQueued()
Page.State.LOAD_PAGE -> setLoading()
@ -203,9 +192,6 @@ class WebtoonPageHolder(
*/
private fun cancelLoadJob() {
loadJob?.cancel()
loadJob = null
statusJob?.cancel()
statusJob = null
}
/**
@ -213,15 +199,6 @@ class WebtoonPageHolder(
*/
private fun cancelProgressJob() {
progressJob?.cancel()
progressJob = null
}
/**
* Unsubscribes from the read image header subscription.
*/
private fun unsubscribeReadImageHeader() {
removeSubscription(readImageHeaderSubscription)
readImageHeaderSubscription = null
}
/**
@ -257,48 +234,40 @@ class WebtoonPageHolder(
/**
* Called when the page is ready.
*/
private fun setImage() {
private suspend fun setImage() {
progressContainer.isVisible = true
progressBar.isVisible = true
progressBar.completeAndFadeOut()
retryContainer?.isVisible = false
removeDecodeErrorLayout()
unsubscribeReadImageHeader()
val streamFn = page?.stream ?: return
var openStream: InputStream? = null
readImageHeaderSubscription = Observable
.fromCallable {
val (openStream, isAnimated) = withIOContext {
val stream = streamFn().buffered(16)
openStream = process(stream)
val openStream = process(stream)
ImageUtil.isAnimatedAndSupported(stream)
val isAnimated = ImageUtil.isAnimatedAndSupported(stream)
Pair(openStream, isAnimated)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext { isAnimated ->
withUIContext {
frame.setImage(
openStream!!,
openStream,
isAnimated,
ReaderPageImageView.Config(
zoomDuration = viewer.config.doubleTapAnimDuration,
minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH,
cropBorders =
if (viewer.hasMargins) {
viewer.config.verticalCropBorders
} else {
viewer.config.webtoonCropBorders
cropBorders = viewer.config.run {
if (viewer.hasMargins) { verticalCropBorders } else { webtoonCropBorders }
},
),
)
}
// Keep the Rx stream alive to close the input stream only when unsubscribed
.flatMap { Observable.never<Unit>() }
.doOnUnsubscribe { openStream?.close() }
.subscribe({}, {})
addSubscription(readImageHeaderSubscription)
// Suspend the coroutine to close the input stream only when the WebtoonPageHolder is recycled
suspendCancellableCoroutine<Nothing> { continuation ->
continuation.invokeOnCancellation { openStream.close() }
}
}
private fun process(imageStream: BufferedInputStream): InputStream {