diff options
Diffstat (limited to 'ui/src/main')
5 files changed, 51 insertions, 11 deletions
diff --git a/ui/src/main/java/com/wireguard/android/databinding/BindingAdapters.kt b/ui/src/main/java/com/wireguard/android/databinding/BindingAdapters.kt index 3460e96e..213338f1 100644 --- a/ui/src/main/java/com/wireguard/android/databinding/BindingAdapters.kt +++ b/ui/src/main/java/com/wireguard/android/databinding/BindingAdapters.kt @@ -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. @@ -124,6 +127,13 @@ object BindingAdapters { } @JvmStatic + @BindingAdapter("onFocusChange") + fun setOnFocusChange(view: EditText, + listener: View.OnFocusChangeListener?) { + view.setOnFocusChangeListener(listener) + } + + @JvmStatic @BindingAdapter("android:text") fun setText(view: TextView, text: Optional<*>) { view.text = text.map { obj: Any -> obj.toString() }.orElse("") diff --git a/ui/src/main/java/com/wireguard/android/databinding/ItemChangeListener.kt b/ui/src/main/java/com/wireguard/android/databinding/ItemChangeListener.kt index 131f3877..29784a75 100644 --- a/ui/src/main/java/com/wireguard/android/databinding/ItemChangeListener.kt +++ b/ui/src/main/java/com/wireguard/android/databinding/ItemChangeListener.kt @@ -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 } diff --git a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt index ff5bb42b..9ac2473c 100644 --- a/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt +++ b/ui/src/main/java/com/wireguard/android/fragment/TunnelEditorFragment.kt @@ -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" diff --git a/ui/src/main/res/layout/tunnel_editor_fragment.xml b/ui/src/main/res/layout/tunnel_editor_fragment.xml index d87e1efb..d5724c11 100644 --- a/ui/src/main/res/layout/tunnel_editor_fragment.xml +++ b/ui/src/main/res/layout/tunnel_editor_fragment.xml @@ -102,9 +102,11 @@ android:id="@+id/private_key_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:inputType="textNoSuggestions|textVisiblePassword" + android:inputType="textNoSuggestions|textPassword" + android:onClick="@{fragment::onKeyClick}" android:text="@={config.interface.privateKey}" - app:filter="@{KeyInputFilter.newInstance()}" /> + app:filter="@{KeyInputFilter.newInstance()}" + app:onFocusChange="@{fragment::onKeyFocusChange}" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout @@ -234,6 +236,7 @@ android:layout_height="wrap_content" android:divider="@null" android:orientation="vertical" + app:fragment="@{fragment}" app:items="@{config.peers}" app:layout="@{@layout/tunnel_editor_peer}" tools:ignore="UselessLeaf" /> diff --git a/ui/src/main/res/layout/tunnel_editor_peer.xml b/ui/src/main/res/layout/tunnel_editor_peer.xml index 2f3b0689..f00a6d26 100644 --- a/ui/src/main/res/layout/tunnel_editor_peer.xml +++ b/ui/src/main/res/layout/tunnel_editor_peer.xml @@ -15,6 +15,10 @@ <variable name="item" type="com.wireguard.android.viewmodel.PeerProxy" /> + + <variable + name="fragment" + type="com.wireguard.android.fragment.TunnelEditorFragment" /> </data> <com.google.android.material.card.MaterialCardView @@ -91,8 +95,11 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/hint_optional" - android:inputType="textNoSuggestions|textVisiblePassword" - android:text="@={item.preSharedKey}" /> + android:inputType="textNoSuggestions|textPassword" + android:onClick="@{fragment::onKeyClick}" + android:text="@={item.preSharedKey}" + app:filter="@{KeyInputFilter.newInstance()}" + app:onFocusChange="@{fragment::onKeyFocusChange}" /> </com.google.android.material.textfield.TextInputLayout> <com.google.android.material.textfield.TextInputLayout |