TunnelEditorFragment: add hooks for biometric auth
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
@@ -6,6 +6,8 @@ package com.wireguard.android.databinding
|
||||
|
||||
import android.text.InputFilter
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.databinding.BindingAdapter
|
||||
@@ -13,6 +15,7 @@ import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ObservableList
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.databinding.adapters.ListenerUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.wireguard.android.BR
|
||||
@@ -41,10 +44,10 @@ object BindingAdapters {
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@BindingAdapter("items", "layout")
|
||||
@BindingAdapter("items", "layout", "fragment")
|
||||
fun <E> setItems(view: LinearLayout,
|
||||
oldList: ObservableList<E>?, oldLayoutId: Int,
|
||||
newList: ObservableList<E>?, newLayoutId: Int) {
|
||||
oldList: ObservableList<E>?, oldLayoutId: Int, @Suppress("UNUSED_PARAMETER") oldFragment: Fragment?,
|
||||
newList: ObservableList<E>?, newLayoutId: Int, newFragment: Fragment?) {
|
||||
if (oldList === newList && oldLayoutId == newLayoutId)
|
||||
return
|
||||
var listener: ItemChangeListener<E>? = ListenerUtil.getListener(view, R.id.item_change_listener)
|
||||
@@ -59,7 +62,7 @@ object BindingAdapters {
|
||||
if (newList == null || newLayoutId == 0)
|
||||
return
|
||||
if (listener == null) {
|
||||
listener = ItemChangeListener(view, newLayoutId)
|
||||
listener = ItemChangeListener(view, newLayoutId, newFragment)
|
||||
ListenerUtil.trackListener(view, listener, R.id.item_change_listener)
|
||||
}
|
||||
// Either the list changed, or this is an entirely new listener because the layout changed.
|
||||
@@ -123,6 +126,13 @@ object BindingAdapters {
|
||||
view.setOnBeforeCheckedChangeListener(listener)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@BindingAdapter("onFocusChange")
|
||||
fun setOnFocusChange(view: EditText,
|
||||
listener: View.OnFocusChangeListener?) {
|
||||
view.setOnFocusChangeListener(listener)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@BindingAdapter("android:text")
|
||||
fun setText(view: TextView, text: Optional<*>) {
|
||||
|
||||
@@ -10,13 +10,14 @@ import android.view.ViewGroup
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ObservableList
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.wireguard.android.BR
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
/**
|
||||
* Helper class for binding an ObservableList to the children of a ViewGroup.
|
||||
*/
|
||||
internal class ItemChangeListener<T>(private val container: ViewGroup, private val layoutId: Int) {
|
||||
internal class ItemChangeListener<T>(private val container: ViewGroup, private val layoutId: Int, private val fragment: Fragment?) {
|
||||
private val callback = OnListChangedCallback(this)
|
||||
private val layoutInflater: LayoutInflater = LayoutInflater.from(container.context)
|
||||
private var list: ObservableList<T>? = null
|
||||
@@ -29,6 +30,7 @@ internal class ItemChangeListener<T>(private val container: ViewGroup, private v
|
||||
require(list != null) { "Trying to get a view while list is still null" }
|
||||
binding!!.setVariable(BR.collection, list)
|
||||
binding.setVariable(BR.item, list!![position])
|
||||
binding.setVariable(BR.fragment, fragment)
|
||||
binding.executePendingBindings()
|
||||
return binding.root
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ package com.wireguard.android.fragment
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
@@ -15,9 +16,9 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.EditText
|
||||
import android.widget.Toast
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.wireguard.android.Application
|
||||
import com.wireguard.android.R
|
||||
import com.wireguard.android.backend.Tunnel
|
||||
@@ -34,6 +35,7 @@ import com.wireguard.config.Config
|
||||
* Fragment for editing a WireGuard configuration.
|
||||
*/
|
||||
class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
|
||||
private var haveShownKeys = false
|
||||
private var binding: TunnelEditorFragmentBinding? = null
|
||||
private var tunnel: ObservableTunnel? = null
|
||||
private fun onConfigLoaded(config: Config) {
|
||||
@@ -76,7 +78,6 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
|
||||
setUpScrollingContent(mainContainer, null)
|
||||
privateKeyTextLayout.setEndIconOnClickListener { config?.`interface`?.generateKeyPair() }
|
||||
}
|
||||
requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
return binding?.root
|
||||
}
|
||||
|
||||
@@ -226,6 +227,23 @@ class TunnelEditorFragment : BaseFragment(), AppExclusionListener {
|
||||
super.onViewStateRestored(savedInstanceState)
|
||||
}
|
||||
|
||||
fun onKeyClick(view: View) = onKeyFocusChange(view, true)
|
||||
|
||||
fun onKeyFocusChange(view: View, isFocused: Boolean) {
|
||||
if (!isFocused) return
|
||||
val edit = view as? EditText ?: return
|
||||
if (!haveShownKeys && edit.text.isNotEmpty()) {
|
||||
if (true /* TODO: do biometric auth prompt */) {
|
||||
haveShownKeys = true
|
||||
} else {
|
||||
/* Unauthorized, so return and don't change visibility. */
|
||||
return
|
||||
}
|
||||
}
|
||||
requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
edit.inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_LOCAL_CONFIG = "local_config"
|
||||
private const val KEY_ORIGINAL_NAME = "original_name"
|
||||
|
||||
Reference in New Issue
Block a user