Surface image loading error in Reader (#1981)

This commit is contained in:
AwkwardPeak7
2025-04-13 19:46:12 +05:00
committed by GitHub
parent f1e2efcb37
commit fefa8f8498
9 changed files with 48 additions and 30 deletions

View File

@ -22,6 +22,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- Significantly improve browsing speed (near instantaneous) ([@AntsyLich](https://github.com/AntsyLich)) ([#1946](https://github.com/mihonapp/mihon/pull/1946))
- Deduplicate entries when browsing ([@AntsyLich](https://github.com/AntsyLich)) ([#1957](https://github.com/mihonapp/mihon/pull/1957))
- Update non-library manga data when browsing ([@AntsyLich](https://github.com/AntsyLich)) ([#1967](https://github.com/mihonapp/mihon/pull/1967))
- Surface image loading error in Reader ([@AwkwardPeak7](https://github.com/AwkwardPeak7)) ([#1981](https://github.com/mihonapp/mihon/pull/1981))
### Changed
- Display all similarly named duplicates in duplicate manga dialogue ([@NarwhalHorns](https://github.com/NarwhalHorns), [@AntsyLich](https://github.com/AntsyLich)) ([#1861](https://github.com/mihonapp/mihon/pull/1861))

View File

@ -365,7 +365,7 @@ class Downloader(
try {
page.imageUrl = download.source.getImageUrl(page)
} catch (e: Throwable) {
page.status = Page.State.Error
page.status = Page.State.Error(e)
}
}
@ -457,7 +457,7 @@ class Downloader(
if (e is CancellationException) throw e
// Mark this page as error and allow to download the remaining
page.progress = 0
page.status = Page.State.Error
page.status = Page.State.Error(e)
notifier.onError(e.message, download.chapter.name, download.manga.title, download.manga.id)
}
}

View File

@ -537,7 +537,7 @@ class ReaderViewModel @JvmOverloads constructor(
readerChapter.requestedPage = pageIndex
chapterPageIndex = pageIndex
if (!incognitoMode && page.status != Page.State.Error) {
if (!incognitoMode && page.status is Page.State.Error) {
readerChapter.chapter.last_page_read = pageIndex
if (readerChapter.pages?.lastIndex == pageIndex) {

View File

@ -88,7 +88,7 @@ internal class HttpPageLoader(
}
// Automatically retry failed pages when subscribed to this page
if (page.status == Page.State.Error) {
if (page.status is Page.State.Error) {
page.status = Page.State.Queue
}
@ -113,7 +113,7 @@ internal class HttpPageLoader(
* Retries a page. This method is only called from user interaction on the viewer.
*/
override fun retryPage(page: ReaderPage) {
if (page.status == Page.State.Error) {
if (page.status is Page.State.Error) {
page.status = Page.State.Queue
}
queue.offer(PriorityPage(page, 2))
@ -184,7 +184,7 @@ internal class HttpPageLoader(
page.stream = { chapterCache.getImageFile(imageUrl).inputStream() }
page.status = Page.State.Ready
} catch (e: Throwable) {
page.status = Page.State.Error
page.status = Page.State.Error(e)
if (e is CancellationException) {
throw e
}

View File

@ -69,7 +69,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
private var config: Config? = null
var onImageLoaded: (() -> Unit)? = null
var onImageLoadError: (() -> Unit)? = null
var onImageLoadError: ((Throwable?) -> Unit)? = null
var onScaleChanged: ((newScale: Float) -> Unit)? = null
var onViewClicked: (() -> Unit)? = null
@ -85,8 +85,8 @@ open class ReaderPageImageView @JvmOverloads constructor(
}
@CallSuper
open fun onImageLoadError() {
onImageLoadError?.invoke()
open fun onImageLoadError(error: Throwable?) {
onImageLoadError?.invoke(error)
}
@CallSuper
@ -114,7 +114,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
}
override fun onImageLoadError(e: Exception) {
onImageLoadError()
onImageLoadError(e)
}
},
)
@ -290,7 +290,7 @@ open class ReaderPageImageView @JvmOverloads constructor(
}
override fun onImageLoadError(e: Exception) {
this@ReaderPageImageView.onImageLoadError()
this@ReaderPageImageView.onImageLoadError(e)
}
},
)
@ -318,8 +318,10 @@ open class ReaderPageImageView @JvmOverloads constructor(
setImage(ImageSource.bitmap(image.bitmap))
isVisible = true
},
onError = {
onImageLoadError()
)
.listener(
onError = { _, result ->
onImageLoadError(result.throwable)
},
)
.size(ViewSizeResolver(this@ReaderPageImageView))
@ -395,8 +397,10 @@ open class ReaderPageImageView @JvmOverloads constructor(
isVisible = true
this@ReaderPageImageView.onImageLoaded()
},
onError = {
this@ReaderPageImageView.onImageLoadError()
)
.listener(
onError = { _, result ->
onImageLoadError(result.throwable)
},
)
.crossfade(false)

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import androidx.core.view.isVisible
import eu.kanade.presentation.util.formattedMessage
import eu.kanade.tachiyomi.databinding.ReaderErrorBinding
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.InsertPage
@ -20,11 +21,13 @@ import kotlinx.coroutines.supervisorScope
import logcat.LogPriority
import okio.Buffer
import okio.BufferedSource
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.core.common.util.system.logcat
import tachiyomi.i18n.MR
/**
* View of the ViewPager that contains a page of a chapter.
@ -105,7 +108,7 @@ class PagerPageHolder(
}
}
Page.State.Ready -> setImage()
Page.State.Error -> setError()
is Page.State.Error -> setError(state.error)
}
}
}
@ -177,7 +180,7 @@ class PagerPageHolder(
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e)
withUIContext {
setError()
setError(e)
}
}
}
@ -242,9 +245,9 @@ class PagerPageHolder(
/**
* Called when the page has an error.
*/
private fun setError() {
private fun setError(error: Throwable?) {
progressIndicator?.hide()
showErrorLayout()
showErrorLayout(error)
}
override fun onImageLoaded() {
@ -255,9 +258,9 @@ class PagerPageHolder(
/**
* Called when an image fails to decode.
*/
override fun onImageLoadError() {
super.onImageLoadError()
setError()
override fun onImageLoadError(error: Throwable?) {
super.onImageLoadError(error)
setError(error)
}
/**
@ -268,7 +271,7 @@ class PagerPageHolder(
viewer.activity.hideMenu()
}
private fun showErrorLayout(): ReaderErrorBinding {
private fun showErrorLayout(error: Throwable?): ReaderErrorBinding {
if (errorLayout == null) {
errorLayout = ReaderErrorBinding.inflate(LayoutInflater.from(context), this, true)
errorLayout?.actionRetry?.viewer = viewer
@ -289,6 +292,9 @@ class PagerPageHolder(
}
}
errorLayout?.errorMessage?.text = with(context) { error?.formattedMessage }
?: context.stringResource(MR.strings.decode_image_error)
errorLayout?.root?.isVisible = true
return errorLayout!!
}

View File

@ -10,6 +10,7 @@ import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updateMargins
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import eu.kanade.presentation.util.formattedMessage
import eu.kanade.tachiyomi.databinding.ReaderErrorBinding
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
@ -25,11 +26,13 @@ import kotlinx.coroutines.supervisorScope
import logcat.LogPriority
import okio.Buffer
import okio.BufferedSource
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.lang.withUIContext
import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.core.common.util.system.logcat
import tachiyomi.i18n.MR
/**
* Holder of the webtoon reader for a single page of a chapter.
@ -81,7 +84,7 @@ class WebtoonPageHolder(
refreshLayoutParams()
frame.onImageLoaded = { onImageDecoded() }
frame.onImageLoadError = { setError() }
frame.onImageLoadError = { error -> setError(error) }
frame.onScaleChanged = { viewer.activity.hideMenu() }
}
@ -145,7 +148,7 @@ class WebtoonPageHolder(
}
}
Page.State.Ready -> setImage()
Page.State.Error -> setError()
is Page.State.Error -> setError(state.error)
}
}
}
@ -207,7 +210,7 @@ class WebtoonPageHolder(
} catch (e: Throwable) {
logcat(LogPriority.ERROR, e)
withUIContext {
setError()
setError(e)
}
}
}
@ -241,9 +244,9 @@ class WebtoonPageHolder(
/**
* Called when the page has an error.
*/
private fun setError() {
private fun setError(error: Throwable?) {
progressContainer.isVisible = false
initErrorLayout()
initErrorLayout(error)
}
/**
@ -273,7 +276,7 @@ class WebtoonPageHolder(
/**
* Initializes a button to retry pages.
*/
private fun initErrorLayout(): ReaderErrorBinding {
private fun initErrorLayout(error: Throwable?): ReaderErrorBinding {
if (errorLayout == null) {
errorLayout = ReaderErrorBinding.inflate(LayoutInflater.from(context), frame, true)
errorLayout?.root?.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, (parentHeight * 0.8).toInt())
@ -293,6 +296,9 @@ class WebtoonPageHolder(
}
}
errorLayout?.errorMessage?.text = with(context) { error?.formattedMessage }
?: context.stringResource(MR.strings.decode_image_error)
return errorLayout!!
}

View File

@ -7,6 +7,7 @@
android:gravity="center">
<TextView
android:id="@+id/error_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"

View File

@ -53,6 +53,6 @@ open class Page(
data object LoadPage : State
data object DownloadImage : State
data object Ready : State
data object Error : State
data class Error(val error: Throwable) : State
}
}