Fix loading empty manga
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
package org.koitharu.kotatsu.core.exceptions
|
||||||
|
|
||||||
|
import org.koitharu.kotatsu.details.ui.pager.EmptyMangaReason
|
||||||
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
|
|
||||||
|
class EmptyMangaException(
|
||||||
|
val reason: EmptyMangaReason?,
|
||||||
|
val manga: Manga,
|
||||||
|
cause: Throwable?
|
||||||
|
) : IllegalStateException(cause)
|
||||||
@@ -16,6 +16,7 @@ import org.koitharu.kotatsu.R
|
|||||||
import org.koitharu.kotatsu.browser.BrowserActivity
|
import org.koitharu.kotatsu.browser.BrowserActivity
|
||||||
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
|
import org.koitharu.kotatsu.browser.cloudflare.CloudFlareActivity
|
||||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.EmptyMangaException
|
||||||
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
||||||
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
|
import org.koitharu.kotatsu.core.exceptions.ProxyConfigException
|
||||||
import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException
|
import org.koitharu.kotatsu.core.exceptions.UnsupportedSourceException
|
||||||
@@ -25,6 +26,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
|
|||||||
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
|
import org.koitharu.kotatsu.core.ui.dialog.buildAlertDialog
|
||||||
import org.koitharu.kotatsu.core.util.ext.isHttpUrl
|
import org.koitharu.kotatsu.core.util.ext.isHttpUrl
|
||||||
import org.koitharu.kotatsu.core.util.ext.restartApplication
|
import org.koitharu.kotatsu.core.util.ext.restartApplication
|
||||||
|
import org.koitharu.kotatsu.details.ui.pager.EmptyMangaReason
|
||||||
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
|
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
|
||||||
import org.koitharu.kotatsu.parsers.exception.NotFoundException
|
import org.koitharu.kotatsu.parsers.exception.NotFoundException
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
@@ -83,6 +85,16 @@ class ExceptionResolver private constructor(
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is EmptyMangaException -> {
|
||||||
|
when (e.reason) {
|
||||||
|
EmptyMangaReason.NO_CHAPTERS -> openAlternatives(e.manga)
|
||||||
|
EmptyMangaReason.LOADING_ERROR -> Unit
|
||||||
|
EmptyMangaReason.RESTRICTED -> host.router.openBrowser(e.manga)
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
is UnsupportedSourceException -> {
|
is UnsupportedSourceException -> {
|
||||||
e.manga?.let { openAlternatives(it) }
|
e.manga?.let { openAlternatives(it) }
|
||||||
false
|
false
|
||||||
@@ -229,6 +241,12 @@ class ExceptionResolver private constructor(
|
|||||||
|
|
||||||
is InteractiveActionRequiredException -> R.string._continue
|
is InteractiveActionRequiredException -> R.string._continue
|
||||||
|
|
||||||
|
is EmptyMangaException -> when (e.reason) {
|
||||||
|
EmptyMangaReason.RESTRICTED -> if (e.manga.publicUrl.isHttpUrl()) R.string.open_in_browser else 0
|
||||||
|
EmptyMangaReason.NO_CHAPTERS -> R.string.alternatives
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -215,6 +215,12 @@ class AppRouter private constructor(
|
|||||||
startActivity(browserIntent(contextOrNull() ?: return, url, source, title))
|
startActivity(browserIntent(contextOrNull() ?: return, url, source, title))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun openBrowser(manga: Manga) = openBrowser(
|
||||||
|
url = manga.publicUrl,
|
||||||
|
source = manga.source,
|
||||||
|
title = manga.title,
|
||||||
|
)
|
||||||
|
|
||||||
fun openColorFilterConfig(manga: Manga, page: MangaPage) {
|
fun openColorFilterConfig(manga: Manga, page: MangaPage) {
|
||||||
startActivity(
|
startActivity(
|
||||||
Intent(contextOrNull(), ColorFilterConfigActivity::class.java)
|
Intent(contextOrNull(), ColorFilterConfigActivity::class.java)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.koitharu.kotatsu.core.exceptions.CaughtException
|
|||||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareBlockedException
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareBlockedException
|
||||||
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException
|
||||||
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
import org.koitharu.kotatsu.core.exceptions.EmptyHistoryException
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.EmptyMangaException
|
||||||
import org.koitharu.kotatsu.core.exceptions.IncompatiblePluginException
|
import org.koitharu.kotatsu.core.exceptions.IncompatiblePluginException
|
||||||
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
import org.koitharu.kotatsu.core.exceptions.InteractiveActionRequiredException
|
||||||
import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException
|
import org.koitharu.kotatsu.core.exceptions.NoDataReceivedException
|
||||||
@@ -103,6 +104,7 @@ private fun Throwable.getDisplayMessageOrNull(resources: Resources): String? = w
|
|||||||
is AccessDeniedException -> resources.getString(R.string.no_access_to_file)
|
is AccessDeniedException -> resources.getString(R.string.no_access_to_file)
|
||||||
is NonFileUriException -> resources.getString(R.string.error_non_file_uri)
|
is NonFileUriException -> resources.getString(R.string.error_non_file_uri)
|
||||||
is EmptyHistoryException -> resources.getString(R.string.history_is_empty)
|
is EmptyHistoryException -> resources.getString(R.string.history_is_empty)
|
||||||
|
is EmptyMangaException -> reason?.let { resources.getString(it.msgResId) } ?: cause?.getDisplayMessage(resources)
|
||||||
is ProxyConfigException -> resources.getString(R.string.invalid_proxy_configuration)
|
is ProxyConfigException -> resources.getString(R.string.invalid_proxy_configuration)
|
||||||
is SyncApiException,
|
is SyncApiException,
|
||||||
is ContentUnavailableException -> message
|
is ContentUnavailableException -> message
|
||||||
@@ -167,6 +169,8 @@ fun Throwable.getCauseUrl(): String? = when (this) {
|
|||||||
is CloudFlareProtectedException -> url
|
is CloudFlareProtectedException -> url
|
||||||
is InteractiveActionRequiredException -> url
|
is InteractiveActionRequiredException -> url
|
||||||
is HttpStatusException -> url
|
is HttpStatusException -> url
|
||||||
|
is UnsupportedSourceException -> manga?.publicUrl?.takeIf { it.isHttpUrl() }
|
||||||
|
is EmptyMangaException -> manga.publicUrl.takeIf { it.isHttpUrl() }
|
||||||
is HttpException -> (response.delegate as? Response)?.request?.url?.toString()
|
is HttpException -> (response.delegate as? Response)?.request?.url?.toString()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.koitharu.kotatsu.core.ui.model.MangaOverride
|
|||||||
import org.koitharu.kotatsu.local.domain.model.LocalManga
|
import org.koitharu.kotatsu.local.domain.model.LocalManga
|
||||||
import org.koitharu.kotatsu.parsers.model.Manga
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||||
|
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||||
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
|
import org.koitharu.kotatsu.parsers.util.ifNullOrEmpty
|
||||||
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
||||||
import org.koitharu.kotatsu.reader.data.filterChapters
|
import org.koitharu.kotatsu.reader.data.filterChapters
|
||||||
@@ -50,6 +51,9 @@ data class MangaDetails(
|
|||||||
.ifNullOrEmpty { localManga?.manga?.coverUrl }
|
.ifNullOrEmpty { localManga?.manga?.coverUrl }
|
||||||
?.nullIfEmpty()
|
?.nullIfEmpty()
|
||||||
|
|
||||||
|
val isRestricted: Boolean
|
||||||
|
get() = manga.state == MangaState.RESTRICTED
|
||||||
|
|
||||||
private val mergedManga by lazy {
|
private val mergedManga by lazy {
|
||||||
if (localManga == null) {
|
if (localManga == null) {
|
||||||
// fast path
|
// fast path
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import kotlinx.coroutines.plus
|
|||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
import org.koitharu.kotatsu.bookmarks.domain.Bookmark
|
||||||
import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository
|
import org.koitharu.kotatsu.bookmarks.domain.BookmarksRepository
|
||||||
|
import org.koitharu.kotatsu.core.exceptions.EmptyMangaException
|
||||||
import org.koitharu.kotatsu.core.model.getPreferredBranch
|
import org.koitharu.kotatsu.core.model.getPreferredBranch
|
||||||
import org.koitharu.kotatsu.core.nav.MangaIntent
|
import org.koitharu.kotatsu.core.nav.MangaIntent
|
||||||
import org.koitharu.kotatsu.core.nav.ReaderIntent
|
import org.koitharu.kotatsu.core.nav.ReaderIntent
|
||||||
@@ -47,6 +48,7 @@ import org.koitharu.kotatsu.details.data.MangaDetails
|
|||||||
import org.koitharu.kotatsu.details.domain.DetailsInteractor
|
import org.koitharu.kotatsu.details.domain.DetailsInteractor
|
||||||
import org.koitharu.kotatsu.details.domain.DetailsLoadUseCase
|
import org.koitharu.kotatsu.details.domain.DetailsLoadUseCase
|
||||||
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesViewModel
|
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesViewModel
|
||||||
|
import org.koitharu.kotatsu.details.ui.pager.EmptyMangaReason
|
||||||
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
import org.koitharu.kotatsu.download.ui.worker.DownloadWorker
|
||||||
import org.koitharu.kotatsu.history.data.HistoryRepository
|
import org.koitharu.kotatsu.history.data.HistoryRepository
|
||||||
import org.koitharu.kotatsu.history.domain.HistoryUpdateUseCase
|
import org.koitharu.kotatsu.history.domain.HistoryUpdateUseCase
|
||||||
@@ -405,9 +407,11 @@ class ReaderViewModel @Inject constructor(
|
|||||||
private fun loadImpl() {
|
private fun loadImpl() {
|
||||||
loadingJob = launchLoadingJob(Dispatchers.Default + EventExceptionHandler(onLoadingError)) {
|
loadingJob = launchLoadingJob(Dispatchers.Default + EventExceptionHandler(onLoadingError)) {
|
||||||
var exception: Exception? = null
|
var exception: Exception? = null
|
||||||
|
var loadedDetails: MangaDetails? = null
|
||||||
try {
|
try {
|
||||||
detailsLoadUseCase(intent, force = false)
|
detailsLoadUseCase(intent, force = false)
|
||||||
.collect { details ->
|
.collect { details ->
|
||||||
|
loadedDetails = details
|
||||||
if (mangaDetails.value == null) {
|
if (mangaDetails.value == null) {
|
||||||
mangaDetails.value = details
|
mangaDetails.value = details
|
||||||
}
|
}
|
||||||
@@ -452,9 +456,28 @@ class ReaderViewModel @Inject constructor(
|
|||||||
exception = e.mergeWith(exception)
|
exception = e.mergeWith(exception)
|
||||||
}
|
}
|
||||||
if (readingState.value == null) {
|
if (readingState.value == null) {
|
||||||
onLoadingError.call(
|
val loadedManga = loadedDetails // for smart cast
|
||||||
exception ?: IllegalStateException("Unable to load manga. This should never happen. Please report"),
|
if (loadedManga != null) {
|
||||||
|
mangaDetails.value = loadedManga.filterChapters(selectedBranch.value)
|
||||||
|
}
|
||||||
|
val loadingError = when {
|
||||||
|
exception != null -> exception
|
||||||
|
loadedManga == null || !loadedManga.isLoaded -> null
|
||||||
|
loadedManga.isRestricted -> EmptyMangaException(
|
||||||
|
EmptyMangaReason.RESTRICTED,
|
||||||
|
loadedManga.toManga(),
|
||||||
|
null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
loadedManga.allChapters.isEmpty() -> EmptyMangaException(
|
||||||
|
EmptyMangaReason.NO_CHAPTERS,
|
||||||
|
loadedManga.toManga(),
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
} ?: IllegalStateException("Unable to load manga. This should never happen. Please report")
|
||||||
|
onLoadingError.call(loadingError)
|
||||||
} else exception?.let { e ->
|
} else exception?.let { e ->
|
||||||
// manga has been loaded but error occurred
|
// manga has been loaded but error occurred
|
||||||
errorEvent.call(e)
|
errorEvent.call(e)
|
||||||
|
|||||||
Reference in New Issue
Block a user