Make a coroutine presenter
This commit is contained in:
parent
d302a0fbc7
commit
644140b617
@ -181,7 +181,7 @@ private suspend fun <T> Observable<T>.awaitOne(): T = suspendCancellableCoroutin
|
||||
internal fun <T> CancellableContinuation<T>.unsubscribeOnCancellation(sub: Subscription) =
|
||||
invokeOnCancellation { sub.unsubscribe() }
|
||||
|
||||
fun <T : Any> Observable<T>.asFlow(): Flow<T> = callbackFlow {
|
||||
fun <T : Any?> Observable<T>.asFlow(): Flow<T> = callbackFlow {
|
||||
val observer = object : Observer<T> {
|
||||
override fun onNext(t: T) {
|
||||
offer(t)
|
||||
@ -199,7 +199,7 @@ fun <T : Any> Observable<T>.asFlow(): Flow<T> = callbackFlow {
|
||||
awaitClose { subscription.unsubscribe() }
|
||||
}
|
||||
|
||||
fun <T : Any> Flow<T>.asObservable(backpressureMode: Emitter.BackpressureMode = Emitter.BackpressureMode.NONE): Observable<T> {
|
||||
fun <T : Any?> Flow<T>.asObservable(backpressureMode: Emitter.BackpressureMode = Emitter.BackpressureMode.NONE): Observable<T> {
|
||||
return Observable.create(
|
||||
{ emitter ->
|
||||
/*
|
||||
|
41
app/src/main/java/exh/ui/base/CoroutinePresenter.kt
Normal file
41
app/src/main/java/exh/ui/base/CoroutinePresenter.kt
Normal file
@ -0,0 +1,41 @@
|
||||
package exh.ui.base
|
||||
|
||||
import androidx.annotation.CallSuper
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import nucleus.presenter.Presenter
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
open class CoroutinePresenter<V> : Presenter<V>() {
|
||||
val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||
|
||||
@Suppress("DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated("Use launchInView")
|
||||
override fun getView(): V? {
|
||||
return super.getView()
|
||||
}
|
||||
|
||||
fun launchInView(block: (CoroutineScope, V) -> Unit) = scope.launch(Dispatchers.Main) {
|
||||
view?.let { block.invoke(this, it) }
|
||||
}
|
||||
|
||||
fun <F> Flow<F>.onEachView(block: (V, F) -> Unit) = onEach {
|
||||
view?.let { view -> block(view, it) }
|
||||
}
|
||||
|
||||
fun <F, P> Flow<F>.mapView(block: (V, F) -> P): Flow<P> = mapNotNull {
|
||||
view?.let { view -> block(view, it) }
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
override fun destroy() {
|
||||
super.destroy()
|
||||
scope.cancel()
|
||||
}
|
||||
}
|
@ -11,12 +11,9 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.databinding.MetadataViewControllerBinding
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import exh.metadata.metadata.base.FlatMetadata
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.source.getMainSource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -74,13 +71,6 @@ class MetadataViewController : NucleusController<MetadataViewControllerBinding,
|
||||
binding.recycler.setHasFixedSize(true)
|
||||
}
|
||||
|
||||
fun onNextMetaInfo(flatMetadata: FlatMetadata) {
|
||||
val mainSource = presenter.source.getMainSource()
|
||||
if (mainSource is MetadataSource<*, *>) {
|
||||
presenter.meta = flatMetadata.raise(mainSource.metaClass)
|
||||
}
|
||||
}
|
||||
|
||||
fun onNextMangaInfo(meta: RaisedSearchMetadata?) {
|
||||
val context = view?.context ?: return
|
||||
data = meta?.getExtraInfoPairs(context).orEmpty()
|
||||
|
@ -1,17 +1,23 @@
|
||||
package exh.ui.metadata
|
||||
|
||||
import android.os.Bundle
|
||||
import com.elvishew.xlog.XLog
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.source.online.MetadataSource
|
||||
import eu.kanade.tachiyomi.util.lang.asFlow
|
||||
import exh.metadata.metadata.base.FlatMetadata
|
||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||
import exh.metadata.metadata.base.getFlatMetadataForManga
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import exh.source.getMainSource
|
||||
import exh.ui.base.CoroutinePresenter
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.plus
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
@ -20,29 +26,31 @@ class MetadataViewPresenter(
|
||||
val source: Source,
|
||||
val preferences: PreferencesHelper = Injekt.get(),
|
||||
private val db: DatabaseHelper = Injekt.get()
|
||||
) : BasePresenter<MetadataViewController>() {
|
||||
) : CoroutinePresenter<MetadataViewController>() {
|
||||
|
||||
var meta: RaisedSearchMetadata? = null
|
||||
val meta = MutableStateFlow<RaisedSearchMetadata?>(null)
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
getMangaMetaObservable().subscribeLatestCache({ view, flatMetadata -> if (flatMetadata != null) view.onNextMetaInfo(flatMetadata) else XLog.tag("MetadataViewPresenter").disableStackTrace().d("Invalid metadata") })
|
||||
getMangaMetaObservable()
|
||||
.onEach {
|
||||
if (it == null) return@onEach
|
||||
val mainSource = source.getMainSource()
|
||||
if (mainSource is MetadataSource<*, *>) {
|
||||
meta.value = it.raise(mainSource.metaClass)
|
||||
}
|
||||
}
|
||||
.launchIn(scope + Dispatchers.IO)
|
||||
|
||||
getMangaObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeLatestCache({ view, _ -> view.onNextMangaInfo(meta) })
|
||||
meta
|
||||
.onEachView { view, metadata ->
|
||||
view.onNextMangaInfo(metadata)
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
private fun getMangaObservable(): Observable<Manga> {
|
||||
return db.getManga(manga.url, manga.source).asRxObservable()
|
||||
}
|
||||
|
||||
private fun getMangaMetaObservable(): Observable<FlatMetadata?> {
|
||||
val mangaId = manga.id
|
||||
return if (mangaId != null) {
|
||||
db.getFlatMetadataForManga(mangaId).asRxObservable()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
} else Observable.just(null)
|
||||
private fun getMangaMetaObservable(): Flow<FlatMetadata?> {
|
||||
return db.getFlatMetadataForManga(manga.id!!).asRxObservable().asFlow()
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user