From 9c521e23ce14be1325f139de86571e09f33cb55c Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Thu, 2 Mar 2023 01:45:48 -0500 Subject: [PATCH] Replace RxJava in webtoonholder --- .../viewer/webtoon/WebtoonPageHolder.kt | 101 ++++++------------ 1 file changed, 35 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt index 56f570f44f..03e98ba2fa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt @@ -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 stream = streamFn().buffered(16) - openStream = process(stream) + val (openStream, isAnimated) = withIOContext { + val stream = streamFn().buffered(16) + val openStream = process(stream) - ImageUtil.isAnimatedAndSupported(stream) - } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnNext { isAnimated -> - frame.setImage( - 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 - }, - ), - ) - } - // Keep the Rx stream alive to close the input stream only when unsubscribed - .flatMap { Observable.never() } - .doOnUnsubscribe { openStream?.close() } - .subscribe({}, {}) + val isAnimated = ImageUtil.isAnimatedAndSupported(stream) + Pair(openStream, isAnimated) + } - addSubscription(readImageHeaderSubscription) + withUIContext { + frame.setImage( + openStream, + isAnimated, + ReaderPageImageView.Config( + zoomDuration = viewer.config.doubleTapAnimDuration, + minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH, + cropBorders = viewer.config.run { + if (viewer.hasMargins) { verticalCropBorders } else { webtoonCropBorders } + }, + ), + ) + } + // Suspend the coroutine to close the input stream only when the WebtoonPageHolder is recycled + suspendCancellableCoroutine { continuation -> + continuation.invokeOnCancellation { openStream.close() } + } } private fun process(imageStream: BufferedInputStream): InputStream {