Fix crash when setting cover errors (closes #7714)

This commit is contained in:
arkon 2022-08-10 16:11:12 -04:00
parent 22e83f408b
commit e511f24979
8 changed files with 34 additions and 43 deletions

View File

@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -36,7 +36,7 @@ class ExtensionDetailsPresenter(
.collectLatest { extension -> .collectLatest { extension ->
// If extension is null it's most likely uninstalled // If extension is null it's most likely uninstalled
if (extension == null) { if (extension == null) {
launchUI { withUIContext {
view?.onExtensionUninstalled() view?.onExtensionUninstalled()
} }
return@collectLatest return@collectLatest

View File

@ -29,7 +29,6 @@ import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchCardItem
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchItem import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchItem
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -98,7 +97,7 @@ class SearchPresenter(
withUIContext { view?.applicationContext?.toast(e.message) } withUIContext { view?.applicationContext?.toast(e.message) }
} }
presenterScope.launchUI { replacingMangaRelay.call(Pair(false, manga)) } withUIContext { replacingMangaRelay.call(Pair(false, manga)) }
} }
} }

View File

@ -22,7 +22,7 @@ import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.ui.manga.MangaController
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
@ -182,7 +182,7 @@ class LibraryController(
else -> QuadStateTextView.State.UNCHECKED.ordinal else -> QuadStateTextView.State.UNCHECKED.ordinal
} }
}.toTypedArray() }.toTypedArray()
launchUI { withUIContext {
ChangeMangaCategoriesDialog(this@LibraryController, mangas.mapNotNull { it.toDomainManga() }, categories, preselected) ChangeMangaCategoriesDialog(this@LibraryController, mangas.mapNotNull { it.toDomainManga() }, categories, preselected)
.showDialog(router) .showDialog(router)
} }

View File

@ -42,7 +42,6 @@ import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.chapter.getChapterSort import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.lang.toRelativeString
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.asHotFlow import eu.kanade.tachiyomi.util.preference.asHotFlow
@ -276,7 +275,7 @@ class MangaPresenter(
if (manga.toDbManga().removeCovers() > 0) { if (manga.toDbManga().removeCovers() > 0) {
updateManga.awaitUpdateCoverLastModified(manga.id) updateManga.awaitUpdateCoverLastModified(manga.id)
} }
launchUI { onRemoved() } withUIContext { onRemoved() }
} }
} else { } else {
// Add to library // Add to library
@ -284,7 +283,7 @@ class MangaPresenter(
if (onDuplicateExists != null) { if (onDuplicateExists != null) {
val duplicate = getDuplicateLibraryManga.await(manga.title, manga.source) val duplicate = getDuplicateLibraryManga.await(manga.title, manga.source)
if (duplicate != null) { if (duplicate != null) {
launchUI { onDuplicateExists(duplicate) } withUIContext { onDuplicateExists(duplicate) }
return@launchIO return@launchIO
} }
} }
@ -299,7 +298,7 @@ class MangaPresenter(
val result = updateManga.awaitUpdateFavorite(manga.id, true) val result = updateManga.awaitUpdateFavorite(manga.id, true)
if (!result) return@launchIO if (!result) return@launchIO
moveMangaToCategory(defaultCategory) moveMangaToCategory(defaultCategory)
launchUI { onAdded() } withUIContext { onAdded() }
} }
// Automatic 'Default' or no categories // Automatic 'Default' or no categories
@ -307,11 +306,11 @@ class MangaPresenter(
val result = updateManga.awaitUpdateFavorite(manga.id, true) val result = updateManga.awaitUpdateFavorite(manga.id, true)
if (!result) return@launchIO if (!result) return@launchIO
moveMangaToCategory(null) moveMangaToCategory(null)
launchUI { onAdded() } withUIContext { onAdded() }
} }
// Choose a category // Choose a category
else -> launchUI { onRequireCategory(manga, categories) } else -> withUIContext { onRequireCategory(manga, categories) }
} }
// Finally match with enhanced tracking when available // Finally match with enhanced tracking when available

View File

@ -28,7 +28,6 @@ import eu.kanade.tachiyomi.data.saver.Location
import eu.kanade.tachiyomi.ui.base.controller.FullComposeController import eu.kanade.tachiyomi.ui.base.controller.FullComposeController
import eu.kanade.tachiyomi.util.editCover import eu.kanade.tachiyomi.util.editCover
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toShareIntent import eu.kanade.tachiyomi.util.system.toShareIntent
@ -81,11 +80,11 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
viewScope.launchIO { viewScope.launchIO {
try { try {
val uri = presenter.saveCover(activity, temp = true) ?: return@launchIO val uri = presenter.saveCover(activity, temp = true) ?: return@launchIO
launchUI { withUIContext {
startActivity(uri.toShareIntent(activity)) startActivity(uri.toShareIntent(activity))
} }
} catch (e: Throwable) { } catch (e: Throwable) {
launchUI { withUIContext {
logcat(LogPriority.ERROR, e) logcat(LogPriority.ERROR, e)
activity.toast(R.string.error_saving_cover) activity.toast(R.string.error_saving_cover)
} }
@ -98,11 +97,11 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
viewScope.launchIO { viewScope.launchIO {
try { try {
presenter.saveCover(activity, temp = false) presenter.saveCover(activity, temp = false)
launchUI { withUIContext {
activity.toast(R.string.cover_saved) activity.toast(R.string.cover_saved)
} }
} catch (e: Throwable) { } catch (e: Throwable) {
launchUI { withUIContext {
logcat(LogPriority.ERROR, e) logcat(LogPriority.ERROR, e)
activity.toast(R.string.error_saving_cover) activity.toast(R.string.error_saving_cover)
} }
@ -209,13 +208,12 @@ class MangaFullCoverDialog : FullComposeController<MangaFullCoverDialog.MangaFul
presenterScope.launchIO { presenterScope.launchIO {
@Suppress("BlockingMethodInNonBlockingContext") @Suppress("BlockingMethodInNonBlockingContext")
context.contentResolver.openInputStream(data)?.use { context.contentResolver.openInputStream(data)?.use {
val result = try { try {
manga.editCover(context, it, updateManga, coverCache) manga.editCover(context, it, updateManga, coverCache)
withUIContext { view?.onSetCoverSuccess() }
} catch (e: Exception) { } catch (e: Exception) {
view?.onSetCoverError(e) withUIContext { view?.onSetCoverError(e) }
false
} }
withUIContext { if (result) view?.onSetCoverSuccess() }
} }
} }
} }

View File

@ -43,7 +43,6 @@ import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.editCover import eu.kanade.tachiyomi.util.editCover
import eu.kanade.tachiyomi.util.lang.byteSize import eu.kanade.tachiyomi.util.lang.byteSize
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.takeBytes import eu.kanade.tachiyomi.util.lang.takeBytes
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
@ -665,7 +664,7 @@ class ReaderPresenter(
location = Location.Pictures.create(relativePath), location = Location.Pictures.create(relativePath),
), ),
) )
launchUI { withUIContext {
notifier.onComplete(uri) notifier.onComplete(uri)
view!!.onSaveImageResult(SaveImageResult.Success(uri)) view!!.onSaveImageResult(SaveImageResult.Success(uri))
} }
@ -702,7 +701,7 @@ class ReaderPresenter(
location = Location.Cache, location = Location.Cache,
), ),
) )
launchUI { withUIContext {
view!!.onShareImageResult(uri, page) view!!.onShareImageResult(uri, page)
} }
} }
@ -720,20 +719,19 @@ class ReaderPresenter(
val stream = page.stream ?: return val stream = page.stream ?: return
presenterScope.launchIO { presenterScope.launchIO {
val result = try { try {
manga.editCover(context, stream()) manga.editCover(context, stream())
} catch (e: Exception) { withUIContext {
false view?.onSetAsCoverResult(
} if (manga.isLocal() || manga.favorite) {
launchUI {
val resultResult = if (!result) {
SetAsCoverResult.Error
} else if (manga.isLocal() || manga.favorite) {
SetAsCoverResult.Success SetAsCoverResult.Success
} else { } else {
SetAsCoverResult.AddToLibraryFirst SetAsCoverResult.AddToLibraryFirst
},
)
} }
view?.onSetAsCoverResult(resultResult) } catch (e: Exception) {
withUIContext { view?.onSetAsCoverResult(SetAsCoverResult.Error) }
} }
} }
} }

View File

@ -25,8 +25,8 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.toDateKey import eu.kanade.tachiyomi.util.lang.toDateKey
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
@ -112,7 +112,7 @@ class HistoryPresenter(
presenterScope.launchIO { presenterScope.launchIO {
val result = deleteHistoryTable.await() val result = deleteHistoryTable.await()
if (!result) return@launchIO if (!result) return@launchIO
launchUI { withUIContext {
view?.activity?.toast(R.string.clear_history_completed) view?.activity?.toast(R.string.clear_history_completed)
} }
} }

View File

@ -80,15 +80,12 @@ suspend fun DomainManga.editCover(
stream: InputStream, stream: InputStream,
updateManga: UpdateManga = Injekt.get(), updateManga: UpdateManga = Injekt.get(),
coverCache: CoverCache = Injekt.get(), coverCache: CoverCache = Injekt.get(),
): Boolean { ) {
return if (isLocal()) { if (isLocal()) {
LocalSource.updateCover(context, toDbManga(), stream) LocalSource.updateCover(context, toDbManga(), stream)
updateManga.awaitUpdateCoverLastModified(id) updateManga.awaitUpdateCoverLastModified(id)
} else if (favorite) { } else if (favorite) {
coverCache.setCustomCoverToCache(toDbManga(), stream) coverCache.setCustomCoverToCache(toDbManga(), stream)
updateManga.awaitUpdateCoverLastModified(id) updateManga.awaitUpdateCoverLastModified(id)
} else {
// We should never reach this block
false
} }
} }