From 4c2570628d6869df546443e5a2dd0d72aca43d76 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 17 Jul 2020 03:02:58 -0700 Subject: [PATCH] Make SettingsItems make much more sense --- .../model/entity/recycler/SettingsItem.kt | 141 ++++++++---------- .../magisk/ui/settings/SettingsViewModel.kt | 48 +++--- .../main/res/layout/item_settings_blank.xml | 4 +- 3 files changed, 86 insertions(+), 107 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/SettingsItem.kt b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/SettingsItem.kt index 8a685468b..c7a62594d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/SettingsItem.kt +++ b/app/src/main/java/com/topjohnwu/magisk/model/entity/recycler/SettingsItem.kt @@ -2,13 +2,10 @@ package com.topjohnwu.magisk.model.entity.recycler import android.content.Context import android.content.res.Resources -import android.view.MotionEvent import android.view.View import androidx.annotation.ArrayRes import androidx.annotation.CallSuper import androidx.databinding.Bindable -import androidx.databinding.ViewDataBinding -import androidx.recyclerview.widget.StaggeredGridLayoutManager import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.R import com.topjohnwu.magisk.databinding.ObservableItem @@ -30,30 +27,19 @@ sealed class SettingsItem : ObservableItem() { var isEnabled = true set(value) = set(value, field, { field = it }, BR.enabled) - protected open val isFullSpan get() = false - - @CallSuper open fun onPressed(view: View, callback: Callback) { - callback.onItemChanged(view, this) + callback.onItemPressed(view, this) } 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 contentSameAs(other: SettingsItem) = itemSameAs(other) // --- interface Callback { - fun onItemPressed(view: View, item: SettingsItem, method: () -> Unit) + fun onItemPressed(view: View, item: SettingsItem, callback: () -> Unit = {}) fun onItemChanged(view: View, item: SettingsItem) } @@ -64,14 +50,38 @@ sealed class SettingsItem : ObservableItem() { @get:Bindable abstract var value: T + protected var callbackVars: Pair? = 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 setV( - new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int) { - set(new, old, setter, BR.value, *fieldIds) + new: T, old: T, setter: (T) -> Unit, vararg fieldIds: Int, afterChanged: (T) -> Unit = {}) { + set(new, old, setter, BR.value, *fieldIds) { + afterChanged(it) + callbackVars?.let { pair -> + callbackVars = null + pair.second.onItemChanged(pair.first, this) + } + } } protected inline fun setV( 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() { override val layoutRes = R.layout.item_settings_toggle - override fun onPressed(view: View, callback: Callback) { - callback.onItemPressed(view, this) { - value = !value - super.onPressed(view, callback) - } + override fun onPressed(view: View) { + value = !value } - - fun onTouched(view: View, callback: Callback, event: MotionEvent): Boolean { - if (event.action == MotionEvent.ACTION_UP) { - onPressed(view, callback) - } - return true - } - } abstract class Input : Value(), KoinComponent { @@ -103,29 +102,26 @@ sealed class SettingsItem : ObservableItem() { protected val resources get() = get() protected abstract val intermediate: String? - override fun onPressed(view: View, callback: Callback) { - callback.onItemPressed(view, this) { - MagiskDialog(view.context) - .applyTitle(title.getText(resources)) - .applyView(getView(view.context)) - .applyButton(MagiskDialog.ButtonType.POSITIVE) { - titleRes = android.R.string.ok - onClick { - intermediate?.let { result -> - preventDismiss = false - value = result - it.dismiss() - super.onPressed(view, callback) - return@onClick - } - preventDismiss = true + override fun onPressed(view: View) { + MagiskDialog(view.context) + .applyTitle(title.getText(resources)) + .applyView(getView(view.context)) + .applyButton(MagiskDialog.ButtonType.POSITIVE) { + titleRes = android.R.string.ok + onClick { + intermediate?.let { result -> + preventDismiss = false + value = result + it.dismiss() + return@onClick } + preventDismiss = true } - .applyButton(MagiskDialog.ButtonType.NEGATIVE) { - titleRes = android.R.string.cancel - } - .reveal() - } + } + .applyButton(MagiskDialog.ButtonType.NEGATIVE) { + titleRes = android.R.string.cancel + } + .reveal() } abstract fun getView(context: Context): View @@ -150,7 +146,7 @@ sealed class SettingsItem : ObservableItem() { protected inline fun setS( 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 = @@ -158,40 +154,29 @@ sealed class SettingsItem : ObservableItem() { override fun onPressed(view: View, callback: Callback) { if (entries.isEmpty() || entryValues.isEmpty()) return - callback.onItemPressed(view, this) { - MagiskDialog(view.context) - .applyTitle(title.getText(resources)) - .applyButton(MagiskDialog.ButtonType.NEGATIVE) { - titleRes = android.R.string.cancel - } - .applyAdapter(entries) { - value = it - notifyPropertyChanged(BR.selectedEntry) - super.onPressed(view, callback) - } - .reveal() - } + super.onPressed(view, callback) + } + + override fun onPressed(view: View) { + MagiskDialog(view.context) + .applyTitle(title.getText(resources)) + .applyButton(MagiskDialog.ButtonType.NEGATIVE) { + titleRes = android.R.string.cancel + } + .applyAdapter(entries) { + value = it + } + .reveal() } } abstract class Blank : SettingsItem() { - 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() { - override val layoutRes = R.layout.item_settings_section - override val isFullSpan get() = true - } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt index 92f1487d1..c5ef91c32 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/topjohnwu/magisk/ui/settings/SettingsViewModel.kt @@ -33,6 +33,12 @@ class SettingsViewModel( val itemBinding = itemBindingOf { it.bindExtra(BR.callback, this) } val items = diffListOf(createItems()) + init { + viewModelScope.launch { + Language.loadLanguages(this) + } + } + private fun createItems(): List { // Customization val list = mutableListOf( @@ -44,9 +50,6 @@ class SettingsViewModel( // making theming a pain in the ass. Just forget about it list.remove(Theme) } - viewModelScope.launch { - Language.loadLanguages(this) - } // Manager list.addAll(listOf( @@ -87,39 +90,34 @@ class SettingsViewModel( return list } - override fun onItemPressed(view: View, item: SettingsItem, method: () -> Unit) = when (item) { - is DownloadPath -> withExternalRW(method) - else -> method() + override fun onItemPressed(view: View, item: SettingsItem, callback: () -> Unit) = when (item) { + is DownloadPath -> withExternalRW(callback) + 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) { - // use only instances you want, don't declare everything - is Theme -> SettingsFragmentDirections.actionSettingsFragmentToThemeFragment().publish() is Language -> RecreateEvent().publish() - is UpdateChannel -> openUrlIfNecessary(view) - is Biometrics -> authenticateOrRevert() - is ClearRepoCache -> clearRepoCache() - is SystemlessHosts -> createHosts() - is Hide -> updateManager(hide = true) - is Restore -> updateManager(hide = false) - + is Hide -> PatchAPK.hideManager(view.context, item.value) else -> Unit } private fun openUrlIfNecessary(view: View) { UpdateChannelUrl.refresh() if (UpdateChannelUrl.isEnabled && UpdateChannelUrl.value.isBlank()) { - UpdateChannelUrl.onPressed(view, this@SettingsViewModel) + UpdateChannelUrl.onPressed(view, this) } } - private fun authenticateOrRevert() { - // immediately revert the preference - Biometrics.value = !Biometrics.value + private fun authenticate(callback: () -> Unit) { BiometricDialog { // allow the change on success - onSuccess { Biometrics.value = !Biometrics.value } + onSuccess { callback() } }.publish() } @@ -136,13 +134,9 @@ class SettingsViewModel( } } - private fun updateManager(hide: Boolean) { - if (hide) { - PatchAPK.hideManager(get(), Hide.value) - } else { - DownloadService(get()) { - subject = DownloadSubject.Manager(Configuration.APK.Restore) - } + private fun restoreManager() { + DownloadService(get()) { + subject = DownloadSubject.Manager(Configuration.APK.Restore) } } diff --git a/app/src/main/res/layout/item_settings_blank.xml b/app/src/main/res/layout/item_settings_blank.xml index 31de4e803..7065e39a0 100644 --- a/app/src/main/res/layout/item_settings_blank.xml +++ b/app/src/main/res/layout/item_settings_blank.xml @@ -21,7 +21,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:alpha="@{item.enabled ? 1f : .5f}" - android:onClick="@{(view) -> callback.onItemChanged(view, item)}" + android:onClick="@{(view) -> item.onPressed(view, callback)}" tools:layout_gravity="center"> - \ No newline at end of file +