@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user