diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt index 5d3372b0..cef0e46a 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/SettingsPreferenceFragment.kt @@ -14,13 +14,12 @@ import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor import be.mygod.vpnhotspot.net.monitor.IpMonitor import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor import be.mygod.vpnhotspot.net.wifi.WifiDoubleLock -import be.mygod.vpnhotspot.preference.AlwaysAutoCompleteEditTextPreferenceDialogFragment +import be.mygod.vpnhotspot.preference.AutoCompleteNetworkPreferenceDialogFragment import be.mygod.vpnhotspot.preference.SharedPreferenceDataStore import be.mygod.vpnhotspot.preference.SummaryFallbackProvider import be.mygod.vpnhotspot.root.Dump import be.mygod.vpnhotspot.root.RootManager import be.mygod.vpnhotspot.util.Services -import be.mygod.vpnhotspot.util.allInterfaceNames import be.mygod.vpnhotspot.util.launchUrl import be.mygod.vpnhotspot.util.showAllowingStateLoss import be.mygod.vpnhotspot.widget.SmartSnackbar @@ -144,16 +143,12 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() { } } - override fun onDisplayPreferenceDialog(preference: Preference) { - when (preference.key) { - UpstreamMonitor.KEY, FallbackUpstreamMonitor.KEY -> - AlwaysAutoCompleteEditTextPreferenceDialogFragment().apply { - setArguments(preference.key, Services.connectivity.allNetworks.mapNotNull { - Services.connectivity.getLinkProperties(it)?.allInterfaceNames - }.flatten().toTypedArray()) - setTargetFragment(this@SettingsPreferenceFragment, 0) - }.showAllowingStateLoss(parentFragmentManager, preference.key) - else -> super.onDisplayPreferenceDialog(preference) - } + override fun onDisplayPreferenceDialog(preference: Preference) = when (preference.key) { + UpstreamMonitor.KEY, FallbackUpstreamMonitor.KEY -> + AutoCompleteNetworkPreferenceDialogFragment().apply { + setArguments(preference.key) + setTargetFragment(this@SettingsPreferenceFragment, 0) + }.showAllowingStateLoss(parentFragmentManager, preference.key) + else -> super.onDisplayPreferenceDialog(preference) } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragment.kt deleted file mode 100644 index c1fce475..00000000 --- a/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragment.kt +++ /dev/null @@ -1,42 +0,0 @@ -package be.mygod.vpnhotspot.preference - -import android.content.Context -import android.view.View -import android.view.ViewGroup -import android.widget.ArrayAdapter -import androidx.core.os.bundleOf -import androidx.preference.EditTextPreferenceDialogFragmentCompat -import be.mygod.vpnhotspot.R -import be.mygod.vpnhotspot.widget.AlwaysAutoCompleteEditText - -class AlwaysAutoCompleteEditTextPreferenceDialogFragment : EditTextPreferenceDialogFragmentCompat() { - companion object { - private const val ARG_SUGGESTIONS = "suggestions" - } - - fun setArguments(key: String, suggestions: Array) { - arguments = bundleOf(ARG_KEY to key, ARG_SUGGESTIONS to suggestions) - } - - private lateinit var editText: AlwaysAutoCompleteEditText - - override fun onCreateDialogView(context: Context) = super.onCreateDialogView(context).apply { - editText = AlwaysAutoCompleteEditText(context).apply { - id = android.R.id.edit - minHeight = resources.getDimensionPixelSize(R.dimen.touch_target_min) - } - val oldEditText = findViewById(android.R.id.edit)!! - val container = oldEditText.parent as ViewGroup - container.removeView(oldEditText) - container.addView(editText, oldEditText.layoutParams) - } - - override fun onBindDialogView(view: View) { - super.onBindDialogView(view) - editText.hint = (preference.summaryProvider as SummaryFallbackProvider).fallback - arguments?.getStringArray(ARG_SUGGESTIONS)?.let { suggestions -> - editText.setAdapter(ArrayAdapter(view.context, android.R.layout.select_dialog_item, suggestions)) - } - editText.clearFocus() // having focus is buggy currently - } -} diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/AutoCompleteNetworkPreferenceDialogFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AutoCompleteNetworkPreferenceDialogFragment.kt new file mode 100644 index 00000000..a2effe05 --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AutoCompleteNetworkPreferenceDialogFragment.kt @@ -0,0 +1,78 @@ +package be.mygod.vpnhotspot.preference + +import android.content.Context +import android.net.ConnectivityManager +import android.net.LinkProperties +import android.net.Network +import android.net.NetworkCapabilities +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import androidx.core.os.bundleOf +import androidx.preference.EditTextPreferenceDialogFragmentCompat +import be.mygod.vpnhotspot.R +import be.mygod.vpnhotspot.util.Services +import be.mygod.vpnhotspot.util.allInterfaceNames +import be.mygod.vpnhotspot.util.globalNetworkRequestBuilder +import be.mygod.vpnhotspot.widget.AlwaysAutoCompleteEditText + +class AutoCompleteNetworkPreferenceDialogFragment : EditTextPreferenceDialogFragmentCompat() { + fun setArguments(key: String) { + arguments = bundleOf(ARG_KEY to key) + } + + private lateinit var editText: AlwaysAutoCompleteEditText + private lateinit var adapter: ArrayAdapter + private fun updateAdapter() { + adapter.clear() + adapter.addAll(interfaceNames.flatMap { it.value }) + } + + private val interfaceNames = mutableMapOf>() + private val callback = object : ConnectivityManager.NetworkCallback() { + override fun onLinkPropertiesChanged(network: Network, properties: LinkProperties) { + interfaceNames[network] = properties.allInterfaceNames + updateAdapter() + } + + override fun onLost(network: Network) { + interfaceNames.remove(network) + updateAdapter() + } + } + + override fun onCreateDialogView(context: Context) = super.onCreateDialogView(context).apply { + editText = AlwaysAutoCompleteEditText(context).apply { + id = android.R.id.edit + minHeight = resources.getDimensionPixelSize(R.dimen.touch_target_min) + } + val oldEditText = findViewById(android.R.id.edit)!! + val container = oldEditText.parent as ViewGroup + container.removeView(oldEditText) + container.addView(editText, oldEditText.layoutParams) + } + + override fun onBindDialogView(view: View) { + super.onBindDialogView(view) + editText.hint = (preference.summaryProvider as SummaryFallbackProvider).fallback + adapter = ArrayAdapter(view.context, android.R.layout.select_dialog_item) + editText.setAdapter(adapter) + editText.clearFocus() // having focus is buggy currently + } + + override fun onStart() { + super.onStart() + Services.connectivity.registerNetworkCallback(globalNetworkRequestBuilder().apply { + removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) + removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED) + removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) + }.build(), callback) + } + + override fun onStop() { + Services.connectivity.unregisterNetworkCallback(callback) + interfaceNames.clear() + updateAdapter() + super.onStop() + } +}