/* 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 . */ 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 LiveData.map(crossinline mapFunction: (X) -> Y): LiveData = Transformations.map(this) { input -> mapFunction(input) } inline fun LiveData.switchMap( crossinline switchMapFunction: (X) -> LiveData ): LiveData = Transformations.switchMap(this) { input -> switchMapFunction(input) } inline fun LiveData.filter(crossinline predicate: (X) -> Boolean): LiveData { val liveData = MediatorLiveData() 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 LiveData.observe(crossinline observer: (T) -> Unit) = this.observe(lifecycleOwner, Observer { observer(it) }) /** * Just hold a subscription, */ fun LiveData.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 combineLiveData(a: LiveData, b: LiveData, combiner: (A, B) -> R): LiveData { val liveData = MediatorLiveData() 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 combineOptionalLiveData(a: LiveData, b: LiveData, combiner: (A?, B?) -> R): LiveData { val liveData = MediatorLiveData() liveData.addSource(a) { liveData.value = combiner(a.value, b.value) } liveData.addSource(b) { liveData.value = combiner(a.value, b.value) } return liveData } fun Single.toLiveData() = LiveDataReactiveStreams.fromPublisher(this.toFlowable()) fun Observable.toLiveData( backpressureStrategy: BackpressureStrategy = BackpressureStrategy.LATEST ) = LiveDataReactiveStreams.fromPublisher(this.toFlowable(BackpressureStrategy.LATEST))