mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-11-25 02:55:33 +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.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
|
|||||||
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(
|
|||||||
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>() {
|
|||||||
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 {
|
|||||||
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
|
|||||||
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>() {
|
|||||||
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>() {
|
|||||||
@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>() {
|
|||||||
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
|
|||||||
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(
|
|||||||
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
|
|||||||
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(
|
|||||||
) : 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
|
|||||||
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(
|
|||||||
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
|
|||||||
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(
|
|||||||
) : 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
|
|||||||
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(
|
|||||||
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
|
|||||||
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(
|
|||||||
|
|
||||||
// --- 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
|
|||||||
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(
|
|||||||
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
|
|||||||
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(
|
|||||||
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() {
|
|||||||
@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
|
|||||||
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() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
|||||||
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() {
|
|||||||
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() =
|
|||||||
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() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
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() {
|
|||||||
|
|
||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
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
|
|||||||
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(
|
|||||||
) : 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
|
|||||||
|
|
||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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(
|
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) {
|
||||||
) = object : ReadWriteProperty<ObservableHost, T> {
|
setter(new)
|
||||||
private var field = initialValue
|
fieldIds.forEach { notifyPropertyChanged(it) }
|
||||||
|
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) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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}")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user