/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.fenix.mvi import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel import io.reactivex.Observable import io.reactivex.Observer import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers abstract class UIComponent( protected val owner: Fragment, protected val actionEmitter: Observer, protected val changesObservable: Observable ) { abstract var initialState: S open val uiView: UIView by lazy { initView() } abstract fun initView(): UIView open fun getContainerId() = uiView.containerId abstract fun render(): Observable } open class UIComponentViewModel( private val initialState: S, val changesObservable: Observable, reducer: Reducer ) : ViewModel() { private val statesObservable: Observable = internalRender(reducer) private var statesDisposable: Disposable? = null /** * Render the ViewState to the View through the Reducer */ fun render(uiView: UIView): Observable { statesDisposable = statesObservable .subscribe(uiView.updateView()) return statesObservable } @Suppress("MemberVisibilityCanBePrivate") protected fun internalRender(reducer: Reducer): Observable = changesObservable .scan(initialState, reducer) .distinctUntilChanged() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .replay(1) .autoConnect(0) override fun onCleared() { super.onCleared() statesDisposable?.dispose() } }