diff --git a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt index b96af1b..5182247 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/group/RawUpdater.kt @@ -292,8 +292,9 @@ object RawUpdater : GroupUpdater() { } } for (opt in proxy) { + if (opt.value == null) continue when (opt.key.replace("_", "-")) { - "name" -> bean.name = opt.value?.toString() + "name" -> bean.name = opt.value.toString() "server" -> bean.serverAddress = opt.value as String "port" -> bean.serverPort = opt.value.toString().toInt() "uuid" -> bean.uuid = opt.value as String @@ -325,12 +326,12 @@ object RawUpdater : GroupUpdater() { opt.value as String "tls" -> bean.security = - if (opt.value?.toString() == "true") "tls" else "" + if (opt.value.toString() == "true") "tls" else "" "skip-cert-verify" -> bean.allowInsecure = - opt.value?.toString() == "true" + opt.value.toString() == "true" - "ws-path" -> bean.path = opt.value?.toString() + "ws-path" -> bean.path = opt.value.toString() "ws-headers" -> for (wsHeader in (opt.value as Map)) { when (wsHeader.key.lowercase()) { "host" -> bean.host = wsHeader.value.toString() @@ -359,7 +360,7 @@ object RawUpdater : GroupUpdater() { } } - "servername" -> bean.host = opt.value?.toString() + "servername" -> bean.host = opt.value.toString() // The format of the VMessBean is wrong, so the `host` `path` has some strange transformations here. "h2-opts", "h2-opt" -> for (h2Opt in (opt.value as Map)) { when (h2Opt.key.lowercase()) { @@ -412,20 +413,21 @@ object RawUpdater : GroupUpdater() { val bean = TrojanBean() bean.security = "tls" for (opt in proxy) { + if (opt.value == null) continue when (opt.key.replace("_", "-")) { - "name" -> bean.name = opt.value?.toString() + "name" -> bean.name = opt.value.toString() "server" -> bean.serverAddress = opt.value as String "port" -> bean.serverPort = opt.value.toString().toInt() - "password" -> bean.password = opt.value?.toString() + "password" -> bean.password = opt.value.toString() "client-fingerprint" -> bean.utlsFingerprint = opt.value as String - "sni" -> bean.sni = opt.value?.toString() + "sni" -> bean.sni = opt.value.toString() "skip-cert-verify" -> bean.allowInsecure = - opt.value?.toString() == "true" + opt.value.toString() == "true" "network" -> when (opt.value) { - "ws", "grpc" -> bean.type = opt.value?.toString() + "ws", "grpc" -> bean.type = opt.value.toString() } "ws-opts", "ws-opt" -> for (wsOpt in (opt.value as Map)) { @@ -456,8 +458,9 @@ object RawUpdater : GroupUpdater() { "hysteria" -> { val bean = HysteriaBean() for (opt in proxy) { + if (opt.value == null) continue when (opt.key.replace("_", "-")) { - "name" -> bean.name = opt.value?.toString() + "name" -> bean.name = opt.value.toString() "server" -> bean.serverAddress = opt.value as String "port" -> bean.serverPort = opt.value.toString().toInt() @@ -465,30 +468,30 @@ object RawUpdater : GroupUpdater() { "auth-str" -> { bean.authPayloadType = HysteriaBean.TYPE_STRING - bean.authPayload = opt.value?.toString() + bean.authPayload = opt.value.toString() } - "sni" -> bean.sni = opt.value?.toString() + "sni" -> bean.sni = opt.value.toString() "skip-cert-verify" -> bean.allowInsecure = - opt.value?.toString() == "true" + opt.value.toString() == "true" "up" -> bean.uploadMbps = - opt.value?.toString()?.substringBefore(" ")?.toIntOrNull() + opt.value.toString().substringBefore(" ").toIntOrNull() ?: 100 "down" -> bean.downloadMbps = - opt.value?.toString()?.substringBefore(" ")?.toIntOrNull() + opt.value.toString().substringBefore(" ").toIntOrNull() ?: 100 "recv-window-conn" -> bean.connectionReceiveWindow = - opt.value?.toString()?.toIntOrNull() ?: 0 + opt.value.toString().toIntOrNull() ?: 0 "recv-window" -> bean.streamReceiveWindow = - opt.value?.toString()?.toIntOrNull() ?: 0 + opt.value.toString().toIntOrNull() ?: 0 "disable-mtu-discovery" -> bean.disableMtuDiscovery = - opt.value?.toString() == "true" || opt.value?.toString() == "1" + opt.value.toString() == "true" || opt.value.toString() == "1" "alpn" -> { val alpn = (opt.value as? (List)) @@ -504,8 +507,9 @@ object RawUpdater : GroupUpdater() { val bean = TuicBean() var ip = "" for (opt in proxy) { + if (opt.value == null) continue when (opt.key.replace("_", "-")) { - "name" -> bean.name = opt.value?.toString() + "name" -> bean.name = opt.value.toString() "server" -> bean.serverAddress = opt.value.toString() "ip" -> ip = opt.value.toString() "port" -> bean.serverPort = opt.value.toString().toInt() @@ -520,13 +524,13 @@ object RawUpdater : GroupUpdater() { "password" -> bean.token = opt.value.toString() "skip-cert-verify" -> bean.allowInsecure = - opt.value?.toString() == "true" + opt.value.toString() == "true" "disable-sni" -> bean.disableSNI = - opt.value?.toString() == "true" + opt.value.toString() == "true" "reduce-rtt" -> bean.reduceRTT = - opt.value?.toString() == "true" + opt.value.toString() == "true" "sni" -> bean.sni = opt.value.toString() diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/AppManagerActivity.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/AppManagerActivity.kt index bc38ce0..fdf3a3f 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/ui/AppManagerActivity.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/ui/AppManagerActivity.kt @@ -246,8 +246,9 @@ class AppManagerActivity : ThemedActivity() { when (item.itemId) { R.id.action_invert_selections -> { runOnDefaultDispatcher { + val proxiedUidsOld = proxiedUids.clone() for (app in apps) { - if (proxiedUids.contains(app.uid)) { + if (proxiedUidsOld.contains(app.uid)) { proxiedUids.delete(app.uid) } else { proxiedUids[app.uid] = true diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt index da1558f..7c19107 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/ui/GroupFragment.kt @@ -29,6 +29,7 @@ import io.nekohasekai.sagernet.widget.UndoSnackbarManager import kotlinx.coroutines.delay import moe.matsuri.nb4a.utils.Util import moe.matsuri.nb4a.utils.toBytesString +import java.lang.NumberFormatException import java.util.* class GroupFragment : ToolbarFragment(R.layout.layout_group), @@ -465,27 +466,31 @@ class GroupFragment : ToolbarFragment(R.layout.layout_group), }.firstOrNull() } - var used: Long = 0 - get("upload=([0-9]+)")?.apply { - used += toLong() - } - get("download=([0-9]+)")?.apply { - used += toLong() - } - val total = get("total=([0-9]+)")?.toLong() ?: 0 - if (used > 0 || total > 0) { - text += getString( - R.string.subscription_traffic, - used.toBytesString(), - (total - used).toBytesString() - ) - } - get("expire=([0-9]+)")?.apply { - text += "\n" - text += getString( - R.string.subscription_expire, - Util.timeStamp2Text(this.toLong() * 1000) - ) + try { + var used: Long = 0 + get("upload=([0-9]+)")?.apply { + used += toLong() + } + get("download=([0-9]+)")?.apply { + used += toLong() + } + val total = get("total=([0-9]+)")?.toLong() ?: 0 + if (used > 0 || total > 0) { + text += getString( + R.string.subscription_traffic, + used.toBytesString(), + (total - used).toBytesString() + ) + } + get("expire=([0-9]+)")?.apply { + text += "\n" + text += getString( + R.string.subscription_expire, + Util.timeStamp2Text(this.toLong() * 1000) + ) + } + } catch (_: NumberFormatException) { + // ignore } if (text.isNotEmpty()) { diff --git a/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt b/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt index d1626df..1ba8f3c 100644 --- a/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt +++ b/app/src/main/java/io/nekohasekai/sagernet/ui/MainActivity.kt @@ -328,7 +328,7 @@ class MainActivity : ThemedActivity(), R.id.nav_about -> displayFragment(AboutFragment()) R.id.nav_tuiguang -> { - launchCustomTab("https://matsuricom.github.io/") + launchCustomTab("https://matsuricom.pages.dev/") return false }