Don't hold resources in Settings objects

This commit is contained in:
topjohnwu 2021-04-18 04:14:43 -07:00
parent 1418bc454d
commit 649b49ff45
3 changed files with 39 additions and 49 deletions

View File

@ -3,18 +3,14 @@ package com.topjohnwu.magisk.ui.settings
import android.content.Context
import android.content.res.Resources
import android.view.View
import androidx.annotation.ArrayRes
import androidx.annotation.CallSuper
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ObservableItem
import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.magisk.utils.set
import com.topjohnwu.magisk.view.MagiskDialog
import org.koin.core.component.KoinComponent
sealed class BaseSettingsItem : ObservableItem<BaseSettingsItem>() {
@ -141,34 +137,29 @@ sealed class BaseSettingsItem : ObservableItem<BaseSettingsItem>() {
abstract fun getView(context: Context): View
}
abstract class Selector : Value<Int>(), KoinComponent {
abstract class Selector : Value<Int>() {
protected val resources get() = get<Resources>()
open val entryRes get() = -1
open val descriptionRes get() = entryRes
open fun entries(res: Resources) = res.getArrayOrEmpty(entryRes)
open fun descriptions(res: Resources) = res.getArrayOrEmpty(descriptionRes)
@ArrayRes open val entryRes = -1
@ArrayRes open val entryValRes = -1
open val entries get() = resources.getArrayOrEmpty(entryRes)
open val entryValues get() = resources.getArrayOrEmpty(entryValRes)
override val description: TextHolder
get() = entries.getOrNull(value)?.asText() ?: TextHolder.EMPTY
override val description = object : TextHolder() {
override fun getText(resources: Resources): CharSequence {
return descriptions(resources).getOrElse(value) { "" }
}
}
private fun Resources.getArrayOrEmpty(id: Int): Array<String> =
runCatching { getStringArray(id) }.getOrDefault(emptyArray())
override fun onPressed(view: View, callback: Callback) {
if (entries.isEmpty()) return
super.onPressed(view, callback)
}
override fun onPressed(view: View) {
MagiskDialog(view.context)
.applyTitle(title.getText(resources))
.applyTitle(title.getText(view.resources))
.applyButton(MagiskDialog.ButtonType.NEGATIVE) {
titleRes = android.R.string.cancel
}
.applyAdapter(entries) {
.applyAdapter(entries(view.resources)) {
value = it
}
.reveal()

View File

@ -1,8 +1,10 @@
package com.topjohnwu.magisk.ui.settings
import android.content.Context
import android.content.res.Resources
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.BuildConfig
@ -20,7 +22,6 @@ import com.topjohnwu.magisk.databinding.DialogSettingsAppNameBinding
import com.topjohnwu.magisk.databinding.DialogSettingsDownloadPathBinding
import com.topjohnwu.magisk.databinding.DialogSettingsUpdateChannelBinding
import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.asText
import com.topjohnwu.magisk.utils.set
@ -41,8 +42,17 @@ object Language : BaseSettingsItem.Selector() {
}
override val title = R.string.language.asText()
override var entries = emptyArray<String>()
override var entryValues = emptyArray<String>()
private var entries = emptyArray<String>()
private var entryValues = emptyArray<String>()
override fun entries(res: Resources) = entries
override fun descriptions(res: Resources) = entries
override fun onPressed(view: View, callback: Callback) {
if (entries.isEmpty()) return
super.onPressed(view, callback)
}
suspend fun loadLanguages(scope: CoroutineScope) {
scope.launch {
@ -137,20 +147,22 @@ object DownloadPath : BaseSettingsItem.Input() {
}
object UpdateChannel : BaseSettingsItem.Selector() {
override var value = Config.updateChannel
override var value = Config.updateChannel.let { if (it < 0) 0 else it }
set(value) = setV(value, field, { field = it }) {
Config.updateChannel = it
Info.remote = Info.EMPTY_REMOTE
}
override val title = R.string.settings_update_channel_title.asText()
override val entries: Array<String> = resources.getStringArray(R.array.update_channel).let {
if (BuildConfig.VERSION_CODE % 100 == 0)
it.toMutableList().apply { removeAt(Config.Value.CANARY_CHANNEL) }.toTypedArray()
override val entryRes = R.array.update_channel
override fun entries(res: Resources): Array<String> {
return super.entries(res).let {
if (!BuildConfig.DEBUG)
it.copyOfRange(0, Config.Value.CANARY_CHANNEL)
else it
}
override val description
get() = entries.getOrNull(value)?.asText() ?: TextHolder.String(entries[0])
}
}
object UpdateChannelUrl : BaseSettingsItem.Input() {
@ -272,15 +284,13 @@ object AccessMode : BaseSettingsItem.Selector() {
object MultiuserMode : BaseSettingsItem.Selector() {
override val title = R.string.multiuser_mode.asText()
override val entryRes = R.array.multiuser_mode
override val descriptionRes = R.array.multiuser_summary
override var value = Config.suMultiuserMode
set(value) = setV(value, field, { field = it }) {
Config.suMultiuserMode = it
}
override val description
get() = resources.getStringArray(R.array.multiuser_summary)[value].asText()
override fun refresh() {
isEnabled = Const.USER_ID == 0
}
@ -289,14 +299,12 @@ object MultiuserMode : BaseSettingsItem.Selector() {
object MountNamespaceMode : BaseSettingsItem.Selector() {
override val title = R.string.mount_namespace_mode.asText()
override val entryRes = R.array.namespace
override val descriptionRes = R.array.namespace_summary
override var value = Config.suMntNamespaceMode
set(value) = setV(value, field, { field = it }) {
Config.suMntNamespaceMode = it
}
override val description
get() = resources.getStringArray(R.array.namespace_summary)[value].asText()
}
object AutomaticResponse : BaseSettingsItem.Selector() {
@ -312,15 +320,15 @@ object AutomaticResponse : BaseSettingsItem.Selector() {
object RequestTimeout : BaseSettingsItem.Selector() {
override val title = R.string.request_timeout.asText()
override val entryRes = R.array.request_timeout
override val entryValRes = R.array.request_timeout_value
private val entryValues = listOf(10, 15, 20, 30, 45, 60)
override var value = selected
set(value) = setV(value, field, { field = it }) {
Config.suDefaultTimeout = entryValues[it].toInt()
Config.suDefaultTimeout = entryValues[it]
}
private val selected: Int
get() = entryValues.indexOfFirst { it.toInt() == Config.suDefaultTimeout }
get() = entryValues.indexOfFirst { it == Config.suDefaultTimeout }
}
object SUNotification : BaseSettingsItem.Selector() {

View File

@ -25,15 +25,6 @@
<item>@string/settings_su_request_60</item>
</string-array>
<string-array name="request_timeout_value">
<item>10</item>
<item>15</item>
<item>20</item>
<item>30</item>
<item>45</item>
<item>60</item>
</string-array>
<string-array name="auto_response">
<item>@string/prompt</item>
<item>@string/deny</item>