Decouple state from BaseViewModel

This commit is contained in:
topjohnwu
2022-06-10 02:13:25 -07:00
parent aabc36f86b
commit 46d4708386
13 changed files with 57 additions and 113 deletions
@@ -2,14 +2,15 @@ package com.topjohnwu.magisk.ui.deny
import android.annotation.SuppressLint
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
import androidx.databinding.Bindable
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.filterableListOf
import com.topjohnwu.magisk.databinding.set
import com.topjohnwu.magisk.ktx.concurrentMap
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.asFlow
@@ -43,13 +44,13 @@ class DenyListViewModel : BaseViewModel() {
it.put(BR.viewModel, this)
}
@get:Bindable
var loading = true
private set(value) = set(value, field, { field = it }, BR.loading)
@SuppressLint("InlinedApi")
override fun refresh() = viewModelScope.launch {
if (!Utils.showSuperUser()) {
state = State.LOADING_FAILED
return@launch
}
state = State.LOADING
loading = true
val (apps, diff) = withContext(Dispatchers.Default) {
val pm = AppContext.packageManager
val denyList = Shell.cmd("magisk --denylist ls").exec().out
@@ -84,6 +85,6 @@ class DenyListViewModel : BaseViewModel() {
(it.isChecked || (filterSystem() && filterOS())) && filterQuery()
}
state = State.LOADED
loading = false
}
}
@@ -35,7 +35,7 @@ class FlashFragment : BaseFragment<FragmentFlashMd2Binding>() {
setHasOptionsMenu(true)
activity?.setTitle(R.string.flash_screen_title)
viewModel.flashState.observe(this) {
viewModel.state.observe(this) {
activity?.supportActionBar?.setSubtitle(
when (it) {
FlashViewModel.State.FLASHING -> R.string.flashing
@@ -32,9 +32,9 @@ class FlashViewModel : BaseViewModel() {
FLASHING, SUCCESS, FAILED
}
private val _flashState = MutableLiveData(State.FLASHING)
val flashState: LiveData<State> get() = _flashState
val flashing = Transformations.map(flashState) { it == State.FLASHING }
private val _state = MutableLiveData(State.FLASHING)
val state: LiveData<State> get() = _state
val flashing = Transformations.map(state) { it == State.FLASHING }
@get:Bindable
var showReboot = Info.isRooted
@@ -89,7 +89,7 @@ class FlashViewModel : BaseViewModel() {
}
private fun onResult(success: Boolean) {
_flashState.value = if (success) State.SUCCESS else State.FAILED
_state.value = if (success) State.SUCCESS else State.FAILED
}
fun onMenuItemClicked(item: MenuItem): Boolean {
@@ -26,14 +26,14 @@ import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch
import kotlin.math.roundToInt
enum class MagiskState {
NOT_INSTALLED, UP_TO_DATE, OBSOLETE, LOADING
}
class HomeViewModel(
private val svc: NetworkService
) : BaseViewModel() {
enum class State {
LOADING, INVALID, OUTDATED, UP_TO_DATE
}
val magiskTitleBarrierIds =
intArrayOf(R.id.home_magisk_icon, R.id.home_magisk_title, R.id.home_magisk_button)
val appTitleBarrierIds =
@@ -43,16 +43,16 @@ class HomeViewModel(
var isNoticeVisible = Config.safetyNotice
set(value) = set(value, field, { field = it }, BR.noticeVisible)
val stateMagisk
val magiskState
get() = when {
!Info.env.isActive -> MagiskState.NOT_INSTALLED
Info.env.versionCode < BuildConfig.VERSION_CODE -> MagiskState.OBSOLETE
else -> MagiskState.UP_TO_DATE
!Info.env.isActive -> State.INVALID
Info.env.versionCode < BuildConfig.VERSION_CODE -> State.OUTDATED
else -> State.UP_TO_DATE
}
@get:Bindable
var stateManager = MagiskState.LOADING
set(value) = set(value, field, { field = it }, BR.stateManager)
var appState = State.LOADING
set(value) = set(value, field, { field = it }, BR.appState)
val magiskInstalledVersion
get() = Info.env.run {
@@ -84,13 +84,11 @@ class HomeViewModel(
}
override fun refresh() = viewModelScope.launch {
state = State.LOADING
appState = State.LOADING
Info.getRemote(svc)?.apply {
state = State.LOADED
stateManager = when {
BuildConfig.VERSION_CODE < magisk.versionCode -> MagiskState.OBSOLETE
else -> MagiskState.UP_TO_DATE
appState = when {
BuildConfig.VERSION_CODE < magisk.versionCode -> State.OUTDATED
else -> State.UP_TO_DATE
}
val isDebug = Config.updateChannel == Config.Value.DEBUG_CHANNEL
@@ -98,7 +96,6 @@ class HomeViewModel(
("${magisk.version} (${magisk.versionCode}) (${stub.versionCode})" +
if (isDebug) " (D)" else "").asText()
} ?: run {
state = State.LOADING_FAILED
managerRemoteVersion = R.string.not_available.asText()
}
ensureEnv()
@@ -119,14 +116,14 @@ class HomeViewModel(
fun onDeletePressed() = UninstallDialog().publish()
fun onManagerPressed() = when (state) {
State.LOADED -> withExternalRW {
fun onManagerPressed() = when (magiskState) {
State.LOADING -> SnackbarEvent(R.string.loading).publish()
State.INVALID -> SnackbarEvent(R.string.no_connection).publish()
else -> withExternalRW {
withInstallPermission {
ManagerInstallDialog().publish()
}
}
State.LOADING -> SnackbarEvent(R.string.loading).publish()
else -> SnackbarEvent(R.string.no_connection).publish()
}
fun onMagiskPressed() = withExternalRW {
@@ -139,7 +136,7 @@ class HomeViewModel(
}
private suspend fun ensureEnv() {
if (MagiskState.NOT_INSTALLED == stateMagisk || checkedEnv) return
if (magiskState == State.INVALID || checkedEnv) return
val cmd = "env_check ${Info.env.versionString} ${Info.env.versionCode}"
if (!Shell.cmd(cmd).await().isSuccess) {
EnvFixDialog(this).publish()
@@ -95,7 +95,6 @@ class InstallViewModel(
R.id.method_inactive_slot -> FlashFragment.flash(true).navigate(true)
else -> error("Unknown value")
}
state = State.LOADING
}
override fun onSaveState(state: Bundle) {
@@ -1,6 +1,7 @@
package com.topjohnwu.magisk.ui.module
import android.net.Uri
import androidx.databinding.Bindable
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
@@ -10,10 +11,7 @@ import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.base.ContentResultCallback
import com.topjohnwu.magisk.core.model.module.LocalModule
import com.topjohnwu.magisk.core.model.module.OnlineModule
import com.topjohnwu.magisk.databinding.MergeObservableList
import com.topjohnwu.magisk.databinding.RvItem
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.diffListOf
import com.topjohnwu.magisk.databinding.*
import com.topjohnwu.magisk.events.GetContentEvent
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.events.dialog.ModuleInstallDialog
@@ -36,6 +34,10 @@ class ModuleViewModel : BaseViewModel() {
val data get() = uri
@get:Bindable
var loading = true
private set(value) = set(value, field, { field = it }, BR.loading)
init {
if (Info.env.isActive && LocalModule.loaded()) {
items.insertItem(InstallModule)
@@ -45,9 +47,9 @@ class ModuleViewModel : BaseViewModel() {
override fun refresh(): Job {
return viewModelScope.launch {
state = State.LOADING
loading = true
loadInstalled()
state = State.LOADED
loading = false
loadUpdateInfo()
}
}
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES
import android.os.Process
import androidx.databinding.Bindable
import androidx.databinding.ObservableArrayList
import androidx.lifecycle.viewModelScope
import com.topjohnwu.magisk.BR
@@ -14,10 +15,7 @@ import com.topjohnwu.magisk.core.di.AppContext
import com.topjohnwu.magisk.core.model.su.SuPolicy
import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.core.utils.currentLocale
import com.topjohnwu.magisk.databinding.AnyDiffRvItem
import com.topjohnwu.magisk.databinding.MergeObservableList
import com.topjohnwu.magisk.databinding.bindExtra
import com.topjohnwu.magisk.databinding.diffListOf
import com.topjohnwu.magisk.databinding.*
import com.topjohnwu.magisk.events.SnackbarEvent
import com.topjohnwu.magisk.events.dialog.BiometricEvent
import com.topjohnwu.magisk.events.dialog.SuperuserRevokeDialog
@@ -45,15 +43,17 @@ class SuperuserViewModel(
it.put(BR.listener, this)
}
// ---
@get:Bindable
var loading = true
private set(value) = set(value, field, { field = it }, BR.loading)
@SuppressLint("InlinedApi")
override fun refresh() = viewModelScope.launch {
if (!Utils.showSuperUser()) {
state = State.LOADING_FAILED
loading = false
return@launch
}
state = State.LOADING
loading = true
val (policies, diff) = withContext(Dispatchers.IO) {
db.deleteOutdated()
db.delete(AppContext.applicationInfo.uid)
@@ -98,7 +98,7 @@ class SuperuserViewModel(
itemsHelpers.clear()
else if (itemsHelpers.isEmpty())
itemsHelpers.add(itemNoData)
state = State.LOADED
loading = false
}
// ---