diff --git a/CHANGELOG.md b/CHANGELOG.md index ad3bca72d..68e88736f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index 5f05f7f54..b9f6c27c6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -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) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index 7654c0102..f40ccddd1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt index 4ceb9ae22..69753b0fc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt @@ -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 } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt index b9173ab66..4ae646e3e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderPageImageView.kt @@ -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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index 47d22c273..ed88eb922 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -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!! } 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 402926d16..574f4da07 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 @@ -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!! } diff --git a/app/src/main/res/layout/reader_error.xml b/app/src/main/res/layout/reader_error.xml index c926ef13d..44e6c7322 100644 --- a/app/src/main/res/layout/reader_error.xml +++ b/app/src/main/res/layout/reader_error.xml @@ -7,6 +7,7 @@ android:gravity="center">