Avoid hard crash if cached image file was already deleted
Closes #9720 (cherry picked from commit 3ea026e3116a77fd58bf656e1ecdb5e1ab6de28a) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt # app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt
This commit is contained in:
parent
3e561f7b67
commit
bd96864895
@ -158,55 +158,62 @@ class PagerPageHolder(
|
|||||||
val streamFn = page.stream ?: return
|
val streamFn = page.stream ?: return
|
||||||
val streamFn2 = extraPage?.stream
|
val streamFn2 = extraPage?.stream
|
||||||
|
|
||||||
val (bais, isAnimated, background) = withIOContext {
|
try {
|
||||||
streamFn().buffered(16).use { stream ->
|
val (bais, isAnimated, background) = withIOContext {
|
||||||
// SY -->
|
streamFn().buffered(16).use { stream ->
|
||||||
(
|
// SY -->
|
||||||
if (extraPage != null) {
|
(
|
||||||
streamFn2?.invoke()
|
if (extraPage != null) {
|
||||||
?.buffered(16)
|
streamFn2?.invoke()
|
||||||
} else {
|
?.buffered(16)
|
||||||
null
|
|
||||||
}
|
|
||||||
).use { stream2 ->
|
|
||||||
if (viewer.config.dualPageSplit) {
|
|
||||||
process(item.first, stream)
|
|
||||||
} else {
|
|
||||||
mergePages(stream, stream2)
|
|
||||||
}.use { itemStream ->
|
|
||||||
// SY <--
|
|
||||||
val bais = ByteArrayInputStream(itemStream.readBytes())
|
|
||||||
val isAnimated = ImageUtil.isAnimatedAndSupported(bais)
|
|
||||||
bais.reset()
|
|
||||||
val background = if (!isAnimated && viewer.config.automaticBackground) {
|
|
||||||
ImageUtil.chooseBackground(context, bais)
|
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
bais.reset()
|
).use { stream2 ->
|
||||||
Triple(bais, isAnimated, background)
|
if (viewer.config.dualPageSplit) {
|
||||||
|
process(item.first, stream)
|
||||||
|
} else {
|
||||||
|
mergePages(stream, stream2)
|
||||||
|
}.use { itemStream ->
|
||||||
|
// SY <--
|
||||||
|
val bais = ByteArrayInputStream(itemStream.readBytes())
|
||||||
|
val isAnimated = ImageUtil.isAnimatedAndSupported(bais)
|
||||||
|
bais.reset()
|
||||||
|
val background = if (!isAnimated && viewer.config.automaticBackground) {
|
||||||
|
ImageUtil.chooseBackground(context, bais)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
bais.reset()
|
||||||
|
Triple(bais, isAnimated, background)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
withUIContext {
|
||||||
|
bais.use {
|
||||||
|
setImage(
|
||||||
|
it,
|
||||||
|
isAnimated,
|
||||||
|
Config(
|
||||||
|
zoomDuration = viewer.config.doubleTapAnimDuration,
|
||||||
|
minimumScaleType = viewer.config.imageScaleType,
|
||||||
|
cropBorders = viewer.config.imageCropBorders,
|
||||||
|
zoomStartPosition = viewer.config.imageZoomType,
|
||||||
|
landscapeZoom = viewer.config.landscapeZoom,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if (!isAnimated) {
|
||||||
|
pageBackground = background
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
removeErrorLayout()
|
||||||
}
|
}
|
||||||
}
|
} catch (e: Throwable) {
|
||||||
withUIContext {
|
logcat(LogPriority.ERROR, e)
|
||||||
bais.use {
|
withUIContext {
|
||||||
setImage(
|
setError()
|
||||||
it,
|
|
||||||
isAnimated,
|
|
||||||
Config(
|
|
||||||
zoomDuration = viewer.config.doubleTapAnimDuration,
|
|
||||||
minimumScaleType = viewer.config.imageScaleType,
|
|
||||||
cropBorders = viewer.config.imageCropBorders,
|
|
||||||
zoomStartPosition = viewer.config.imageZoomType,
|
|
||||||
landscapeZoom = viewer.config.landscapeZoom,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if (!isAnimated) {
|
|
||||||
pageBackground = background
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
removeErrorLayout()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,12 @@ import kotlinx.coroutines.flow.collectLatest
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.util.lang.launchIO
|
import tachiyomi.core.util.lang.launchIO
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
import tachiyomi.core.util.lang.withIOContext
|
||||||
import tachiyomi.core.util.lang.withUIContext
|
import tachiyomi.core.util.lang.withUIContext
|
||||||
import tachiyomi.core.util.system.ImageUtil
|
import tachiyomi.core.util.system.ImageUtil
|
||||||
|
import tachiyomi.core.util.system.logcat
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
@ -184,28 +186,35 @@ class WebtoonPageHolder(
|
|||||||
|
|
||||||
val streamFn = page?.stream ?: return
|
val streamFn = page?.stream ?: return
|
||||||
|
|
||||||
val (openStream, isAnimated) = withIOContext {
|
try {
|
||||||
val stream = streamFn().buffered(16)
|
val (openStream, isAnimated) = withIOContext {
|
||||||
val openStream = process(stream)
|
val stream = streamFn().buffered(16)
|
||||||
|
val openStream = process(stream)
|
||||||
|
|
||||||
val isAnimated = ImageUtil.isAnimatedAndSupported(stream)
|
val isAnimated = ImageUtil.isAnimatedAndSupported(stream)
|
||||||
Pair(openStream, isAnimated)
|
Pair(openStream, isAnimated)
|
||||||
}
|
}
|
||||||
withUIContext {
|
withUIContext {
|
||||||
frame.setImage(
|
frame.setImage(
|
||||||
openStream,
|
openStream,
|
||||||
isAnimated,
|
isAnimated,
|
||||||
ReaderPageImageView.Config(
|
ReaderPageImageView.Config(
|
||||||
zoomDuration = viewer.config.doubleTapAnimDuration,
|
zoomDuration = viewer.config.doubleTapAnimDuration,
|
||||||
minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH,
|
minimumScaleType = SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH,
|
||||||
cropBorders = (viewer.config.imageCropBorders && viewer.isContinuous) || (viewer.config.continuousCropBorders && !viewer.isContinuous),
|
cropBorders = (viewer.config.imageCropBorders && viewer.isContinuous) || (viewer.config.continuousCropBorders && !viewer.isContinuous),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
removeErrorLayout()
|
removeErrorLayout()
|
||||||
}
|
}
|
||||||
// Suspend the coroutine to close the input stream only when the WebtoonPageHolder is recycled
|
// Suspend the coroutine to close the input stream only when the WebtoonPageHolder is recycled
|
||||||
suspendCancellableCoroutine<Nothing> { continuation ->
|
suspendCancellableCoroutine<Nothing> { continuation ->
|
||||||
continuation.invokeOnCancellation { openStream.close() }
|
continuation.invokeOnCancellation { openStream.close() }
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
logcat(LogPriority.ERROR, e)
|
||||||
|
withUIContext {
|
||||||
|
setError()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user