Commit 60e1e07e authored by topjohnwu's avatar topjohnwu

Proper SafetyNet UI databinding

parent e51a3dac
package com.topjohnwu.magisk.databinding package com.topjohnwu.magisk.databinding
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.content.res.ColorStateList
import android.graphics.Paint import android.graphics.Paint
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.util.TypedValue import android.util.TypedValue
import android.view.ContextThemeWrapper
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.* import android.widget.Button
import android.widget.ImageView
import android.widget.ProgressBar
import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.updateLayoutParams import androidx.core.view.updateLayoutParams
import androidx.core.widget.ImageViewCompat
import androidx.databinding.BindingAdapter import androidx.databinding.BindingAdapter
import androidx.databinding.InverseBindingAdapter import androidx.databinding.InverseBindingAdapter
import androidx.databinding.InverseBindingListener import androidx.databinding.InverseBindingListener
...@@ -288,3 +292,8 @@ fun CardView.setCardBackgroundColorAttr(attr: Int) { ...@@ -288,3 +292,8 @@ fun CardView.setCardBackgroundColorAttr(attr: Int) {
context.theme.resolveAttribute(attr, tv, true) context.theme.resolveAttribute(attr, tv, true)
setCardBackgroundColor(tv.data) setCardBackgroundColor(tv.data)
} }
@BindingAdapter("tint")
fun ImageView.setTint(color: Int) {
ImageViewCompat.setImageTintList(this, ColorStateList.valueOf(color))
}
package com.topjohnwu.magisk.di package com.topjohnwu.magisk.di
import android.view.ContextThemeWrapper
import com.topjohnwu.magisk.ui.MainViewModel import com.topjohnwu.magisk.ui.MainViewModel
import com.topjohnwu.magisk.ui.flash.FlashFragmentArgs import com.topjohnwu.magisk.ui.flash.FlashFragmentArgs
import com.topjohnwu.magisk.ui.flash.FlashViewModel import com.topjohnwu.magisk.ui.flash.FlashViewModel
...@@ -21,7 +22,7 @@ val viewModelModules = module { ...@@ -21,7 +22,7 @@ val viewModelModules = module {
viewModel { HomeViewModel(get()) } viewModel { HomeViewModel(get()) }
viewModel { LogViewModel(get()) } viewModel { LogViewModel(get()) }
viewModel { ModuleViewModel(get(), get(), get()) } viewModel { ModuleViewModel(get(), get(), get()) }
viewModel { SafetynetViewModel() } viewModel { (context: ContextThemeWrapper) -> SafetynetViewModel(context) }
viewModel { SettingsViewModel(get()) } viewModel { SettingsViewModel(get()) }
viewModel { SuperuserViewModel(get(), get()) } viewModel { SuperuserViewModel(get(), get()) }
viewModel { ThemeViewModel() } viewModel { ThemeViewModel() }
......
...@@ -8,11 +8,14 @@ import com.topjohnwu.magisk.R ...@@ -8,11 +8,14 @@ import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseUIFragment import com.topjohnwu.magisk.arch.BaseUIFragment
import com.topjohnwu.magisk.databinding.FragmentSafetynetMd2Binding import com.topjohnwu.magisk.databinding.FragmentSafetynetMd2Binding
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koin.core.parameter.parametersOf
class SafetynetFragment : BaseUIFragment<SafetynetViewModel, FragmentSafetynetMd2Binding>() { class SafetynetFragment : BaseUIFragment<SafetynetViewModel, FragmentSafetynetMd2Binding>() {
override val layoutRes = R.layout.fragment_safetynet_md2 override val layoutRes = R.layout.fragment_safetynet_md2
override val viewModel by viewModel<SafetynetViewModel>() override val viewModel by viewModel<SafetynetViewModel>() {
parametersOf(activity)
}
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
......
package com.topjohnwu.magisk.ui.safetynet package com.topjohnwu.magisk.ui.safetynet
import android.util.TypedValue
import android.view.ContextThemeWrapper
import androidx.databinding.Bindable import androidx.databinding.Bindable
import com.topjohnwu.magisk.BR import com.topjohnwu.magisk.BR
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.arch.BaseViewModel import com.topjohnwu.magisk.arch.BaseViewModel
import com.topjohnwu.magisk.ui.safetynet.SafetyNetState.*
import com.topjohnwu.magisk.utils.set import com.topjohnwu.magisk.utils.set
import org.json.JSONObject import org.json.JSONObject
enum class SafetyNetState {
LOADING, PASS, FAILED
}
data class SafetyNetResult( data class SafetyNetResult(
val response: JSONObject? = null, val response: JSONObject? = null,
val dismiss: Boolean = false val dismiss: Boolean = false
) )
class SafetynetViewModel : BaseViewModel() { class SafetynetViewModel(context: ContextThemeWrapper) : BaseViewModel() {
@get:Bindable @get:Bindable
var safetyNetTitle = R.string.empty var safetyNetTitle = R.string.empty
...@@ -36,23 +33,33 @@ class SafetynetViewModel : BaseViewModel() { ...@@ -36,23 +33,33 @@ class SafetynetViewModel : BaseViewModel() {
set(value) = set(value, field, { field = it }, BR.evalType) set(value) = set(value, field, { field = it }, BR.evalType)
@get:Bindable @get:Bindable
val isChecking get() = currentState == LOADING var isChecking = false
set(value) = set(value, field, { field = it }, BR.checking)
@get:Bindable @get:Bindable
val isFailed get() = currentState == FAILED var isSuccess = false
set(value) = set(value, field, { field = it }, BR.success, BR.textColor)
@get:Bindable @get:Bindable
val isSuccess get() = currentState == PASS val textColor get() = if (isSuccess) colorOnPrimary else colorOnError
private var currentState = LOADING private val colorOnPrimary: Int
set(value) = set(value, field, { field = it }, BR.checking, BR.failed, BR.success) private val colorOnError: Int
init { init {
val tv = TypedValue()
context.theme.resolveAttribute(R.attr.colorOnPrimary, tv, true)
colorOnPrimary = tv.data
context.theme.resolveAttribute(R.attr.colorOnError, tv, true)
colorOnError = tv.data
cachedResult?.also { cachedResult?.also {
resolveResponse(SafetyNetResult(it)) resolveResponse(SafetyNetResult(it))
} ?: attest() } ?: attest()
} }
private fun attest() { private fun attest() {
currentState = LOADING isChecking = true
CheckSafetyNetEvent { CheckSafetyNetEvent {
resolveResponse(it) resolveResponse(it)
}.publish() }.publish()
...@@ -61,6 +68,8 @@ class SafetynetViewModel : BaseViewModel() { ...@@ -61,6 +68,8 @@ class SafetynetViewModel : BaseViewModel() {
fun reset() = attest() fun reset() = attest()
private fun resolveResponse(response: SafetyNetResult) { private fun resolveResponse(response: SafetyNetResult) {
isChecking = false
if (response.dismiss) { if (response.dismiss) {
back() back()
return return
...@@ -76,19 +85,19 @@ class SafetynetViewModel : BaseViewModel() { ...@@ -76,19 +85,19 @@ class SafetynetViewModel : BaseViewModel() {
ctsState = cts ctsState = cts
basicIntegrityState = basic basicIntegrityState = basic
evalType = if (eval.contains("HARDWARE")) "HARDWARE" else "BASIC" evalType = if (eval.contains("HARDWARE")) "HARDWARE" else "BASIC"
currentState = if (result) PASS else FAILED isSuccess = result
safetyNetTitle = safetyNetTitle =
if (result) R.string.safetynet_attest_success if (result) R.string.safetynet_attest_success
else R.string.safetynet_attest_failure else R.string.safetynet_attest_failure
}.onFailure { }.onFailure {
currentState = FAILED isSuccess = false
ctsState = false ctsState = false
basicIntegrityState = false basicIntegrityState = false
evalType = "N/A" evalType = "N/A"
safetyNetTitle = R.string.safetynet_res_invalid safetyNetTitle = R.string.safetynet_res_invalid
} }
} ?: { } ?: {
currentState = FAILED isSuccess = false
ctsState = false ctsState = false
basicIntegrityState = false basicIntegrityState = false
evalType = "N/A" evalType = "N/A"
......
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
android:gravity="center" android:gravity="center"
android:text="@{viewModel.safetyNetTitle}" android:text="@{viewModel.safetyNetTitle}"
android:textAppearance="@style/AppearanceFoundation.Display.OnPrimary" android:textAppearance="@style/AppearanceFoundation.Display.OnPrimary"
android:textColor="@{viewModel.textColor}"
android:textStyle="bold" android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed" app:layout_constraintHorizontal_chainStyle="packed"
...@@ -93,7 +94,7 @@ ...@@ -93,7 +94,7 @@
android:layout_height="4dp" android:layout_height="4dp"
android:layout_marginTop="@dimen/l2" android:layout_marginTop="@dimen/l2"
app:srcCompat="@drawable/bg_divider_rounded_on_primary" app:srcCompat="@drawable/bg_divider_rounded_on_primary"
app:tint="?colorOnPrimary" app:tint="@{viewModel.textColor}"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/safetynet_title" /> app:layout_constraintTop_toBottomOf="@+id/safetynet_title" />
...@@ -116,6 +117,7 @@ ...@@ -116,6 +117,7 @@
android:text="basicIntegrity" android:text="basicIntegrity"
android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary" android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@{viewModel.textColor}"
android:layout_marginTop="@dimen/l2" android:layout_marginTop="@dimen/l2"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="@id/snet_barrier" app:layout_constraintEnd_toEndOf="@id/snet_barrier"
...@@ -131,6 +133,7 @@ ...@@ -131,6 +133,7 @@
android:text="ctsProfile" android:text="ctsProfile"
android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary" android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@{viewModel.textColor}"
android:layout_marginTop="@dimen/l2" android:layout_marginTop="@dimen/l2"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="@id/snet_barrier" app:layout_constraintEnd_toEndOf="@id/snet_barrier"
...@@ -149,6 +152,7 @@ ...@@ -149,6 +152,7 @@
isSelected="@{viewModel.basicIntegrityState}" isSelected="@{viewModel.basicIntegrityState}"
android:layout_gravity="center" android:layout_gravity="center"
app:srcCompat="@drawable/ic_check_circle_md2" app:srcCompat="@drawable/ic_check_circle_md2"
app:tint="@{viewModel.textColor}"
app:layout_constraintStart_toEndOf="@id/snet_barrier" app:layout_constraintStart_toEndOf="@id/snet_barrier"
app:layout_constraintTop_toTopOf="@id/basic_text" app:layout_constraintTop_toTopOf="@id/basic_text"
app:layout_constraintBottom_toBottomOf="@id/basic_text"/> app:layout_constraintBottom_toBottomOf="@id/basic_text"/>
...@@ -158,6 +162,7 @@ ...@@ -158,6 +162,7 @@
isSelected="@{viewModel.ctsState}" isSelected="@{viewModel.ctsState}"
android:layout_gravity="center" android:layout_gravity="center"
app:srcCompat="@drawable/ic_check_circle_md2" app:srcCompat="@drawable/ic_check_circle_md2"
app:tint="@{viewModel.textColor}"
app:layout_constraintStart_toEndOf="@id/snet_barrier" app:layout_constraintStart_toEndOf="@id/snet_barrier"
app:layout_constraintTop_toTopOf="@id/cts_text" app:layout_constraintTop_toTopOf="@id/cts_text"
app:layout_constraintBottom_toBottomOf="@id/cts_text"/> app:layout_constraintBottom_toBottomOf="@id/cts_text"/>
...@@ -181,6 +186,7 @@ ...@@ -181,6 +186,7 @@
android:text="evalType" android:text="evalType"
android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary" android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@{viewModel.textColor}"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
...@@ -189,6 +195,7 @@ ...@@ -189,6 +195,7 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary" android:textAppearance="@style/AppearanceFoundation.Body.OnPrimary"
android:textStyle="bold" android:textStyle="bold"
android:textColor="@{viewModel.textColor}"
android:layout_marginStart="@dimen/l1" android:layout_marginStart="@dimen/l1"
android:text="@{viewModel.evalType}" android:text="@{viewModel.evalType}"
tools:text="HARDWARE"/> tools:text="HARDWARE"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment