From 3cfbb82a39ab24e8844466ae15674cb9eada99f2 Mon Sep 17 00:00:00 2001 From: Mygod Date: Thu, 4 Jan 2018 15:54:46 +0800 Subject: [PATCH] Auto-complete interface names --- .../be/mygod/vpnhotspot/HotspotService.kt | 3 +- .../be/mygod/vpnhotspot/SettingsFragment.kt | 12 ++++ .../main/java/be/mygod/vpnhotspot/Utils.kt | 6 ++ .../preference/AlwaysAutoCompleteEditText.kt | 25 ++++++++ .../AlwaysAutoCompleteEditTextPreference.kt | 23 ++++++++ ...eEditTextPreferenceDialogFragmentCompat.kt | 59 +++++++++++++++++++ mobile/src/main/res/xml/pref_settings.xml | 2 +- 7 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditText.kt create mode 100644 mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreference.kt create mode 100644 mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat.kt diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt index f555e7bb..c537d770 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/HotspotService.kt @@ -22,6 +22,7 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener { companion object { const val CHANNEL = "hotspot" const val STATUS_CHANGED = "be.mygod.vpnhotspot.HotspotService.STATUS_CHANGED" + const val KEY_UPSTREAM = "service.upstream" private const val TAG = "HotspotService" } @@ -75,7 +76,7 @@ class HotspotService : Service(), WifiP2pManager.ChannelListener { var downstream: String? = null private set - private val upstream get() = app.pref.getString("service.upstream", "tun0") + private val upstream get() = app.pref.getString(KEY_UPSTREAM, "tun0") /** * subnetPrefixLength has been the same forever but this option is here anyways. Source: * https://android.googlesource.com/platform/frameworks/base/+/android-4.0.1_r1/wifi/java/android/net/wifi/p2p/WifiP2pService.java#1028 diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/SettingsFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/SettingsFragment.kt index b11202d0..82cf0c75 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/SettingsFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/SettingsFragment.kt @@ -11,7 +11,9 @@ import android.support.customtabs.CustomTabsIntent import android.support.v4.content.ContextCompat import android.support.v4.content.LocalBroadcastManager import android.support.v7.preference.Preference +import be.mygod.vpnhotspot.preference.AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat import com.takisoft.fix.support.v7.preference.PreferenceFragmentCompatDividers +import java.net.NetworkInterface class SettingsFragment : PreferenceFragmentCompatDividers(), ServiceConnection { private lateinit var service: Preference @@ -51,6 +53,16 @@ class SettingsFragment : PreferenceFragmentCompatDividers(), ServiceConnection { } } + override fun onDisplayPreferenceDialog(preference: Preference) = when (preference.key) { + HotspotService.KEY_UPSTREAM -> displayPreferenceDialog( + AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat(), HotspotService.KEY_UPSTREAM, + Bundle().put(AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat.KEY_SUGGESTIONS, + NetworkInterface.getNetworkInterfaces().asSequence() + .filter { it.isUp && !it.isLoopback && it.interfaceAddresses.isNotEmpty() } + .map { it.name }.toList().toTypedArray())) + else -> super.onDisplayPreferenceDialog(preference) + } + override fun onStart() { super.onStart() val activity = activity!! diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt b/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt index 89b267fa..8a3b675b 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt @@ -4,6 +4,7 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.os.Bundle import android.util.Log fun broadcastReceiver(receiver: (Context, Intent) -> Unit) = object : BroadcastReceiver() { @@ -16,6 +17,11 @@ fun intentFilter(vararg actions: String): IntentFilter { return result } +fun Bundle.put(key: String, map: Array): Bundle { + putStringArray(key, map) + return this +} + const val NOISYSU_TAG = "NoisySU" const val NOISYSU_SUFFIX = "SUCCESS\n" fun noisySu(vararg commands: String): Boolean { diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditText.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditText.kt new file mode 100644 index 00000000..cb6c333d --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditText.kt @@ -0,0 +1,25 @@ +package be.mygod.vpnhotspot.preference + +import android.content.Context +import android.graphics.Rect +import android.support.v7.widget.AppCompatAutoCompleteTextView +import android.util.AttributeSet +import android.view.View +import be.mygod.vpnhotspot.R + +/** + * Based on: https://gist.github.com/furycomptuers/4961368 + */ +class AlwaysAutoCompleteEditText @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, + defStyleAttr: Int = R.attr.autoCompleteTextViewStyle) : + AppCompatAutoCompleteTextView(context, attrs, defStyleAttr) { + override fun enoughToFilter() = true + + override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) { + super.onFocusChanged(focused, direction, previouslyFocusedRect) + if (focused && windowVisibility != View.GONE) { + performFiltering(text, 0) + showDropDown() + } + } +} diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreference.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreference.kt new file mode 100644 index 00000000..e17d6c2b --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreference.kt @@ -0,0 +1,23 @@ +package be.mygod.vpnhotspot.preference + +import android.content.Context +import android.text.TextUtils +import android.util.AttributeSet +import be.mygod.vpnhotspot.R +import com.takisoft.fix.support.v7.preference.AutoSummaryEditTextPreference + +open class AlwaysAutoCompleteEditTextPreference @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.attr.editTextPreferenceStyle, + defStyleRes: Int = 0) : AutoSummaryEditTextPreference(context, attrs, defStyleAttr, defStyleRes) { + val editText = AlwaysAutoCompleteEditText(context, attrs) + + init { + editText.id = android.R.id.edit + } + + override fun setText(text: String) { + val oldText = getText() + super.setText(text) + if (!TextUtils.equals(text, oldText)) notifyChanged() + } +} diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat.kt b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat.kt new file mode 100644 index 00000000..d5fae19b --- /dev/null +++ b/mobile/src/main/java/be/mygod/vpnhotspot/preference/AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat.kt @@ -0,0 +1,59 @@ +package be.mygod.vpnhotspot.preference + +import android.support.v7.preference.PreferenceDialogFragmentCompat +import android.support.v7.widget.AppCompatAutoCompleteTextView +import android.view.View +import android.view.ViewGroup +import android.widget.ArrayAdapter +import android.widget.EditText + +open class AlwaysAutoCompleteEditTextPreferenceDialogFragmentCompat : PreferenceDialogFragmentCompat() { + companion object { + const val KEY_SUGGESTIONS = "suggestions" + } + + private lateinit var editText: AppCompatAutoCompleteTextView + private val editTextPreference get() = this.preference as AlwaysAutoCompleteEditTextPreference + + override fun onBindDialogView(view: View) { + super.onBindDialogView(view) + + editText = editTextPreference.editText + editText.setText(this.editTextPreference.text) + + val text = editText.text + if (text != null) editText.setSelection(text.length, text.length) + + val suggestions = arguments?.getStringArray(KEY_SUGGESTIONS) + if (suggestions != null) + editText.setAdapter(ArrayAdapter(view.context, android.R.layout.select_dialog_item, suggestions)) + + val oldParent = editText.parent as? ViewGroup? + if (oldParent !== view) { + oldParent?.removeView(editText) + onAddEditTextToDialogView(view, editText) + } + } + + override fun needInputMethod(): Boolean = true + + protected fun onAddEditTextToDialogView(dialogView: View, editText: EditText) { + val oldEditText = dialogView.findViewById(android.R.id.edit) + if (oldEditText != null) { + val container = oldEditText.parent as? ViewGroup? + if (container != null) { + container.removeView(oldEditText) + container.addView(editText, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + } + } + + override fun onDialogClosed(positiveResult: Boolean) { + if (positiveResult) { + val value = this.editText.text.toString() + if (this.editTextPreference.callChangeListener(value)) { + this.editTextPreference.text = value + } + } + } +} diff --git a/mobile/src/main/res/xml/pref_settings.xml b/mobile/src/main/res/xml/pref_settings.xml index 6e706d11..ffdbc615 100644 --- a/mobile/src/main/res/xml/pref_settings.xml +++ b/mobile/src/main/res/xml/pref_settings.xml @@ -3,7 +3,7 @@ -