Make SettingsItems make much more sense
This commit is contained in:
parent
113eec59f9
commit
4c2570628d
@ -2,13 +2,10 @@ package com.topjohnwu.magisk.model.entity.recycler
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.ArrayRes
|
import androidx.annotation.ArrayRes
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
import androidx.databinding.Bindable
|
import androidx.databinding.Bindable
|
||||||
import androidx.databinding.ViewDataBinding
|
|
||||||
import androidx.recyclerview.widget.StaggeredGridLayoutManager
|
|
||||||
import com.topjohnwu.magisk.BR
|
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
|
||||||
@ -30,30 +27,19 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
var isEnabled = true
|
var isEnabled = true
|
||||||
set(value) = set(value, field, { field = it }, BR.enabled)
|
set(value) = set(value, field, { field = it }, BR.enabled)
|
||||||
|
|
||||||
protected open val isFullSpan get() = false
|
|
||||||
|
|
||||||
@CallSuper
|
|
||||||
open fun onPressed(view: View, callback: Callback) {
|
open fun onPressed(view: View, callback: Callback) {
|
||||||
callback.onItemChanged(view, this)
|
callback.onItemPressed(view, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun refresh() {}
|
open fun refresh() {}
|
||||||
|
|
||||||
override fun onBindingBound(binding: ViewDataBinding) {
|
|
||||||
super.onBindingBound(binding)
|
|
||||||
if (isFullSpan) {
|
|
||||||
val params = binding.root.layoutParams as? StaggeredGridLayoutManager.LayoutParams
|
|
||||||
params?.isFullSpan = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
fun onItemPressed(view: View, item: SettingsItem, method: () -> Unit)
|
fun onItemPressed(view: View, item: SettingsItem, callback: () -> Unit = {})
|
||||||
fun onItemChanged(view: View, item: SettingsItem)
|
fun onItemChanged(view: View, item: SettingsItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,14 +50,38 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
@get:Bindable
|
@get:Bindable
|
||||||
abstract var value: T
|
abstract var value: T
|
||||||
|
|
||||||
|
protected var callbackVars: Pair<View, Callback>? = null
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
override fun onPressed(view: View, callback: Callback) {
|
||||||
|
callbackVars = view to callback
|
||||||
|
callback.onItemPressed(view, this) {
|
||||||
|
onPressed(view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun onPressed(view: View)
|
||||||
|
|
||||||
protected inline fun <reified T> setV(
|
protected inline fun <reified T> setV(
|
||||||
new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int) {
|
new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int, afterChanged: (T) -> Unit = {}) {
|
||||||
set(new, old, setter, BR.value, *fieldIds)
|
set(new, old, setter, BR.value, *fieldIds) {
|
||||||
|
afterChanged(it)
|
||||||
|
callbackVars?.let { pair ->
|
||||||
|
callbackVars = null
|
||||||
|
pair.second.onItemChanged(pair.first, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected inline fun <reified T> setV(
|
protected inline fun <reified T> setV(
|
||||||
new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
|
new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
|
||||||
set(new, old, setter, BR.value, afterChanged = afterChanged)
|
set(new, old, setter, BR.value) {
|
||||||
|
afterChanged(it)
|
||||||
|
callbackVars?.let { pair ->
|
||||||
|
callbackVars = null
|
||||||
|
pair.second.onItemChanged(pair.first, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,20 +89,9 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
override val layoutRes = R.layout.item_settings_toggle
|
override val layoutRes = R.layout.item_settings_toggle
|
||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
override fun onPressed(view: View) {
|
||||||
callback.onItemPressed(view, this) {
|
value = !value
|
||||||
value = !value
|
|
||||||
super.onPressed(view, callback)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onTouched(view: View, callback: Callback, event: MotionEvent): Boolean {
|
|
||||||
if (event.action == MotionEvent.ACTION_UP) {
|
|
||||||
onPressed(view, callback)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Input : Value<String>(), KoinComponent {
|
abstract class Input : Value<String>(), KoinComponent {
|
||||||
@ -103,29 +102,26 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
protected val resources get() = get<Resources>()
|
protected val resources get() = get<Resources>()
|
||||||
protected abstract val intermediate: String?
|
protected abstract val intermediate: String?
|
||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
override fun onPressed(view: View) {
|
||||||
callback.onItemPressed(view, this) {
|
MagiskDialog(view.context)
|
||||||
MagiskDialog(view.context)
|
.applyTitle(title.getText(resources))
|
||||||
.applyTitle(title.getText(resources))
|
.applyView(getView(view.context))
|
||||||
.applyView(getView(view.context))
|
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
|
||||||
.applyButton(MagiskDialog.ButtonType.POSITIVE) {
|
titleRes = android.R.string.ok
|
||||||
titleRes = android.R.string.ok
|
onClick {
|
||||||
onClick {
|
intermediate?.let { result ->
|
||||||
intermediate?.let { result ->
|
preventDismiss = false
|
||||||
preventDismiss = false
|
value = result
|
||||||
value = result
|
it.dismiss()
|
||||||
it.dismiss()
|
return@onClick
|
||||||
super.onPressed(view, callback)
|
|
||||||
return@onClick
|
|
||||||
}
|
|
||||||
preventDismiss = true
|
|
||||||
}
|
}
|
||||||
|
preventDismiss = true
|
||||||
}
|
}
|
||||||
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
}
|
||||||
titleRes = android.R.string.cancel
|
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||||
}
|
titleRes = android.R.string.cancel
|
||||||
.reveal()
|
}
|
||||||
}
|
.reveal()
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun getView(context: Context): View
|
abstract fun getView(context: Context): View
|
||||||
@ -150,7 +146,7 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
protected inline fun <reified T> setS(
|
protected inline fun <reified T> setS(
|
||||||
new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
|
new: T, old: T, setter: (T) -> Unit, afterChanged: (T) -> Unit = {}) {
|
||||||
set(new, old, setter, BR.value, BR.selectedEntry, BR.description, afterChanged = afterChanged)
|
setV(new, old, setter, BR.selectedEntry, BR.description, afterChanged = afterChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Resources.getArrayOrEmpty(id: Int): Array<String> =
|
private fun Resources.getArrayOrEmpty(id: Int): Array<String> =
|
||||||
@ -158,40 +154,29 @@ sealed class SettingsItem : ObservableItem<SettingsItem>() {
|
|||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
override fun onPressed(view: View, callback: Callback) {
|
||||||
if (entries.isEmpty() || entryValues.isEmpty()) return
|
if (entries.isEmpty() || entryValues.isEmpty()) return
|
||||||
callback.onItemPressed(view, this) {
|
super.onPressed(view, callback)
|
||||||
MagiskDialog(view.context)
|
}
|
||||||
.applyTitle(title.getText(resources))
|
|
||||||
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
override fun onPressed(view: View) {
|
||||||
titleRes = android.R.string.cancel
|
MagiskDialog(view.context)
|
||||||
}
|
.applyTitle(title.getText(resources))
|
||||||
.applyAdapter(entries) {
|
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
|
||||||
value = it
|
titleRes = android.R.string.cancel
|
||||||
notifyPropertyChanged(BR.selectedEntry)
|
}
|
||||||
super.onPressed(view, callback)
|
.applyAdapter(entries) {
|
||||||
}
|
value = it
|
||||||
.reveal()
|
}
|
||||||
}
|
.reveal()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Blank : SettingsItem() {
|
abstract class Blank : SettingsItem() {
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_settings_blank
|
override val layoutRes = R.layout.item_settings_blank
|
||||||
|
|
||||||
override fun onPressed(view: View, callback: Callback) {
|
|
||||||
callback.onItemPressed(view, this) {
|
|
||||||
super.onPressed(view, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Section : SettingsItem() {
|
abstract class Section : SettingsItem() {
|
||||||
|
|
||||||
override val layoutRes = R.layout.item_settings_section
|
override val layoutRes = R.layout.item_settings_section
|
||||||
override val isFullSpan get() = true
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,12 @@ class SettingsViewModel(
|
|||||||
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
|
val itemBinding = itemBindingOf<SettingsItem> { it.bindExtra(BR.callback, this) }
|
||||||
val items = diffListOf(createItems())
|
val items = diffListOf(createItems())
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch {
|
||||||
|
Language.loadLanguages(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun createItems(): List<SettingsItem> {
|
private fun createItems(): List<SettingsItem> {
|
||||||
// Customization
|
// Customization
|
||||||
val list = mutableListOf(
|
val list = mutableListOf(
|
||||||
@ -44,9 +50,6 @@ class SettingsViewModel(
|
|||||||
// making theming a pain in the ass. Just forget about it
|
// making theming a pain in the ass. Just forget about it
|
||||||
list.remove(Theme)
|
list.remove(Theme)
|
||||||
}
|
}
|
||||||
viewModelScope.launch {
|
|
||||||
Language.loadLanguages(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manager
|
// Manager
|
||||||
list.addAll(listOf(
|
list.addAll(listOf(
|
||||||
@ -87,39 +90,34 @@ class SettingsViewModel(
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemPressed(view: View, item: SettingsItem, method: () -> Unit) = when (item) {
|
override fun onItemPressed(view: View, item: SettingsItem, callback: () -> Unit) = when (item) {
|
||||||
is DownloadPath -> withExternalRW(method)
|
is DownloadPath -> withExternalRW(callback)
|
||||||
else -> method()
|
is Biometrics -> authenticate(callback)
|
||||||
|
is Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().publish()
|
||||||
|
is ClearRepoCache -> clearRepoCache()
|
||||||
|
is SystemlessHosts -> createHosts()
|
||||||
|
is Restore -> restoreManager()
|
||||||
|
else -> callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onItemChanged(view: View, item: SettingsItem) = when (item) {
|
override fun onItemChanged(view: View, item: SettingsItem) = when (item) {
|
||||||
// use only instances you want, don't declare everything
|
|
||||||
is Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().publish()
|
|
||||||
is Language -> RecreateEvent().publish()
|
is Language -> RecreateEvent().publish()
|
||||||
|
|
||||||
is UpdateChannel -> openUrlIfNecessary(view)
|
is UpdateChannel -> openUrlIfNecessary(view)
|
||||||
is Biometrics -> authenticateOrRevert()
|
is Hide -> PatchAPK.hideManager(view.context, item.value)
|
||||||
is ClearRepoCache -> clearRepoCache()
|
|
||||||
is SystemlessHosts -> createHosts()
|
|
||||||
is Hide -> updateManager(hide = true)
|
|
||||||
is Restore -> updateManager(hide = false)
|
|
||||||
|
|
||||||
else -> Unit
|
else -> Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openUrlIfNecessary(view: View) {
|
private fun openUrlIfNecessary(view: View) {
|
||||||
UpdateChannelUrl.refresh()
|
UpdateChannelUrl.refresh()
|
||||||
if (UpdateChannelUrl.isEnabled && UpdateChannelUrl.value.isBlank()) {
|
if (UpdateChannelUrl.isEnabled && UpdateChannelUrl.value.isBlank()) {
|
||||||
UpdateChannelUrl.onPressed(view, this@SettingsViewModel)
|
UpdateChannelUrl.onPressed(view, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun authenticateOrRevert() {
|
private fun authenticate(callback: () -> Unit) {
|
||||||
// immediately revert the preference
|
|
||||||
Biometrics.value = !Biometrics.value
|
|
||||||
BiometricDialog {
|
BiometricDialog {
|
||||||
// allow the change on success
|
// allow the change on success
|
||||||
onSuccess { Biometrics.value = !Biometrics.value }
|
onSuccess { callback() }
|
||||||
}.publish()
|
}.publish()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,13 +134,9 @@ class SettingsViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateManager(hide: Boolean) {
|
private fun restoreManager() {
|
||||||
if (hide) {
|
DownloadService(get()) {
|
||||||
PatchAPK.hideManager(get(), Hide.value)
|
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
||||||
} else {
|
|
||||||
DownloadService(get()) {
|
|
||||||
subject = DownloadSubject.Manager(Configuration.APK.Restore)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:alpha="@{item.enabled ? 1f : .5f}"
|
android:alpha="@{item.enabled ? 1f : .5f}"
|
||||||
android:onClick="@{(view) -> callback.onItemChanged(view, item)}"
|
android:onClick="@{(view) -> item.onPressed(view, callback)}"
|
||||||
tools:layout_gravity="center">
|
tools:layout_gravity="center">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
@ -93,4 +93,4 @@
|
|||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
</layout>
|
</layout>
|
||||||
|
Loading…
Reference in New Issue
Block a user