Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44723c56ad | ||
|
|
e53c36b53b | ||
|
|
80f26cd4b8 | ||
|
|
b023414cd0 | ||
|
|
2f56104565 | ||
|
|
9cd5fefdca | ||
|
|
25c42c475f | ||
|
|
96e66da071 | ||
|
|
6914b9ee1b | ||
|
|
cfc6546c97 | ||
|
|
0880313659 | ||
|
|
875ca02126 | ||
|
|
c2d5925053 | ||
|
|
547bbf8e95 | ||
|
|
2218251b03 | ||
|
|
4da3a23162 | ||
|
|
28a90baf88 | ||
|
|
7bbdda2f2f |
@@ -11,8 +11,8 @@ android {
|
||||
applicationId = "com.v2ray.ang"
|
||||
minSdk = 21
|
||||
targetSdk = 35
|
||||
versionCode = 607
|
||||
versionName = "1.9.12"
|
||||
versionCode = 612
|
||||
versionName = "1.9.16"
|
||||
multiDexEnabled = true
|
||||
splits {
|
||||
abi {
|
||||
|
||||
@@ -41,14 +41,90 @@
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理海外公共DNSIP",
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"1.1.1.1",
|
||||
"1.0.0.1",
|
||||
"2606:4700:4700::1111",
|
||||
"2606:4700:4700::1001",
|
||||
"1.1.1.2",
|
||||
"1.0.0.2",
|
||||
"2606:4700:4700::1112",
|
||||
"2606:4700:4700::1002",
|
||||
"1.1.1.3",
|
||||
"1.0.0.3",
|
||||
"2606:4700:4700::1113",
|
||||
"2606:4700:4700::1003",
|
||||
"8.8.8.8",
|
||||
"8.8.4.4",
|
||||
"2001:4860:4860::8888",
|
||||
"2001:4860:4860::8844",
|
||||
"94.140.14.14",
|
||||
"94.140.15.15",
|
||||
"2a10:50c0::ad1:ff",
|
||||
"2a10:50c0::ad2:ff",
|
||||
"94.140.14.15",
|
||||
"94.140.15.16",
|
||||
"2a10:50c0::bad1:ff",
|
||||
"2a10:50c0::bad2:ff",
|
||||
"94.140.14.140",
|
||||
"94.140.14.141",
|
||||
"2a10:50c0::1:ff",
|
||||
"2a10:50c0::2:ff",
|
||||
"208.67.222.222",
|
||||
"208.67.220.220",
|
||||
"2620:119:35::35",
|
||||
"2620:119:53::53",
|
||||
"208.67.222.123",
|
||||
"208.67.220.123",
|
||||
"2620:119:35::123",
|
||||
"2620:119:53::123",
|
||||
"9.9.9.9",
|
||||
"149.112.112.112",
|
||||
"2620:fe::9",
|
||||
"2620:fe::fe",
|
||||
"9.9.9.11",
|
||||
"149.112.112.11",
|
||||
"2620:fe::11",
|
||||
"2620:fe::fe:11",
|
||||
"9.9.9.10",
|
||||
"149.112.112.10",
|
||||
"2620:fe::10",
|
||||
"2620:fe::fe:10",
|
||||
"77.88.8.8",
|
||||
"77.88.8.1",
|
||||
"2a02:6b8::feed:0ff",
|
||||
"2a02:6b8:0:1::feed:0ff",
|
||||
"77.88.8.88",
|
||||
"77.88.8.2",
|
||||
"2a02:6b8::feed:bad",
|
||||
"2a02:6b8:0:1::feed:bad",
|
||||
"77.88.8.7",
|
||||
"77.88.8.3",
|
||||
"2a02:6b8::feed:a11",
|
||||
"2a02:6b8:0:1::feed:a11"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理海外公共DNS域名",
|
||||
"outboundTag": "proxy",
|
||||
"domain": [
|
||||
"domain:cloudflare-dns.com",
|
||||
"domain:one.one.one.one",
|
||||
"domain:dns.google",
|
||||
"domain:adguard-dns.com",
|
||||
"domain:opendns.com",
|
||||
"domain:umbrella.com",
|
||||
"domain:quad9.net",
|
||||
"domain:yandex.net"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "代理IP",
|
||||
"outboundTag": "proxy",
|
||||
"ip": [
|
||||
"1.0.0.1",
|
||||
"1.1.1.1",
|
||||
"8.8.8.8",
|
||||
"8.8.4.4",
|
||||
"geoip:facebook",
|
||||
"geoip:fastly",
|
||||
"geoip:google",
|
||||
|
||||
@@ -34,29 +34,62 @@
|
||||
"geosite:private"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国公共DNSIP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"223.5.5.5",
|
||||
"223.6.6.6",
|
||||
"2400:3200::1",
|
||||
"2400:3200:baba::1",
|
||||
"119.29.29.29",
|
||||
"1.12.12.12",
|
||||
"120.53.53.53",
|
||||
"2402:4e00::",
|
||||
"2402:4e00:1::",
|
||||
"180.76.76.76",
|
||||
"2400:da00::6666",
|
||||
"114.114.114.114",
|
||||
"114.114.115.115",
|
||||
"114.114.114.119",
|
||||
"114.114.115.119",
|
||||
"114.114.114.110",
|
||||
"114.114.115.110",
|
||||
"180.184.1.1",
|
||||
"180.184.2.2",
|
||||
"101.226.4.6",
|
||||
"218.30.118.6",
|
||||
"123.125.81.6",
|
||||
"140.207.198.6",
|
||||
"1.2.4.8",
|
||||
"210.2.4.8",
|
||||
"52.80.66.66",
|
||||
"117.50.22.22",
|
||||
"2400:7fc0:849e:200::4",
|
||||
"2404:c2c0:85d8:901::4",
|
||||
"117.50.10.10",
|
||||
"52.80.52.52",
|
||||
"2400:7fc0:849e:200::8",
|
||||
"2404:c2c0:85d8:901::8",
|
||||
"117.50.60.30",
|
||||
"52.80.60.30"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国公共DNS域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:alidns.com",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:360.cn",
|
||||
"domain:onedns.net"
|
||||
]
|
||||
},
|
||||
{
|
||||
"remarks": "绕过中国IP",
|
||||
"outboundTag": "direct",
|
||||
"ip": [
|
||||
"223.5.5.5/32",
|
||||
"223.6.6.6/32",
|
||||
"2400:3200::1/128",
|
||||
"2400:3200:baba::1/128",
|
||||
"119.29.29.29/32",
|
||||
"1.12.12.12/32",
|
||||
"120.53.53.53/32",
|
||||
"2402:4e00::/128",
|
||||
"2402:4e00:1::/128",
|
||||
"180.76.76.76/32",
|
||||
"2400:da00::6666/128",
|
||||
"114.114.114.114/32",
|
||||
"114.114.115.115/32",
|
||||
"180.184.1.1/32",
|
||||
"180.184.2.2/32",
|
||||
"101.226.4.6/32",
|
||||
"218.30.118.6/32",
|
||||
"123.125.81.6/32",
|
||||
"140.207.198.6/32",
|
||||
"geoip:cn"
|
||||
]
|
||||
},
|
||||
@@ -64,13 +97,7 @@
|
||||
"remarks": "绕过中国域名",
|
||||
"outboundTag": "direct",
|
||||
"domain": [
|
||||
"domain:dns.alidns.com",
|
||||
"domain:doh.pub",
|
||||
"domain:dot.pub",
|
||||
"domain:doh.360.cn",
|
||||
"domain:dot.360.cn",
|
||||
"geosite:cn",
|
||||
"geosite:geolocation-cn"
|
||||
"geosite:cn"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -161,15 +161,20 @@ object AppConfig {
|
||||
const val GOOGLEAPIS_COM_DOMAIN = "googleapis.com"
|
||||
|
||||
// Android Private DNS constants
|
||||
const val DNS_PUB_DOMAIN = "dns.pub"
|
||||
const val DNS_DNSPOD_DOMAIN = "dot.pub"
|
||||
const val DNS_ALIDNS_DOMAIN = "dns.alidns.com"
|
||||
const val DNS_ONE_ONE_DOMAIN = "one.one.one.one"
|
||||
const val DNS_CLOUDFLARE_DOMAIN = "one.one.one.one"
|
||||
const val DNS_GOOGLE_DOMAIN = "dns.google"
|
||||
const val DNS_QUAD9_DOMAIN = "dns.quad9.net"
|
||||
const val DNS_YANDEX_DOMAIN = "common.dot.dns.yandex.net"
|
||||
|
||||
val DNS_PUB_ADDRESSES = arrayListOf("1.12.12.12", "120.53.53.53")
|
||||
|
||||
val DNS_ALIDNS_ADDRESSES = arrayListOf("223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1")
|
||||
val DNS_ONE_ONE_ADDRESSES = arrayListOf("1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001")
|
||||
val DNS_CLOUDFLARE_ADDRESSES = arrayListOf("1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001")
|
||||
val DNS_DNSPOD_ADDRESSES = arrayListOf("1.12.12.12", "120.53.53.53")
|
||||
val DNS_GOOGLE_ADDRESSES = arrayListOf("8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844")
|
||||
val DNS_QUAD9_ADDRESSES = arrayListOf("9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9")
|
||||
val DNS_YANDEX_ADDRESSES = arrayListOf("77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff")
|
||||
|
||||
const val DEFAULT_PORT = 443
|
||||
const val DEFAULT_SECURITY = "auto"
|
||||
|
||||
@@ -470,16 +470,16 @@ data class V2rayConfig(
|
||||
if (protocol.equals(EConfigType.VMESS.name, true)
|
||||
|| protocol.equals(EConfigType.VLESS.name, true)
|
||||
) {
|
||||
return settings?.vnext?.get(0)?.address
|
||||
return settings?.vnext?.first()?.address
|
||||
} else if (protocol.equals(EConfigType.SHADOWSOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.SOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.HTTP.name, true)
|
||||
|| protocol.equals(EConfigType.TROJAN.name, true)
|
||||
|| protocol.equals(EConfigType.HYSTERIA2.name, true)
|
||||
) {
|
||||
return settings?.servers?.get(0)?.address
|
||||
return settings?.servers?.first()?.address
|
||||
} else if (protocol.equals(EConfigType.WIREGUARD.name, true)) {
|
||||
return settings?.peers?.get(0)?.endpoint?.substringBeforeLast(":")
|
||||
return settings?.peers?.first()?.endpoint?.substringBeforeLast(":")
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -488,16 +488,16 @@ data class V2rayConfig(
|
||||
if (protocol.equals(EConfigType.VMESS.name, true)
|
||||
|| protocol.equals(EConfigType.VLESS.name, true)
|
||||
) {
|
||||
return settings?.vnext?.get(0)?.port
|
||||
return settings?.vnext?.first()?.port
|
||||
} else if (protocol.equals(EConfigType.SHADOWSOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.SOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.HTTP.name, true)
|
||||
|| protocol.equals(EConfigType.TROJAN.name, true)
|
||||
|| protocol.equals(EConfigType.HYSTERIA2.name, true)
|
||||
) {
|
||||
return settings?.servers?.get(0)?.port
|
||||
return settings?.servers?.first()?.port
|
||||
} else if (protocol.equals(EConfigType.WIREGUARD.name, true)) {
|
||||
return settings?.peers?.get(0)?.endpoint?.substringAfterLast(":")?.toInt()
|
||||
return settings?.peers?.first()?.endpoint?.substringAfterLast(":")?.toInt()
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -512,16 +512,16 @@ data class V2rayConfig(
|
||||
if (protocol.equals(EConfigType.VMESS.name, true)
|
||||
|| protocol.equals(EConfigType.VLESS.name, true)
|
||||
) {
|
||||
return settings?.vnext?.get(0)?.users?.get(0)?.id
|
||||
return settings?.vnext?.first()?.users?.first()?.id
|
||||
} else if (protocol.equals(EConfigType.SHADOWSOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.TROJAN.name, true)
|
||||
|| protocol.equals(EConfigType.HYSTERIA2.name, true)
|
||||
) {
|
||||
return settings?.servers?.get(0)?.password
|
||||
return settings?.servers?.first()?.password
|
||||
} else if (protocol.equals(EConfigType.SOCKS.name, true)
|
||||
|| protocol.equals(EConfigType.HTTP.name, true)
|
||||
) {
|
||||
return settings?.servers?.get(0)?.users?.get(0)?.pass
|
||||
return settings?.servers?.first()?.users?.first()?.pass
|
||||
} else if (protocol.equals(EConfigType.WIREGUARD.name, true)) {
|
||||
return settings?.secretKey
|
||||
}
|
||||
@@ -530,9 +530,9 @@ data class V2rayConfig(
|
||||
|
||||
fun getSecurityEncryption(): String? {
|
||||
return when {
|
||||
protocol.equals(EConfigType.VMESS.name, true) -> settings?.vnext?.get(0)?.users?.get(0)?.security
|
||||
protocol.equals(EConfigType.VLESS.name, true) -> settings?.vnext?.get(0)?.users?.get(0)?.encryption
|
||||
protocol.equals(EConfigType.SHADOWSOCKS.name, true) -> settings?.servers?.get(0)?.method
|
||||
protocol.equals(EConfigType.VMESS.name, true) -> settings?.vnext?.first()?.users?.first()?.security
|
||||
protocol.equals(EConfigType.VLESS.name, true) -> settings?.vnext?.first()?.users?.first()?.encryption
|
||||
protocol.equals(EConfigType.SHADOWSOCKS.name, true) -> settings?.servers?.first()?.method
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ object HttpFmt : FmtBase() {
|
||||
fun toOutbound(profileItem: ProfileItem): OutboundBean? {
|
||||
val outboundBean = OutboundBean.create(EConfigType.HTTP)
|
||||
|
||||
outboundBean?.settings?.servers?.get(0)?.let { server ->
|
||||
outboundBean?.settings?.servers?.first()?.let { server ->
|
||||
server.address = profileItem.server.orEmpty()
|
||||
server.port = profileItem.serverPort.orEmpty().toInt()
|
||||
if (profileItem.username.isNotNullEmpty()) {
|
||||
|
||||
@@ -9,10 +9,16 @@ import java.net.URI
|
||||
|
||||
object ShadowsocksFmt : FmtBase() {
|
||||
fun parse(str: String): ProfileItem? {
|
||||
return parseSip002(str) ?: parseLegacy(str)
|
||||
}
|
||||
|
||||
fun parseSip002(str: String): ProfileItem? {
|
||||
val config = ProfileItem.create(EConfigType.SHADOWSOCKS)
|
||||
|
||||
val uri = URI(Utils.fixIllegalUrl(str))
|
||||
if (uri.idnHost.isEmpty() || uri.userInfo.isEmpty()) return null
|
||||
if (uri.idnHost.isEmpty()) return null
|
||||
if (uri.port <= 0) return null
|
||||
if (uri.userInfo.isNullOrEmpty()) return null
|
||||
|
||||
config.remarks = Utils.urlDecode(uri.fragment.orEmpty())
|
||||
config.server = uri.idnHost
|
||||
@@ -42,16 +48,53 @@ object ShadowsocksFmt : FmtBase() {
|
||||
return config
|
||||
}
|
||||
|
||||
fun parseLegacy(str: String): ProfileItem? {
|
||||
val config = ProfileItem.create(EConfigType.SHADOWSOCKS)
|
||||
var result = str.replace(EConfigType.SHADOWSOCKS.protocolScheme, "")
|
||||
val indexSplit = result.indexOf("#")
|
||||
if (indexSplit > 0) {
|
||||
try {
|
||||
config.remarks =
|
||||
Utils.urlDecode(result.substring(indexSplit + 1, result.length))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
result = result.substring(0, indexSplit)
|
||||
}
|
||||
|
||||
//part decode
|
||||
val indexS = result.indexOf("@")
|
||||
result = if (indexS > 0) {
|
||||
Utils.decode(result.substring(0, indexS)) + result.substring(
|
||||
indexS,
|
||||
result.length
|
||||
)
|
||||
} else {
|
||||
Utils.decode(result)
|
||||
}
|
||||
|
||||
val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)/?$".toRegex()
|
||||
val match = legacyPattern.matchEntire(result) ?: return null
|
||||
|
||||
config.server = match.groupValues[3].removeSurrounding("[", "]")
|
||||
config.serverPort = match.groupValues[4]
|
||||
config.password = match.groupValues[2]
|
||||
config.method = match.groupValues[1].lowercase()
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
fun toUri(config: ProfileItem): String {
|
||||
val pw = "${config.method}:${config.password}"
|
||||
|
||||
return toUri(config, pw, null)
|
||||
return toUri(config, Utils.encode(pw), null)
|
||||
}
|
||||
|
||||
fun toOutbound(profileItem: ProfileItem): OutboundBean? {
|
||||
val outboundBean = OutboundBean.create(EConfigType.SHADOWSOCKS)
|
||||
|
||||
outboundBean?.settings?.servers?.get(0)?.let { server ->
|
||||
outboundBean?.settings?.servers?.first()?.let { server ->
|
||||
server.address = profileItem.server.orEmpty()
|
||||
server.port = profileItem.serverPort.orEmpty().toInt()
|
||||
server.password = profileItem.password
|
||||
|
||||
@@ -15,6 +15,7 @@ object SocksFmt : FmtBase() {
|
||||
|
||||
val uri = URI(Utils.fixIllegalUrl(str))
|
||||
if (uri.idnHost.isEmpty()) return null
|
||||
if (uri.port <= 0) return null
|
||||
|
||||
config.remarks = Utils.urlDecode(uri.fragment.orEmpty())
|
||||
config.server = uri.idnHost
|
||||
@@ -38,13 +39,13 @@ object SocksFmt : FmtBase() {
|
||||
else
|
||||
":"
|
||||
|
||||
return toUri(config, pw, null)
|
||||
return toUri(config, Utils.encode(pw), null)
|
||||
}
|
||||
|
||||
fun toOutbound(profileItem: ProfileItem): OutboundBean? {
|
||||
val outboundBean = OutboundBean.create(EConfigType.SOCKS)
|
||||
|
||||
outboundBean?.settings?.servers?.get(0)?.let { server ->
|
||||
outboundBean?.settings?.servers?.first()?.let { server ->
|
||||
server.address = profileItem.server.orEmpty()
|
||||
server.port = profileItem.serverPort.orEmpty().toInt()
|
||||
if (profileItem.username.isNotNullEmpty()) {
|
||||
|
||||
@@ -22,9 +22,9 @@ object TrojanFmt : FmtBase() {
|
||||
config.password = uri.userInfo
|
||||
|
||||
if (uri.rawQuery.isNullOrEmpty()) {
|
||||
config.network = "tcp"
|
||||
config.security = AppConfig.TLS
|
||||
config.insecure = allowInsecure
|
||||
|
||||
} else {
|
||||
val queryParam = getQueryParam(uri)
|
||||
|
||||
@@ -40,7 +40,7 @@ object TrojanFmt : FmtBase() {
|
||||
config.serviceName = queryParam["serviceName"]
|
||||
config.authority = queryParam["authority"]
|
||||
|
||||
config.security = queryParam["security"]
|
||||
config.security = queryParam["security"] ?: AppConfig.TLS
|
||||
config.insecure = if (queryParam["allowInsecure"].isNullOrEmpty()) {
|
||||
allowInsecure
|
||||
} else {
|
||||
@@ -67,7 +67,7 @@ object TrojanFmt : FmtBase() {
|
||||
fun toOutbound(profileItem: ProfileItem): OutboundBean? {
|
||||
val outboundBean = OutboundBean.create(EConfigType.TROJAN)
|
||||
|
||||
outboundBean?.settings?.servers?.get(0)?.let { server ->
|
||||
outboundBean?.settings?.servers?.first()?.let { server ->
|
||||
server.address = profileItem.server.orEmpty()
|
||||
server.port = profileItem.serverPort.orEmpty().toInt()
|
||||
server.password = profileItem.password
|
||||
|
||||
@@ -65,7 +65,7 @@ object VlessFmt : FmtBase() {
|
||||
fun toOutbound(profileItem: ProfileItem): OutboundBean? {
|
||||
val outboundBean = OutboundBean.create(EConfigType.VLESS)
|
||||
|
||||
outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
|
||||
outboundBean?.settings?.vnext?.first()?.let { vnext ->
|
||||
vnext.address = profileItem.server.orEmpty()
|
||||
vnext.port = profileItem.serverPort.orEmpty().toInt()
|
||||
vnext.users[0].id = profileItem.password.orEmpty()
|
||||
|
||||
@@ -162,7 +162,7 @@ object VmessFmt : FmtBase() {
|
||||
fun toOutbound(profileItem: ProfileItem): OutboundBean? {
|
||||
val outboundBean = OutboundBean.create(EConfigType.VMESS)
|
||||
|
||||
outboundBean?.settings?.vnext?.get(0)?.let { vnext ->
|
||||
outboundBean?.settings?.vnext?.first()?.let { vnext ->
|
||||
vnext.address = profileItem.server.orEmpty()
|
||||
vnext.port = profileItem.serverPort.orEmpty().toInt()
|
||||
vnext.users[0].id = profileItem.password.orEmpty()
|
||||
|
||||
@@ -82,8 +82,8 @@ object WireguardFmt : FmtBase() {
|
||||
outboundBean?.settings?.let { wireguard ->
|
||||
wireguard.secretKey = profileItem.secretKey
|
||||
wireguard.address = (profileItem.localAddress ?: WIREGUARD_LOCAL_ADDRESS_V4).split(",")
|
||||
wireguard.peers?.get(0)?.publicKey = profileItem.publicKey.orEmpty()
|
||||
wireguard.peers?.get(0)?.endpoint = Utils.getIpv6Address(profileItem.server) + ":${profileItem.serverPort}"
|
||||
wireguard.peers?.first()?.publicKey = profileItem.publicKey.orEmpty()
|
||||
wireguard.peers?.first()?.endpoint = Utils.getIpv6Address(profileItem.server) + ":${profileItem.serverPort}"
|
||||
wireguard.mtu = profileItem.mtu?.toInt()
|
||||
wireguard.reserved = profileItem.reserved?.split(",")?.map { it.toInt() }
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ object MigrateManager {
|
||||
|
||||
//check and remove old
|
||||
decodeServerConfig(guid) ?: continue
|
||||
//serverStorage.remove(guid)
|
||||
serverStorage.remove(guid)
|
||||
Log.d(ANG_PACKAGE, "migrateServerConfig2Profile-" + config.remarks)
|
||||
}
|
||||
Log.d(ANG_PACKAGE, "migrateServerConfig2Profile-end")
|
||||
@@ -70,7 +70,7 @@ object MigrateManager {
|
||||
config.serverPort = outbound.getServerPort().toString()
|
||||
config.method = outbound.getSecurityEncryption()
|
||||
config.password = outbound.getPassword()
|
||||
config.flow = outbound?.settings?.vnext?.get(0)?.users?.get(0)?.flow ?: outbound?.settings?.servers?.get(0)?.flow
|
||||
config.flow = outbound?.settings?.vnext?.first()?.users?.first()?.flow ?: outbound?.settings?.servers?.first()?.flow
|
||||
|
||||
config.network = outbound?.streamSettings?.network ?: "tcp"
|
||||
outbound.getTransportSettingDetails()?.let { transportDetails ->
|
||||
@@ -107,7 +107,7 @@ object MigrateManager {
|
||||
config.remarks = configOld.remarks
|
||||
config.server = outbound.getServerAddress()
|
||||
config.serverPort = outbound.getServerPort().toString()
|
||||
config.username = outbound.settings?.servers?.get(0)?.users?.get(0)?.user
|
||||
config.username = outbound.settings?.servers?.first()?.users?.first()?.user
|
||||
config.password = outbound.getPassword()
|
||||
|
||||
return config
|
||||
@@ -120,7 +120,7 @@ object MigrateManager {
|
||||
config.remarks = configOld.remarks
|
||||
config.server = outbound.getServerAddress()
|
||||
config.serverPort = outbound.getServerPort().toString()
|
||||
config.username = outbound.settings?.servers?.get(0)?.users?.get(0)?.user
|
||||
config.username = outbound.settings?.servers?.first()?.users?.first()?.user
|
||||
config.password = outbound.getPassword()
|
||||
|
||||
return config
|
||||
|
||||
@@ -8,12 +8,16 @@ import com.v2ray.ang.AppConfig.ANG_PACKAGE
|
||||
import com.v2ray.ang.AppConfig.DEFAULT_NETWORK
|
||||
import com.v2ray.ang.AppConfig.DNS_ALIDNS_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_ALIDNS_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_CLOUDFLARE_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_CLOUDFLARE_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_DNSPOD_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_DNSPOD_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_GOOGLE_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_GOOGLE_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_ONE_ONE_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_ONE_ONE_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_PUB_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_PUB_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_QUAD9_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_QUAD9_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.DNS_YANDEX_ADDRESSES
|
||||
import com.v2ray.ang.AppConfig.DNS_YANDEX_DOMAIN
|
||||
import com.v2ray.ang.AppConfig.GEOIP_CN
|
||||
import com.v2ray.ang.AppConfig.GEOSITE_CN
|
||||
import com.v2ray.ang.AppConfig.GEOSITE_PRIVATE
|
||||
@@ -57,7 +61,7 @@ object V2rayConfigManager {
|
||||
}
|
||||
|
||||
val result = getV2rayNonCustomConfig(context, config)
|
||||
Log.d(ANG_PACKAGE, result.content)
|
||||
//Log.d(ANG_PACKAGE, result.content)
|
||||
result.guid = guid
|
||||
return result
|
||||
} catch (e: Exception) {
|
||||
@@ -376,10 +380,12 @@ object V2rayConfigManager {
|
||||
hosts[GOOGLEAPIS_CN_DOMAIN] = GOOGLEAPIS_COM_DOMAIN
|
||||
|
||||
// hardcode popular Android Private DNS rule to fix localhost DNS problem
|
||||
hosts[DNS_PUB_DOMAIN] = DNS_PUB_ADDRESSES
|
||||
hosts[DNS_ALIDNS_DOMAIN] = DNS_ALIDNS_ADDRESSES
|
||||
hosts[DNS_ONE_ONE_DOMAIN] = DNS_ONE_ONE_ADDRESSES
|
||||
hosts[DNS_CLOUDFLARE_DOMAIN] = DNS_CLOUDFLARE_ADDRESSES
|
||||
hosts[DNS_DNSPOD_DOMAIN] = DNS_DNSPOD_ADDRESSES
|
||||
hosts[DNS_GOOGLE_DOMAIN] = DNS_GOOGLE_ADDRESSES
|
||||
hosts[DNS_QUAD9_DOMAIN] = DNS_QUAD9_ADDRESSES
|
||||
hosts[DNS_YANDEX_DOMAIN] = DNS_YANDEX_ADDRESSES
|
||||
|
||||
|
||||
// DNS dns对象
|
||||
@@ -419,7 +425,7 @@ object V2rayConfigManager {
|
||||
) {
|
||||
muxEnabled = false
|
||||
} else if (protocol.equals(EConfigType.VLESS.name, true)
|
||||
&& outbound.settings?.vnext?.get(0)?.users?.get(0)?.flow?.isNotEmpty() == true
|
||||
&& outbound.settings?.vnext?.first()?.users?.first()?.flow?.isNotEmpty() == true
|
||||
) {
|
||||
muxEnabled = false
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import android.service.quicksettings.TileService
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.extension.v2RayApplication
|
||||
import com.v2ray.ang.util.MessageUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.lang.ref.SoftReference
|
||||
@@ -41,23 +40,24 @@ class QSTileService : TileService() {
|
||||
|
||||
override fun onStartListening() {
|
||||
super.onStartListening()
|
||||
|
||||
setState(Tile.STATE_INACTIVE)
|
||||
mMsgReceive = ReceiveMessageHandler(this)
|
||||
val mFilter = IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.registerReceiver(applicationContext,mMsgReceive,mFilter,ContextCompat.RECEIVER_EXPORTED)
|
||||
} else {
|
||||
ContextCompat.registerReceiver(applicationContext,mMsgReceive,mFilter,ContextCompat.RECEIVER_NOT_EXPORTED)
|
||||
}
|
||||
|
||||
ContextCompat.registerReceiver(applicationContext, mMsgReceive, mFilter, Utils.receiverFlags())
|
||||
MessageUtil.sendMsg2Service(this, AppConfig.MSG_REGISTER_CLIENT, "")
|
||||
}
|
||||
|
||||
override fun onStopListening() {
|
||||
super.onStopListening()
|
||||
|
||||
unregisterReceiver(mMsgReceive)
|
||||
mMsgReceive = null
|
||||
try {
|
||||
applicationContext.unregisterReceiver(mMsgReceive)
|
||||
mMsgReceive = null
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onClick() {
|
||||
|
||||
@@ -148,17 +148,7 @@ object V2RayServiceManager {
|
||||
mFilter.addAction(Intent.ACTION_SCREEN_ON)
|
||||
mFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||
mFilter.addAction(Intent.ACTION_USER_PRESENT)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.registerReceiver(
|
||||
service, mMsgReceive, mFilter,
|
||||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
} else {
|
||||
ContextCompat.registerReceiver(
|
||||
service, mMsgReceive, mFilter,
|
||||
ContextCompat.RECEIVER_NOT_EXPORTED
|
||||
)
|
||||
}
|
||||
ContextCompat.registerReceiver(service, mMsgReceive, mFilter, Utils.receiverFlags())
|
||||
} catch (e: Exception) {
|
||||
Log.d(ANG_PACKAGE, e.toString())
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import libv2ray.Libv2ray
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class V2RayTestService : Service() {
|
||||
private val realTestScope by lazy { CoroutineScope(Executors.newFixedThreadPool(10).asCoroutineDispatcher()) }
|
||||
private val realTestScope by lazy { CoroutineScope(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()).asCoroutineDispatcher()) }
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
@@ -153,15 +153,32 @@ class ServerActivity : BaseActivity() {
|
||||
sp_header_type_title?.text = if (networks[position] == "grpc")
|
||||
getString(R.string.server_lab_mode_type) else
|
||||
getString(R.string.server_lab_head_type)
|
||||
config?.headerType?.let { it ->
|
||||
sp_header_type?.setSelection(Utils.arrayFind(types, it))
|
||||
}
|
||||
config?.host?.let { it ->
|
||||
et_request_host?.text = Utils.getEditable(it)
|
||||
}
|
||||
config?.path?.let { it ->
|
||||
et_path?.text = Utils.getEditable(it)
|
||||
}
|
||||
sp_header_type?.setSelection(
|
||||
Utils.arrayFind(
|
||||
types,
|
||||
when (networks[position]) {
|
||||
"grpc" -> config?.mode
|
||||
else -> config?.headerType
|
||||
}.orEmpty()
|
||||
)
|
||||
)
|
||||
|
||||
et_request_host?.text = Utils.getEditable(
|
||||
when (networks[position]) {
|
||||
"quic" -> config?.quicSecurity
|
||||
"grpc" -> config?.authority
|
||||
else -> config?.host
|
||||
}.orEmpty()
|
||||
)
|
||||
et_path?.text = Utils.getEditable(
|
||||
when (networks[position]) {
|
||||
"kcp" -> config?.seed
|
||||
"quic" -> config?.quicKey
|
||||
"grpc" -> config?.serviceName
|
||||
else -> config?.path
|
||||
}.orEmpty()
|
||||
)
|
||||
|
||||
tv_request_host?.text = Utils.getEditable(
|
||||
getString(
|
||||
when (networks[position]) {
|
||||
|
||||
@@ -12,10 +12,9 @@ import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivityServerCustomConfigBinding
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.fmt.CustomFmt
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.util.JsonUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
import me.drakeet.support.toast.ToastCompat
|
||||
|
||||
@@ -75,8 +74,8 @@ class ServerCustomConfigActivity : BaseActivity() {
|
||||
return false
|
||||
}
|
||||
|
||||
val v2rayConfig = try {
|
||||
JsonUtil.fromJson(binding.editor.text.toString(), V2rayConfig::class.java)
|
||||
val profileItem = try {
|
||||
CustomFmt.parse(binding.editor.text.toString())
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
ToastCompat.makeText(this, "${getString(R.string.toast_malformed_josn)} ${e.cause?.message}", Toast.LENGTH_LONG).show()
|
||||
@@ -84,7 +83,11 @@ class ServerCustomConfigActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
val config = MmkvManager.decodeServerConfig(editGuid) ?: ProfileItem.create(EConfigType.CUSTOM)
|
||||
config.remarks = if (binding.etRemarks.text.isNullOrEmpty()) v2rayConfig.remarks.orEmpty() else binding.etRemarks.text.toString()
|
||||
binding.etRemarks.text.let {
|
||||
config.remarks = if (it.isNullOrEmpty()) profileItem?.remarks.orEmpty() else it.toString()
|
||||
}
|
||||
config.server = profileItem?.server
|
||||
config.serverPort = profileItem?.serverPort
|
||||
|
||||
MmkvManager.encodeServerConfig(editGuid, config)
|
||||
MmkvManager.encodeServerRaw(editGuid, binding.editor.text.toString())
|
||||
|
||||
@@ -17,6 +17,7 @@ import android.util.Log
|
||||
import android.util.Patterns
|
||||
import android.webkit.URLUtil
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.AppConfig.ANG_PACKAGE
|
||||
import com.v2ray.ang.AppConfig.LOOPBACK
|
||||
@@ -482,5 +483,11 @@ object Utils {
|
||||
return false
|
||||
}
|
||||
|
||||
fun receiverFlags(): Int = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.RECEIVER_EXPORTED
|
||||
} else {
|
||||
ContextCompat.RECEIVER_NOT_EXPORTED
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import com.v2ray.ang.util.MessageUtil
|
||||
import com.v2ray.ang.util.SpeedtestUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -53,18 +54,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
|
||||
fun startListenBroadcast() {
|
||||
isRunning.value = false
|
||||
val mFilter = IntentFilter(AppConfig.BROADCAST_ACTION_ACTIVITY)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
ContextCompat.registerReceiver(
|
||||
getApplication(), mMsgReceiver, mFilter,
|
||||
ContextCompat.RECEIVER_EXPORTED
|
||||
)
|
||||
} else {
|
||||
ContextCompat.registerReceiver(
|
||||
getApplication(), mMsgReceiver, mFilter,
|
||||
ContextCompat.RECEIVER_NOT_EXPORTED
|
||||
)
|
||||
}
|
||||
ContextCompat.registerReceiver(getApplication(), mMsgReceiver, mFilter, Utils.receiverFlags())
|
||||
MessageUtil.sendMsg2Service(getApplication(), AppConfig.MSG_REGISTER_CLIENT, "")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<LinearLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
@@ -18,9 +19,9 @@
|
||||
android:id="@+id/layout_backup"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
@@ -58,9 +59,9 @@
|
||||
android:id="@+id/layout_share"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/server_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
@@ -82,9 +83,9 @@
|
||||
android:id="@+id/layout_restore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/server_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
@@ -114,9 +115,9 @@
|
||||
android:id="@+id/layout_soure_ccode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/server_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
@@ -138,9 +139,9 @@
|
||||
android:id="@+id/layout_feedback"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/server_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
@@ -163,9 +164,9 @@
|
||||
android:id="@+id/layout_tg_channel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/server_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
@@ -187,9 +188,9 @@
|
||||
android:id="@+id/layout_privacy_policy"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/server_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/padding">
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
@@ -39,7 +40,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="2"
|
||||
android:text="@string/title_pref_per_app_proxy"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -57,7 +59,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/switch_bypass_apps_mode"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Small"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:paddingStart="@dimen/padding_start"
|
||||
android:paddingEnd="@dimen/padding_end"
|
||||
tools:context=".ui.LogcatActivity">
|
||||
@@ -19,10 +20,10 @@
|
||||
android:id="@+id/sv_logcat"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:fillViewport="false"
|
||||
android:foregroundGravity="bottom">
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
@@ -24,8 +24,7 @@
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/main_content"
|
||||
@@ -39,19 +38,19 @@
|
||||
|
||||
<com.google.android.material.progressindicator.LinearProgressIndicator
|
||||
android:id="@+id/pb_waiting"
|
||||
app:indicatorColor="@color/color_fab_active"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:visibility="invisible" />
|
||||
android:visibility="invisible"
|
||||
app:indicatorColor="@color/color_fab_active" />
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/tab_group"
|
||||
app:tabMode="scrollable"
|
||||
app:tabTextAppearance="@style/TabLayoutTextStyle"
|
||||
app:tabIndicatorFullWidth="false"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent" />
|
||||
app:tabIndicatorFullWidth="false"
|
||||
app:tabMode="scrollable"
|
||||
app:tabTextAppearance="@style/TabLayoutTextStyle" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
@@ -65,11 +64,11 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/connection_test_height"
|
||||
android:background="@color/colorPrimary"
|
||||
android:gravity="center|start"
|
||||
android:nextFocusRight="@+id/fab"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:nextFocusLeft="@+id/recycler_view">
|
||||
android:gravity="center|start"
|
||||
android:nextFocusLeft="@+id/recycler_view"
|
||||
android:nextFocusRight="@+id/fab">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_test_state"
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.SubSettingActivity">
|
||||
|
||||
<LinearLayout
|
||||
@@ -42,9 +44,10 @@
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/chk_locked"
|
||||
android:text="@string/routing_settings_locked"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/routing_settings_locked"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
@@ -74,10 +77,10 @@
|
||||
<EditText
|
||||
android:id="@+id/et_domain"
|
||||
android:layout_width="match_parent"
|
||||
android:maxLines="10"
|
||||
android:hint="@string/routing_settings_tips"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine" />
|
||||
android:hint="@string/routing_settings_tips"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLines="10" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
@@ -93,11 +96,11 @@
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_ip"
|
||||
android:maxLines="10"
|
||||
android:hint="@string/routing_settings_tips"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textMultiLine" />
|
||||
android:hint="@string/routing_settings_tips"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLines="10" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
@@ -132,8 +135,8 @@
|
||||
<EditText
|
||||
android:id="@+id/et_protocol"
|
||||
android:layout_width="match_parent"
|
||||
android:hint="@string/routing_settings_protocol_tip"
|
||||
android:layout_height="@dimen/edit_height"
|
||||
android:hint="@string/routing_settings_protocol_tip"
|
||||
android:inputType="text" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -151,8 +154,8 @@
|
||||
<EditText
|
||||
android:id="@+id/et_network"
|
||||
android:layout_width="match_parent"
|
||||
android:hint="@string/routing_settings_network_tip"
|
||||
android:layout_height="@dimen/edit_height"
|
||||
android:hint="@string/routing_settings_network_tip"
|
||||
android:inputType="text" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -179,8 +182,8 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerCustomConfigActivity">
|
||||
|
||||
<LinearLayout
|
||||
@@ -13,8 +14,8 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="@dimen/layout_margin_spacing">
|
||||
android:layout_margin="@dimen/layout_margin_spacing"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
@@ -27,8 +28,8 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_margin="@dimen/layout_margin_spacing">
|
||||
android:layout_margin="@dimen/layout_margin_spacing"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
@@ -69,11 +70,11 @@
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead" />
|
||||
|
||||
<com.blacksquircle.ui.editorkit.widget.TextProcessor
|
||||
android:id="@+id/editor"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="top|start"
|
||||
android:id="@+id/editor"
|
||||
android:layout_marginTop="@dimen/layout_margin_top_height" />
|
||||
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||
android:gravity="top|start" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.ServerActivity">
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/fragment_settings"
|
||||
android:name="com.v2ray.ang.ui.SettingsActivity$SettingsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.SettingsActivity" />
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.SettingsActivity">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/fragment_settings"
|
||||
android:name="com.v2ray.ang.ui.SettingsActivity$SettingsFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -3,6 +3,8 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.SubSettingActivity">
|
||||
|
||||
<LinearLayout
|
||||
@@ -108,7 +110,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/padding_start"
|
||||
android:paddingEnd="@dimen/padding_end" />
|
||||
android:paddingEnd="@dimen/padding_end"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -130,7 +133,8 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="@dimen/padding_start"
|
||||
android:paddingEnd="@dimen/padding_end" />
|
||||
android:paddingEnd="@dimen/padding_end"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -149,8 +153,8 @@
|
||||
android:id="@+id/et_pre_profile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/edit_height"
|
||||
android:inputType="text"
|
||||
android:hint="@string/sub_setting_pre_profile_tip" />
|
||||
android:hint="@string/sub_setting_pre_profile_tip"
|
||||
android:inputType="text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -169,8 +173,8 @@
|
||||
android:id="@+id/et_next_profile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/edit_height"
|
||||
android:inputType="text"
|
||||
android:hint="@string/sub_setting_pre_profile_tip" />
|
||||
android:hint="@string/sub_setting_pre_profile_tip"
|
||||
android:inputType="text" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -178,8 +182,8 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/padding"
|
||||
tools:context=".ui.TaskerActivity">
|
||||
@@ -22,11 +23,11 @@
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@id/switch_start_service"
|
||||
android:layout_toStartOf="@id/switch_start_service"
|
||||
android:layout_toLeftOf="@id/switch_start_service"
|
||||
android:text="@string/tasker_start_service"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".ui.UserAssetUrlActivity">
|
||||
|
||||
<LinearLayout
|
||||
@@ -77,8 +78,8 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||
android:layout_marginTop="@dimen/layout_margin_top_height"
|
||||
android:layout_marginBottom="@dimen/layout_margin_top_height"
|
||||
android:orientation="vertical" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/sub_height"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:nextFocusRight="@+id/layout_edit"
|
||||
android:orientation="horizontal">
|
||||
@@ -46,10 +46,10 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/img_locked"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="@dimen/padding_start"
|
||||
android:layout_width="@dimen/padding"
|
||||
android:layout_height="@dimen/padding"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="@dimen/padding_start"
|
||||
app:srcCompat="@drawable/ic_lock_24dp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -76,9 +76,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/sub_height"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="@dimen/padding_start"
|
||||
android:paddingEnd="@dimen/padding_end"
|
||||
android:orientation="vertical">
|
||||
android:paddingEnd="@dimen/padding_end">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_edit"
|
||||
@@ -107,7 +107,8 @@
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/chk_enable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/sub_height"
|
||||
android:layout_gravity="center"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center"
|
||||
android:nextFocusRight="@+id/layout_edit"
|
||||
android:orientation="horizontal">
|
||||
@@ -55,9 +55,10 @@
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/chk_enable"
|
||||
android:text="@string/sub_setting_enable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/sub_setting_enable"
|
||||
app:theme="@style/BrandedSwitch" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -173,7 +173,7 @@
|
||||
<string name="title_pref_domestic_dns">DNS داخلی (اختیاری)</string>
|
||||
<string name="summary_pref_domestic_dns">DNS</string>
|
||||
|
||||
<string name="title_pref_delay_test_url">True delay test url (http/https)</string>
|
||||
<string name="title_pref_delay_test_url">آدرس اینترنتی آزمایش تاخیر واقعی کانفیگ ها (http/https)</string>
|
||||
<string name="summary_pref_delay_test_url">Url</string>
|
||||
|
||||
<string name="title_pref_proxy_sharing_enabled">اجازه اتصالات از طریق LAN</string>
|
||||
@@ -277,11 +277,11 @@
|
||||
|
||||
<string name="import_subscription_success">اشتراک با موفقیت ذخیره شد</string>
|
||||
<string name="import_subscription_failure">ذخیره اشتراک ناموفق بود</string>
|
||||
<string name="title_fragment_settings">تنظیمات Fragment</string>
|
||||
<string name="title_pref_fragment_packets">Fragment Packets</string>
|
||||
<string name="title_pref_fragment_length">Fragment Length (min-max)</string>
|
||||
<string name="title_pref_fragment_interval">Fragment Interval (min-max)</string>
|
||||
<string name="title_pref_fragment_enabled">فعال کردن Fragment</string>
|
||||
<string name="title_fragment_settings">تنظیمات فرگمنت</string>
|
||||
<string name="title_pref_fragment_packets">بسته های فرگمنت</string>
|
||||
<string name="title_pref_fragment_length">طول بسته های فرگمنت (حداقل-حداکثر)</string>
|
||||
<string name="title_pref_fragment_interval">فاصله بین بسته های فرگمنت (حداقل-حداکثر)</string>
|
||||
<string name="title_pref_fragment_enabled">فعال کردن فرگمنت</string>
|
||||
<string-array name="share_method">
|
||||
<item>QRcode</item>
|
||||
<item>خروجی گرفتن در کلیپ بورد</item>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</style>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"></style>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar" />
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
@@ -27,4 +27,8 @@
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
</style>
|
||||
|
||||
<style name="BrandedSwitch" parent="AppTheme">
|
||||
<item name="colorAccent">@color/color_fab_active</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
||||
@@ -6,7 +6,7 @@ constraintlayout = "2.2.0"
|
||||
core = "3.5.3"
|
||||
editorkit = "2.9.0"
|
||||
flexbox = "3.0.0"
|
||||
fragmentKtx = "1.8.4"
|
||||
fragmentKtx = "1.8.5"
|
||||
gson = "2.11.0"
|
||||
junit = "4.13.2"
|
||||
kotlinReflect = "2.0.21"
|
||||
|
||||
Reference in New Issue
Block a user