Consolidate base viewmodel implementation
This commit is contained in:
parent
3490ba0a56
commit
84f1e78660
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
201
app/src/main/java/com/topjohnwu/magisk/base/BaseViewModel.kt
Normal file
201
app/src/main/java/com/topjohnwu/magisk/base/BaseViewModel.kt
Normal file
@ -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<ViewEvent> get() = _viewEvents
|
||||
val insets = KObservableField(Insets.NONE)
|
||||
|
||||
var state: State = initialState
|
||||
set(value) {
|
||||
field = value
|
||||
notifyStateChanged()
|
||||
}
|
||||
|
||||
private val disposables = CompositeDisposable()
|
||||
private val _viewEvents = MutableLiveData<ViewEvent>()
|
||||
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<Boolean> {
|
||||
val subject = PublishSubject.create<Boolean>()
|
||||
return subject.doOnSubscribeUi { PermissionEvent(permissions.toList(), subject).publish() }
|
||||
}
|
||||
|
||||
fun back() = BackPressEvent().publish()
|
||||
|
||||
fun <Event : ViewEvent> 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 <T> Observable<T>.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 <T> Single<T>.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 <T> Maybe<T>.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 <T> Flowable<T>.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
|
||||
}
|
@ -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<Boolean> {
|
||||
val subject = PublishSubject.create<Boolean>()
|
||||
return subject.doOnSubscribeUi { PermissionEvent(permissions.toList(), subject).publish() }
|
||||
}
|
||||
|
||||
fun back() = BackPressEvent().publish()
|
||||
|
||||
}
|
@ -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<LoadingViewModel.State>(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 <T> Observable<T>.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 <T> Single<T>.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 <T> Maybe<T>.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 <T> Flowable<T>.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
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package com.topjohnwu.magisk.base.viewmodel
|
||||
|
||||
abstract class StatefulViewModel<State : Enum<*>>(
|
||||
val defaultState: State
|
||||
) : ObservableViewModel() {
|
||||
|
||||
var state: State = defaultState
|
||||
set(value) {
|
||||
field = value
|
||||
notifyStateChanged()
|
||||
}
|
||||
|
||||
open fun notifyStateChanged() = Unit
|
||||
|
||||
}
|
@ -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<ViewEvent>()
|
||||
val viewEvents: LiveData<ViewEvent> get() = _viewEvents
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
disposables.clear()
|
||||
}
|
||||
|
||||
fun <Event : ViewEvent> Event.publish() {
|
||||
_viewEvents.postValue(this)
|
||||
}
|
||||
|
||||
fun Int.publish() {
|
||||
_viewEvents.postValue(SimpleViewEvent(this))
|
||||
}
|
||||
|
||||
fun Disposable.add() {
|
||||
disposables.add(this)
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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<ViewModel : CompatViewModel, Binding : ViewDataBinding> :
|
||||
abstract class CompatActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
||||
BaseActivity<ViewModel, Binding>(), CompatView<ViewModel>, Navigator {
|
||||
|
||||
override val themeRes = Theme.selected.themeRes
|
||||
|
@ -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<ViewModel : CompatViewModel, Binding : ViewDataBinding>
|
||||
abstract class CompatFragment<ViewModel : BaseViewModel, Binding : ViewDataBinding>
|
||||
: BaseFragment<ViewModel, Binding>(), CompatView<ViewModel> {
|
||||
|
||||
override val viewRoot: View get() = binding.root
|
||||
|
@ -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<ViewModel : CompatViewModel> {
|
||||
internal interface CompatView<ViewModel : BaseViewModel> {
|
||||
|
||||
val viewRoot: View
|
||||
val viewModel: ViewModel
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
}
|
@ -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()
|
||||
|
@ -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() }
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() }
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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) {
|
||||
|
@ -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<SettingsItem>()
|
||||
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user