mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 22:07:38 +00:00
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.BR
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.Config
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
import com.topjohnwu.magisk.base.viewmodel.BaseViewModel
|
|
||||||
import com.topjohnwu.magisk.extensions.set
|
import com.topjohnwu.magisk.extensions.set
|
||||||
import com.topjohnwu.magisk.model.events.EventHandler
|
import com.topjohnwu.magisk.model.events.EventHandler
|
||||||
import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
|
import com.topjohnwu.magisk.model.permissions.PermissionRequestBuilder
|
||||||
|
@ -8,7 +8,6 @@ import androidx.databinding.DataBindingUtil
|
|||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.BR
|
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.EventHandler
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
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.Config
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.Const
|
||||||
import com.topjohnwu.magisk.R
|
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.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.extensions.*
|
import com.topjohnwu.magisk.extensions.*
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.ConsoleRvItem
|
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.Config
|
||||||
import com.topjohnwu.magisk.Const
|
import com.topjohnwu.magisk.Const
|
||||||
import com.topjohnwu.magisk.R
|
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.data.database.PolicyDao
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
import com.topjohnwu.magisk.extensions.now
|
import com.topjohnwu.magisk.extensions.now
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.ui
|
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.databinding.ViewDataBinding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseActivity
|
import com.topjohnwu.magisk.base.BaseActivity
|
||||||
|
import com.topjohnwu.magisk.base.BaseViewModel
|
||||||
import com.topjohnwu.magisk.extensions.snackbar
|
import com.topjohnwu.magisk.extensions.snackbar
|
||||||
import com.topjohnwu.magisk.extensions.startAnimations
|
import com.topjohnwu.magisk.extensions.startAnimations
|
||||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||||
@ -21,7 +22,7 @@ import com.topjohnwu.magisk.ui.theme.Theme
|
|||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
|
||||||
abstract class CompatActivity<ViewModel : CompatViewModel, Binding : ViewDataBinding> :
|
abstract class CompatActivity<ViewModel : BaseViewModel, Binding : ViewDataBinding> :
|
||||||
BaseActivity<ViewModel, Binding>(), CompatView<ViewModel>, Navigator {
|
BaseActivity<ViewModel, Binding>(), CompatView<ViewModel>, Navigator {
|
||||||
|
|
||||||
override val themeRes = Theme.selected.themeRes
|
override val themeRes = Theme.selected.themeRes
|
||||||
|
@ -7,10 +7,11 @@ import androidx.databinding.OnRebindCallback
|
|||||||
import androidx.databinding.ViewDataBinding
|
import androidx.databinding.ViewDataBinding
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import com.topjohnwu.magisk.base.BaseFragment
|
import com.topjohnwu.magisk.base.BaseFragment
|
||||||
|
import com.topjohnwu.magisk.base.BaseViewModel
|
||||||
import com.topjohnwu.magisk.extensions.startAnimations
|
import com.topjohnwu.magisk.extensions.startAnimations
|
||||||
import com.topjohnwu.magisk.model.events.ViewEvent
|
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> {
|
: BaseFragment<ViewModel, Binding>(), CompatView<ViewModel> {
|
||||||
|
|
||||||
override val viewRoot: View get() = binding.root
|
override val viewRoot: View get() = binding.root
|
||||||
|
@ -2,8 +2,9 @@ package com.topjohnwu.magisk.ui.compat
|
|||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.graphics.Insets
|
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 viewRoot: View
|
||||||
val viewModel: ViewModel
|
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
|
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.StatefulProcess
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.HideItem
|
import com.topjohnwu.magisk.model.entity.recycler.HideItem
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.HideProcessItem
|
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.Queryable
|
||||||
import com.topjohnwu.magisk.ui.compat.filterableListOf
|
import com.topjohnwu.magisk.ui.compat.filterableListOf
|
||||||
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
||||||
@ -21,7 +21,7 @@ import com.topjohnwu.magisk.utils.currentLocale
|
|||||||
|
|
||||||
class HideViewModel(
|
class HideViewModel(
|
||||||
private val magiskRepo: MagiskRepository
|
private val magiskRepo: MagiskRepository
|
||||||
) : CompatViewModel(), Queryable by Queryable.impl(1000) {
|
) : BaseViewModel(), Queryable by Queryable.impl(1000) {
|
||||||
|
|
||||||
override val queryRunnable = Runnable { query() }
|
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.events.dialog.UninstallDialog
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
import com.topjohnwu.magisk.model.navigation.Navigation
|
||||||
import com.topjohnwu.magisk.model.observer.Observer
|
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.ui.compat.itemBindingOf
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -35,7 +35,7 @@ enum class MagiskState {
|
|||||||
|
|
||||||
class HomeViewModel(
|
class HomeViewModel(
|
||||||
private val repoMagisk: MagiskRepository
|
private val repoMagisk: MagiskRepository
|
||||||
) : CompatViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
val isNoticeVisible = KObservableField(Config.safetyNotice)
|
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.Configuration
|
||||||
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
import com.topjohnwu.magisk.model.entity.internal.DownloadSubject
|
||||||
import com.topjohnwu.magisk.model.events.RequestFileEvent
|
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.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import com.topjohnwu.superuser.ShellUtils
|
import com.topjohnwu.superuser.ShellUtils
|
||||||
import org.koin.core.get
|
import org.koin.core.get
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
class InstallViewModel : CompatViewModel(State.LOADED) {
|
class InstallViewModel : BaseViewModel(State.LOADED) {
|
||||||
|
|
||||||
val isRooted = Shell.rootAccess()
|
val isRooted = Shell.rootAccess()
|
||||||
val isAB = isABDevice()
|
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.LogItem
|
||||||
import com.topjohnwu.magisk.model.entity.recycler.TextItem
|
import com.topjohnwu.magisk.model.entity.recycler.TextItem
|
||||||
import com.topjohnwu.magisk.model.events.SnackbarEvent
|
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.diffListOf
|
||||||
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
||||||
import com.topjohnwu.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
@ -26,7 +26,7 @@ import java.util.*
|
|||||||
|
|
||||||
class LogViewModel(
|
class LogViewModel(
|
||||||
private val repo: LogRepository
|
private val repo: LogRepository
|
||||||
) : CompatViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
// --- empty view
|
// --- empty view
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import androidx.databinding.ObservableArrayList
|
|||||||
import com.topjohnwu.magisk.BR
|
import com.topjohnwu.magisk.BR
|
||||||
import com.topjohnwu.magisk.Config
|
import com.topjohnwu.magisk.Config
|
||||||
import com.topjohnwu.magisk.R
|
import com.topjohnwu.magisk.R
|
||||||
|
import com.topjohnwu.magisk.base.BaseViewModel
|
||||||
import com.topjohnwu.magisk.data.database.RepoByNameDao
|
import com.topjohnwu.magisk.data.database.RepoByNameDao
|
||||||
import com.topjohnwu.magisk.data.database.RepoByUpdatedDao
|
import com.topjohnwu.magisk.data.database.RepoByUpdatedDao
|
||||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||||
@ -37,7 +38,7 @@ class ModuleViewModel(
|
|||||||
private val repoName: RepoByNameDao,
|
private val repoName: RepoByNameDao,
|
||||||
private val repoUpdated: RepoByUpdatedDao,
|
private val repoUpdated: RepoByUpdatedDao,
|
||||||
private val repoUpdater: RepoUpdater
|
private val repoUpdater: RepoUpdater
|
||||||
) : CompatViewModel(), Queryable by Queryable.impl(1000) {
|
) : BaseViewModel(), Queryable by Queryable.impl(1000) {
|
||||||
|
|
||||||
override val queryRunnable = Runnable { query() }
|
override val queryRunnable = Runnable { query() }
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package com.topjohnwu.magisk.ui.request
|
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.extensions.subscribeK
|
||||||
import com.topjohnwu.magisk.model.events.SafetyNetResult
|
import com.topjohnwu.magisk.model.events.SafetyNetResult
|
||||||
import com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent
|
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.ui.safetynet.SafetyNetState.*
|
||||||
import com.topjohnwu.magisk.utils.KObservableField
|
import com.topjohnwu.magisk.utils.KObservableField
|
||||||
import com.topjohnwu.magisk.utils.RxBus
|
import com.topjohnwu.magisk.utils.RxBus
|
||||||
@ -18,7 +18,7 @@ enum class SafetyNetState {
|
|||||||
|
|
||||||
class SafetynetViewModel(
|
class SafetynetViewModel(
|
||||||
rxBus: RxBus
|
rxBus: RxBus
|
||||||
) : CompatViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
private var currentState = IDLE
|
private var currentState = IDLE
|
||||||
set(value) {
|
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.RecreateEvent
|
||||||
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
|
import com.topjohnwu.magisk.model.events.dialog.BiometricDialog
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
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.adapterOf
|
||||||
import com.topjohnwu.magisk.ui.compat.diffListOf
|
import com.topjohnwu.magisk.ui.compat.diffListOf
|
||||||
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
||||||
@ -28,7 +28,7 @@ import org.koin.core.get
|
|||||||
|
|
||||||
class SettingsViewModel(
|
class SettingsViewModel(
|
||||||
private val repositoryDao: RepoDao
|
private val repositoryDao: RepoDao
|
||||||
) : CompatViewModel(), SettingsItem.Callback {
|
) : BaseViewModel(), SettingsItem.Callback {
|
||||||
|
|
||||||
val adapter = adapterOf<SettingsItem>()
|
val adapter = adapterOf<SettingsItem>()
|
||||||
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
|
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.BiometricDialog
|
||||||
import com.topjohnwu.magisk.model.events.dialog.SuperuserRevokeDialog
|
import com.topjohnwu.magisk.model.events.dialog.SuperuserRevokeDialog
|
||||||
import com.topjohnwu.magisk.model.navigation.Navigation
|
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.adapterOf
|
||||||
import com.topjohnwu.magisk.ui.compat.diffListOf
|
import com.topjohnwu.magisk.ui.compat.diffListOf
|
||||||
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
import com.topjohnwu.magisk.ui.compat.itemBindingOf
|
||||||
@ -32,7 +32,7 @@ class SuperuserViewModel(
|
|||||||
private val db: PolicyDao,
|
private val db: PolicyDao,
|
||||||
private val packageManager: PackageManager,
|
private val packageManager: PackageManager,
|
||||||
private val resources: Resources
|
private val resources: Resources
|
||||||
) : CompatViewModel(), TappableHeadlineItem.Listener {
|
) : BaseViewModel(), TappableHeadlineItem.Listener {
|
||||||
|
|
||||||
private val itemNoData = TextItem(R.string.superuser_policy_none)
|
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.entity.recycler.TappableHeadlineItem
|
||||||
import com.topjohnwu.magisk.model.events.RecreateEvent
|
import com.topjohnwu.magisk.model.events.RecreateEvent
|
||||||
import com.topjohnwu.magisk.model.events.dialog.DarkThemeDialog
|
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
|
val themeHeadline = TappableHeadlineItem.ThemeMode
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user