|
@@ -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)
|
|
|
- manga.initialized = true
|
|
|
- db.insertManga(manga).executeAsBlocking()
|
|
|
- Observable.just(manga)
|
|
|
- }
|
|
|
- .onErrorResumeNext { Observable.just(manga) }
|
|
|
+ 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()
|
|
|
+ manga
|
|
|
+ }
|
|
|
+ } catch (e: Exception) {
|
|
|
+ manga
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -279,7 +287,7 @@ open class BrowseSourcePresenter(
|
|
|
* Refreshes the active display mode.
|
|
|
*/
|
|
|
fun refreshDisplayMode() {
|
|
|
- subscribeToMangaInitializer()
|
|
|
+ initializeManga()
|
|
|
}
|
|
|
|
|
|
/**
|