Use BaseCoroutine classes for Manga details

This commit is contained in:
Jays2Kings 2022-04-22 04:18:24 -04:00
parent 6af488b8e7
commit b4fd3d2220
2 changed files with 63 additions and 70 deletions

View file

@ -59,7 +59,7 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
import eu.kanade.tachiyomi.ui.base.SmallToolbarInterface
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.BaseCoroutineController
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
import eu.kanade.tachiyomi.ui.library.LibraryController
@ -118,7 +118,7 @@ import kotlin.math.max
import kotlin.math.roundToInt
class MangaDetailsController :
BaseController<MangaDetailsControllerBinding>,
BaseCoroutineController<MangaDetailsControllerBinding, MangaDetailsPresenter>,
FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener,
ActionMode.Callback,
@ -143,7 +143,7 @@ class MangaDetailsController :
if (manga != null) {
source = Injekt.get<SourceManager>().getOrStub(manga.source)
}
presenter = MangaDetailsPresenter(this, manga!!, source!!)
presenter = MangaDetailsPresenter(manga!!, source!!)
}
constructor(mangaId: Long) : this(
@ -163,7 +163,7 @@ class MangaDetailsController :
private var manga: Manga? = null
private var source: Source? = null
private var colorAnimator: ValueAnimator? = null
val presenter: MangaDetailsPresenter
override val presenter: MangaDetailsPresenter
private var coverColor: Int? = null
private var accentColor: Int? = null
private var headerColor: Int? = null
@ -211,7 +211,7 @@ class MangaDetailsController :
activityBinding?.appBar?.y = 0f
}
presenter.onCreate()
presenter.onFirstLoad()
binding.swipeRefresh.isRefreshing = presenter.isLoading
binding.swipeRefresh.setOnRefreshListener { presenter.refreshAll() }
updateToolbarTitleAlpha()
@ -353,7 +353,6 @@ class MangaDetailsController :
override fun onDestroyView(view: View) {
snack?.dismiss()
presenter.onDestroy()
adapter = null
trackingBottomSheet = null
super.onDestroyView(view)
@ -565,9 +564,6 @@ class MangaDetailsController :
if (router.backstack.lastOrNull()?.controller is DialogController) {
return
}
if (type == ControllerChangeType.POP_EXIT) {
presenter.cancelScope()
}
colorAnimator?.cancel()
getHeader()?.clearDescFocus()

View file

@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.ui.manga.track.TrackingBottomSheet
@ -55,12 +56,9 @@ import eu.kanade.tachiyomi.util.system.executeOnIO
import eu.kanade.tachiyomi.util.system.launchIO
import eu.kanade.tachiyomi.util.system.withUIContext
import eu.kanade.tachiyomi.widget.TriStateCheckBox
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
@ -73,17 +71,14 @@ import java.io.OutputStream
import java.util.Date
class MangaDetailsPresenter(
private val controller: MangaDetailsController,
val manga: Manga,
val source: Source,
val preferences: PreferencesHelper = Injekt.get(),
val coverCache: CoverCache = Injekt.get(),
val db: DatabaseHelper = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
private val chapterFilter: ChapterFilter = Injekt.get()
) : DownloadQueue.DownloadListener, LibraryServiceListener {
private var scope = CoroutineScope(Job() + Dispatchers.Default)
chapterFilter: ChapterFilter = Injekt.get()
) : BaseCoroutinePresenter<MangaDetailsController>(), DownloadQueue.DownloadListener, LibraryServiceListener {
private val customMangaManager: CustomMangaManager by injectLazy()
private val mangaShortcutManager: MangaShortcutManager by injectLazy()
@ -107,10 +102,11 @@ class MangaDetailsPresenter(
var allChapters: List<ChapterItem> = emptyList()
private set
var headerItem = MangaHeaderItem(manga, controller.fromCatalogue)
val headerItem by lazy { MangaHeaderItem(manga, controller?.fromCatalogue == true) }
var tabletChapterHeaderItem: MangaHeaderItem? = null
var allChapterScanlators: Set<String> = emptySet()
fun onCreate() {
fun onFirstLoad() {
val controller = controller ?: return
headerItem.isTablet = controller.isTablet
if (controller.isTablet) {
tabletChapterHeaderItem = MangaHeaderItem(manga, false)
@ -136,20 +132,17 @@ class MangaDetailsPresenter(
refreshTracking(false)
}
fun onDestroy() {
override fun onDestroy() {
super.onDestroy()
downloadManager.removeListener(this)
LibraryUpdateService.removeListener(this)
}
fun cancelScope() {
scope.cancel()
}
fun fetchChapters(andTracking: Boolean = true) {
scope.launch {
presenterScope.launch {
getChapters()
if (andTracking) fetchTracks()
withContext(Dispatchers.Main) { controller.updateChapters(chapters) }
withContext(Dispatchers.Main) { controller?.updateChapters(chapters) }
}
}
@ -182,16 +175,16 @@ class MangaDetailsPresenter(
override fun updateDownload(download: Download) {
chapters.find { it.id == download.chapter.id }?.download = download
scope.launch(Dispatchers.Main) {
controller.updateChapterDownload(download)
presenterScope.launchIO {
controller?.updateChapterDownload(download)
}
}
override fun updateDownloads() {
scope.launch(Dispatchers.Default) {
presenterScope.launch(Dispatchers.Default) {
getChapters()
withContext(Dispatchers.Main) {
controller.updateChapters(chapters)
controller?.updateChapters(chapters)
}
}
}
@ -281,7 +274,7 @@ class MangaDetailsPresenter(
download = null
}
controller.updateChapters(this.chapters)
controller?.updateChapters(this.chapters)
}
/**
@ -303,7 +296,7 @@ class MangaDetailsPresenter(
}
}
if (update) controller.updateChapters(this.chapters)
if (update) controller?.updateChapters(this.chapters)
}
fun refreshMangaFromDb(): Manga {
@ -314,8 +307,8 @@ class MangaDetailsPresenter(
/** Refresh Manga Info and Chapter List (not tracking) */
fun refreshAll() {
if (controller.isNotOnline() && manga.source != LocalSource.ID) return
scope.launch {
if (controller?.isNotOnline() == true && manga.source != LocalSource.ID) return
presenterScope.launch {
isLoading = true
var mangaError: java.lang.Exception? = null
var chapterError: java.lang.Exception? = null
@ -360,7 +353,7 @@ class MangaDetailsPresenter(
if (Coil.imageLoader(preferences.context).execute(request) is SuccessResult) {
preferences.context.imageLoader.memoryCache.remove(MemoryCache.Key(manga.key()))
withContext(Dispatchers.Main) {
controller.setPaletteColor()
controller?.setPaletteColor()
}
}
}
@ -384,7 +377,7 @@ class MangaDetailsPresenter(
}
if (removedChapters.isNotEmpty()) {
withContext(Dispatchers.Main) {
controller.showChaptersRemovedPopup(
controller?.showChaptersRemovedPopup(
removedChapters
)
}
@ -393,16 +386,18 @@ class MangaDetailsPresenter(
getChapters()
}
isLoading = false
if (chapterError == null) withContext(Dispatchers.Main) { controller.updateChapters(this@MangaDetailsPresenter.chapters) }
if (chapterError == null) withContext(Dispatchers.Main) {
controller?.updateChapters(this@MangaDetailsPresenter.chapters)
}
if (chapterError != null) {
withContext(Dispatchers.Main) {
controller.showError(
controller?.showError(
trimException(chapterError!!)
)
}
return@launch
} else if (mangaError != null) withContext(Dispatchers.Main) {
controller.showError(
controller?.showError(
trimException(mangaError!!)
)
}
@ -416,11 +411,11 @@ class MangaDetailsPresenter(
hasRequested = true
isLoading = true
scope.launch(Dispatchers.IO) {
presenterScope.launch(Dispatchers.IO) {
val chapters = try {
source.getChapterList(manga.toMangaInfo()).map { it.toSChapter() }
} catch (e: Exception) {
withContext(Dispatchers.Main) { controller.showError(trimException(e)) }
withContext(Dispatchers.Main) { controller?.showError(trimException(e)) }
return@launch
}
isLoading = false
@ -428,10 +423,12 @@ class MangaDetailsPresenter(
syncChaptersWithSource(db, chapters, manga, source)
getChapters()
withContext(Dispatchers.Main) { controller.updateChapters(this@MangaDetailsPresenter.chapters) }
withContext(Dispatchers.Main) {
controller?.updateChapters(this@MangaDetailsPresenter.chapters)
}
} catch (e: java.lang.Exception) {
withContext(Dispatchers.Main) {
controller.showError(trimException(e))
controller?.showError(trimException(e))
}
}
}
@ -452,13 +449,13 @@ class MangaDetailsPresenter(
* @param selectedChapters the list of chapters to bookmark.
*/
fun bookmarkChapters(selectedChapters: List<ChapterItem>, bookmarked: Boolean) {
scope.launch(Dispatchers.IO) {
presenterScope.launch(Dispatchers.IO) {
selectedChapters.forEach {
it.bookmark = bookmarked
}
db.updateChaptersProgress(selectedChapters).executeAsBlocking()
getChapters()
withContext(Dispatchers.Main) { controller.updateChapters(chapters) }
withContext(Dispatchers.Main) { controller?.updateChapters(chapters) }
}
}
@ -474,7 +471,7 @@ class MangaDetailsPresenter(
lastRead: Int? = null,
pagesLeft: Int? = null
) {
scope.launch(Dispatchers.IO) {
presenterScope.launch(Dispatchers.IO) {
selectedChapters.forEach {
it.read = read
if (!read) {
@ -487,7 +484,7 @@ class MangaDetailsPresenter(
deleteChapters(selectedChapters, false)
}
getChapters()
withContext(Dispatchers.Main) { controller.updateChapters(chapters) }
withContext(Dispatchers.Main) { controller?.updateChapters(chapters) }
}
}
@ -571,7 +568,7 @@ class MangaDetailsPresenter(
if (mangaFilterMatchesDefault()) {
manga.setFilterToGlobal()
}
controller.refreshAdapter()
controller?.refreshAdapter()
}
fun resetFilterToDefault() {
@ -611,10 +608,10 @@ class MangaDetailsPresenter(
}
private fun asyncUpdateMangaAndChapters(justChapters: Boolean = false) {
scope.launch {
presenterScope.launch {
if (!justChapters) db.updateChapterFlags(manga).executeOnIO()
getChapters()
withContext(Dispatchers.Main) { controller.updateChapters(chapters) }
withContext(Dispatchers.Main) { controller?.updateChapters(chapters) }
}
}
@ -648,7 +645,7 @@ class MangaDetailsPresenter(
}
db.insertManga(manga).executeAsBlocking()
controller.updateHeader()
controller?.updateHeader()
return manga.favorite
}
@ -688,12 +685,12 @@ class MangaDetailsPresenter(
val destDir = File(context.cacheDir, "shared_image")
scope.launchIO {
presenterScope.launchIO {
destDir.deleteRecursively()
try {
val file = saveCover(destDir)
withUIContext {
controller.shareManga(file)
controller?.shareManga(file)
}
} catch (e: java.lang.Exception) {
}
@ -766,9 +763,9 @@ class MangaDetailsPresenter(
editCoverWithStream(uri)
} else if (resetCover) {
coverCache.deleteCustomCover(manga)
controller.setPaletteColor()
controller?.setPaletteColor()
}
controller.updateHeader()
controller?.updateHeader()
}
private fun setSeriesType(seriesType: Int, genres: String? = null): Array<String> {
@ -789,13 +786,13 @@ class MangaDetailsPresenter(
downloadManager.context.contentResolver.openInputStream(uri) ?: return false
if (manga.source == LocalSource.ID) {
LocalSource.updateCover(downloadManager.context, manga, inputStream)
controller.setPaletteColor()
controller?.setPaletteColor()
return true
}
if (manga.favorite) {
coverCache.setCustomCoverToCache(manga, inputStream)
controller.setPaletteColor()
controller?.setPaletteColor()
return true
}
return false
@ -851,7 +848,7 @@ class MangaDetailsPresenter(
// Tracking
private fun setTrackItems() {
scope.launch {
presenterScope.launch {
trackList = loggedServices.map { service ->
TrackItem(tracks.find { it.sync_id == service.id }, service)
}
@ -863,12 +860,12 @@ class MangaDetailsPresenter(
trackList = loggedServices.map { service ->
TrackItem(tracks.find { it.sync_id == service.id }, service)
}
withContext(Dispatchers.Main) { controller.refreshTracking(trackList) }
withContext(Dispatchers.Main) { controller?.refreshTracking(trackList) }
}
fun refreshTracking(showOfflineSnack: Boolean = false) {
if (!controller.isNotOnline(showOfflineSnack)) {
scope.launch {
if (controller?.isNotOnline(showOfflineSnack) == false) {
presenterScope.launch {
val asyncList = trackList.filter { it.track != null }.map { item ->
async(Dispatchers.IO) {
val trackItem = try {
@ -893,15 +890,15 @@ class MangaDetailsPresenter(
}
fun trackSearch(query: String, service: TrackService) {
if (!controller.isNotOnline()) {
scope.launch(Dispatchers.IO) {
if (controller?.isNotOnline() == false) {
presenterScope.launch(Dispatchers.IO) {
val results = try {
service.search(query)
} catch (e: Exception) {
withContext(Dispatchers.Main) { controller.trackSearchError(e) }
withContext(Dispatchers.Main) { controller?.trackSearchError(e) }
return@launch
}
withContext(Dispatchers.Main) { controller.onTrackSearchResults(results.orEmpty()) }
withContext(Dispatchers.Main) { controller?.onTrackSearchResults(results) }
}
}
}
@ -910,7 +907,7 @@ class MangaDetailsPresenter(
if (item != null) {
item.manga_id = manga.id!!
scope.launch {
presenterScope.launch {
val binding = try {
service.bind(item)
} catch (e: Exception) {
@ -932,7 +929,7 @@ class MangaDetailsPresenter(
}
fun removeTracker(trackItem: TrackItem, removeFromService: Boolean) {
scope.launch {
presenterScope.launch {
withContext(Dispatchers.IO) {
db.deleteTrackForManga(manga, trackItem.service).executeAsBlocking()
if (removeFromService && trackItem.service.canRemoveFromService()) {
@ -944,7 +941,7 @@ class MangaDetailsPresenter(
}
private fun updateRemote(track: Track, service: TrackService) {
scope.launch {
presenterScope.launch {
val binding = try {
service.update(track)
} catch (e: Exception) {
@ -959,11 +956,11 @@ class MangaDetailsPresenter(
}
private fun trackRefreshDone() {
scope.launch(Dispatchers.Main) { controller.trackRefreshDone() }
presenterScope.launch(Dispatchers.Main) { controller?.trackRefreshDone() }
}
private fun trackError(error: Exception) {
scope.launch(Dispatchers.Main) { controller.trackRefreshError(error) }
presenterScope.launch(Dispatchers.Main) { controller?.trackRefreshError(error) }
}
fun setStatus(item: TrackItem, index: Int) {