From 84f1e78660608bd232623efe5c8c210006dea466 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Mon, 13 Jan 2020 03:56:03 +0800 Subject: [PATCH] Consolidate base viewmodel implementation --- .../com/topjohnwu/magisk/base/BaseActivity.kt | 1 - .../com/topjohnwu/magisk/base/BaseFragment.kt | 1 - .../topjohnwu/magisk/base/BaseViewModel.kt | 201 ++++++++++++++++++ .../magisk/base/viewmodel/BaseViewModel.kt | 31 --- .../magisk/base/viewmodel/LoadingViewModel.kt | 78 ------- .../base/viewmodel/ObservableViewModel.kt | 46 ---- .../base/viewmodel/StatefulViewModel.kt | 15 -- .../magisk/base/viewmodel/TeanityViewModel.kt | 33 --- .../magisk/legacy/flash/FlashViewModel.kt | 2 +- .../legacy/surequest/SuRequestViewModel.kt | 2 +- .../com/topjohnwu/magisk/ui/MainViewModel.kt | 4 +- .../magisk/ui/compat/CompatActivity.kt | 3 +- .../magisk/ui/compat/CompatFragment.kt | 3 +- .../topjohnwu/magisk/ui/compat/CompatView.kt | 3 +- .../magisk/ui/compat/CompatViewModel.kt | 45 ---- .../magisk/ui/flash/FlashViewModel.kt | 4 +- .../topjohnwu/magisk/ui/hide/HideViewModel.kt | 4 +- .../topjohnwu/magisk/ui/home/HomeViewModel.kt | 4 +- .../magisk/ui/install/InstallViewModel.kt | 4 +- .../topjohnwu/magisk/ui/log/LogViewModel.kt | 4 +- .../magisk/ui/module/ModuleViewModel.kt | 3 +- .../magisk/ui/request/RequestViewModel.kt | 4 +- .../magisk/ui/safetynet/SafetynetViewModel.kt | 4 +- .../magisk/ui/settings/SettingsViewModel.kt | 4 +- .../magisk/ui/superuser/SuperuserViewModel.kt | 4 +- .../magisk/ui/theme/ThemeViewModel.kt | 4 +- 26 files changed, 233 insertions(+), 278 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/base/BaseViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/base/viewmodel/LoadingViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/base/viewmodel/ObservableViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/base/viewmodel/StatefulViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/base/viewmodel/TeanityViewModel.kt delete mode 100644 app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatViewModel.kt diff --git a/app/src/main/java/com/topjohnwu/magisk/base/BaseActivity.kt b/app/src/main/java/com/topjohnwu/magisk/base/BaseActivity.kt index 667c39b62..f308ef624 100644 --- a/app/src/main/java/com/topjohnwu/magisk/base/BaseActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/base/BaseActivity.kt @@ -16,7 +16,6 @@ import androidx.databinding.ViewDataBinding import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.R -import com.topjohnwu.magisk.base.viewmodel.BaseViewModel import com.topjohnwu.magisk.extensions.set import com.topjohnwu.magisk.model.events.EventHandler import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder diff --git a/app/src/main/java/com/topjohnwu/magisk/base/BaseFragment.kt b/app/src/main/java/com/topjohnwu/magisk/base/BaseFragment.kt index 8c0f43b59..cd275e8ff 100644 --- a/app/src/main/java/com/topjohnwu/magisk/base/BaseFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/base/BaseFragment.kt @@ -8,7 +8,6 @@ import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment import com.topjohnwu.magisk.BR -import com.topjohnwu.magisk.base.viewmodel.BaseViewModel import com.topjohnwu.magisk.model.events.EventHandler import com.topjohnwu.magisk.model.events.ViewEvent diff --git a/app/src/main/java/com/topjohnwu/magisk/base/BaseViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/BaseViewModel.kt new file mode 100644 index 000000000..729c40d41 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/base/BaseViewModel.kt @@ -0,0 +1,201 @@ +package com.topjohnwu.magisk.base + +import androidx.annotation.CallSuper +import androidx.core.graphics.Insets +import androidx.databinding.Bindable +import androidx.databinding.PropertyChangeRegistry +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.topjohnwu.magisk.BR +import com.topjohnwu.magisk.Info +import com.topjohnwu.magisk.extensions.doOnSubscribeUi +import com.topjohnwu.magisk.model.events.* +import com.topjohnwu.magisk.model.observer.Observer +import com.topjohnwu.magisk.utils.KObservableField +import io.reactivex.* +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.disposables.Disposable +import io.reactivex.subjects.PublishSubject +import org.koin.core.KoinComponent +import androidx.databinding.Observable as BindingObservable + +abstract class BaseViewModel( + initialState: State = State.LOADING +) : ViewModel(), BindingObservable, KoinComponent { + + enum class State { + LOADED, LOADING, LOADING_FAILED + } + + val loading @Bindable get() = state == State.LOADING + val loaded @Bindable get() = state == State.LOADED + val loadingFailed @Bindable get() = state == State.LOADING_FAILED + + val isConnected = Observer(Info.isConnected) { Info.isConnected.value } + val viewEvents: LiveData get() = _viewEvents + val insets = KObservableField(Insets.NONE) + + var state: State = initialState + set(value) { + field = value + notifyStateChanged() + } + + private val disposables = CompositeDisposable() + private val _viewEvents = MutableLiveData() + private var runningTask: Disposable? = null + private val refreshCallback = object : androidx.databinding.Observable.OnPropertyChangedCallback() { + override fun onPropertyChanged(sender: androidx.databinding.Observable?, propertyId: Int) { + requestRefresh() + } + } + + init { + isConnected.addOnPropertyChangedCallback(refreshCallback) + } + + /** This should probably never be called manually, it's called manually via delegate. */ + @Synchronized + fun requestRefresh() { + if (runningTask?.isDisposed?.not() == true) { + return + } + runningTask = refresh() + } + + protected open fun refresh(): Disposable? = null + + open fun notifyStateChanged() { + notifyPropertyChanged(BR.loading) + notifyPropertyChanged(BR.loaded) + notifyPropertyChanged(BR.loadingFailed) + } + + @CallSuper + override fun onCleared() { + isConnected.removeOnPropertyChangedCallback(refreshCallback) + disposables.clear() + super.onCleared() + } + + fun withView(action: BaseActivity<*, *>.() -> Unit) { + ViewActionEvent(action).publish() + } + + fun withPermissions(vararg permissions: String): Observable { + val subject = PublishSubject.create() + return subject.doOnSubscribeUi { PermissionEvent(permissions.toList(), subject).publish() } + } + + fun back() = BackPressEvent().publish() + + fun Event.publish() { + _viewEvents.postValue(this) + } + + fun Int.publish() { + _viewEvents.postValue(SimpleViewEvent(this)) + } + + fun Disposable.add() { + disposables.add(this) + } + + // The following is copied from androidx.databinding.BaseObservable + + @Transient + private var callbacks: PropertyChangeRegistry? = null + + @Synchronized + override fun addOnPropertyChangedCallback(callback: BindingObservable.OnPropertyChangedCallback) { + if (callbacks == null) { + callbacks = PropertyChangeRegistry() + } + callbacks?.add(callback) + } + + @Synchronized + override fun removeOnPropertyChangedCallback(callback: BindingObservable.OnPropertyChangedCallback) { + callbacks?.remove(callback) + } + + /** + * Notifies listeners that all properties of this instance have changed. + */ + @Synchronized + fun notifyChange() { + callbacks?.notifyCallbacks(this, 0, null) + } + + /** + * Notifies listeners that a specific property has changed. The getter for the property + * that changes should be marked with [androidx.databinding.Bindable] to generate a field in + * `BR` to be used as `fieldId`. + * + * @param fieldId The generated BR id for the Bindable field. + */ + fun notifyPropertyChanged(fieldId: Int) { + callbacks?.notifyCallbacks(this, fieldId, null) + } + + //region Rx + protected fun Observable.applyViewModel(viewModel: BaseViewModel, allowFinishing: Boolean = true) = + doOnSubscribe { viewModel.state = + State.LOADING + } + .doOnError { viewModel.state = + State.LOADING_FAILED + } + .doOnNext { if (allowFinishing) viewModel.state = + State.LOADED + } + + protected fun Single.applyViewModel(viewModel: BaseViewModel, allowFinishing: Boolean = true) = + doOnSubscribe { viewModel.state = + State.LOADING + } + .doOnError { viewModel.state = + State.LOADING_FAILED + } + .doOnSuccess { if (allowFinishing) viewModel.state = + State.LOADED + } + + protected fun Maybe.applyViewModel(viewModel: BaseViewModel, allowFinishing: Boolean = true) = + doOnSubscribe { viewModel.state = + State.LOADING + } + .doOnError { viewModel.state = + State.LOADING_FAILED + } + .doOnComplete { if (allowFinishing) viewModel.state = + State.LOADED + } + .doOnSuccess { if (allowFinishing) viewModel.state = + State.LOADED + } + + protected fun Flowable.applyViewModel(viewModel: BaseViewModel, allowFinishing: Boolean = true) = + doOnSubscribe { viewModel.state = + State.LOADING + } + .doOnError { viewModel.state = + State.LOADING_FAILED + } + .doOnNext { if (allowFinishing) viewModel.state = + State.LOADED + } + + protected fun Completable.applyViewModel(viewModel: BaseViewModel, allowFinishing: Boolean = true) = + doOnSubscribe { viewModel.state = + State.LOADING + } + .doOnError { viewModel.state = + State.LOADING_FAILED + } + .doOnComplete { if (allowFinishing) viewModel.state = + State.LOADED + } + //endregion +} diff --git a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt deleted file mode 100644 index 8b938c7eb..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/BaseViewModel.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.topjohnwu.magisk.base.viewmodel - -import com.topjohnwu.magisk.base.BaseActivity -import com.topjohnwu.magisk.extensions.doOnSubscribeUi -import com.topjohnwu.magisk.model.events.BackPressEvent -import com.topjohnwu.magisk.model.events.PermissionEvent -import com.topjohnwu.magisk.model.events.ViewActionEvent -import com.topjohnwu.magisk.model.observer.Observer -import io.reactivex.Observable -import io.reactivex.subjects.PublishSubject -import com.topjohnwu.magisk.Info.isConnected as gIsConnected - - -abstract class BaseViewModel( - initialState: State = State.LOADING -) : LoadingViewModel(initialState) { - - val isConnected = Observer(gIsConnected) { gIsConnected.value } - - fun withView(action: BaseActivity<*, *>.() -> Unit) { - ViewActionEvent(action).publish() - } - - fun withPermissions(vararg permissions: String): Observable { - val subject = PublishSubject.create() - return subject.doOnSubscribeUi { PermissionEvent(permissions.toList(), subject).publish() } - } - - fun back() = BackPressEvent().publish() - -} diff --git a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/LoadingViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/LoadingViewModel.kt deleted file mode 100644 index bd4ac195d..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/LoadingViewModel.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.topjohnwu.magisk.base.viewmodel - -import androidx.databinding.Bindable -import com.topjohnwu.magisk.BR -import io.reactivex.* - -abstract class LoadingViewModel(defaultState: State = State.LOADING) : - StatefulViewModel(defaultState) { - - val loading @Bindable get() = state == State.LOADING - val loaded @Bindable get() = state == State.LOADED - val loadingFailed @Bindable get() = state == State.LOADING_FAILED - - @Deprecated( - "Direct access is recommended since 0.2. This access method will be removed in 1.0", - ReplaceWith("state = State.LOADING", "com.topjohnwu.magisk.base.viewmodel.LoadingViewModel.State"), - DeprecationLevel.WARNING - ) - fun setLoading() { - state = State.LOADING - } - - @Deprecated( - "Direct access is recommended since 0.2. This access method will be removed in 1.0", - ReplaceWith("state = State.LOADED", "com.topjohnwu.magisk.base.viewmodel.LoadingViewModel.State"), - DeprecationLevel.WARNING - ) - fun setLoaded() { - state = State.LOADED - } - - @Deprecated( - "Direct access is recommended since 0.2. This access method will be removed in 1.0", - ReplaceWith("state = State.LOADING_FAILED", "com.topjohnwu.magisk.base.viewmodel.LoadingViewModel.State"), - DeprecationLevel.WARNING - ) - fun setLoadingFailed() { - state = State.LOADING_FAILED - } - - override fun notifyStateChanged() { - notifyPropertyChanged(BR.loading) - notifyPropertyChanged(BR.loaded) - notifyPropertyChanged(BR.loadingFailed) - } - - enum class State { - LOADED, LOADING, LOADING_FAILED - } - - //region Rx - protected fun Observable.applyViewModel(viewModel: LoadingViewModel, allowFinishing: Boolean = true) = - doOnSubscribe { viewModel.state = State.LOADING } - .doOnError { viewModel.state = State.LOADING_FAILED } - .doOnNext { if (allowFinishing) viewModel.state = State.LOADED } - - protected fun Single.applyViewModel(viewModel: LoadingViewModel, allowFinishing: Boolean = true) = - doOnSubscribe { viewModel.state = State.LOADING } - .doOnError { viewModel.state = State.LOADING_FAILED } - .doOnSuccess { if (allowFinishing) viewModel.state = State.LOADED } - - protected fun Maybe.applyViewModel(viewModel: LoadingViewModel, allowFinishing: Boolean = true) = - doOnSubscribe { viewModel.state = State.LOADING } - .doOnError { viewModel.state = State.LOADING_FAILED } - .doOnComplete { if (allowFinishing) viewModel.state = State.LOADED } - .doOnSuccess { if (allowFinishing) viewModel.state = State.LOADED } - - protected fun Flowable.applyViewModel(viewModel: LoadingViewModel, allowFinishing: Boolean = true) = - doOnSubscribe { viewModel.state = State.LOADING } - .doOnError { viewModel.state = State.LOADING_FAILED } - .doOnNext { if (allowFinishing) viewModel.state = State.LOADED } - - protected fun Completable.applyViewModel(viewModel: LoadingViewModel, allowFinishing: Boolean = true) = - doOnSubscribe { viewModel.state = State.LOADING } - .doOnError { viewModel.state = State.LOADING_FAILED } - .doOnComplete { if (allowFinishing) viewModel.state = State.LOADED } - //endregion -} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/ObservableViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/ObservableViewModel.kt deleted file mode 100644 index 8b6e53498..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/ObservableViewModel.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.topjohnwu.magisk.base.viewmodel - -import androidx.databinding.Observable -import androidx.databinding.PropertyChangeRegistry -import androidx.lifecycle.ViewModel - -/** - * Copy of [androidx.databinding.BaseObservable] which extends [ViewModel] - */ -abstract class ObservableViewModel : TeanityViewModel(), Observable { - - @Transient - private var callbacks: PropertyChangeRegistry? = null - - @Synchronized - override fun addOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) { - if (callbacks == null) { - callbacks = PropertyChangeRegistry() - } - callbacks?.add(callback) - } - - @Synchronized - override fun removeOnPropertyChangedCallback(callback: Observable.OnPropertyChangedCallback) { - callbacks?.remove(callback) - } - - /** - * Notifies listeners that all properties of this instance have changed. - */ - @Synchronized - fun notifyChange() { - callbacks?.notifyCallbacks(this, 0, null) - } - - /** - * Notifies listeners that a specific property has changed. The getter for the property - * that changes should be marked with [androidx.databinding.Bindable] to generate a field in - * `BR` to be used as `fieldId`. - * - * @param fieldId The generated BR id for the Bindable field. - */ - fun notifyPropertyChanged(fieldId: Int) { - callbacks?.notifyCallbacks(this, fieldId, null) - } -} diff --git a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/StatefulViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/StatefulViewModel.kt deleted file mode 100644 index e441c84db..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/StatefulViewModel.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.topjohnwu.magisk.base.viewmodel - -abstract class StatefulViewModel>( - val defaultState: State -) : ObservableViewModel() { - - var state: State = defaultState - set(value) { - field = value - notifyStateChanged() - } - - open fun notifyStateChanged() = Unit - -} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/TeanityViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/TeanityViewModel.kt deleted file mode 100644 index 17449a115..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/base/viewmodel/TeanityViewModel.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.topjohnwu.magisk.base.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import com.topjohnwu.magisk.model.events.SimpleViewEvent -import com.topjohnwu.magisk.model.events.ViewEvent -import io.reactivex.disposables.CompositeDisposable -import io.reactivex.disposables.Disposable - -abstract class TeanityViewModel : ViewModel() { - - private val disposables = CompositeDisposable() - private val _viewEvents = MutableLiveData() - val viewEvents: LiveData get() = _viewEvents - - override fun onCleared() { - super.onCleared() - disposables.clear() - } - - fun Event.publish() { - _viewEvents.postValue(this) - } - - fun Int.publish() { - _viewEvents.postValue(SimpleViewEvent(this)) - } - - fun Disposable.add() { - disposables.add(this) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/legacy/flash/FlashViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/legacy/flash/FlashViewModel.kt index ca68bfa55..b39654507 100644 --- a/app/src/main/java/com/topjohnwu/magisk/legacy/flash/FlashViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/legacy/flash/FlashViewModel.kt @@ -11,7 +11,7 @@ import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.R -import com.topjohnwu.magisk.base.viewmodel.BaseViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.extensions.* import com.topjohnwu.magisk.model.entity.recycler.ConsoleRvItem diff --git a/app/src/main/java/com/topjohnwu/magisk/legacy/surequest/SuRequestViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/legacy/surequest/SuRequestViewModel.kt index 363b0c471..7230a2983 100644 --- a/app/src/main/java/com/topjohnwu/magisk/legacy/surequest/SuRequestViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/legacy/surequest/SuRequestViewModel.kt @@ -10,7 +10,7 @@ import com.topjohnwu.magisk.BuildConfig import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.Const import com.topjohnwu.magisk.R -import com.topjohnwu.magisk.base.viewmodel.BaseViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.data.database.PolicyDao import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.extensions.now diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/MainViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/MainViewModel.kt index 63104cbd5..831449270 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/MainViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/MainViewModel.kt @@ -1,5 +1,5 @@ package com.topjohnwu.magisk.ui -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel -class MainViewModel : CompatViewModel() +class MainViewModel : BaseViewModel() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatActivity.kt b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatActivity.kt index 66229faa8..928f2661d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatActivity.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatActivity.kt @@ -11,6 +11,7 @@ import androidx.databinding.OnRebindCallback import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment import com.topjohnwu.magisk.base.BaseActivity +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.extensions.snackbar import com.topjohnwu.magisk.extensions.startAnimations import com.topjohnwu.magisk.model.events.SnackbarEvent @@ -21,7 +22,7 @@ import com.topjohnwu.magisk.ui.theme.Theme import kotlin.reflect.KClass -abstract class CompatActivity : +abstract class CompatActivity : BaseActivity(), CompatView, Navigator { override val themeRes = Theme.selected.themeRes diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatFragment.kt b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatFragment.kt index 14e60a9eb..decb4c34a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatFragment.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatFragment.kt @@ -7,10 +7,11 @@ import androidx.databinding.OnRebindCallback import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment import com.topjohnwu.magisk.base.BaseFragment +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.extensions.startAnimations import com.topjohnwu.magisk.model.events.ViewEvent -abstract class CompatFragment +abstract class CompatFragment : BaseFragment(), CompatView { override val viewRoot: View get() = binding.root diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatView.kt b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatView.kt index 919851df6..84e1724c2 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatView.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatView.kt @@ -2,8 +2,9 @@ package com.topjohnwu.magisk.ui.compat import android.view.View import androidx.core.graphics.Insets +import com.topjohnwu.magisk.base.BaseViewModel -internal interface CompatView { +internal interface CompatView { val viewRoot: View val viewModel: ViewModel diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatViewModel.kt deleted file mode 100644 index c22ae870f..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/ui/compat/CompatViewModel.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.topjohnwu.magisk.ui.compat - -import androidx.annotation.CallSuper -import androidx.core.graphics.Insets -import androidx.databinding.Observable -import com.topjohnwu.magisk.base.viewmodel.BaseViewModel -import com.topjohnwu.magisk.utils.KObservableField -import io.reactivex.disposables.Disposable -import org.koin.core.KoinComponent - -abstract class CompatViewModel( - initialState: State = State.LOADING -) : BaseViewModel(initialState), KoinComponent { - - val insets = KObservableField(Insets.NONE) - - private var runningTask: Disposable? = null - private val refreshCallback = object : Observable.OnPropertyChangedCallback() { - override fun onPropertyChanged(sender: Observable?, propertyId: Int) { - requestRefresh() - } - } - - init { - isConnected.addOnPropertyChangedCallback(refreshCallback) - } - - /** This should probably never be called manually, it's called manually via delegate. */ - @Synchronized - fun requestRefresh() { - if (runningTask?.isDisposed?.not() == true) { - return - } - runningTask = refresh() - } - - protected open fun refresh(): Disposable? = null - - @CallSuper - override fun onCleared() { - isConnected.removeOnPropertyChangedCallback(refreshCallback) - super.onCleared() - } - -} diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt index a70f2f3df..bd4938fb3 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/flash/FlashViewModel.kt @@ -1,5 +1,5 @@ package com.topjohnwu.magisk.ui.flash -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel -class FlashViewModel : CompatViewModel() +class FlashViewModel : BaseViewModel() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt index 966821f8f..252d95016 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/hide/HideViewModel.kt @@ -12,7 +12,7 @@ import com.topjohnwu.magisk.model.entity.ProcessHideApp import com.topjohnwu.magisk.model.entity.StatefulProcess import com.topjohnwu.magisk.model.entity.recycler.HideItem import com.topjohnwu.magisk.model.entity.recycler.HideProcessItem -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.ui.compat.Queryable import com.topjohnwu.magisk.ui.compat.filterableListOf import com.topjohnwu.magisk.ui.compat.itemBindingOf @@ -21,7 +21,7 @@ import com.topjohnwu.magisk.utils.currentLocale class HideViewModel( private val magiskRepo: MagiskRepository -) : CompatViewModel(), Queryable by Queryable.impl(1000) { +) : BaseViewModel(), Queryable by Queryable.impl(1000) { override val queryRunnable = Runnable { query() } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt index 52ccc1a71..f998ff320 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/home/HomeViewModel.kt @@ -22,7 +22,7 @@ import com.topjohnwu.magisk.model.events.dialog.ManagerInstallDialog import com.topjohnwu.magisk.model.events.dialog.UninstallDialog import com.topjohnwu.magisk.model.navigation.Navigation import com.topjohnwu.magisk.model.observer.Observer -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.ui.compat.itemBindingOf import com.topjohnwu.magisk.utils.KObservableField import com.topjohnwu.superuser.Shell @@ -35,7 +35,7 @@ enum class MagiskState { class HomeViewModel( private val repoMagisk: MagiskRepository -) : CompatViewModel() { +) : BaseViewModel() { val isNoticeVisible = KObservableField(Config.safetyNotice) diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/install/InstallViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/install/InstallViewModel.kt index 58a2da93d..9e6dc3b5d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/install/InstallViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/install/InstallViewModel.kt @@ -8,14 +8,14 @@ import com.topjohnwu.magisk.model.download.RemoteFileService import com.topjohnwu.magisk.model.entity.internal.Configuration import com.topjohnwu.magisk.model.entity.internal.DownloadSubject import com.topjohnwu.magisk.model.events.RequestFileEvent -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.utils.KObservableField import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.ShellUtils import org.koin.core.get import kotlin.math.roundToInt -class InstallViewModel : CompatViewModel(State.LOADED) { +class InstallViewModel : BaseViewModel(State.LOADED) { val isRooted = Shell.rootAccess() val isAB = isABDevice() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt index c88ebb873..520094e00 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/log/LogViewModel.kt @@ -12,7 +12,7 @@ import com.topjohnwu.magisk.model.entity.recycler.ConsoleItem import com.topjohnwu.magisk.model.entity.recycler.LogItem import com.topjohnwu.magisk.model.entity.recycler.TextItem import com.topjohnwu.magisk.model.events.SnackbarEvent -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.ui.compat.diffListOf import com.topjohnwu.magisk.ui.compat.itemBindingOf import com.topjohnwu.superuser.Shell @@ -26,7 +26,7 @@ import java.util.* class LogViewModel( private val repo: LogRepository -) : CompatViewModel() { +) : BaseViewModel() { // --- empty view diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt index 40421f29d..200473367 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/module/ModuleViewModel.kt @@ -6,6 +6,7 @@ import androidx.databinding.ObservableArrayList import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.Config import com.topjohnwu.magisk.R +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.data.database.RepoByNameDao import com.topjohnwu.magisk.data.database.RepoByUpdatedDao import com.topjohnwu.magisk.databinding.ComparableRvItem @@ -37,7 +38,7 @@ class ModuleViewModel( private val repoName: RepoByNameDao, private val repoUpdated: RepoByUpdatedDao, private val repoUpdater: RepoUpdater -) : CompatViewModel(), Queryable by Queryable.impl(1000) { +) : BaseViewModel(), Queryable by Queryable.impl(1000) { override val queryRunnable = Runnable { query() } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/request/RequestViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/request/RequestViewModel.kt index 52ab65141..355a6dedf 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/request/RequestViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/request/RequestViewModel.kt @@ -1,5 +1,5 @@ package com.topjohnwu.magisk.ui.request -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel -class RequestViewModel : CompatViewModel() +class RequestViewModel : BaseViewModel() diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt index d8a6627b0..25eb3d63a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/safetynet/SafetynetViewModel.kt @@ -6,7 +6,7 @@ import com.topjohnwu.magisk.R import com.topjohnwu.magisk.extensions.subscribeK import com.topjohnwu.magisk.model.events.SafetyNetResult import com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.* import com.topjohnwu.magisk.utils.KObservableField import com.topjohnwu.magisk.utils.RxBus @@ -18,7 +18,7 @@ enum class SafetyNetState { class SafetynetViewModel( rxBus: RxBus -) : CompatViewModel() { +) : BaseViewModel() { private var currentState = IDLE set(value) { diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt index 47cfadd55..9f5a90db8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt @@ -15,7 +15,7 @@ import com.topjohnwu.magisk.model.events.PermissionEvent import com.topjohnwu.magisk.model.events.RecreateEvent import com.topjohnwu.magisk.model.events.dialog.BiometricDialog import com.topjohnwu.magisk.model.navigation.Navigation -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.ui.compat.adapterOf import com.topjohnwu.magisk.ui.compat.diffListOf import com.topjohnwu.magisk.ui.compat.itemBindingOf @@ -28,7 +28,7 @@ import org.koin.core.get class SettingsViewModel( private val repositoryDao: RepoDao -) : CompatViewModel(), SettingsItem.Callback { +) : BaseViewModel(), SettingsItem.Callback { val adapter = adapterOf() val itemBinding = itemBindingOf { it.bindExtra(BR.callback, this) } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt index 9c3e77ae4..f0b58c24a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/superuser/SuperuserViewModel.kt @@ -19,7 +19,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent import com.topjohnwu.magisk.model.events.dialog.BiometricDialog import com.topjohnwu.magisk.model.events.dialog.SuperuserRevokeDialog import com.topjohnwu.magisk.model.navigation.Navigation -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel import com.topjohnwu.magisk.ui.compat.adapterOf import com.topjohnwu.magisk.ui.compat.diffListOf import com.topjohnwu.magisk.ui.compat.itemBindingOf @@ -32,7 +32,7 @@ class SuperuserViewModel( private val db: PolicyDao, private val packageManager: PackageManager, private val resources: Resources -) : CompatViewModel(), TappableHeadlineItem.Listener { +) : BaseViewModel(), TappableHeadlineItem.Listener { private val itemNoData = TextItem(R.string.superuser_policy_none) diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/theme/ThemeViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/theme/ThemeViewModel.kt index 132b8b7f2..3cb572173 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/theme/ThemeViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/theme/ThemeViewModel.kt @@ -3,9 +3,9 @@ package com.topjohnwu.magisk.ui.theme import com.topjohnwu.magisk.model.entity.recycler.TappableHeadlineItem import com.topjohnwu.magisk.model.events.RecreateEvent import com.topjohnwu.magisk.model.events.dialog.DarkThemeDialog -import com.topjohnwu.magisk.ui.compat.CompatViewModel +import com.topjohnwu.magisk.base.BaseViewModel -class ThemeViewModel : CompatViewModel(), TappableHeadlineItem.Listener { +class ThemeViewModel : BaseViewModel(), TappableHeadlineItem.Listener { val themeHeadline = TappableHeadlineItem.ThemeMode