Merge branch 'main' into feat/configurable-proxy

# Conflicts:
#	.gitignore
#	client/lib/l10n/strings_es.dart
#	client/lib/l10n/strings_ja.dart
#	client/lib/l10n/strings_ko.dart
#	client/lib/l10n/strings_ru.dart
#	docs/index.html
#	scripts/local_test.sh
This commit is contained in:
wangjia
2026-07-28 07:17:34 +08:00
46 changed files with 5136 additions and 120 deletions
+3
View File
@@ -1,5 +1,8 @@
allprojects {
repositories {
// 国内镜像优先(见 settings.gradle 同注);原仓库保留作 fallback。
maven { url "https://maven.aliyun.com/repository/google" }
maven { url "https://maven.aliyun.com/repository/public" }
google()
mavenCentral()
}
+3 -1
View File
@@ -2,4 +2,6 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
# 国内镜像:services.gradle.org 被 GFW 墙(SSL 重置),CI runner 在墙内下载发行版会失败。
# 腾讯云 gradle 镜像提供同一份 zip。见 client/android/{settings,build}.gradle 的 maven 镜像同理。
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.7-bin.zip
+5
View File
@@ -10,6 +10,11 @@ pluginManagement {
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
repositories {
// 国内镜像优先(CI runner 在墙内,直连 google/central/gradlePluginPortal 会被 GFW 重置);
// 原仓库保留作 fallback。与 deploy-client.yml 的 GOPROXY/PUB 镜像同理。
maven { url "https://maven.aliyun.com/repository/google" }
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/gradle-plugin" }
google()
mavenCentral()
gradlePluginPortal()
@@ -206,6 +206,7 @@ final class PangolinPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol
let ipv4 = NEIPv4Settings(addresses: v4addrs.map(\.address),
subnetMasks: v4addrs.map(\.mask))
ipv4.includedRoutes = includedRoutes4(options)
ipv4.excludedRoutes = excludedRoutes4(options)
settings.ipv4Settings = ipv4
}
let v6addrs = routePrefixes(options.getInet6Address())
@@ -213,6 +214,7 @@ final class PangolinPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol
let ipv6 = NEIPv6Settings(addresses: v6addrs.map(\.address),
networkPrefixLengths: v6addrs.map { NSNumber(value: $0.prefix) })
ipv6.includedRoutes = includedRoutes6(options)
ipv6.excludedRoutes = excludedRoutes6(options)
settings.ipv6Settings = ipv6
}
if let dns = try? options.getDNSServerAddress(), !dns.value.isEmpty {
@@ -311,6 +313,19 @@ final class PangolinPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol
networkPrefixLength: NSNumber(value: $0.prefix)) }
}
// :sing-box config route_exclude_address( LAN ) libbox
// includedRoutes excludedRoutes strict_route LAN
// ,VPN /NAS/ excludedRoutes LAN
private func excludedRoutes4(_ o: any LibboxTunOptionsProtocol) -> [NEIPv4Route] {
routePrefixes(o.getInet4RouteExcludeAddress())
.map { NEIPv4Route(destinationAddress: $0.address, subnetMask: $0.mask) }
}
private func excludedRoutes6(_ o: any LibboxTunOptionsProtocol) -> [NEIPv6Route] {
routePrefixes(o.getInet6RouteExcludeAddress())
.map { NEIPv6Route(destinationAddress: $0.address,
networkPrefixLength: NSNumber(value: $0.prefix)) }
}
// utun fd:getpeername sockaddr_ctl, utun id(WireGuard )
private static func tunFd() -> Int32? {
var ctlInfo = ctl_info()
+1 -1
View File
@@ -343,7 +343,7 @@ class StringsEs extends AppText {
@override
String get payMethodCrypto => 'USDT (TRC20)';
@override
String get choosePayMethod => 'Elige el método de pago';
String get choosePayMethod => 'Elige un método de pago';
@override
String get proMonthly => 'Pro · Mensual';
@override
+1 -1
View File
@@ -345,7 +345,7 @@ class StringsJa extends AppText {
@override
String get choosePayMethod => 'お支払い方法を選択';
@override
String get proMonthly => 'Pro · 月額';
String get proMonthly => 'Pro月額';
@override
String get proQuarterly => 'Pro · 3か月';
@override
+2 -2
View File
@@ -333,7 +333,7 @@ class StringsRu extends AppText {
@override
String get ob3Sub => 'Сквозное шифрование. Мы не храним журналы просмотров.';
@override
String get purchaseTitle => 'Покупка тарифа';
String get purchaseTitle => 'Купить тариф';
@override
String get paymentTitle => 'Оплата';
@override
@@ -345,7 +345,7 @@ class StringsRu extends AppText {
@override
String get choosePayMethod => 'Выберите способ оплаты';
@override
String get proMonthly => 'Pro · Месяц';
String get proMonthly => 'Pro · Помесячно';
@override
String get proQuarterly => 'Pro · Квартал';
@override
@@ -201,6 +201,7 @@ final class PangolinPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol
let ipv4 = NEIPv4Settings(addresses: v4addrs.map(\.address),
subnetMasks: v4addrs.map(\.mask))
ipv4.includedRoutes = includedRoutes4(options)
ipv4.excludedRoutes = excludedRoutes4(options)
settings.ipv4Settings = ipv4
}
let v6addrs = routePrefixes(options.getInet6Address())
@@ -208,6 +209,7 @@ final class PangolinPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol
let ipv6 = NEIPv6Settings(addresses: v6addrs.map(\.address),
networkPrefixLengths: v6addrs.map { NSNumber(value: $0.prefix) })
ipv6.includedRoutes = includedRoutes6(options)
ipv6.excludedRoutes = excludedRoutes6(options)
settings.ipv6Settings = ipv6
}
if let dns = try? options.getDNSServerAddress(), !dns.value.isEmpty {
@@ -301,6 +303,19 @@ final class PangolinPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol
networkPrefixLength: NSNumber(value: $0.prefix)) }
}
// :sing-box config route_exclude_address( LAN ) libbox
// includedRoutes excludedRoutes strict_route LAN
// ,VPN /NAS/ excludedRoutes LAN
private func excludedRoutes4(_ o: any LibboxTunOptionsProtocol) -> [NEIPv4Route] {
routePrefixes(o.getInet4RouteExcludeAddress())
.map { NEIPv4Route(destinationAddress: $0.address, subnetMask: $0.mask) }
}
private func excludedRoutes6(_ o: any LibboxTunOptionsProtocol) -> [NEIPv6Route] {
routePrefixes(o.getInet6RouteExcludeAddress())
.map { NEIPv6Route(destinationAddress: $0.address,
networkPrefixLength: NSNumber(value: $0.prefix)) }
}
// utun fd:getpeername sockaddr_ctl, utun id(WireGuard )
private static func tunFd() -> Int32? {
var ctlInfo = ctl_info()