mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
Use BaseCoroutine classes for Manga details
This commit is contained in:
parent
6af488b8e7
commit
b4fd3d2220
2 changed files with 63 additions and 70 deletions
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue