Allow monitoring current upstreams

Fix #139.
This commit is contained in:
Mygod
2020-01-20 10:02:26 +08:00
parent 59b4a464b0
commit cce3223311
5 changed files with 74 additions and 1 deletions

View File

@@ -81,7 +81,7 @@ class ClientsFragment : Fragment() {
data class StatsArg(val title: CharSequence, val stats: ClientStats) : Parcelable data class StatsArg(val title: CharSequence, val stats: ClientStats) : Parcelable
class StatsDialogFragment : AlertDialogFragment<StatsArg, Empty>() { class StatsDialogFragment : AlertDialogFragment<StatsArg, Empty>() {
override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) { override fun AlertDialog.Builder.prepare(listener: DialogInterface.OnClickListener) {
setTitle(SpanFormatter.format(getString(R.string.clients_stats_title), arg.title)) setTitle(SpanFormatter.format(getText(R.string.clients_stats_title), arg.title))
val context = context val context = context
val resources = resources val resources = resources
val format = NumberFormat.getIntegerInstance(resources.configuration.locale) val format = NumberFormat.getIntegerInstance(resources.configuration.locale)

View File

@@ -0,0 +1,65 @@
package be.mygod.vpnhotspot.preference
import android.content.Context
import android.graphics.Typeface
import android.net.LinkProperties
import android.text.SpannableStringBuilder
import android.text.style.StyleSpan
import android.util.AttributeSet
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.net.monitor.FallbackUpstreamMonitor
import be.mygod.vpnhotspot.net.monitor.UpstreamMonitor
import be.mygod.vpnhotspot.util.SpanFormatter
import be.mygod.vpnhotspot.util.parseNumericAddress
class UpstreamsPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs),
DefaultLifecycleObserver {
companion object {
private val internetAddress = parseNumericAddress("8.8.8.8")
}
private data class Interface(val ifname: String, val internet: Boolean)
private inner class Monitor : UpstreamMonitor.Callback {
private var currentInterface: Interface? = null
val charSequence get() = currentInterface?.run {
if (internet) SpannableStringBuilder(ifname).apply {
setSpan(StyleSpan(Typeface.BOLD), 0, length, 0)
} else ifname
} ?: ""
override fun onAvailable(ifname: String, properties: LinkProperties) {
currentInterface = Interface(ifname, properties.routes.any { it.matches(internetAddress) })
onUpdate()
}
override fun onLost() {
currentInterface = null
onUpdate()
}
}
private val primary = Monitor()
private val fallback = Monitor()
init {
(context as LifecycleOwner).lifecycle.addObserver(this)
}
override fun onStart(owner: LifecycleOwner) {
UpstreamMonitor.registerCallback(primary)
FallbackUpstreamMonitor.registerCallback(fallback)
}
override fun onStop(owner: LifecycleOwner) {
UpstreamMonitor.unregisterCallback(primary)
FallbackUpstreamMonitor.unregisterCallback(fallback)
}
private fun onUpdate() = (context as LifecycleOwner).lifecycleScope.launchWhenStarted {
summary = SpanFormatter.format(context.getText(R.string.settings_service_upstream_monitor_summary),
primary.charSequence, fallback.charSequence)
}
}

View File

@@ -98,6 +98,8 @@
<string name="settings_service_ip_monitor_monitor_root">Netlink 监听 (root)</string> <string name="settings_service_ip_monitor_monitor_root">Netlink 监听 (root)</string>
<string name="settings_service_ip_monitor_poll">轮询</string> <string name="settings_service_ip_monitor_poll">轮询</string>
<string name="settings_service_ip_monitor_poll_root">轮询 (root)</string> <string name="settings_service_ip_monitor_poll_root">轮询 (root)</string>
<string name="settings_service_upstream_monitor">当前上游接口</string>
<string name="settings_service_upstream_monitor_summary">%1$s备用%2$s</string>
<string name="settings_service_upstream">上游网络接口</string> <string name="settings_service_upstream">上游网络接口</string>
<string name="settings_service_upstream_auto">自动检测系统 VPN</string> <string name="settings_service_upstream_auto">自动检测系统 VPN</string>
<string name="settings_upstream_fallback">备用上游接口</string> <string name="settings_upstream_fallback">备用上游接口</string>

View File

@@ -103,6 +103,8 @@
<string name="settings_service_ip_monitor_monitor_root">Netlink monitor with root</string> <string name="settings_service_ip_monitor_monitor_root">Netlink monitor with root</string>
<string name="settings_service_ip_monitor_poll">Poll</string> <string name="settings_service_ip_monitor_poll">Poll</string>
<string name="settings_service_ip_monitor_poll_root">Poll with root</string> <string name="settings_service_ip_monitor_poll_root">Poll with root</string>
<string name="settings_service_upstream_monitor">Current upstreams</string>
<string name="settings_service_upstream_monitor_summary">%1$s; fallback: %2$s</string>
<string name="settings_service_upstream">Upstream network interface</string> <string name="settings_service_upstream">Upstream network interface</string>
<string name="settings_service_upstream_auto">Auto detect system VPN</string> <string name="settings_service_upstream_auto">Auto detect system VPN</string>
<string name="settings_upstream_fallback">Fallback upstream interface</string> <string name="settings_upstream_fallback">Fallback upstream interface</string>

View File

@@ -7,6 +7,10 @@
app:summary="@string/settings_service_clean_summary"/> app:summary="@string/settings_service_clean_summary"/>
<PreferenceCategory <PreferenceCategory
app:title="@string/settings_upstream"> app:title="@string/settings_upstream">
<be.mygod.vpnhotspot.preference.UpstreamsPreference
app:key="service.upstream.monitor"
app:icon="@drawable/ic_image_remove_red_eye"
app:title="@string/settings_service_upstream_monitor"/>
<EditTextPreference <EditTextPreference
app:key="service.upstream" app:key="service.upstream"
app:icon="@drawable/ic_action_settings_ethernet" app:icon="@drawable/ic_action_settings_ethernet"