Commit 6c6368fd authored by topjohnwu's avatar topjohnwu

Reduce usage of delegation

parent ba31c6b6
...@@ -7,17 +7,21 @@ import com.topjohnwu.magisk.databinding.ObservableItem ...@@ -7,17 +7,21 @@ import com.topjohnwu.magisk.databinding.ObservableItem
import com.topjohnwu.magisk.ktx.timeDateFormat import com.topjohnwu.magisk.ktx.timeDateFormat
import com.topjohnwu.magisk.ktx.toTime import com.topjohnwu.magisk.ktx.toTime
import com.topjohnwu.magisk.model.entity.MagiskLog import com.topjohnwu.magisk.model.entity.MagiskLog
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
class LogItem(val item: MagiskLog) : ObservableItem<LogItem>() { class LogItem(val item: MagiskLog) : ObservableItem<LogItem>() {
override val layoutRes = R.layout.item_log_access_md2 override val layoutRes = R.layout.item_log_access_md2
val date = item.time.toTime(timeDateFormat) val date = item.time.toTime(timeDateFormat)
@get:Bindable @get:Bindable
var isTop by observable(false, BR.top) var isTop = false
set(value) = set(value, field, { field = it }, BR.top)
@get:Bindable @get:Bindable
var isBottom by observable(false, BR.bottom) var isBottom = false
set(value) = set(value, field, { field = it }, BR.bottom)
override fun itemSameAs(other: LogItem) = item.appName == other.item.appName override fun itemSameAs(other: LogItem) = item.appName == other.item.appName
......
...@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.model.module.Repo ...@@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.model.module.Repo
import com.topjohnwu.magisk.databinding.ComparableRvItem import com.topjohnwu.magisk.databinding.ComparableRvItem
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ObservableItem
import com.topjohnwu.magisk.ui.module.ModuleViewModel import com.topjohnwu.magisk.ui.module.ModuleViewModel
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
object InstallModule : ComparableRvItem<InstallModule>() { object InstallModule : ComparableRvItem<InstallModule>() {
override val layoutRes = R.layout.item_module_download override val layoutRes = R.layout.item_module_download
...@@ -34,11 +34,16 @@ class SectionTitle( ...@@ -34,11 +34,16 @@ class SectionTitle(
override val layoutRes = R.layout.item_section_md2 override val layoutRes = R.layout.item_section_md2
@get:Bindable @get:Bindable
var button by observable(_button, BR.button) var button = _button
set(value) = set(value, field, { field = it }, BR.button)
@get:Bindable @get:Bindable
var icon by observable(_icon, BR.icon) var icon = _icon
set(value) = set(value, field, { field = it }, BR.icon)
@get:Bindable @get:Bindable
var hasButton by observable(_button != 0 && _icon != 0, BR.hasButton) var hasButton = _button != 0 && _icon != 0
set(value) = set(value, field, { field = it }, BR.hasButton)
override fun onBindingBound(binding: ViewDataBinding) { override fun onBindingBound(binding: ViewDataBinding) {
super.onBindingBound(binding) super.onBindingBound(binding)
...@@ -54,9 +59,13 @@ sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() { ...@@ -54,9 +59,13 @@ sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
override val layoutRes: Int = R.layout.item_repo_md2 override val layoutRes: Int = R.layout.item_repo_md2
@get:Bindable @get:Bindable
var progress by observable(0, BR.progress) var progress = 0
set(value) = set(value, field, { field = it }, BR.progress)
@get:Bindable @get:Bindable
var isUpdate by observable(false, BR.update) var isUpdate = false
set(value) = set(value, field, { field = it }, BR.update)
override fun contentSameAs(other: RepoItem): Boolean = item == other.item override fun contentSameAs(other: RepoItem): Boolean = item == other.item
override fun itemSameAs(other: RepoItem): Boolean = item.id == other.item.id override fun itemSameAs(other: RepoItem): Boolean = item.id == other.item.id
...@@ -75,7 +84,8 @@ class ModuleItem(val item: Module) : ObservableItem<ModuleItem>(), Observable { ...@@ -75,7 +84,8 @@ class ModuleItem(val item: Module) : ObservableItem<ModuleItem>(), Observable {
override val layoutRes = R.layout.item_module_md2 override val layoutRes = R.layout.item_module_md2
@get:Bindable @get:Bindable
var repo: Repo? by observable(null, BR.repo) var repo: Repo? = null
set(value) = set(value, field, { field = it }, BR.repo)
@get:Bindable @get:Bindable
var isEnabled var isEnabled
......
...@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.BR ...@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ObservableItem import com.topjohnwu.magisk.databinding.ObservableItem
import com.topjohnwu.magisk.utils.TransitiveText import com.topjohnwu.magisk.utils.TransitiveText
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.magisk.view.MagiskDialog import com.topjohnwu.magisk.view.MagiskDialog
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
import org.koin.core.get import org.koin.core.get
...@@ -27,7 +27,8 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() { ...@@ -27,7 +27,8 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
open val description: TransitiveText get() = TransitiveText.EMPTY open val description: TransitiveText get() = TransitiveText.EMPTY
@get:Bindable @get:Bindable
var isEnabled by observable(true, BR.enabled) var isEnabled = true
set(value) = set(value, field, { field = it }, BR.enabled)
protected open val isFullSpan get() = false protected open val isFullSpan get() = false
...@@ -63,12 +64,15 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() { ...@@ -63,12 +64,15 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
@get:Bindable @get:Bindable
abstract var value: T abstract var value: T
protected inline fun <reified T> value( protected inline fun <reified T> setV(
initialValue: T, new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int) {
vararg fieldIds: Int, set(new, old, setter, BR.value, *fieldIds)
crossinline setter: (T) -> Unit = {} }
) = observable(initialValue, BR.value, *fieldIds, afterChanged = setter)
protected inline fun <reified T> setV(
new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
set(new, old, setter, BR.value, afterChanged = afterChanged)
}
} }
abstract class Toggle : Value<Boolean>() { abstract class Toggle : Value<Boolean>() {
...@@ -142,10 +146,10 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() { ...@@ -142,10 +146,10 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
val selectedEntry val selectedEntry
get() = entries.getOrNull(value) get() = entries.getOrNull(value)
/* override */ protected inline fun value( protected inline fun <reified T> setS(
initialValue: Int, new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
crossinline setter: (Int) -> Unit set(new, old, setter, BR.value, BR.selectedEntry, BR.description, afterChanged = afterChanged)
) = observable(initialValue, BR.value, BR.selectedEntry, BR.description, afterChanged = setter) }
private fun Resources.getArrayOrEmpty(id: Int): Array<String> = private fun Resources.getArrayOrEmpty(id: Int): Array<String> =
runCatching { getStringArray(id) }.getOrDefault(emptyArray()) runCatching { getStringArray(id) }.getOrDefault(emptyArray())
......
...@@ -17,7 +17,7 @@ import com.topjohnwu.magisk.core.base.BaseActivity ...@@ -17,7 +17,7 @@ import com.topjohnwu.magisk.core.base.BaseActivity
import com.topjohnwu.magisk.model.events.* import com.topjohnwu.magisk.model.events.*
import com.topjohnwu.magisk.model.navigation.NavigationWrapper import com.topjohnwu.magisk.model.navigation.NavigationWrapper
import com.topjohnwu.magisk.utils.ObservableHost import com.topjohnwu.magisk.utils.ObservableHost
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import org.koin.core.KoinComponent import org.koin.core.KoinComponent
...@@ -42,9 +42,11 @@ abstract class BaseViewModel( ...@@ -42,9 +42,11 @@ abstract class BaseViewModel(
val viewEvents: LiveData<ViewEvent> get() = _viewEvents val viewEvents: LiveData<ViewEvent> get() = _viewEvents
@get:Bindable @get:Bindable
var insets by observable(Insets.NONE, BR.insets) var insets = Insets.NONE
set(value) = set(value, field, { field = it }, BR.insets)
var state by observable(initialState, BR.loading, BR.loaded, BR.loadFailed) var state= initialState
set(value) = set(value, field, { field = it }, BR.loading, BR.loaded, BR.loadFailed)
private val _viewEvents = MutableLiveData<ViewEvent>() private val _viewEvents = MutableLiveData<ViewEvent>()
private var runningJob: Job? = null private var runningJob: Job? = null
......
...@@ -20,7 +20,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent ...@@ -20,7 +20,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.diffListOf import com.topjohnwu.magisk.ui.base.diffListOf
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
...@@ -34,9 +34,12 @@ class FlashViewModel( ...@@ -34,9 +34,12 @@ class FlashViewModel(
) : BaseViewModel() { ) : BaseViewModel() {
@get:Bindable @get:Bindable
var showReboot by observable(Shell.rootAccess(), BR.showReboot) var showReboot = Shell.rootAccess()
set(value) = set(value, field, { field = it }, BR.showReboot)
@get:Bindable @get:Bindable
var behaviorText by observable(resources.getString(R.string.flashing), BR.behaviorText) var behaviorText = resources.getString(R.string.flashing)
set(value) = set(value, field, { field = it }, BR.behaviorText)
val adapter = BindingAdapter<ConsoleItem>() val adapter = BindingAdapter<ConsoleItem>()
val items = diffListOf<ConsoleItem>() val items = diffListOf<ConsoleItem>()
......
...@@ -17,7 +17,7 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel ...@@ -17,7 +17,7 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.Queryable import com.topjohnwu.magisk.ui.base.Queryable
import com.topjohnwu.magisk.ui.base.filterableListOf import com.topjohnwu.magisk.ui.base.filterableListOf
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
...@@ -29,14 +29,16 @@ class HideViewModel( ...@@ -29,14 +29,16 @@ class HideViewModel(
override val queryDelay = 1000L override val queryDelay = 1000L
@get:Bindable @get:Bindable
var isShowSystem by observable(false, BR.showSystem) { var isShowSystem = false
submitQuery() set(value) = set(value, field, { field = it }, BR.showSystem){
} submitQuery()
}
@get:Bindable @get:Bindable
var query by observable("", BR.query) { var query = ""
submitQuery() set(value) = set(value, field, { field = it }, BR.query){
} submitQuery()
}
val items = filterableListOf<HideItem>() val items = filterableListOf<HideItem>()
val itemBinding = itemBindingOf<HideItem> { val itemBinding = itemBindingOf<HideItem> {
......
...@@ -27,7 +27,7 @@ import com.topjohnwu.magisk.model.events.dialog.ManagerInstallDialog ...@@ -27,7 +27,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.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.tatarka.bindingcollectionadapter2.BR import me.tatarka.bindingcollectionadapter2.BR
...@@ -42,25 +42,37 @@ class HomeViewModel( ...@@ -42,25 +42,37 @@ class HomeViewModel(
) : BaseViewModel() { ) : BaseViewModel() {
@get:Bindable @get:Bindable
var isNoticeVisible by observable(Config.safetyNotice, BR.noticeVisible) var isNoticeVisible = Config.safetyNotice
set(value) = set(value, field, { field = it }, BR.noticeVisible)
@get:Bindable @get:Bindable
var stateMagisk by observable(MagiskState.LOADING, BR.stateMagisk) var stateMagisk = MagiskState.LOADING
set(value) = set(value, field, { field = it }, BR.stateMagisk)
@get:Bindable @get:Bindable
var stateManager by observable(MagiskState.LOADING, BR.stateManager) var stateManager = MagiskState.LOADING
set(value) = set(value, field, { field = it }, BR.stateManager)
@get:Bindable @get:Bindable
var magiskRemoteVersion by observable(R.string.loading.res(), BR.magiskRemoteVersion) var magiskRemoteVersion = R.string.loading.res()
set(value) = set(value, field, { field = it }, BR.magiskRemoteVersion)
val magiskInstalledVersion get() = val magiskInstalledVersion get() =
"${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})" "${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})"
val magiskMode get() = R.string.home_status_normal.res() val magiskMode get() = R.string.home_status_normal.res()
@get:Bindable @get:Bindable
var managerRemoteVersion by observable(R.string.loading.res(), BR.managerRemoteVersion) var managerRemoteVersion = R.string.loading.res()
set(value) = set(value, field, { field = it }, BR.managerRemoteVersion)
val managerInstalledVersion = Info.stub?.let { val managerInstalledVersion = Info.stub?.let {
"${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) (${it.version})" "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) (${it.version})"
} ?: "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" } ?: "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
val statePackageName = packageName val statePackageName = packageName
@get:Bindable @get:Bindable
var stateManagerProgress by observable(0, BR.stateManagerProgress) var stateManagerProgress = 0
set(value) = set(value, field, { field = it }, BR.stateManagerProgress)
val items = listOf(DeveloperItem.Mainline, DeveloperItem.App, DeveloperItem.Project) val items = listOf(DeveloperItem.Mainline, DeveloperItem.App, DeveloperItem.Project)
val itemBinding = itemBindingOf<HomeItem> { val itemBinding = itemBindingOf<HomeItem> {
......
...@@ -16,7 +16,7 @@ import com.topjohnwu.magisk.model.entity.internal.DownloadSubject ...@@ -16,7 +16,7 @@ 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.model.events.dialog.SecondSlotWarningDialog import com.topjohnwu.magisk.model.events.dialog.SecondSlotWarningDialog
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.core.get import org.koin.core.get
...@@ -30,25 +30,34 @@ class InstallViewModel( ...@@ -30,25 +30,34 @@ class InstallViewModel(
val isAB get() = Info.isAB val isAB get() = Info.isAB
@get:Bindable @get:Bindable
var step by observable(0, BR.step) var step = 0
set(value) = set(value, field, { field = it }, BR.step)
@get:Bindable @get:Bindable
var method by observable(-1, BR.method) { var method = -1
when (it) { set(value) = set(value, field, { field = it }, BR.method) {
R.id.method_patch -> { when (it) {
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG) R.id.method_patch -> {
RequestFileEvent().publish() Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
} RequestFileEvent().publish()
R.id.method_inactive_slot -> { }
SecondSlotWarningDialog().publish() R.id.method_inactive_slot -> {
SecondSlotWarningDialog().publish()
}
} }
} }
}
@get:Bindable @get:Bindable
var progress by observable(0, BR.progress) var progress = 0
set(value) = set(value, field, { field = it }, BR.progress)
@get:Bindable @get:Bindable
var data by observable(null as Uri?, BR.data) var data: Uri? = null
set(value) = set(value, field, { field = it }, BR.data)
@get:Bindable @get:Bindable
var notes by observable("", BR.notes) var notes = ""
set(value) = set(value, field, { field = it }, BR.notes)
init { init {
RemoteFileService.reset() RemoteFileService.reset()
......
...@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent ...@@ -13,7 +13,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.base.diffListOf import com.topjohnwu.magisk.ui.base.diffListOf
import com.topjohnwu.magisk.ui.base.itemBindingOf import com.topjohnwu.magisk.ui.base.itemBindingOf
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
...@@ -41,7 +41,8 @@ class LogViewModel( ...@@ -41,7 +41,8 @@ class LogViewModel(
// --- magisk log // --- magisk log
@get:Bindable @get:Bindable
var consoleText by observable(" ", BR.consoleText) var consoleText= " "
set(value) = set(value, field, { field = it }, BR.consoleText)
override fun refresh() = viewModelScope.launch { override fun refresh() = viewModelScope.launch {
consoleText = repo.fetchMagiskLogs() consoleText = repo.fetchMagiskLogs()
......
...@@ -23,7 +23,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent ...@@ -23,7 +23,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
import com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog import com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog
import com.topjohnwu.magisk.ui.base.* import com.topjohnwu.magisk.ui.base.*
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import kotlinx.coroutines.* import kotlinx.coroutines.*
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
import kotlin.math.roundToInt import kotlin.math.roundToInt
...@@ -53,17 +53,21 @@ class ModuleViewModel( ...@@ -53,17 +53,21 @@ class ModuleViewModel(
private var remoteJob: Job? = null private var remoteJob: Job? = null
@get:Bindable @get:Bindable
var isRemoteLoading by observable(false, BR.remoteLoading) var isRemoteLoading = false
set(value) = set(value, field, { field = it }, BR.remoteLoading)
@get:Bindable @get:Bindable
var query by observable("", BR.query) { var query = ""
submitQuery() set(value) = set(value, field, { field = it }, BR.query) {
// Yes we do lie about the search being loaded submitQuery()
searchLoading = true // Yes we do lie about the search being loaded
} searchLoading = true
}
@get:Bindable @get:Bindable
var searchLoading by observable(false, BR.searchLoading) var searchLoading = false
set(value) = set(value, field, { field = it }, BR.searchLoading)
val itemsSearch = diffListOf<RepoItem>() val itemsSearch = diffListOf<RepoItem>()
val itemSearchBinding = itemBindingOf<RepoItem> { val itemSearchBinding = itemBindingOf<RepoItem> {
it.bindExtra(BR.viewModel, this) it.bindExtra(BR.viewModel, this)
......
...@@ -6,7 +6,7 @@ import com.topjohnwu.magisk.R ...@@ -6,7 +6,7 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.model.events.CheckSafetyNetEvent import com.topjohnwu.magisk.model.events.CheckSafetyNetEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.* import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.*
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import org.json.JSONObject import org.json.JSONObject
enum class SafetyNetState { enum class SafetyNetState {
...@@ -21,13 +21,20 @@ data class SafetyNetResult( ...@@ -21,13 +21,20 @@ data class SafetyNetResult(
class SafetynetViewModel : BaseViewModel() { class SafetynetViewModel : BaseViewModel() {
@get:Bindable @get:Bindable
var safetyNetTitle by observable(R.string.empty, BR.safetyNetTitle) var safetyNetTitle = R.string.empty
set(value) = set(value, field, { field = it }, BR.safetyNetTitle)
@get:Bindable @get:Bindable
var ctsState by observable(false, BR.ctsState) var ctsState = false
set(value) = set(value, field, { field = it }, BR.ctsState)
@get:Bindable @get:Bindable
var basicIntegrityState by observable(false, BR.basicIntegrityState) var basicIntegrityState = false
set(value) = set(value, field, { field = it }, BR.basicIntegrityState)
@get:Bindable @get:Bindable
var evalType by observable("") var evalType = ""
set(value) = set(value, field, { field = it }, BR.evalType)
@get:Bindable @get:Bindable
val isChecking get() = currentState == LOADING val isChecking get() = currentState == LOADING
...@@ -36,7 +43,8 @@ class SafetynetViewModel : BaseViewModel() { ...@@ -36,7 +43,8 @@ class SafetynetViewModel : BaseViewModel() {
@get:Bindable @get:Bindable
val isSuccess get() = currentState == PASS val isSuccess get() = currentState == PASS
private var currentState by observable(IDLE, BR.checking, BR.failed, BR.success) private var currentState = IDLE
set(value) = set(value, field, { field = it }, BR.checking, BR.failed, BR.success)
init { init {
cachedResult?.also { cachedResult?.also {
......
...@@ -21,7 +21,7 @@ import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding ...@@ -21,7 +21,7 @@ import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
import com.topjohnwu.magisk.ktx.get import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.model.entity.recycler.SettingsItem import com.topjohnwu.magisk.model.entity.recycler.SettingsItem
import com.topjohnwu.magisk.utils.asTransitive import com.topjohnwu.magisk.utils.asTransitive
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
...@@ -34,9 +34,10 @@ object Customization : SettingsItem.Section() { ...@@ -34,9 +34,10 @@ object Customization : SettingsItem.Section() {
} }
object Language : SettingsItem.Selector() { object Language : SettingsItem.Selector() {
override var value by value(-1) { override var value = -1
Config.locale = entryValues[it] set(value) = setS(value, field, { field = it }) {
} Config.locale = entryValues[it]
}
override val title = R.string.language.asTransitive() override val title = R.string.language.asTransitive()
override var entries = emptyArray<String>() override var entries = emptyArray<String>()
...@@ -49,7 +50,6 @@ object Language : SettingsItem.Selector() { ...@@ -49,7 +50,6 @@ object Language : SettingsItem.Selector() {
entryValues = values entryValues = values
val selectedLocale = currentLocale.getDisplayName(currentLocale) val selectedLocale = currentLocale.getDisplayName(currentLocale)
value = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it } value = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it }
notifyPropertyChanged(BR.selectedEntry)
} }
} }
} }
...@@ -79,7 +79,8 @@ object Hide : SettingsItem.Input() { ...@@ -79,7 +79,8 @@ object Hide : SettingsItem.Input() {
override val title = R.string.settings_hide_manager_title.asTransitive() override val title = R.string.settings_hide_manager_title.asTransitive()
override val description = R.string.settings_hide_manager_summary.asTransitive() override val description = R.string.settings_hide_manager_summary.asTransitive()
override val showStrip = false override val showStrip = false
override var value by value(resources.getString(R.string.re_app_name), BR.error) override var value = resources.getString(R.string.re_app_name)
set(value) = setV(value, field, { field = it }, BR.error)
@get:Bindable @get:Bindable
val isError get() = value.length > 14 || value.isBlank() val isError get() = value.length > 14 || value.isBlank()
...@@ -101,13 +102,15 @@ fun HideOrRestore() = ...@@ -101,13 +102,15 @@ fun HideOrRestore() =
if (get<Context>().packageName == BuildConfig.APPLICATION_ID) Hide else Restore if (get<Context>().packageName == BuildConfig.APPLICATION_ID) Hide else Restore
object DownloadPath : SettingsItem.Input() { object DownloadPath : SettingsItem.Input() {
override var value: String by value(Config.downloadPath) { Config.downloadPath = it } override var value = Config.downloadPath
set(value) = setV(value, field, { field = it }) { Config.downloadPath = it }
override val title = R.string.settings_download_path_title.asTransitive() override val title = R.string.settings_download_path_title.asTransitive()
override val intermediate: String? override val intermediate: String?
get() = if (Utils.ensureDownloadPath(result) != null) result else null get() = if (Utils.ensureDownloadPath(result) != null) result else null
@get:Bindable @get:Bindable
var result by observable(value, BR.result, BR.path) var result = value
set(value) = set(value, field, { field = it }, BR.result, BR.path)
@get:Bindable @get:Bindable
val path get() = File(Environment.getExternalStorageDirectory(), result).absolutePath.orEmpty() val path get() = File(Environment.getExternalStorageDirectory(), result).absolutePath.orEmpty()
...@@ -117,7 +120,8 @@ object DownloadPath : SettingsItem.Input() { ...@@ -117,7 +120,8 @@ object DownloadPath : SettingsItem.Input() {
} }
object UpdateChannel : SettingsItem.Selector() { object UpdateChannel : SettingsItem.Selector() {
override var value by value(Config.updateChannel) { Config.updateChannel = it } override var value = Config.updateChannel
set(value) = setS(value, field, { field = it }) { Config.updateChannel = it }
override val title = R.string.settings_update_channel_title.asTransitive() override val title = R.string.settings_update_channel_title.asTransitive()
override val entries get() = resources.getStringArray(R.array.update_channel).let { override val entries get() = resources.getStringArray(R.array.update_channel).let {
...@@ -128,11 +132,13 @@ object UpdateChannel : SettingsItem.Selector() { ...@@ -128,11 +132,13 @@ object UpdateChannel : SettingsItem.Selector() {
object UpdateChannelUrl : SettingsItem.Input() { object UpdateChannelUrl : SettingsItem.Input() {
override val title = R.string.settings_update_custom.asTransitive() override val title = R.string.settings_update_custom.asTransitive()
override var value by value(Config.customChannelUrl) { Config.customChannelUrl = it } override var value = Config.customChannelUrl
set(value) = setV(value, field, { field = it }) { Config.customChannelUrl = it }
override val intermediate: String? get() = result override val intermediate: String? get() = result
@get:Bindable @get:Bindable
var result by observable(value, BR.result) var result = value
set(value) = set(value, field, { field = it }, BR.result)
override fun refresh() { override fun refresh() {
isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL
...@@ -145,10 +151,11 @@ object UpdateChannelUrl : SettingsItem.Input() { ...@@ -145,10 +151,11 @@ object UpdateChannelUrl : SettingsItem.Input() {
object UpdateChecker : SettingsItem.Toggle() { object UpdateChecker : SettingsItem.Toggle() {
override val title = R.string.settings_check_update_title.asTransitive() override val title = R.string.settings_check_update_title.asTransitive()
override val description = R.string.settings_check_update_summary.asTransitive() override val description = R.string.settings_check_update_summary.asTransitive()
override var value by value(Config.checkUpdate) { override var value = Config.checkUpdate
Config.checkUpdate = it set(value) = setV(value, field, { field = it }) {
Utils.scheduleUpdateCheck(get()) Config.checkUpdate = it
} Utils.scheduleUpdateCheck(get())
}
} }
// check whether is module already installed beforehand? // check whether is module already installed beforehand?
...@@ -159,7 +166,8 @@ object SystemlessHosts : SettingsItem.Blank() { ...@@ -159,7 +166,8 @@ object SystemlessHosts : SettingsItem.Blank() {
object Biometrics : SettingsItem.Toggle() { object Biometrics : SettingsItem.Toggle() {
override val title = R.string.settings_su_biometric_title.asTransitive() override val title = R.string.settings_su_biometric_title.asTransitive()
override var value by value(Config.suBiometric) { Config.suBiometric = it } override var value = Config.suBiometric
set(value) = setV(value, field, { field = it }) { Config.suBiometric = it }
override var description = R.string.settings_su_biometric_summary.asTransitive() override var description = R.string.settings_su_biometric_summary.asTransitive()
override fun refresh() { override fun refresh() {
...@@ -174,7 +182,8 @@ object Biometrics : SettingsItem.Toggle() { ...@@ -174,7 +182,8 @@ object Biometrics : SettingsItem.Toggle() {
object Reauthenticate : SettingsItem.Toggle() { object Reauthenticate : SettingsItem.Toggle() {
override val title = R.string.settings_su_reauth_title.asTransitive() override val title = R.string.settings_su_reauth_title.asTransitive()
override val description = R.string.settings_su_reauth_summary.asTransitive() override val description = R.string.settings_su_reauth_summary.asTransitive()
override var value by value(Config.suReAuth) { Config.suReAuth = it } override var value = Config.suReAuth
set(value) = setV(value, field, { field = it }) { Config.suReAuth = it }
override fun refresh() { override fun refresh() {
isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O && Utils.showSuperUser() isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O && Utils.showSuperUser()
...@@ -190,13 +199,14 @@ object Magisk : SettingsItem.Section() { ...@@ -190,13 +199,14 @@ object Magisk : SettingsItem.Section() {
object MagiskHide : SettingsItem.Toggle() { object MagiskHide : SettingsItem.Toggle() {
override val title = R.string.magiskhide.asTransitive() override val title = R.string.magiskhide.asTransitive()
override val description = R.string.settings_magiskhide_summary.asTransitive() override val description = R.string.settings_magiskhide_summary.asTransitive()
override var value by value(Config.magiskHide) { override var value = Config.magiskHide
Config.magiskHide = it set(value) = setV(value, field, { field = it }) {
when { Config.magiskHide = it
it -> Shell.su("magiskhide --enable").submit() when {
else -> Shell.su("magiskhide --disable").submit() it -> Shell.su("magiskhide --enable").submit()
else -> Shell.su("magiskhide --disable").submit()
}
} }
}
} }
// --- Superuser // --- Superuser
...@@ -210,9 +220,10 @@ object AccessMode : SettingsItem.Selector() { ...@@ -210,9 +220,10 @@ object AccessMode : SettingsItem.Selector() {
override val entryRes = R.array.su_access override val entryRes = R.array.su_access
override val entryValRes = R.array.value_array override val entryValRes = R.array.value_array
override var value by value(Config.rootMode) { override var value = Config.rootMode
Config.rootMode = entryValues[it].toInt() set(value) = setS(value, field, { field = it }) {
} Config.rootMode = entryValues[it].toInt()
}
} }
object MultiuserMode : SettingsItem.Selector() { object MultiuserMode : SettingsItem.Selector() {
...@@ -220,9 +231,10 @@ object MultiuserMode : SettingsItem.Selector() { ...@@ -220,9 +231,10 @@ object MultiuserMode : SettingsItem.Selector() {
override val entryRes = R.array.multiuser_mode override val entryRes = R.array.multiuser_mode
override val entryValRes = R.array.value_array override val entryValRes = R.array.value_array
override var value by value(Config.suMultiuserMode) { override var value = Config.suMultiuserMode
Config.suMultiuserMode = entryValues[it].toInt() set(value) = setS(value, field, { field = it }) {
} Config.suMultiuserMode = entryValues[it].toInt()
}
override val description override val description
get() = resources.getStringArray(R.array.multiuser_summary)[value].asTransitive() get() = resources.getStringArray(R.array.multiuser_summary)[value].asTransitive()
...@@ -237,9 +249,10 @@ object MountNamespaceMode : SettingsItem.Selector() { ...@@ -237,9 +249,10 @@ object MountNamespaceMode : SettingsItem.Selector() {
override val entryRes = R.array.namespace override val entryRes = R.array.namespace
override val entryValRes = R.array.value_array override val entryValRes = R.array.value_array
override var value by value(Config.suMntNamespaceMode) { override var value = Config.suMntNamespaceMode
Config.suMntNamespaceMode = entryValues[it].toInt() set(value) = setS(value, field, { field = it }) {
} Config.suMntNamespaceMode = entryValues[it].toInt()
}
override val description override val description
get() = resources.getStringArray(R.array.namespace_summary)[value].asTransitive() get() = resources.getStringArray(R.array.namespace_summary)[value].asTransitive()
...@@ -250,9 +263,10 @@ object AutomaticResponse : SettingsItem.Selector() { ...@@ -250,9 +263,10 @@ object AutomaticResponse : SettingsItem.Selector() {
override val entryRes = R.array.auto_response override val entryRes = R.array.auto_response
override val entryValRes = R.array.value_array override val entryValRes = R.array.value_array
override var value by value(Config.suAutoReponse) { override var value = Config.suAutoReponse
Config.suAutoReponse = entryValues[it].toInt() set(value) = setS(value, field, { field = it }) {
} Config.suAutoReponse = entryValues[it].toInt()
}
} }
object RequestTimeout : SettingsItem.Selector() { object RequestTimeout : SettingsItem.Selector() {
...@@ -260,9 +274,10 @@ object RequestTimeout : SettingsItem.Selector() { ...@@ -260,9 +274,10 @@ object RequestTimeout : SettingsItem.Selector() {
override val entryRes = R.array.request_timeout override val entryRes = R.array.request_timeout
override val entryValRes = R.array.request_timeout_value override val entryValRes = R.array.request_timeout_value
override var value by value(selected) { override var value = selected
Config.suDefaultTimeout = entryValues[it].toInt() set(value) = setS(value, field, { field = it }) {
} Config.suDefaultTimeout = entryValues[it].toInt()
}
private val selected: Int private val selected: Int
get() = entryValues.indexOfFirst { it.toInt() == Config.suDefaultTimeout } get() = entryValues.indexOfFirst { it.toInt() == Config.suDefaultTimeout }
...@@ -273,7 +288,8 @@ object SUNotification : SettingsItem.Selector() { ...@@ -273,7 +288,8 @@ object SUNotification : SettingsItem.Selector() {
override val entryRes = R.array.su_notification override val entryRes = R.array.su_notification
override val entryValRes = R.array.value_array override val entryValRes = R.array.value_array
override var value by value(Config.suNotification) { override var value = Config.suNotification
Config.suNotification = entryValues[it].toInt() set(value) = setS(value, field, { field = it }) {
} Config.suNotification = entryValues[it].toInt()
}
} }
...@@ -19,7 +19,7 @@ import com.topjohnwu.magisk.core.utils.BiometricHelper ...@@ -19,7 +19,7 @@ import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem
import com.topjohnwu.magisk.model.events.DieEvent import com.topjohnwu.magisk.model.events.DieEvent
import com.topjohnwu.magisk.ui.base.BaseViewModel import com.topjohnwu.magisk.ui.base.BaseViewModel
import com.topjohnwu.magisk.utils.observable import com.topjohnwu.magisk.utils.set
import com.topjohnwu.superuser.internal.UiThreadHandler import com.topjohnwu.superuser.internal.UiThreadHandler
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
...@@ -34,19 +34,32 @@ class SuRequestViewModel( ...@@ -34,19 +34,32 @@ class SuRequestViewModel(
) : BaseViewModel() { ) : BaseViewModel() {
@get:Bindable @get:Bindable
var icon by observable(null as Drawable?, BR.icon) var icon: Drawable? = null
set(value) = set(value, field, { field = it }, BR.icon)
@get:Bindable @get:Bindable
var title by observable("", BR.title) var title = ""
set(value) = set(value, field, { field = it }, BR.title)
@get:Bindable @get:Bindable
var packageName by observable("", BR.packageName) var packageName = ""
set(value) = set(value, field, { field = it }, BR.packageName)
@get:Bindable @get:Bindable
var denyText by observable(res.getString(R.string.deny), BR.denyText) var denyText = res.getString(R.string.deny)
set(value) = set(value, field, { field = it }, BR.denyText)
@get:Bindable @get:Bindable
var warningText by observable(res.getString(R.string.su_warning), BR.warningText) var warningText = res.getString(R.string.su_warning)
set(value) = set(value, field, { field = it }, BR.warningText)
@get:Bindable @get:Bindable
var selectedItemPosition by observable(0, BR.selectedItemPosition) var selectedItemPosition = 0
set(value) = set(value, field, { field = it }, BR.selectedItemPosition)
@get:Bindable @get:Bindable
var grantEnabled by observable(false, BR.grantEnabled) var grantEnabled = false
set(value) = set(value, field, { field = it }, BR.grantEnabled)
private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) } private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) }
val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply { val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply {
......
...@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.utils ...@@ -2,8 +2,6 @@ package com.topjohnwu.magisk.utils
import androidx.databinding.Observable import androidx.databinding.Observable
import androidx.databinding.PropertyChangeRegistry import androidx.databinding.PropertyChangeRegistry
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/** /**
* Modified from https://github.com/skoumalcz/teanity/blob/1.2/core/src/main/java/com/skoumal/teanity/observable/Notifyable.kt * Modified from https://github.com/skoumalcz/teanity/blob/1.2/core/src/main/java/com/skoumal/teanity/observable/Notifyable.kt
...@@ -52,105 +50,32 @@ interface ObservableHost : Observable { ...@@ -52,105 +50,32 @@ interface ObservableHost : Observable {
} }
/** /**
* Declares delegated property in [ObservableHost] parent. This property is available for DataBinding * Injects boilerplate implementation for {@literal @}[androidx.databinding.Bindable] field setters.
* to be observed as usual. The only caveat is that in order for binding to generate the [fieldId]
* it has to be annotated accordingly.
*
* The annotation however give very strict control over your internal fields and overall reduce
* overhead in notifying observers. (In comparison to [androidx.databinding.ObservableField])
* It helps the kotlin code to feel more,... _native_, while respecting the original functionality.
* *
* # Examples: * # Examples:
*
* ## The most basic usage would probably be:
* ```kotlin * ```kotlin
* @get:Bindable * @get:Bindable
* var myField by observable(defaultValue, BR.myField) * var myField = defaultValue
* private set * set(value) = set(value, field, { field = it }, BR.myField) {
* doSomething(it)
* }
* ``` * ```
*
* ## You can use the field as public read/write, of course:
* ```kotlin
* @get:Bindable
* var myField by observable(defaultValue, BR.myField)
* ```
*
* ## Please beware that delegated property instantiates one class per property
* We discourage using simple getters via delegated properties. Instead you can do something like
* this:
*
* ```kotlin
* @get:Bindable
* var myField by observable(defaultValue, BR.myField, BR.myTransformedField)
*
* var myTransformedField
* @Bindable get() {
* return myField.transform()
* }
* set(value) {
* myField = value.transform()
* }
* ```
*
* */ * */
// Optimize for the most common use case inline fun <reified T> ObservableHost.set(
// Generic type is reified to optimize primitive types new: T, old: T, setter: (T) -> Unit, fieldId: Int, afterChanged: (T) -> Unit = {}) {
inline fun <reified T> ObservableHost.observable( if (old != new) {
initialValue: T, setter(new)
fieldId: Int notifyPropertyChanged(fieldId)
) = object : ReadWriteProperty<ObservableHost, T> { afterChanged(new)
private var field = initialValue
override fun getValue(thisRef: ObservableHost, property: KProperty<*>): T {
return field
}
@Synchronized
override fun setValue(thisRef: ObservableHost, property: KProperty<*>, value: T) {
if (field != value) {
field = value
notifyPropertyChanged(fieldId)
}
}
}
inline fun <reified T> ObservableHost.observable(
initialValue: T,
vararg fieldIds: Int
) = object : ReadWriteProperty<ObservableHost, T> {
private var field = initialValue
override fun getValue(thisRef: ObservableHost, property: KProperty<*>): T {
return field
}
@Synchronized
override fun setValue(thisRef: ObservableHost, property: KProperty<*>, value: T) {
if (field != value) {
field = value
fieldIds.forEach { notifyPropertyChanged(it) }
}
} }
} }
inline fun <reified T> ObservableHost.observable( inline fun <reified T> ObservableHost.set(
initialValue: T, new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int, afterChanged: (T) -> Unit = {}) {
vararg fieldIds: Int, if (old != new) {
crossinline afterChanged: (T) -> Unit setter(new)
) = object : ReadWriteProperty<ObservableHost, T> { fieldIds.forEach { notifyPropertyChanged(it) }
private var field = initialValue afterChanged(new)
override fun getValue(thisRef: ObservableHost, property: KProperty<*>): T {
return field
}
@Synchronized
override fun setValue(thisRef: ObservableHost, property: KProperty<*>, value: T) {
if (field != value) {
field = value
fieldIds.forEach { notifyPropertyChanged(it) }
afterChanged(value)
}
} }
} }
...@@ -16,7 +16,7 @@ buildscript { ...@@ -16,7 +16,7 @@ buildscript {
} }
dependencies { dependencies {
classpath("com.android.tools.build:gradle:4.0.0") classpath("com.android.tools.build:gradle:4.0.1")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${Deps.vNav}") classpath("androidx.navigation:navigation-safe-args-gradle-plugin:${Deps.vNav}")
......
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