Don't hold resources in ViewModels

This commit is contained in:
topjohnwu 2021-04-18 02:12:53 -07:00
parent 29cc372bfa
commit 1418bc454d
7 changed files with 33 additions and 41 deletions

View File

@ -28,5 +28,5 @@ val viewModelModules = module {
viewModel { InstallViewModel(get()) } viewModel { InstallViewModel(get()) }
viewModel { MainViewModel() } viewModel { MainViewModel() }
viewModel { (args: FlashFragmentArgs) -> FlashViewModel(args) } viewModel { (args: FlashFragmentArgs) -> FlashViewModel(args) }
viewModel { SuRequestViewModel(get(), get(), get(SUTimeout), get()) } viewModel { SuRequestViewModel(get(), get(SUTimeout)) }
} }

View File

@ -26,7 +26,7 @@ import com.topjohnwu.superuser.Shell
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class FlashViewModel(private val args: FlashFragmentArgs) : BaseViewModel() { class FlashViewModel(var args: FlashFragmentArgs) : BaseViewModel() {
@get:Bindable @get:Bindable
var showReboot = Shell.rootAccess() var showReboot = Shell.rootAccess()

View File

@ -1,13 +0,0 @@
package com.topjohnwu.magisk.ui.superuser
import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.databinding.ComparableRvItem
class SpinnerRvItem(val item: String) : ComparableRvItem<SpinnerRvItem>() {
override val layoutRes: Int = R.layout.item_spinner
override fun contentSameAs(other: SpinnerRvItem) = itemSameAs(other)
override fun itemSameAs(other: SpinnerRvItem) = item == other.item
}

View File

@ -1,9 +1,9 @@
package com.topjohnwu.magisk.ui.surequest package com.topjohnwu.magisk.ui.surequest
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Bundle import android.os.Bundle
@ -30,19 +30,17 @@ import com.topjohnwu.magisk.core.utils.BiometricHelper
import com.topjohnwu.magisk.events.DieEvent import com.topjohnwu.magisk.events.DieEvent
import com.topjohnwu.magisk.events.ShowUIEvent import com.topjohnwu.magisk.events.ShowUIEvent
import com.topjohnwu.magisk.events.dialog.BiometricEvent import com.topjohnwu.magisk.events.dialog.BiometricEvent
import com.topjohnwu.magisk.ui.superuser.SpinnerRvItem import com.topjohnwu.magisk.ktx.get
import com.topjohnwu.magisk.utils.TextHolder
import com.topjohnwu.magisk.utils.Utils import com.topjohnwu.magisk.utils.Utils
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.tatarka.bindingcollectionadapter2.BindingListViewAdapter
import me.tatarka.bindingcollectionadapter2.ItemBinding import me.tatarka.bindingcollectionadapter2.ItemBinding
import java.util.concurrent.TimeUnit.SECONDS import java.util.concurrent.TimeUnit.SECONDS
class SuRequestViewModel( class SuRequestViewModel(
pm: PackageManager,
policyDB: PolicyDao, policyDB: PolicyDao,
private val timeoutPrefs: SharedPreferences, private val timeoutPrefs: SharedPreferences
private val res: Resources
) : BaseViewModel() { ) : BaseViewModel() {
lateinit var icon: Drawable lateinit var icon: Drawable
@ -50,8 +48,7 @@ class SuRequestViewModel(
lateinit var packageName: String lateinit var packageName: String
@get:Bindable @get:Bindable
var denyText = res.getString(R.string.deny) val denyText = DenyText()
set(value) = set(value, field, { field = it }, BR.denyText)
@get:Bindable @get:Bindable
var selectedItemPosition = 0 var selectedItemPosition = 0
@ -74,15 +71,9 @@ class SuRequestViewModel(
false false
} }
private val items = res.getStringArray(R.array.allow_timeout).map { SpinnerRvItem(it) } val itemBinding = ItemBinding.of<String>(BR.item, R.layout.item_spinner)
val adapter = BindingListViewAdapter<SpinnerRvItem>(1).apply {
itemBinding = ItemBinding.of { binding, _, item ->
item.bind(binding)
}
setItems(items)
}
private val handler = SuRequestHandler(pm, policyDB) private val handler = SuRequestHandler(get<Context>().packageManager, policyDB)
private lateinit var timer: CountDownTimer private lateinit var timer: CountDownTimer
fun grantPressed() { fun grantPressed() {
@ -143,7 +134,7 @@ class SuRequestViewModel(
private fun cancelTimer() { private fun cancelTimer() {
timer.cancel() timer.cancel()
denyText = res.getString(R.string.deny) denyText.seconds = 0
} }
private inner class SuTimer( private inner class SuTimer(
@ -155,16 +146,30 @@ class SuRequestViewModel(
if (!grantEnabled && remains <= millis - 1000) { if (!grantEnabled && remains <= millis - 1000) {
grantEnabled = true grantEnabled = true
} }
denyText = "${res.getString(R.string.deny)} (${(remains / 1000) + 1})" denyText.seconds = (remains / 1000).toInt() + 1
} }
override fun onFinish() { override fun onFinish() {
denyText = res.getString(R.string.deny) denyText.seconds = 0
respond(DENY) respond(DENY)
} }
} }
inner class DenyText : TextHolder() {
var seconds = 0
set(value) = set(value, field, { field = it }, BR.denyText)
override val isEmpty get() = false
override fun getText(resources: Resources): CharSequence {
return if (seconds != 0)
"${resources.getString(R.string.deny)} ($seconds)"
else
resources.getString(R.string.deny)
}
}
// Invisible for accessibility services // Invisible for accessibility services
object EmptyAccessibilityDelegate : View.AccessibilityDelegate() { object EmptyAccessibilityDelegate : View.AccessibilityDelegate() {
override fun sendAccessibilityEvent(host: View?, eventType: Int) {} override fun sendAccessibilityEvent(host: View?, eventType: Int) {}

View File

@ -4,7 +4,7 @@ import android.content.res.Resources
import android.widget.TextView import android.widget.TextView
import androidx.databinding.BindingAdapter import androidx.databinding.BindingAdapter
sealed class TextHolder { abstract class TextHolder {
abstract val isEmpty: Boolean abstract val isEmpty: Boolean
abstract fun getText(resources: Resources): CharSequence abstract fun getText(resources: Resources): CharSequence

View File

@ -5,6 +5,8 @@
<data> <data>
<import type="java.util.Arrays"/>
<variable <variable
name="viewModel" name="viewModel"
type="com.topjohnwu.magisk.ui.surequest.SuRequestViewModel" /> type="com.topjohnwu.magisk.ui.surequest.SuRequestViewModel" />
@ -99,7 +101,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:enabled="@{viewModel.grantEnabled}" android:enabled="@{viewModel.grantEnabled}"
android:adapter="@{viewModel.adapter}" app:items="@{Arrays.asList(@stringArray/allow_timeout)}"
app:itemBinding="@{viewModel.itemBinding}"
android:selection="@={viewModel.selectedItemPosition}" /> android:selection="@={viewModel.selectedItemPosition}" />
<TextView <TextView

View File

@ -4,14 +4,11 @@
<data> <data>
<variable <variable name="item" type="String" />
name="item"
type="com.topjohnwu.magisk.ui.superuser.SpinnerRvItem" />
</data> </data>
<TextView <TextView
android:id="@android:id/text1"
style="?android:attr/spinnerItemStyle" style="?android:attr/spinnerItemStyle"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -21,7 +18,7 @@
android:gravity="center_vertical" android:gravity="center_vertical"
android:minHeight="?attr/listPreferredItemHeightSmall" android:minHeight="?attr/listPreferredItemHeightSmall"
android:singleLine="true" android:singleLine="true"
android:text="@{item.item}" android:text="@{item}"
android:textAlignment="inherit" android:textAlignment="inherit"
tools:text="Forever" /> tools:text="Forever" />