mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-01-13 15:53:37 +00:00
Update SettingsItems
This commit is contained in:
parent
2c12fe6eb2
commit
45fabf8e03
@ -11,6 +11,7 @@ import com.topjohnwu.magisk.core.magiskdb.SettingsDao
|
|||||||
import com.topjohnwu.magisk.core.magiskdb.StringDao
|
import com.topjohnwu.magisk.core.magiskdb.StringDao
|
||||||
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
import com.topjohnwu.magisk.core.utils.Utils
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
|
import com.topjohnwu.magisk.core.utils.refreshLocale
|
||||||
import com.topjohnwu.magisk.data.repository.DBConfig
|
import com.topjohnwu.magisk.data.repository.DBConfig
|
||||||
import com.topjohnwu.magisk.di.Protected
|
import com.topjohnwu.magisk.di.Protected
|
||||||
import com.topjohnwu.magisk.ktx.get
|
import com.topjohnwu.magisk.ktx.get
|
||||||
@ -125,7 +126,13 @@ object Config : PreferenceModel, DBConfig {
|
|||||||
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
var showSystemApp by preference(Key.SHOW_SYSTEM_APP, false)
|
||||||
|
|
||||||
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
var customChannelUrl by preference(Key.CUSTOM_CHANNEL, "")
|
||||||
var locale by preference(Key.LOCALE, "")
|
private var localePrefs by preference(Key.LOCALE, "")
|
||||||
|
var locale
|
||||||
|
get() = localePrefs
|
||||||
|
set(value) {
|
||||||
|
localePrefs = value
|
||||||
|
refreshLocale()
|
||||||
|
}
|
||||||
|
|
||||||
var rootMode by dbSettings(Key.ROOT_ACCESS, Value.ROOT_ACCESS_APPS_AND_ADB)
|
var rootMode by dbSettings(Key.ROOT_ACCESS, Value.ROOT_ACCESS_APPS_AND_ADB)
|
||||||
var suMntNamespaceMode by dbSettings(Key.SU_MNT_NS, Value.NAMESPACE_MODE_REQUESTER)
|
var suMntNamespaceMode by dbSettings(Key.SU_MNT_NS, Value.NAMESPACE_MODE_REQUESTER)
|
||||||
|
@ -13,11 +13,10 @@ 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.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
|
||||||
import kotlin.properties.ObservableProperty
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
||||||
|
|
||||||
@ -28,17 +27,13 @@ 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 bindable(true, BR.enabled)
|
var isEnabled by observable(true, BR.enabled)
|
||||||
|
|
||||||
protected open val isFullSpan get() = false
|
protected open val isFullSpan get() = false
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
open fun onPressed(view: View, callback: Callback) {
|
open fun onPressed(view: View, callback: Callback) {
|
||||||
callback.onItemChanged(view, this)
|
callback.onItemChanged(view, this)
|
||||||
|
|
||||||
// notify only after the callback invocation; callback can invalidate the backing data,
|
|
||||||
// which wouldn't be recognized with reverse approach
|
|
||||||
notifyPropertyChanged(BR.description)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun refresh() {}
|
open fun refresh() {}
|
||||||
@ -54,17 +49,6 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
override fun itemSameAs(other: SettingsItem) = this === other
|
override fun itemSameAs(other: SettingsItem) = this === other
|
||||||
override fun contentSameAs(other: SettingsItem) = itemSameAs(other)
|
override fun contentSameAs(other: SettingsItem) = itemSameAs(other)
|
||||||
|
|
||||||
protected inline fun <T> bindable(
|
|
||||||
initialValue: T,
|
|
||||||
fieldId: Int,
|
|
||||||
crossinline setter: (T) -> Unit = {}
|
|
||||||
) = object : ObservableProperty<T>(initialValue) {
|
|
||||||
override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) {
|
|
||||||
setter(newValue)
|
|
||||||
notifyPropertyChanged(fieldId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
@ -79,10 +63,11 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
@get:Bindable
|
@get:Bindable
|
||||||
abstract var value: T
|
abstract var value: T
|
||||||
|
|
||||||
protected inline fun bindableValue(
|
protected inline fun <reified T> value(
|
||||||
initialValue: T,
|
initialValue: T,
|
||||||
crossinline setter: (T) -> Unit
|
vararg fieldIds: Int,
|
||||||
) = bindable(initialValue, BR.value, setter)
|
crossinline setter: (T) -> Unit = {}
|
||||||
|
) = observable(initialValue, BR.value, *fieldIds, afterChanged = setter)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +142,11 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
val selectedEntry
|
val selectedEntry
|
||||||
get() = entries.getOrNull(value)
|
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)
|
||||||
|
|
||||||
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())
|
||||||
|
|
||||||
|
@ -11,13 +11,17 @@ import com.topjohnwu.magisk.R
|
|||||||
import com.topjohnwu.magisk.core.Config
|
import com.topjohnwu.magisk.core.Config
|
||||||
import com.topjohnwu.magisk.core.Const
|
import com.topjohnwu.magisk.core.Const
|
||||||
import com.topjohnwu.magisk.core.Info
|
import com.topjohnwu.magisk.core.Info
|
||||||
import com.topjohnwu.magisk.core.utils.*
|
import com.topjohnwu.magisk.core.utils.BiometricHelper
|
||||||
|
import com.topjohnwu.magisk.core.utils.Utils
|
||||||
|
import com.topjohnwu.magisk.core.utils.availableLocales
|
||||||
|
import com.topjohnwu.magisk.core.utils.currentLocale
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
|
||||||
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
|
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.superuser.Shell
|
import com.topjohnwu.superuser.Shell
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -30,9 +34,8 @@ object Customization : SettingsItem.Section() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object Language : SettingsItem.Selector() {
|
object Language : SettingsItem.Selector() {
|
||||||
override var value by bindableValue(0) {
|
override var value by value(-1) {
|
||||||
Config.locale = entryValues[it]
|
Config.locale = entryValues[it]
|
||||||
refreshLocale()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val title = R.string.language.asTransitive()
|
override val title = R.string.language.asTransitive()
|
||||||
@ -76,12 +79,7 @@ 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: String = resources.getString(R.string.re_app_name)
|
override var value by value(resources.getString(R.string.re_app_name), BR.error)
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
notifyPropertyChanged(BR.value)
|
|
||||||
notifyPropertyChanged(BR.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
val isError get() = value.length > 14 || value.isBlank()
|
val isError get() = value.length > 14 || value.isBlank()
|
||||||
@ -103,29 +101,23 @@ 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 bindableValue(Config.downloadPath) { Config.downloadPath = it }
|
override var value: String by value(Config.downloadPath) { 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 = value
|
var result by observable(value, BR.result, BR.path)
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
notifyPropertyChanged(BR.result)
|
|
||||||
notifyPropertyChanged(BR.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
val path
|
val path get() = File(Environment.getExternalStorageDirectory(), result).absolutePath.orEmpty()
|
||||||
get() = File(Environment.getExternalStorageDirectory(), result).absolutePath.orEmpty()
|
|
||||||
|
|
||||||
override fun getView(context: Context) = DialogSettingsDownloadPathBinding
|
override fun getView(context: Context) = DialogSettingsDownloadPathBinding
|
||||||
.inflate(LayoutInflater.from(context)).also { it.data = this }.root
|
.inflate(LayoutInflater.from(context)).also { it.data = this }.root
|
||||||
}
|
}
|
||||||
|
|
||||||
object UpdateChannel : SettingsItem.Selector() {
|
object UpdateChannel : SettingsItem.Selector() {
|
||||||
override var value by bindableValue(Config.updateChannel) { Config.updateChannel = it }
|
override var value by value(Config.updateChannel) { 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 {
|
||||||
@ -136,15 +128,11 @@ 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 bindableValue(Config.customChannelUrl) { Config.customChannelUrl = it }
|
override var value by value(Config.customChannelUrl) { Config.customChannelUrl = it }
|
||||||
override val intermediate: String? get() = result
|
override val intermediate: String? get() = result
|
||||||
|
|
||||||
@get:Bindable
|
@get:Bindable
|
||||||
var result = value
|
var result by observable(value, BR.result)
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
notifyPropertyChanged(BR.result)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun refresh() {
|
override fun refresh() {
|
||||||
isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL
|
isEnabled = UpdateChannel.value == Config.Value.CUSTOM_CHANNEL
|
||||||
@ -157,7 +145,7 @@ 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 bindableValue(Config.checkUpdate) {
|
override var value by value(Config.checkUpdate) {
|
||||||
Config.checkUpdate = it
|
Config.checkUpdate = it
|
||||||
Utils.scheduleUpdateCheck(get())
|
Utils.scheduleUpdateCheck(get())
|
||||||
}
|
}
|
||||||
@ -171,7 +159,7 @@ 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 bindableValue(Config.suBiometric) { Config.suBiometric = it }
|
override var value by value(Config.suBiometric) { 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() {
|
||||||
@ -186,7 +174,7 @@ 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 bindableValue(Config.suReAuth) { Config.suReAuth = it }
|
override var value by value(Config.suReAuth) { 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()
|
||||||
@ -202,7 +190,7 @@ 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 bindableValue(Config.magiskHide) {
|
override var value by value(Config.magiskHide) {
|
||||||
Config.magiskHide = it
|
Config.magiskHide = it
|
||||||
when {
|
when {
|
||||||
it -> Shell.su("magiskhide --enable").submit()
|
it -> Shell.su("magiskhide --enable").submit()
|
||||||
@ -222,7 +210,7 @@ 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 bindableValue(Config.rootMode) {
|
override var value by value(Config.rootMode) {
|
||||||
Config.rootMode = entryValues[it].toInt()
|
Config.rootMode = entryValues[it].toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +220,7 @@ 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 bindableValue(Config.suMultiuserMode) {
|
override var value by value(Config.suMultiuserMode) {
|
||||||
Config.suMultiuserMode = entryValues[it].toInt()
|
Config.suMultiuserMode = entryValues[it].toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +237,7 @@ 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 bindableValue(Config.suMntNamespaceMode) {
|
override var value by value(Config.suMntNamespaceMode) {
|
||||||
Config.suMntNamespaceMode = entryValues[it].toInt()
|
Config.suMntNamespaceMode = entryValues[it].toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +250,7 @@ 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 bindableValue(Config.suAutoReponse) {
|
override var value by value(Config.suAutoReponse) {
|
||||||
Config.suAutoReponse = entryValues[it].toInt()
|
Config.suAutoReponse = entryValues[it].toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -272,7 +260,7 @@ 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 bindableValue(selected) {
|
override var value by value(selected) {
|
||||||
Config.suDefaultTimeout = entryValues[it].toInt()
|
Config.suDefaultTimeout = entryValues[it].toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +273,7 @@ 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 bindableValue(Config.suNotification) {
|
override var value by value(Config.suNotification) {
|
||||||
Config.suNotification = entryValues[it].toInt()
|
Config.suNotification = entryValues[it].toInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user