Compare commits

..
6 Commits
Author SHA1 Message Date
2dust 57907cf354 up 2.3.15 2026-11-01 14:52:46 +08:00
rasa68andrasa68 f94e997870 Info box: show infinity when there is no expiry; keep 'used / total' left-to-right in RTL (#6356)
Co-authored-by: rasa68 <noreply@example.com>
2026-11-01 14:39:11 +08:00
cin fc926f5291 ui(wireguard): clearer hint for the remoteDNS field + locales (#6381)
ru,en: handwritten.
other: AI-generated.
2026-11-01 14:38:26 +08:00
cin 5cb002f69d fix: crash on WireGuard profiles with empty remote DNS (#6379)
When a WireGuard profile has no remote DNS, CoreOutboundBuilder fell
back to listOf(WIREGUARD_LOCAL_REMOTE_DNS). The constant is a single
comma-separated string, so the core received one list element holding
all four addresses and panicked on start:

  panic: ParseAddr("1.1.1.1,1.0.0.1,2606:4700:4700::1111,..."):
  unexpected character

closes: #6373
2026-11-01 14:37:02 +08:00
DHR60 35f5c4e538 Try fix dns (#6376) 2026-11-01 14:35:48 +08:00
2dust fa30dc1a31 Update AndroidLibXrayLite 2026-11-01 14:33:53 +08:00
18 changed files with 53 additions and 27 deletions

No files matched your search

+2 -2
View File
@@ -13,8 +13,8 @@ android {
applicationId = "com.v2ray.ang"
minSdk = 24
targetSdk = 37
versionCode = 754
versionName = "2.3.14"
versionCode = 755
versionName = "2.3.15"
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
splits {
@@ -888,8 +888,6 @@ object CoreConfigManager {
val remoteDns = SettingsManager.getRemoteDnsServers()
val domesticDns = SettingsManager.getDomesticDnsServers()
remoteDns.forEach { servers.add(it) }
val hosts = buildDnsHostsFromRoutingRules(configContext)
val cnDomesticDnsTags = buildDnsCnModeFromRoutingRules(configContext, servers, domesticDns)
val domesticDnsTags = buildDnsFromRoutingRules(
@@ -900,6 +898,8 @@ object CoreConfigManager {
)
domesticDnsTags.addAll(cnDomesticDnsTags)
remoteDns.forEach { servers.add(it) }
v2rayConfig.dns = V2rayConfig.DnsBean(
servers = servers,
hosts = hosts,
@@ -1042,6 +1042,7 @@ object CoreConfigManager {
address = address,
domains = rule.domain,
skipFallback = true,
finalQuery = if (dnsIndex == domesticDns.lastIndex) true else null,
tag = tag
)
)
@@ -1051,12 +1052,15 @@ object CoreConfigManager {
AppConfig.TAG_BLOCKED -> Unit
else -> {
servers.add(
V2rayConfig.DnsBean.ServersBean(
address = remoteDns.first(),
domains = rule.domain,
remoteDns.forEachIndexed { index, address ->
servers.add(
V2rayConfig.DnsBean.ServersBean(
address = address,
domains = rule.domain,
finalQuery = if (index == remoteDns.lastIndex) true else null
)
)
)
}
}
}
}
@@ -252,18 +252,21 @@ object CoreOutboundBuilder {
ipv4Addresses.ifEmpty { listOf(AppConfig.WIREGUARD_LOCAL_ADDRESS_V4) }
}
val defaultDns = AppConfig.WIREGUARD_LOCAL_REMOTE_DNS.split(",").map { it.trim() }
val rawDNS = profileItem.remoteDNS
?.split(",")
?.map { it.trim() }
?.filter { it.isNotEmpty() }
?.ifEmpty { null }
?: listOf(AppConfig.WIREGUARD_LOCAL_REMOTE_DNS)
?: defaultDns
val remotes = if (MmkvManager.decodeSettingsBool(AppConfig.PREF_IPV6_ENABLED) == true) {
rawDNS
} else {
val ipv4Dns = rawDNS.filter { !it.contains(":") }
ipv4Dns.ifEmpty { listOf(AppConfig.WIREGUARD_LOCAL_REMOTE_DNS) }
rawDNS.filter { !it.contains(":") }
// falling back to the IPv4 entries of the default list
.ifEmpty { defaultDns.filter { !it.contains(":")} }
}
outboundBean?.settings?.let { wireguard ->
@@ -353,6 +353,7 @@ data class V2rayConfig(
var expectIPs: List<String>? = null,
val clientIp: String? = null,
val skipFallback: Boolean? = null,
val finalQuery: Boolean? = null,
val tag: String? = null,
)
}
@@ -32,7 +32,7 @@ object WireguardFmt : FmtBase() {
config.publicKey = queryParam["publickey"].orEmpty()
config.preSharedKey = queryParam["presharedkey"]?.nullIfBlank()
config.mtu = Utils.parseInt(queryParam["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU)
config.remoteDNS = queryParam["dns"] ?: AppConfig.WIREGUARD_LOCAL_REMOTE_DNS
config.remoteDNS = queryParam["dns"] ?: ""
config.reserved = queryParam["reserved"] ?: "0,0,0"
config.finalMask = (queryParam["fm"] ?: queryParam["finalmask"] ?: queryParam["finalMask"])?.nullIfBlank()
@@ -83,7 +83,7 @@ object WireguardFmt : FmtBase() {
config.remarks = System.currentTimeMillis().toString()
config.localAddress = interfaceParams["address"] ?: AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
config.mtu = Utils.parseInt(interfaceParams["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU)
config.remoteDNS = interfaceParams["dns"] ?: AppConfig.WIREGUARD_LOCAL_REMOTE_DNS
config.remoteDNS = interfaceParams["dns"] ?: ""
config.publicKey = peerParams["publickey"].orEmpty()
config.preSharedKey = peerParams["presharedkey"]?.nullIfBlank()
val endpoint = peerParams["endpoint"].orEmpty()
@@ -26,6 +26,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.v2ray.ang.R
@@ -36,6 +37,7 @@ import com.v2ray.ang.util.Utils
private const val MILLIS_PER_SECOND = 1000L
private const val EXPIRY_DATE_PATTERN = "yyyy-MM-dd"
private const val NO_EXPIRY_SYMBOL = "\u221E"
private const val CARD_ALPHA = 0.97f
/** Locale-neutral values the subscription information box renders. */
@@ -175,23 +177,25 @@ private fun StatsRow(model: SubscriptionInfoUiModel) {
} else {
stringResource(R.string.sub_info_unlimited)
}
// Figures and the slash between them always read left to right, also in right-to-left languages;
// otherwise the bidi algorithm swaps "used / total" around the slash.
val figuresStyle = MaterialTheme.typography.bodySmall.copy(textDirection = TextDirection.Ltr)
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
Text(
text = stringResource(R.string.sub_info_traffic, model.usedBytes.toTrafficString(), totalText),
modifier = Modifier.weight(1f, fill = false),
style = MaterialTheme.typography.bodySmall,
style = figuresStyle,
color = if (model.trafficLow) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onSurface,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
model.expireMillis?.let { expireMillis ->
Spacer(Modifier.size(8.dp))
Text(
text = Utils.formatTimestamp(expireMillis, EXPIRY_DATE_PATTERN),
style = MaterialTheme.typography.bodySmall,
color = if (model.expired) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
)
}
Spacer(Modifier.size(8.dp))
Text(
// No expiry date means the subscription never expires.
text = model.expireMillis?.let { Utils.formatTimestamp(it, EXPIRY_DATE_PATTERN) } ?: NO_EXPIRY_SYMBOL,
style = figuresStyle,
color = if (model.expired) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onSurfaceVariant,
maxLines = 1,
)
}
}
@@ -5,6 +5,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType
import com.v2ray.ang.AppConfig
import com.v2ray.ang.R
import com.v2ray.ang.enums.EConfigType
import com.v2ray.ang.ui.compose.FormTextField
@@ -77,8 +78,11 @@ class ServerWireguardActivity : BaseServerActivity() {
FormTextField(
stringResource(R.string.server_lab_remote_dns),
state.remoteDNS,
{ state.remoteDNS = it }
{ state.remoteDNS = it },
supportingText = stringResource(
R.string.server_lab_remote_dns_hint,
AppConfig.WIREGUARD_LOCAL_REMOTE_DNS
)
)
}
}
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">العنوان المحلي (اختياري IPv4/IPv6، مفصولة بفواصل)</string>
<string name="server_lab_local_mtu">MTU (اختياري، الافتراضي 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (اختياري، عناوين IPv4/IPv6 مفصولة بفواصل)</string>
<string name="server_lab_remote_dns_hint">إذا كان فارغًا، فسيُستخدم %1$s افتراضيًا. لا تُستخدم عناوين IPv6 إلا عند تفعيل IPv6.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (اختياري، الافتراضي 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (اختياري، الافتراضي 50 مللي ثانية)</string>
<string name="toast_success">نجاح</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">Yerli ünvan (istəyə bağlı IPv4/IPv6, vergüllə ayrılmış)</string>
<string name="server_lab_local_mtu">MTU (istəyə bağlı, standart 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (istəyə bağlı, vergüllə ayrılmış IPv4/IPv6)</string>
<string name="server_lab_remote_dns_hint">Boşdursa, standart olaraq %1$s istifadə olunur. IPv6 ünvanları yalnız IPv6 aktiv olduqda istifadə edilir.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (istəyə bağlı, standart 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (istəyə bağlı, standart 50 ms)</string>
<string name="toast_success">Uğurlu</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">স্থানীয় ঠিকানা (ঐচ্ছিক IPv4/IPv6, কমা দ্বারা পৃথক করা)</string>
<string name="server_lab_local_mtu">MTU (ঐচ্ছিক, ডিফল্ট 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (ঐচ্ছিক, কমা দ্বারা পৃথক করা IPv4/IPv6 ঠিকানা)</string>
<string name="server_lab_remote_dns_hint">খালি থাকলে ডিফল্টভাবে %1$s ব্যবহৃত হয়। IPv6 চালু থাকলেই কেবল IPv6 ঠিকানা ব্যবহৃত হয়।</string>
<string name="server_lab_kcp_mtu">mKCP MTU (ঐচ্ছিক, ডিফল্ট 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (ঐচ্ছিক, ডিফল্ট 50 মিলিসেকেন্ড)</string>
<string name="toast_success">সফল</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">نشۊوی مهلی (اختیاری IPv4/IPv6، وا کاما (,) ز یک جوڌا ابۊن)</string>
<string name="server_lab_local_mtu">MTU(اختیاری، پؽش فرز 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (اختياری، نشۊویا IPv4/IPv6 جوڌا وابیڌه وا کاما، یا «local» سی و کار گرؽڌن DNS دسگا)</string>
<string name="server_lab_remote_dns_hint">اگه خالی بی، پؽش فرز %1$s سی و کار گرؽڌه وابی. نشۊویا IPv6 فقظ وختؽ کار گرؽڌه وابیڌه که IPv6 رۊشن بی.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (اختیاری، پؽش فرز 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (اختیاری، پؽش فرز 50 میلی‌سانیه)</string>
<string name="toast_success">وا مووفقیت ٱنجوم وابی</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">آدرس محلی (IPv4/IPv6 اختیاری، جدا شده با کاما)</string>
<string name="server_lab_local_mtu">MTU (اختیاری، پیش‌فرض 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (اختیاری، آدرس‌های IPv4/IPv6 جدا شده با کاما)</string>
<string name="server_lab_remote_dns_hint">اگر خالی باشد، به‌طور پیش‌فرض از %1$s استفاده می‌شود. آدرس‌های IPv6 فقط زمانی استفاده می‌شوند که IPv6 فعال باشد.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (اختیاری، پیش‌فرض 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (اختیاری، پیش‌فرض 50 میلی‌ثانیه)</string>
<string name="toast_success">موفقیت‌آمیز</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">Локальный адрес (необязательно, IPv4/IPv6 через запятую)</string>
<string name="server_lab_local_mtu">MTU (необязательно, по умолчанию 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (необязательно, IPv4/IPv6-адреса через запятую)</string>
<string name="server_lab_remote_dns_hint">Если пусто, используется %1$s. IPv6-адреса применяются только при включённом IPv6.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (необязательно, по умолчанию 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (необязательно, по умолчанию 50 мс)</string>
<string name="toast_success">Успешно</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">Địa chỉ cục bộ (IPv4/IPv6 không bắt buộc, phân cách bằng dấu phẩy)</string>
<string name="server_lab_local_mtu">MTU (không bắt buộc, mặc định 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (tùy chọn, các địa chỉ IPv4/IPv6 cách nhau bằng dấu phẩy)</string>
<string name="server_lab_remote_dns_hint">Nếu để trống, mặc định là %1$s. Địa chỉ IPv6 chỉ được dùng khi IPv6 được bật.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (không bắt buộc, mặc định 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (không bắt buộc, mặc định 50 ms)</string>
<string name="toast_success">Thành công!</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">本地地址 (可选 IPv4/IPv6,逗号隔开)</string>
<string name="server_lab_local_mtu">MTU(可选,默认 1420)</string>
<string name="server_lab_remote_dns">remoteDNS(可选,多个 IPv4/IPv6 地址用逗号分隔)</string>
<string name="server_lab_remote_dns_hint">留空时默认使用 %1$s。仅在启用 IPv6 时才使用 IPv6 地址。</string>
<string name="server_lab_kcp_mtu">mKCP MTU(可选,默认 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI(可选,默认 50 毫秒)</string>
<string name="toast_success">成功</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">本機位址 (可選 IPv4/IPv6,逗號隔開)</string>
<string name="server_lab_local_mtu">MTU(可選,預設 1420)</string>
<string name="server_lab_remote_dns">remoteDNS(選填,多個 IPv4/IPv6 位址以逗號分隔)</string>
<string name="server_lab_remote_dns_hint">留空時預設使用 %1$s。僅在啟用 IPv6 時才使用 IPv6 位址。</string>
<string name="server_lab_kcp_mtu">mKCP MTU(可選,預設 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI(可選,預設 50 毫秒)</string>
<string name="toast_success">成功</string>
@@ -104,6 +104,7 @@
<string name="server_lab_local_address">Local address (optional IPv4/IPv6, separated by commas)</string>
<string name="server_lab_local_mtu">MTU (optional, default 1420)</string>
<string name="server_lab_remote_dns">remoteDNS (optional, comma-separated IPv4/IPv6)</string>
<string name="server_lab_remote_dns_hint">If empty, defaults to %1$s. IPv6 addresses are used only when IPv6 is enabled.</string>
<string name="server_lab_kcp_mtu">mKCP MTU (optional, default 1350)</string>
<string name="server_lab_kcp_tti">mKCP TTI (optional, default 50 ms)</string>
<string name="toast_success">Success</string>