Commit 60e1e07e authored by topjohnwu's avatar topjohnwu

Proper SafetyNet UI databinding

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