Use 1.x API to fetch manga details in browse view

This commit is contained in:
arkon 2020-10-31 10:00:02 -04:00
parent b1ce3693ed
commit 7310ec4fe4

View File

@ -8,12 +8,14 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.filter.CheckboxItem
import eu.kanade.tachiyomi.ui.browse.source.filter.CheckboxSectionItem
@ -29,12 +31,17 @@ import eu.kanade.tachiyomi.ui.browse.source.filter.TextSectionItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.removeCovers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.isActive
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import rx.subjects.PublishSubject
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -85,9 +92,9 @@ open class BrowseSourcePresenter(
private lateinit var pager: Pager
/**
* Subject that initializes a list of manga.
* Flow of manga list to initialize.
*/
private val mangaDetailSubject = PublishSubject.create<List<Manga>>()
private val mangaDetailsFlow = MutableStateFlow<List<Manga>>(emptyList())
/**
* Subscription for the pager.
@ -100,9 +107,9 @@ open class BrowseSourcePresenter(
private var pageSubscription: Subscription? = null
/**
* Subscription to initialize manga details.
* Job to initialize manga details.
*/
private var initializerSubscription: Subscription? = null
private var initializerJob: Job? = null
override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState)
@ -133,7 +140,7 @@ open class BrowseSourcePresenter(
this.query = query
this.appliedFilters = filters
subscribeToMangaInitializer()
initializeManga()
// Create a new pager.
pager = createPager(query, filters)
@ -189,24 +196,22 @@ open class BrowseSourcePresenter(
/**
* Subscribes to the initializer of manga details and updates the view if needed.
*/
private fun subscribeToMangaInitializer() {
initializerSubscription?.let { remove(it) }
initializerSubscription = mangaDetailSubject.observeOn(Schedulers.io())
.flatMap { Observable.from(it) }
.filter { it.thumbnail_url == null && !it.initialized }
.concatMap { getMangaDetailsObservable(it) }
.onBackpressureBuffer()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ manga ->
@Suppress("DEPRECATION")
view?.onMangaInitialized(manga)
},
{ error ->
Timber.e(error)
private fun initializeManga() {
initializerJob?.cancel()
initializerJob = launchIO {
mangaDetailsFlow
.onEach { mangas ->
if (!isActive) return@onEach
try {
mangas.filter { it.thumbnail_url == null && !it.initialized }
.map { getMangaDetails(it) }
.forEach { launchUI { view?.onMangaInitialized(it) } }
} catch (error: Exception) {
launchUI { Timber.e(error) }
}
}
}
)
.apply { add(this) }
}
/**
@ -234,24 +239,27 @@ open class BrowseSourcePresenter(
* @param mangas the list of manga to initialize.
*/
fun initializeMangas(mangas: List<Manga>) {
mangaDetailSubject.onNext(mangas)
launchIO { mangaDetailsFlow.emit(mangas) }
}
/**
* Returns an observable of manga that initializes the given manga.
* Returns the initialized manga.
*
* @param manga the manga to initialize.
* @return an observable of the manga to initialize
* @return the initialized manga
*/
private fun getMangaDetailsObservable(manga: Manga): Observable<Manga> {
return source.fetchMangaDetails(manga)
.flatMap { networkManga ->
manga.copyFrom(networkManga)
private suspend fun getMangaDetails(manga: Manga): Manga {
return try {
source.getMangaDetails(manga.toMangaInfo())
.let { networkManga ->
manga.copyFrom(networkManga.toSManga())
manga.initialized = true
db.insertManga(manga).executeAsBlocking()
Observable.just(manga)
manga
}
} catch (e: Exception) {
manga
}
.onErrorResumeNext { Observable.just(manga) }
}
/**
@ -279,7 +287,7 @@ open class BrowseSourcePresenter(
* Refreshes the active display mode.
*/
fun refreshDisplayMode() {
subscribeToMangaInitializer()
initializeManga()
}
/**