chinwag-android/app/src/main/java/com/keylesspalace/tusky/util/LiveDataUtil.kt
Konrad Pozniak 16ffcca748
add ktlint plugin to project and apply default code style (#2209)
* add ktlint plugin to project and apply default code style

* some manual adjustments, fix wildcard imports

* update CONTRIBUTING.md

* fix formatting
2021-06-28 21:13:24 +02:00

98 lines
3.8 KiB
Kotlin

/* Copyright 2019 Tusky Contributors
*
* This file is a part of Tusky.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see <http://www.gnu.org/licenses>. */
package com.keylesspalace.tusky.util
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.LiveDataReactiveStreams
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.Transformations
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
inline fun <X, Y> LiveData<X>.map(crossinline mapFunction: (X) -> Y): LiveData<Y> =
Transformations.map(this) { input -> mapFunction(input) }
inline fun <X, Y> LiveData<X>.switchMap(
crossinline switchMapFunction: (X) -> LiveData<Y>
): LiveData<Y> = Transformations.switchMap(this) { input -> switchMapFunction(input) }
inline fun <X> LiveData<X>.filter(crossinline predicate: (X) -> Boolean): LiveData<X> {
val liveData = MediatorLiveData<X>()
liveData.addSource(this) { value ->
if (predicate(value)) {
liveData.value = value
}
}
return liveData
}
fun LifecycleOwner.withLifecycleContext(body: LifecycleContext.() -> Unit) =
LifecycleContext(this).apply(body)
class LifecycleContext(val lifecycleOwner: LifecycleOwner) {
inline fun <T> LiveData<T>.observe(crossinline observer: (T) -> Unit) =
this.observe(lifecycleOwner, Observer { observer(it) })
/**
* Just hold a subscription,
*/
fun <T> LiveData<T>.subscribe() =
this.observe(lifecycleOwner, Observer { })
}
/**
* Invokes @param [combiner] when value of both @param [a] and @param [b] are not null. Returns
* [LiveData] with value set to the result of calling [combiner] with value of both.
* Important! You still need to observe to the returned [LiveData] for [combiner] to be invoked.
*/
fun <A, B, R> combineLiveData(a: LiveData<A>, b: LiveData<B>, combiner: (A, B) -> R): LiveData<R> {
val liveData = MediatorLiveData<R>()
liveData.addSource(a) {
if (a.value != null && b.value != null) {
liveData.value = combiner(a.value!!, b.value!!)
}
}
liveData.addSource(b) {
if (a.value != null && b.value != null) {
liveData.value = combiner(a.value!!, b.value!!)
}
}
return liveData
}
/**
* Returns [LiveData] with value set to the result of calling [combiner] with value of [a] and [b]
* after either changes. Doesn't check if either has value.
* Important! You still need to observe to the returned [LiveData] for [combiner] to be invoked.
*/
fun <A, B, R> combineOptionalLiveData(a: LiveData<A>, b: LiveData<B>, combiner: (A?, B?) -> R): LiveData<R> {
val liveData = MediatorLiveData<R>()
liveData.addSource(a) {
liveData.value = combiner(a.value, b.value)
}
liveData.addSource(b) {
liveData.value = combiner(a.value, b.value)
}
return liveData
}
fun <T> Single<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this.toFlowable())
fun <T> Observable<T>.toLiveData(
backpressureStrategy: BackpressureStrategy = BackpressureStrategy.LATEST
) = LiveDataReactiveStreams.fromPublisher(this.toFlowable(BackpressureStrategy.LATEST))