mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
Replace RxJava in webtoonholder
This commit is contained in:
parent
b7fc06d2ad
commit
9c521e23ce
1 changed files with 35 additions and 66 deletions
|
@ -23,14 +23,15 @@ import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar
|
||||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
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.Job
|
||||||
import kotlinx.coroutines.MainScope
|
import kotlinx.coroutines.MainScope
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import rx.Observable
|
import kotlinx.coroutines.supervisorScope
|
||||||
import rx.Subscription
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
|
||||||
import rx.schedulers.Schedulers
|
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
|
@ -85,22 +86,11 @@ class WebtoonPageHolder(
|
||||||
*/
|
*/
|
||||||
private var loadJob: Job? = null
|
private var loadJob: Job? = null
|
||||||
|
|
||||||
/**
|
|
||||||
* Job for status changes of the page.
|
|
||||||
*/
|
|
||||||
private var statusJob: Job? = null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Job for progress changes of the page.
|
* Job for progress changes of the page.
|
||||||
*/
|
*/
|
||||||
private var progressJob: Job? = null
|
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 {
|
init {
|
||||||
refreshLayoutParams()
|
refreshLayoutParams()
|
||||||
frame.setBackgroundColor(Color.BLACK)
|
frame.setBackgroundColor(Color.BLACK)
|
||||||
|
@ -136,7 +126,6 @@ class WebtoonPageHolder(
|
||||||
override fun recycle() {
|
override fun recycle() {
|
||||||
cancelLoadJob()
|
cancelLoadJob()
|
||||||
cancelProgressJob()
|
cancelProgressJob()
|
||||||
unsubscribeReadImageHeader()
|
|
||||||
|
|
||||||
removeDecodeErrorLayout()
|
removeDecodeErrorLayout()
|
||||||
frame.recycle()
|
frame.recycle()
|
||||||
|
@ -150,13 +139,14 @@ class WebtoonPageHolder(
|
||||||
*/
|
*/
|
||||||
private fun launchLoadJob() {
|
private fun launchLoadJob() {
|
||||||
cancelLoadJob()
|
cancelLoadJob()
|
||||||
|
loadJob = scope.launch { loadPageAndProcessStatus() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun loadPageAndProcessStatus() {
|
||||||
val page = page ?: return
|
val page = page ?: return
|
||||||
val loader = page.chapter.pageLoader ?: return
|
val loader = page.chapter.pageLoader ?: return
|
||||||
loadJob = scope.launch {
|
supervisorScope {
|
||||||
loader.loadPage(page)
|
launchIO { loader.loadPage(page) }
|
||||||
}
|
|
||||||
statusJob = scope.launch {
|
|
||||||
page.statusFlow.collectLatest { processStatus(it) }
|
page.statusFlow.collectLatest { processStatus(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +158,6 @@ class WebtoonPageHolder(
|
||||||
cancelProgressJob()
|
cancelProgressJob()
|
||||||
|
|
||||||
val page = page ?: return
|
val page = page ?: return
|
||||||
|
|
||||||
progressJob = scope.launch {
|
progressJob = scope.launch {
|
||||||
page.progressFlow.collectLatest { value -> progressBar.setProgress(value) }
|
page.progressFlow.collectLatest { value -> progressBar.setProgress(value) }
|
||||||
}
|
}
|
||||||
|
@ -179,7 +168,7 @@ class WebtoonPageHolder(
|
||||||
*
|
*
|
||||||
* @param status the new status of the page.
|
* @param status the new status of the page.
|
||||||
*/
|
*/
|
||||||
private fun processStatus(status: Page.State) {
|
private suspend fun processStatus(status: Page.State) {
|
||||||
when (status) {
|
when (status) {
|
||||||
Page.State.QUEUE -> setQueued()
|
Page.State.QUEUE -> setQueued()
|
||||||
Page.State.LOAD_PAGE -> setLoading()
|
Page.State.LOAD_PAGE -> setLoading()
|
||||||
|
@ -203,9 +192,6 @@ class WebtoonPageHolder(
|
||||||
*/
|
*/
|
||||||
private fun cancelLoadJob() {
|
private fun cancelLoadJob() {
|
||||||
loadJob?.cancel()
|
loadJob?.cancel()
|
||||||
loadJob = null
|
|
||||||
statusJob?.cancel()
|
|
||||||
statusJob = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,15 +199,6 @@ class WebtoonPageHolder(
|
||||||
*/
|
*/
|
||||||
private fun cancelProgressJob() {
|
private fun cancelProgressJob() {
|
||||||
progressJob?.cancel()
|
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.
|
* Called when the page is ready.
|
||||||
*/
|
*/
|
||||||
private fun setImage() {
|
private suspend fun setImage() {
|
||||||
progressContainer.isVisible = true
|
progressContainer.isVisible = true
|
||||||
progressBar.isVisible = true
|
progressBar.isVisible = true
|
||||||
progressBar.completeAndFadeOut()
|
progressBar.completeAndFadeOut()
|
||||||
retryContainer?.isVisible = false
|
retryContainer?.isVisible = false
|
||||||
removeDecodeErrorLayout()
|
removeDecodeErrorLayout()
|
||||||
|
|
||||||
unsubscribeReadImageHeader()
|
|
||||||
val streamFn = page?.stream ?: return
|
val streamFn = page?.stream ?: return
|
||||||
|
|
||||||
var openStream: InputStream? = null
|
val (openStream, isAnimated) = withIOContext {
|
||||||
readImageHeaderSubscription = Observable
|
val stream = streamFn().buffered(16)
|
||||||
.fromCallable {
|
val openStream = process(stream)
|
||||||
val stream = streamFn().buffered(16)
|
|
||||||
openStream = process(stream)
|
|
||||||
|
|
||||||
ImageUtil.isAnimatedAndSupported(stream)
|
val isAnimated = ImageUtil.isAnimatedAndSupported(stream)
|
||||||
}
|
Pair(openStream, isAnimated)
|
||||||
.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<Unit>() }
|
|
||||||
.doOnUnsubscribe { openStream?.close() }
|
|
||||||
.subscribe({}, {})
|
|
||||||
|
|
||||||
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<Nothing> { continuation ->
|
||||||
|
continuation.invokeOnCancellation { openStream.close() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun process(imageStream: BufferedInputStream): InputStream {
|
private fun process(imageStream: BufferedInputStream): InputStream {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue