mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-21 23:47:39 +00:00
Reduce usage of delegation
This commit is contained in:
parent
ba31c6b625
commit
6c6368fd81
@ -7,17 +7,21 @@ import com.topjohnwu.magisk.databinding.ObservableItem
|
||||
import com.topjohnwu.magisk.ktx.timeDateFormat
|
||||
import com.topjohnwu.magisk.ktx.toTime
|
||||
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>() {
|
||||
|
||||
override val layoutRes = R.layout.item_log_access_md2
|
||||
|
||||
val date = item.time.toTime(timeDateFormat)
|
||||
|
||||
@get:Bindable
|
||||
var isTop by observable(false, BR.top)
|
||||
var isTop = false
|
||||
set(value) = set(value, field, { field = it }, BR.top)
|
||||
|
||||
@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
|
||||
|
||||
|
@ -11,7 +11,7 @@ import com.topjohnwu.magisk.core.model.module.Repo
|
||||
import com.topjohnwu.magisk.databinding.ComparableRvItem
|
||||
import com.topjohnwu.magisk.databinding.ObservableItem
|
||||
import com.topjohnwu.magisk.ui.module.ModuleViewModel
|
||||
import com.topjohnwu.magisk.utils.observable
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
|
||||
object InstallModule : ComparableRvItem<InstallModule>() {
|
||||
override val layoutRes = R.layout.item_module_download
|
||||
@ -34,11 +34,16 @@ class SectionTitle(
|
||||
override val layoutRes = R.layout.item_section_md2
|
||||
|
||||
@get:Bindable
|
||||
var button by observable(_button, BR.button)
|
||||
var button = _button
|
||||
set(value) = set(value, field, { field = it }, BR.button)
|
||||
|
||||
@get:Bindable
|
||||
var icon by observable(_icon, BR.icon)
|
||||
var icon = _icon
|
||||
set(value) = set(value, field, { field = it }, BR.icon)
|
||||
|
||||
@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) {
|
||||
super.onBindingBound(binding)
|
||||
@ -54,9 +59,13 @@ sealed class RepoItem(val item: Repo) : ObservableItem<RepoItem>() {
|
||||
override val layoutRes: Int = R.layout.item_repo_md2
|
||||
|
||||
@get:Bindable
|
||||
var progress by observable(0, BR.progress)
|
||||
var progress = 0
|
||||
set(value) = set(value, field, { field = it }, BR.progress)
|
||||
|
||||
@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 itemSameAs(other: RepoItem): Boolean = item.id == other.item.id
|
||||
@ -75,7 +84,8 @@ class ModuleItem(val item: Module) : ObservableItem<ModuleItem>(), Observable {
|
||||
override val layoutRes = R.layout.item_module_md2
|
||||
|
||||
@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
|
||||
var isEnabled
|
||||
|
@ -13,7 +13,7 @@ import com.topjohnwu.magisk.BR
|
||||
import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.databinding.ObservableItem
|
||||
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 org.koin.core.KoinComponent
|
||||
import org.koin.core.get
|
||||
@ -27,7 +27,8 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
||||
open val description: TransitiveText get() = TransitiveText.EMPTY
|
||||
|
||||
@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
|
||||
|
||||
@ -63,12 +64,15 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
||||
@get:Bindable
|
||||
abstract var value: T
|
||||
|
||||
protected inline fun <reified T> value(
|
||||
initialValue: T,
|
||||
vararg fieldIds: Int,
|
||||
crossinline setter: (T) -> Unit = {}
|
||||
) = observable(initialValue, BR.value, *fieldIds, afterChanged = setter)
|
||||
protected inline fun <reified T> setV(
|
||||
new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int) {
|
||||
set(new, old, setter, BR.value, *fieldIds)
|
||||
}
|
||||
|
||||
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>() {
|
||||
@ -142,10 +146,10 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
||||
val selectedEntry
|
||||
get() = entries.getOrNull(value)
|
||||
|
||||
/* override */ protected inline fun value(
|
||||
initialValue: Int,
|
||||
crossinline setter: (Int) -> Unit
|
||||
) = observable(initialValue, BR.value, BR.selectedEntry, BR.description, afterChanged = setter)
|
||||
protected inline fun <reified T> setS(
|
||||
new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
|
||||
set(new, old, setter, BR.value, BR.selectedEntry, BR.description, afterChanged = afterChanged)
|
||||
}
|
||||
|
||||
private fun Resources.getArrayOrEmpty(id: Int): Array<String> =
|
||||
runCatching { getStringArray(id) }.getOrDefault(emptyArray())
|
||||
|
@ -17,7 +17,7 @@ import com.topjohnwu.magisk.core.base.BaseActivity
|
||||
import com.topjohnwu.magisk.model.events.*
|
||||
import com.topjohnwu.magisk.model.navigation.NavigationWrapper
|
||||
import com.topjohnwu.magisk.utils.ObservableHost
|
||||
import com.topjohnwu.magisk.utils.observable
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import kotlinx.coroutines.Job
|
||||
import org.koin.core.KoinComponent
|
||||
|
||||
@ -42,9 +42,11 @@ abstract class BaseViewModel(
|
||||
val viewEvents: LiveData<ViewEvent> get() = _viewEvents
|
||||
|
||||
@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 var runningJob: Job? = null
|
||||
|
@ -20,7 +20,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||
import com.topjohnwu.magisk.ui.base.diffListOf
|
||||
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 kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -34,9 +34,12 @@ class FlashViewModel(
|
||||
) : BaseViewModel() {
|
||||
|
||||
@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
|
||||
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 items = diffListOf<ConsoleItem>()
|
||||
|
@ -17,7 +17,7 @@ import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||
import com.topjohnwu.magisk.ui.base.Queryable
|
||||
import com.topjohnwu.magisk.ui.base.filterableListOf
|
||||
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.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -29,14 +29,16 @@ class HideViewModel(
|
||||
override val queryDelay = 1000L
|
||||
|
||||
@get:Bindable
|
||||
var isShowSystem by observable(false, BR.showSystem) {
|
||||
submitQuery()
|
||||
}
|
||||
var isShowSystem = false
|
||||
set(value) = set(value, field, { field = it }, BR.showSystem){
|
||||
submitQuery()
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var query by observable("", BR.query) {
|
||||
submitQuery()
|
||||
}
|
||||
var query = ""
|
||||
set(value) = set(value, field, { field = it }, BR.query){
|
||||
submitQuery()
|
||||
}
|
||||
|
||||
val items = filterableListOf<HideItem>()
|
||||
val itemBinding = itemBindingOf<HideItem> {
|
||||
|
@ -27,7 +27,7 @@ import com.topjohnwu.magisk.model.events.dialog.ManagerInstallDialog
|
||||
import com.topjohnwu.magisk.model.events.dialog.UninstallDialog
|
||||
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||
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 kotlinx.coroutines.launch
|
||||
import me.tatarka.bindingcollectionadapter2.BR
|
||||
@ -42,25 +42,37 @@ class HomeViewModel(
|
||||
) : BaseViewModel() {
|
||||
|
||||
@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
|
||||
var stateMagisk by observable(MagiskState.LOADING, BR.stateMagisk)
|
||||
var stateMagisk = MagiskState.LOADING
|
||||
set(value) = set(value, field, { field = it }, BR.stateMagisk)
|
||||
|
||||
@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
|
||||
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() =
|
||||
"${Info.env.magiskVersionString} (${Info.env.magiskVersionCode})"
|
||||
val magiskMode get() = R.string.home_status_normal.res()
|
||||
|
||||
@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 {
|
||||
"${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) (${it.version})"
|
||||
} ?: "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
|
||||
val statePackageName = packageName
|
||||
|
||||
@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 itemBinding = itemBindingOf<HomeItem> {
|
||||
|
@ -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.dialog.SecondSlotWarningDialog
|
||||
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 kotlinx.coroutines.launch
|
||||
import org.koin.core.get
|
||||
@ -30,25 +30,34 @@ class InstallViewModel(
|
||||
val isAB get() = Info.isAB
|
||||
|
||||
@get:Bindable
|
||||
var step by observable(0, BR.step)
|
||||
var step = 0
|
||||
set(value) = set(value, field, { field = it }, BR.step)
|
||||
|
||||
@get:Bindable
|
||||
var method by observable(-1, BR.method) {
|
||||
when (it) {
|
||||
R.id.method_patch -> {
|
||||
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||
RequestFileEvent().publish()
|
||||
}
|
||||
R.id.method_inactive_slot -> {
|
||||
SecondSlotWarningDialog().publish()
|
||||
var method = -1
|
||||
set(value) = set(value, field, { field = it }, BR.method) {
|
||||
when (it) {
|
||||
R.id.method_patch -> {
|
||||
Utils.toast(R.string.patch_file_msg, Toast.LENGTH_LONG)
|
||||
RequestFileEvent().publish()
|
||||
}
|
||||
R.id.method_inactive_slot -> {
|
||||
SecondSlotWarningDialog().publish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@get:Bindable
|
||||
var progress by observable(0, BR.progress)
|
||||
var progress = 0
|
||||
set(value) = set(value, field, { field = it }, BR.progress)
|
||||
|
||||
@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
|
||||
var notes by observable("", BR.notes)
|
||||
var notes = ""
|
||||
set(value) = set(value, field, { field = it }, BR.notes)
|
||||
|
||||
init {
|
||||
RemoteFileService.reset()
|
||||
|
@ -13,7 +13,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||
import com.topjohnwu.magisk.ui.base.diffListOf
|
||||
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 kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@ -41,7 +41,8 @@ class LogViewModel(
|
||||
|
||||
// --- magisk log
|
||||
@get:Bindable
|
||||
var consoleText by observable(" ", BR.consoleText)
|
||||
var consoleText= " "
|
||||
set(value) = set(value, field, { field = it }, BR.consoleText)
|
||||
|
||||
override fun refresh() = viewModelScope.launch {
|
||||
consoleText = repo.fetchMagiskLogs()
|
||||
|
@ -23,7 +23,7 @@ import com.topjohnwu.magisk.model.events.SnackbarEvent
|
||||
import com.topjohnwu.magisk.model.events.dialog.ModuleInstallDialog
|
||||
import com.topjohnwu.magisk.ui.base.*
|
||||
import com.topjohnwu.magisk.utils.EndlessRecyclerScrollListener
|
||||
import com.topjohnwu.magisk.utils.observable
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import kotlinx.coroutines.*
|
||||
import me.tatarka.bindingcollectionadapter2.collections.MergeObservableList
|
||||
import kotlin.math.roundToInt
|
||||
@ -53,17 +53,21 @@ class ModuleViewModel(
|
||||
private var remoteJob: Job? = null
|
||||
|
||||
@get:Bindable
|
||||
var isRemoteLoading by observable(false, BR.remoteLoading)
|
||||
var isRemoteLoading = false
|
||||
set(value) = set(value, field, { field = it }, BR.remoteLoading)
|
||||
|
||||
@get:Bindable
|
||||
var query by observable("", BR.query) {
|
||||
submitQuery()
|
||||
// Yes we do lie about the search being loaded
|
||||
searchLoading = true
|
||||
}
|
||||
var query = ""
|
||||
set(value) = set(value, field, { field = it }, BR.query) {
|
||||
submitQuery()
|
||||
// Yes we do lie about the search being loaded
|
||||
searchLoading = true
|
||||
}
|
||||
|
||||
@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 itemSearchBinding = itemBindingOf<RepoItem> {
|
||||
it.bindExtra(BR.viewModel, this)
|
||||
|
@ -6,7 +6,7 @@ import com.topjohnwu.magisk.R
|
||||
import com.topjohnwu.magisk.model.events.CheckSafetyNetEvent
|
||||
import com.topjohnwu.magisk.ui.base.BaseViewModel
|
||||
import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.*
|
||||
import com.topjohnwu.magisk.utils.observable
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import org.json.JSONObject
|
||||
|
||||
enum class SafetyNetState {
|
||||
@ -21,13 +21,20 @@ data class SafetyNetResult(
|
||||
class SafetynetViewModel : BaseViewModel() {
|
||||
|
||||
@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
|
||||
var ctsState by observable(false, BR.ctsState)
|
||||
var ctsState = false
|
||||
set(value) = set(value, field, { field = it }, BR.ctsState)
|
||||
|
||||
@get:Bindable
|
||||
var basicIntegrityState by observable(false, BR.basicIntegrityState)
|
||||
var basicIntegrityState = false
|
||||
set(value) = set(value, field, { field = it }, BR.basicIntegrityState)
|
||||
|
||||
@get:Bindable
|
||||
var evalType by observable("")
|
||||
var evalType = ""
|
||||
set(value) = set(value, field, { field = it }, BR.evalType)
|
||||
|
||||
@get:Bindable
|
||||
val isChecking get() = currentState == LOADING
|
||||
@ -36,7 +43,8 @@ class SafetynetViewModel : BaseViewModel() {
|
||||
@get:Bindable
|
||||
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 {
|
||||
cachedResult?.also {
|
||||
|
@ -21,7 +21,7 @@ import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
||||
import com.topjohnwu.magisk.ktx.get
|
||||
import com.topjohnwu.magisk.model.entity.recycler.SettingsItem
|
||||
import com.topjohnwu.magisk.utils.asTransitive
|
||||
import com.topjohnwu.magisk.utils.observable
|
||||
import com.topjohnwu.magisk.utils.set
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
@ -34,9 +34,10 @@ object Customization : SettingsItem.Section() {
|
||||
}
|
||||
|
||||
object Language : SettingsItem.Selector() {
|
||||
override var value by value(-1) {
|
||||
Config.locale = entryValues[it]
|
||||
}
|
||||
override var value = -1
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.locale = entryValues[it]
|
||||
}
|
||||
|
||||
override val title = R.string.language.asTransitive()
|
||||
override var entries = emptyArray<String>()
|
||||
@ -49,7 +50,6 @@ object Language : SettingsItem.Selector() {
|
||||
entryValues = values
|
||||
val selectedLocale = currentLocale.getDisplayName(currentLocale)
|
||||
value = names.indexOfFirst { it == selectedLocale }.let { if (it == -1) 0 else it }
|
||||
notifyPropertyChanged(BR.selectedEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -79,7 +79,8 @@ object Hide : SettingsItem.Input() {
|
||||
override val title = R.string.settings_hide_manager_title.asTransitive()
|
||||
override val description = R.string.settings_hide_manager_summary.asTransitive()
|
||||
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
|
||||
val isError get() = value.length > 14 || value.isBlank()
|
||||
@ -101,13 +102,15 @@ fun HideOrRestore() =
|
||||
if (get<Context>().packageName == BuildConfig.APPLICATION_ID) Hide else Restore
|
||||
|
||||
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 intermediate: String?
|
||||
get() = if (Utils.ensureDownloadPath(result) != null) result else null
|
||||
|
||||
@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
|
||||
val path get() = File(Environment.getExternalStorageDirectory(), result).absolutePath.orEmpty()
|
||||
@ -117,7 +120,8 @@ object DownloadPath : SettingsItem.Input() {
|
||||
}
|
||||
|
||||
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 entries get() = resources.getStringArray(R.array.update_channel).let {
|
||||
@ -128,11 +132,13 @@ object UpdateChannel : SettingsItem.Selector() {
|
||||
|
||||
object UpdateChannelUrl : SettingsItem.Input() {
|
||||
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
|
||||
|
||||
@get:Bindable
|
||||
var result by observable(value, BR.result)
|
||||
var result = value
|
||||
set(value) = set(value, field, { field = it }, BR.result)
|
||||
|
||||
override fun refresh() {
|
||||
isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL
|
||||
@ -145,10 +151,11 @@ object UpdateChannelUrl : SettingsItem.Input() {
|
||||
object UpdateChecker : SettingsItem.Toggle() {
|
||||
override val title = R.string.settings_check_update_title.asTransitive()
|
||||
override val description = R.string.settings_check_update_summary.asTransitive()
|
||||
override var value by value(Config.checkUpdate) {
|
||||
Config.checkUpdate = it
|
||||
Utils.scheduleUpdateCheck(get())
|
||||
}
|
||||
override var value = Config.checkUpdate
|
||||
set(value) = setV(value, field, { field = it }) {
|
||||
Config.checkUpdate = it
|
||||
Utils.scheduleUpdateCheck(get())
|
||||
}
|
||||
}
|
||||
|
||||
// check whether is module already installed beforehand?
|
||||
@ -159,7 +166,8 @@ object SystemlessHosts : SettingsItem.Blank() {
|
||||
|
||||
object Biometrics : SettingsItem.Toggle() {
|
||||
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 fun refresh() {
|
||||
@ -174,7 +182,8 @@ object Biometrics : SettingsItem.Toggle() {
|
||||
object Reauthenticate : SettingsItem.Toggle() {
|
||||
override val title = R.string.settings_su_reauth_title.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() {
|
||||
isEnabled = Build.VERSION.SDK_INT < Build.VERSION_CODES.O && Utils.showSuperUser()
|
||||
@ -190,13 +199,14 @@ object Magisk : SettingsItem.Section() {
|
||||
object MagiskHide : SettingsItem.Toggle() {
|
||||
override val title = R.string.magiskhide.asTransitive()
|
||||
override val description = R.string.settings_magiskhide_summary.asTransitive()
|
||||
override var value by value(Config.magiskHide) {
|
||||
Config.magiskHide = it
|
||||
when {
|
||||
it -> Shell.su("magiskhide --enable").submit()
|
||||
else -> Shell.su("magiskhide --disable").submit()
|
||||
override var value = Config.magiskHide
|
||||
set(value) = setV(value, field, { field = it }) {
|
||||
Config.magiskHide = it
|
||||
when {
|
||||
it -> Shell.su("magiskhide --enable").submit()
|
||||
else -> Shell.su("magiskhide --disable").submit()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Superuser
|
||||
@ -210,9 +220,10 @@ object AccessMode : SettingsItem.Selector() {
|
||||
override val entryRes = R.array.su_access
|
||||
override val entryValRes = R.array.value_array
|
||||
|
||||
override var value by value(Config.rootMode) {
|
||||
Config.rootMode = entryValues[it].toInt()
|
||||
}
|
||||
override var value = Config.rootMode
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.rootMode = entryValues[it].toInt()
|
||||
}
|
||||
}
|
||||
|
||||
object MultiuserMode : SettingsItem.Selector() {
|
||||
@ -220,9 +231,10 @@ object MultiuserMode : SettingsItem.Selector() {
|
||||
override val entryRes = R.array.multiuser_mode
|
||||
override val entryValRes = R.array.value_array
|
||||
|
||||
override var value by value(Config.suMultiuserMode) {
|
||||
Config.suMultiuserMode = entryValues[it].toInt()
|
||||
}
|
||||
override var value = Config.suMultiuserMode
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.suMultiuserMode = entryValues[it].toInt()
|
||||
}
|
||||
|
||||
override val description
|
||||
get() = resources.getStringArray(R.array.multiuser_summary)[value].asTransitive()
|
||||
@ -237,9 +249,10 @@ object MountNamespaceMode : SettingsItem.Selector() {
|
||||
override val entryRes = R.array.namespace
|
||||
override val entryValRes = R.array.value_array
|
||||
|
||||
override var value by value(Config.suMntNamespaceMode) {
|
||||
Config.suMntNamespaceMode = entryValues[it].toInt()
|
||||
}
|
||||
override var value = Config.suMntNamespaceMode
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.suMntNamespaceMode = entryValues[it].toInt()
|
||||
}
|
||||
|
||||
override val description
|
||||
get() = resources.getStringArray(R.array.namespace_summary)[value].asTransitive()
|
||||
@ -250,9 +263,10 @@ object AutomaticResponse : SettingsItem.Selector() {
|
||||
override val entryRes = R.array.auto_response
|
||||
override val entryValRes = R.array.value_array
|
||||
|
||||
override var value by value(Config.suAutoReponse) {
|
||||
Config.suAutoReponse = entryValues[it].toInt()
|
||||
}
|
||||
override var value = Config.suAutoReponse
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.suAutoReponse = entryValues[it].toInt()
|
||||
}
|
||||
}
|
||||
|
||||
object RequestTimeout : SettingsItem.Selector() {
|
||||
@ -260,9 +274,10 @@ object RequestTimeout : SettingsItem.Selector() {
|
||||
override val entryRes = R.array.request_timeout
|
||||
override val entryValRes = R.array.request_timeout_value
|
||||
|
||||
override var value by value(selected) {
|
||||
Config.suDefaultTimeout = entryValues[it].toInt()
|
||||
}
|
||||
override var value = selected
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.suDefaultTimeout = entryValues[it].toInt()
|
||||
}
|
||||
|
||||
private val selected: Int
|
||||
get() = entryValues.indexOfFirst { it.toInt() == Config.suDefaultTimeout }
|
||||
@ -273,7 +288,8 @@ object SUNotification : SettingsItem.Selector() {
|
||||
override val entryRes = R.array.su_notification
|
||||
override val entryValRes = R.array.value_array
|
||||
|
||||
override var value by value(Config.suNotification) {
|
||||
Config.suNotification = entryValues[it].toInt()
|
||||
}
|
||||
override var value = Config.suNotification
|
||||
set(value) = setS(value, field, { field = it }) {
|
||||
Config.suNotification = entryValues[it].toInt()
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||
import com.topjohnwu.magisk.model.entity.recycler.SpinnerRvItem
|
||||
import com.topjohnwu.magisk.model.events.DieEvent
|
||||
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 kotlinx.coroutines.launch
|
||||
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
|
||||
@ -34,19 +34,32 @@ class SuRequestViewModel(
|
||||
) : BaseViewModel() {
|
||||
|
||||
@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
|
||||
var title by observable("", BR.title)
|
||||
var title = ""
|
||||
set(value) = set(value, field, { field = it }, BR.title)
|
||||
|
||||
@get:Bindable
|
||||
var packageName by observable("", BR.packageName)
|
||||
var packageName = ""
|
||||
set(value) = set(value, field, { field = it }, BR.packageName)
|
||||
|
||||
@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
|
||||
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
|
||||
var selectedItemPosition by observable(0, BR.selectedItemPosition)
|
||||
var selectedItemPosition = 0
|
||||
set(value) = set(value, field, { field = it }, BR.selectedItemPosition)
|
||||
|
||||
@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) }
|
||||
val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply {
|
||||
|
@ -2,8 +2,6 @@ package com.topjohnwu.magisk.utils
|
||||
|
||||
import androidx.databinding.Observable
|
||||
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
|
||||
@ -52,105 +50,32 @@ interface ObservableHost : Observable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares delegated property in [ObservableHost] parent. This property is available for DataBinding
|
||||
* 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.
|
||||
* Injects boilerplate implementation for {@literal @}[androidx.databinding.Bindable] field setters.
|
||||
*
|
||||
* # Examples:
|
||||
*
|
||||
* ## The most basic usage would probably be:
|
||||
* ```kotlin
|
||||
* @get:Bindable
|
||||
* var myField by observable(defaultValue, BR.myField)
|
||||
* private set
|
||||
* var myField = defaultValue
|
||||
* 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
|
||||
// Generic type is reified to optimize primitive types
|
||||
inline fun <reified T> ObservableHost.observable(
|
||||
initialValue: T,
|
||||
fieldId: 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
|
||||
notifyPropertyChanged(fieldId)
|
||||
}
|
||||
inline fun <reified T> ObservableHost.set(
|
||||
new: T, old: T, setter: (T) -> Unit, fieldId: Int, afterChanged: (T) -> Unit = {}) {
|
||||
if (old != new) {
|
||||
setter(new)
|
||||
notifyPropertyChanged(fieldId)
|
||||
afterChanged(new)
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
initialValue: T,
|
||||
vararg fieldIds: Int,
|
||||
crossinline afterChanged: (T) -> Unit
|
||||
) = 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) }
|
||||
afterChanged(value)
|
||||
}
|
||||
inline fun <reified T> ObservableHost.set(
|
||||
new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int, afterChanged: (T) -> Unit = {}) {
|
||||
if (old != new) {
|
||||
setter(new)
|
||||
fieldIds.forEach { notifyPropertyChanged(it) }
|
||||
afterChanged(new)
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ buildscript {
|
||||
}
|
||||
|
||||
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("androidx.navigation:navigation-safe-args-gradle-plugin:${Deps.vNav}")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user