Commit 84f1e786 authored by topjohnwu's avatar topjohnwu

Consolidate base viewmodel implementation

parent 3490ba0a
......@@ -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
......
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
}
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()
}
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
}
\ No newline at end of file
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)
}
}
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
}
\ No newline at end of file
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)
}
}
\ No newline at end of file
......@@ -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
......
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
......
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()
}
}
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() }
......
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment