From 1f8dd1a52d9d365a031621beb9af5666c8f27746 Mon Sep 17 00:00:00 2001 From: JieXu Date: Mon, 10 Nov 2025 19:59:29 +0800 Subject: [PATCH 01/52] Update ResUI.fr.resx (#8297) --- v2rayN/ServiceLib/Resx/ResUI.fr.resx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index 41d086d8..50a488e0 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -1603,10 +1603,10 @@ Certificate Pinning - Server Certificate (PEM format, optional) -When specified, the certificate will be pinned, and "Allow Insecure" will be disabled. + Certificat serveur (format PEM, facultatif) +Si le certificat est défini, il est fixé et l’option « Ignorer la vérification » est désactivée. -The "Get Certificate" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA. +Si un certificat auto-signé est utilisé ou si le système contient une CA non fiable ou malveillante, l’action « Obtenir le certificat » peut échouer. Obtenir le certificat @@ -1630,6 +1630,6 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if Chemin script proxy système personnalisé - macOS displays this in the Dock (requires restart) + Afficher dans le Dock de macOS (redém. requis) - \ No newline at end of file + From 53bd03dea275061d6af929ee04df8f2382e07c83 Mon Sep 17 00:00:00 2001 From: tt2563 <243264479+tt2563@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:30:41 +0800 Subject: [PATCH 02/52] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=B9=81=E9=AB=94?= =?UTF-8?q?=E4=B8=AD=E6=96=87=E7=BF=BB=E8=AD=AF=20(#8302)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: tes2511 --- v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index b45480a4..d8d5a710 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1600,28 +1600,28 @@ 自動從訂閱分組新增過濾後的配置 - Certificate Pinning + 憑證綁定 - Server Certificate (PEM format, optional) -When specified, the certificate will be pinned, and "Allow Insecure" will be disabled. + 伺服器憑證(PEM 格式,可選) +若已指定,憑證將會被綁定,並且「跳過憑證驗證」將被停用。 -The "Get Certificate" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA. +若使用自簽憑證,或系統中存在不受信任或惡意的 CA,「取得憑證」動作可能會失敗。 - Fetch Certificate + 獲取憑證 - Fetch Certificate Chain + 獲取憑證鏈 - Please set a valid domain + 請設定有效的網域名稱 - Certificate not set + 尚未設定憑證 - Certificate set + 已設定憑證 自訂 PAC 檔案路徑 From df7ca81837232266f08a6024d388aa4ea2229a32 Mon Sep 17 00:00:00 2001 From: JieXu Date: Tue, 11 Nov 2025 19:31:06 +0800 Subject: [PATCH 03/52] Update package-osx.sh (#8303) --- package-osx.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package-osx.sh b/package-osx.sh index 042e29b7..5ed390ca 100755 --- a/package-osx.sh +++ b/package-osx.sh @@ -43,6 +43,8 @@ cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF NSHighResolutionCapable + LSMinimumSystemVersion + 12.7 EOF @@ -55,4 +57,4 @@ create-dmg \ --hide-extension "v2rayN.app" \ --app-drop-link 500 185 \ "v2rayN-${Arch}.dmg" \ - "$PackagePath/v2rayN.app" \ No newline at end of file + "$PackagePath/v2rayN.app" From f6779342579b697f6420341ec382924203516821 Mon Sep 17 00:00:00 2001 From: MkQtS <81752398+MkQtS@users.noreply.github.com> Date: Wed, 12 Nov 2025 19:08:36 +0800 Subject: [PATCH 04/52] Proxy all Google domains (#8287) * Proxy all Google domains Default geosite-cn(dat/srs) used by v2rayN contains google@cn, which performs poorly in certain user environments. * Resolve all Google domains via remote server * fix typo * Add google to default geofiles --- package-rhel.sh | 2 +- v2rayN/ServiceLib/Sample/custom_routing_black | 15 +++++++-------- v2rayN/ServiceLib/Sample/custom_routing_white | 15 +++++++-------- v2rayN/ServiceLib/Sample/dns_singbox_normal | 5 ++--- v2rayN/ServiceLib/Sample/dns_v2ray_normal | 3 +-- v2rayN/ServiceLib/Sample/tun_singbox_dns | 5 ++--- v2rayN/ServiceLib/Services/UpdateService.cs | 1 + 7 files changed, 21 insertions(+), 25 deletions(-) diff --git a/package-rhel.sh b/package-rhel.sh index b93ea82c..5ef75ab5 100644 --- a/package-rhel.sh +++ b/package-rhel.sh @@ -458,7 +458,7 @@ download_geo_assets() { "https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geoip/$f" || true done for f in \ - geosite-cn.srs geosite-gfw.srs geosite-greatfire.srs \ + geosite-cn.srs geosite-gfw.srs geosite-google.srs geosite-greatfire.srs \ geosite-geolocation-cn.srs geosite-category-ads-all.srs geosite-private.srs; do curl -fsSL -o "$srss_dir/$f" \ "https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geosite/$f" || true diff --git a/v2rayN/ServiceLib/Sample/custom_routing_black b/v2rayN/ServiceLib/Sample/custom_routing_black index ff2aa075..41fbdfaa 100644 --- a/v2rayN/ServiceLib/Sample/custom_routing_black +++ b/v2rayN/ServiceLib/Sample/custom_routing_black @@ -13,20 +13,19 @@ "api.ip.sb" ] }, - { - "remarks": "Google cn", - "outboundTag": "proxy", - "domain": [ - "domain:googleapis.cn", - "domain:gstatic.com" - ] - }, { "remarks": "阻断udp443", "outboundTag": "block", "port": "443", "network": "udp" }, + { + "remarks": "代理Google", + "outboundTag": "proxy", + "domain": [ + "geosite:google" + ] + }, { "remarks": "绕过局域网IP", "outboundTag": "direct", diff --git a/v2rayN/ServiceLib/Sample/custom_routing_white b/v2rayN/ServiceLib/Sample/custom_routing_white index 10dae092..4f8540fe 100644 --- a/v2rayN/ServiceLib/Sample/custom_routing_white +++ b/v2rayN/ServiceLib/Sample/custom_routing_white @@ -1,18 +1,17 @@ [ - { - "remarks": "Google cn", - "outboundTag": "proxy", - "domain": [ - "domain:googleapis.cn", - "domain:gstatic.com" - ] - }, { "remarks": "阻断udp443", "outboundTag": "block", "port": "443", "network": "udp" }, + { + "remarks": "代理Google", + "outboundTag": "proxy", + "domain": [ + "geosite:google" + ] + }, { "remarks": "绕过局域网IP", "outboundTag": "direct", diff --git a/v2rayN/ServiceLib/Sample/dns_singbox_normal b/v2rayN/ServiceLib/Sample/dns_singbox_normal index b32b439c..2df81395 100644 --- a/v2rayN/ServiceLib/Sample/dns_singbox_normal +++ b/v2rayN/ServiceLib/Sample/dns_singbox_normal @@ -14,9 +14,8 @@ ], "rules": [ { - "domain_suffix": [ - "googleapis.cn", - "gstatic.com" + "rule_set": [ + "geosite-google" ], "server": "remote", "strategy": "prefer_ipv4" diff --git a/v2rayN/ServiceLib/Sample/dns_v2ray_normal b/v2rayN/ServiceLib/Sample/dns_v2ray_normal index fdb30dae..867bb646 100644 --- a/v2rayN/ServiceLib/Sample/dns_v2ray_normal +++ b/v2rayN/ServiceLib/Sample/dns_v2ray_normal @@ -8,8 +8,7 @@ "address": "1.1.1.1", "skipFallback": true, "domains": [ - "domain:googleapis.cn", - "domain:gstatic.com" + "geosite:google" ] }, { diff --git a/v2rayN/ServiceLib/Sample/tun_singbox_dns b/v2rayN/ServiceLib/Sample/tun_singbox_dns index 3dd55eef..4f91c6ff 100644 --- a/v2rayN/ServiceLib/Sample/tun_singbox_dns +++ b/v2rayN/ServiceLib/Sample/tun_singbox_dns @@ -14,9 +14,8 @@ ], "rules": [ { - "domain_suffix": [ - "googleapis.cn", - "gstatic.com" + "rule_set": [ + "geosite-google" ], "server": "remote", "strategy": "prefer_ipv4" diff --git a/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayN/ServiceLib/Services/UpdateService.cs index fc636c60..d71719a0 100644 --- a/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayN/ServiceLib/Services/UpdateService.cs @@ -396,6 +396,7 @@ public class UpdateService(Config config, Func updateFunc) } //append dns items TODO + geoSiteFiles.Add("google"); geoSiteFiles.Add("cn"); geoSiteFiles.Add("geolocation-cn"); geoSiteFiles.Add("category-ads-all"); From 30e9e64fd5a223592ac4de863bd0ca4e2c731270 Mon Sep 17 00:00:00 2001 From: MkQtS <81752398+MkQtS@users.noreply.github.com> Date: Wed, 12 Nov 2025 19:08:57 +0800 Subject: [PATCH 05/52] Simplify sing-box rules for domain_suffix (#8306) adapt to new domain_suffix behavior since sing-box 1.9.0 --- .../Services/CoreConfig/Singbox/SingboxRoutingService.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs index 33fde24e..87cb7c33 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs @@ -316,10 +316,8 @@ public partial class CoreConfigSingboxService } else if (domain.StartsWith("domain:")) { - rule.domain ??= []; rule.domain_suffix ??= []; - rule.domain?.Add(domain.Substring(7)); - rule.domain_suffix?.Add("." + domain.Substring(7)); + rule.domain_suffix?.Add(domain.Substring(7)); } else if (domain.StartsWith("full:")) { From 31a8ddef2378c39ed0dc50bed01a482f874ccd7f Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Wed, 12 Nov 2025 19:33:32 +0800 Subject: [PATCH 06/52] Update Directory.Packages.props --- v2rayN/Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2rayN/Directory.Packages.props b/v2rayN/Directory.Packages.props index 1e4f9e33..cd23d54f 100644 --- a/v2rayN/Directory.Packages.props +++ b/v2rayN/Directory.Packages.props @@ -22,7 +22,7 @@ - + From 24f8d767b11ce22789b0363cd9a4c4f420fe2fbb Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Wed, 12 Nov 2025 19:34:04 +0800 Subject: [PATCH 07/52] Update routing version prefix to V4 --- v2rayN/ServiceLib/Handler/ConfigHandler.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/ConfigHandler.cs b/v2rayN/ServiceLib/Handler/ConfigHandler.cs index b3433437..f0243076 100644 --- a/v2rayN/ServiceLib/Handler/ConfigHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConfigHandler.cs @@ -2080,7 +2080,7 @@ public static class ConfigHandler /// 0 if successful public static async Task InitBuiltinRouting(Config config, bool blImportAdvancedRules = false) { - var ver = "V3-"; + var ver = "V4-"; var items = await AppManager.Instance.RoutingItems(); //TODO Temporary code to be removed later @@ -2091,7 +2091,7 @@ public static class ConfigHandler items = await AppManager.Instance.RoutingItems(); } - if (!blImportAdvancedRules && items.Count > 0) + if (!blImportAdvancedRules && items.Count(u => u.Remarks.StartsWith(ver)) > 0) { //migrate //TODO Temporary code to be removed later From e634e6dae3b9d20c64fa6aea6ea16436e7da56f0 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 13 Nov 2025 20:31:02 +0800 Subject: [PATCH 08/52] Code clean --- v2rayN/ServiceLib/Manager/CertPemManager.cs | 4 +++ v2rayN/ServiceLib/Services/UpdateService.cs | 28 ++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/v2rayN/ServiceLib/Manager/CertPemManager.cs b/v2rayN/ServiceLib/Manager/CertPemManager.cs index 9421aabf..247b5842 100644 --- a/v2rayN/ServiceLib/Manager/CertPemManager.cs +++ b/v2rayN/ServiceLib/Manager/CertPemManager.cs @@ -374,11 +374,15 @@ public class CertPemManager { var beginIndex = pemChain.IndexOf(beginMarker, index, StringComparison.Ordinal); if (beginIndex == -1) + { break; + } var endIndex = pemChain.IndexOf(endMarker, beginIndex, StringComparison.Ordinal); if (endIndex == -1) + { break; + } // Extract certificate content var base64Start = beginIndex + beginMarker.Length; diff --git a/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayN/ServiceLib/Services/UpdateService.cs index d71719a0..a1d72655 100644 --- a/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayN/ServiceLib/Services/UpdateService.cs @@ -17,17 +17,17 @@ public class UpdateService(Config config, Func updateFunc) { if (args.Success) { - UpdateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully); - UpdateFunc(true, Utils.UrlEncode(fileName)); + _ = UpdateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully); + _ = UpdateFunc(true, Utils.UrlEncode(fileName)); } else { - UpdateFunc(false, args.Msg); + _ = UpdateFunc(false, args.Msg); } }; downloadHandle.Error += (sender2, args) => { - UpdateFunc(false, args.GetException().Message); + _ = UpdateFunc(false, args.GetException().Message); }; await UpdateFunc(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN)); @@ -57,26 +57,26 @@ public class UpdateService(Config config, Func updateFunc) { if (args.Success) { - UpdateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully); - UpdateFunc(false, ResUI.MsgUnpacking); + _ = UpdateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully); + _ = UpdateFunc(false, ResUI.MsgUnpacking); try { - UpdateFunc(true, fileName); + _ = UpdateFunc(true, fileName); } catch (Exception ex) { - UpdateFunc(false, ex.Message); + _ = UpdateFunc(false, ex.Message); } } else { - UpdateFunc(false, args.Msg); + _ = UpdateFunc(false, args.Msg); } }; downloadHandle.Error += (sender2, args) => { - UpdateFunc(false, args.GetException().Message); + _ = UpdateFunc(false, args.GetException().Message); }; await UpdateFunc(false, string.Format(ResUI.MsgStartUpdating, type)); @@ -439,7 +439,7 @@ public class UpdateService(Config config, Func updateFunc) { if (args.Success) { - UpdateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, fileName)); + _ = UpdateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, fileName)); try { @@ -453,17 +453,17 @@ public class UpdateService(Config config, Func updateFunc) } catch (Exception ex) { - UpdateFunc(false, ex.Message); + _ = UpdateFunc(false, ex.Message); } } else { - UpdateFunc(false, args.Msg); + _ = UpdateFunc(false, args.Msg); } }; downloadHandle.Error += (sender2, args) => { - UpdateFunc(false, args.GetException().Message); + _ = UpdateFunc(false, args.GetException().Message); }; await downloadHandle.DownloadFileAsync(url, tmpFileName, true, _timeout); From 7e712fcdeb94eea27de1cd11d7840ae2d7744081 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Fri, 14 Nov 2025 19:44:09 +0800 Subject: [PATCH 09/52] Refactor menu layouts in window views --- v2rayN/v2rayN.Desktop/Views/MainWindow.axaml | 51 +++++++++---------- .../Views/RoutingRuleSettingWindow.axaml | 17 +++---- .../Views/RoutingSettingWindow.axaml | 14 ++--- .../Views/SubSettingWindow.axaml | 21 +++----- v2rayN/v2rayN/Views/MainWindow.xaml | 19 +------ 5 files changed, 43 insertions(+), 79 deletions(-) diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml index 5a391134..4eb8392e 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml @@ -24,13 +24,8 @@ - - - - - - - + + @@ -51,12 +46,7 @@ - - - - - - + @@ -65,20 +55,24 @@ - - - - - - + - + - - + + @@ -90,15 +84,16 @@ - + - + + + + - + - - - + diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml index 7e51192e..8f50f883 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml @@ -14,17 +14,12 @@ WindowStartupLocation="CenterScreen" mc:Ignorable="d"> - - - - - - - - + + + + + + - - - - - - + + + + - - - - - - - - - + + + + + + + - \ No newline at end of file + diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml b/v2rayN/v2rayN/Views/MainWindow.xaml index 908eb710..25b44106 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml +++ b/v2rayN/v2rayN/Views/MainWindow.xaml @@ -246,23 +246,6 @@ - - - - - - - - - - - + + From 3f0bcf7b836e8245d099986daff1aa4a0ffebb03 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Fri, 14 Nov 2025 19:46:54 +0800 Subject: [PATCH 10/52] up 7.16.2 --- v2rayN/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2rayN/Directory.Build.props b/v2rayN/Directory.Build.props index 2e863e42..b3df5f80 100644 --- a/v2rayN/Directory.Build.props +++ b/v2rayN/Directory.Build.props @@ -1,7 +1,7 @@ - 7.16.1 + 7.16.2 From 4fb41aeca1a68811346918985696d5456d1dd71d Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Sun, 16 Nov 2025 14:21:34 +0800 Subject: [PATCH 11/52] Remove redundant string operation (#8324) --- v2rayN/ServiceLib/Common/Utils.cs | 2 +- v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs | 6 +++--- .../Services/CoreConfig/Singbox/SingboxRoutingService.cs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/v2rayN/ServiceLib/Common/Utils.cs b/v2rayN/ServiceLib/Common/Utils.cs index 1712b40c..fe2b1549 100644 --- a/v2rayN/ServiceLib/Common/Utils.cs +++ b/v2rayN/ServiceLib/Common/Utils.cs @@ -425,7 +425,7 @@ public class Utils var domain = authority; // Handle IPv6 addresses, e.g., "[2001:db8::1]:443" - if (authority.StartsWith("[") && authority.Contains("]")) + if (authority.StartsWith('[') && authority.Contains(']')) { var closingBracketIndex = authority.LastIndexOf(']'); if (closingBracketIndex < authority.Length - 1 && authority[closingBracketIndex + 1] == ':') diff --git a/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs index dbecdade..ae837793 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs @@ -45,18 +45,18 @@ public class SocksFmt : BaseFmt }; result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..]; //remark - var indexRemark = result.IndexOf("#"); + var indexRemark = result.IndexOf('#'); if (indexRemark > 0) { try { - item.Remarks = Utils.UrlDecode(result.Substring(indexRemark + 1, result.Length - indexRemark - 1)); + item.Remarks = Utils.UrlDecode(result.Substring(indexRemark + 1)); } catch { } result = result[..indexRemark]; } //part decode - var indexS = result.IndexOf("@"); + var indexS = result.IndexOf('@'); if (indexS > 0) { } diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs index 87cb7c33..b77a227b 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs @@ -300,7 +300,7 @@ public partial class CoreConfigSingboxService private bool ParseV2Domain(string domain, Rule4Sbox rule) { - if (domain.StartsWith("#") || domain.StartsWith("ext:") || domain.StartsWith("ext-domain:")) + if (domain.StartsWith('#') || domain.StartsWith("ext:") || domain.StartsWith("ext-domain:")) { return false; } From 8ea5a57988e7e40b95fdff547541b3f19b2607a5 Mon Sep 17 00:00:00 2001 From: Harry Huang Date: Sun, 16 Nov 2025 14:58:55 +0800 Subject: [PATCH 12/52] Optimize speedtest (#8325) * Optimize stop-speedtest tip display * Fix speedtest termination latency --- v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 11 +++- v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx | 5 +- v2rayN/ServiceLib/Resx/ResUI.fr.resx | 5 +- v2rayN/ServiceLib/Resx/ResUI.hu.resx | 5 +- v2rayN/ServiceLib/Resx/ResUI.resx | 5 +- v2rayN/ServiceLib/Resx/ResUI.ru.resx | 5 +- v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 5 +- v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 5 +- .../ServiceLib/Services/SpeedtestService.cs | 52 +++++++++++++------ 9 files changed, 75 insertions(+), 23 deletions(-) diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index f9d9493e..03c38114 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -2355,6 +2355,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Press ESC to terminate the test 的本地化字符串。 + /// + public static string SpeedtestingPressEscToExit { + get { + return ResourceManager.GetString("SpeedtestingPressEscToExit", resourceCulture); + } + } + /// /// 查找类似 Skip test 的本地化字符串。 /// @@ -2383,7 +2392,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Waiting for testing (press ESC to terminate)... 的本地化字符串。 + /// 查找类似 Waiting... 的本地化字符串。 /// public static string SpeedtestingWait { get { diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 67504966..f495cebb 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -976,7 +976,10 @@ فعال‌ سازی شتاب‌ دهنده سخت‌ افزاری (نیاز به راه‌اندازی مجدد) - در انتظار آزمایش (برای پایان دادن به ESC فشار دهید)... + در انتظار آزمایش... + + + برای پایان دادن به ESC فشار دهید لطفاً در صورت قطع غیرعادی آن را خاموش کنید diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index 50a488e0..32a2c585 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -976,7 +976,10 @@ Activer l’accélération matérielle (redémarrage requis) - En attente du test (appuyer sur Échap pour arrêter)... + En attente du test... + + + Appuyer sur Échap pour arrêter Désactiver cette option si coupure anormale diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index c71e741f..4df5e94b 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -976,7 +976,10 @@ Hardveres gyorsítás engedélyezése (újraindítást igényel) - Tesztelésre vár (ESC megnyomásával megszakítható)... + Tesztelésre vár... + + + ESC megnyomásával megszakítható Kérjük, kapcsolja ki rendellenes megszakadás esetén diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 66381a90..785f13a3 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -976,7 +976,10 @@ Enable hardware acceleration (requires restart) - Waiting for testing (press ESC to terminate)... + Waiting... + + + Press ESC to terminate the test Please turn off when there is an abnormal disconnection diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 2694db03..4ba40e54 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -976,7 +976,10 @@ Включить аппаратное ускорение (требуется перезагрузка) - Ожидание тестирования (нажмите ESC для отмены)… + Ожидание тестирования… + + + нажмите ESC для отмены Отключите при аномальном разрыве соединения diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 2f3d0622..df77a6e8 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -976,7 +976,10 @@ 启用硬件加速 (需重启) - 等待测试中 (按 ESC 终止)... + 等待测试... + + + 按 ESC 可终止测试 当有异常断流时请关闭 diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index d8d5a710..f69ff6ff 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -976,7 +976,10 @@ 啟用硬體加速 (需重啟) - 等待測試中(按 ESC 終止)... + 等待測試中... + + + 按 ECS 以終止測試 當有異常斷流時請關閉 diff --git a/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayN/ServiceLib/Services/SpeedtestService.cs index 600ba4d1..00f54427 100644 --- a/v2rayN/ServiceLib/Services/SpeedtestService.cs +++ b/v2rayN/ServiceLib/Services/SpeedtestService.cs @@ -19,7 +19,7 @@ public class SpeedtestService(Config config, Func updateF public void ExitLoop() { - if (_lstExitLoop.Count > 0) + if (!_lstExitLoop.IsEmpty) { _ = UpdateFunc("", ResUI.SpeedtestingStop); @@ -27,6 +27,11 @@ public class SpeedtestService(Config config, Func updateF } } + private static bool ShouldStopTest(string exitLoopKey) + { + return !_lstExitLoop.Any(p => p == exitLoopKey); + } + private async Task RunAsync(ESpeedActionType actionType, List selecteds) { var exitLoopKey = Utils.GetGuid(false); @@ -103,6 +108,11 @@ public class SpeedtestService(Config config, Func updateF } } + if (lstSelected.Count > 1 && (actionType == ESpeedActionType.Speedtest || actionType == ESpeedActionType.Mixedtest)) + { + NoticeManager.Instance.Enqueue(ResUI.SpeedtestingPressEscToExit); + } + return lstSelected; } @@ -152,7 +162,7 @@ public class SpeedtestService(Config config, Func updateF var pageSizeNext = pageSize / 2; if (lstFailed.Count > 0 && pageSizeNext > 0) { - if (_lstExitLoop.Any(p => p == exitLoopKey) == false) + if (ShouldStopTest(exitLoopKey)) { await UpdateFunc("", ResUI.SpeedtestingSkip); return; @@ -190,6 +200,12 @@ public class SpeedtestService(Config config, Func updateF { continue; } + + if (ShouldStopTest(exitLoopKey)) + { + return false; + } + tasks.Add(Task.Run(async () => { await DoRealPing(it); @@ -218,7 +234,7 @@ public class SpeedtestService(Config config, Func updateF List tasks = new(); foreach (var it in selecteds) { - if (_lstExitLoop.Any(p => p == exitLoopKey) == false) + if (ShouldStopTest(exitLoopKey)) { await UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); continue; @@ -234,21 +250,27 @@ public class SpeedtestService(Config config, Func updateF if (processService is null) { await UpdateFunc(it.IndexId, "", ResUI.FailedToRunCore); + return; } - else + + await Task.Delay(1000); + + var delay = await DoRealPing(it); + if (blSpeedTest) { - await Task.Delay(1000); - var delay = await DoRealPing(it); - if (blSpeedTest) + if (ShouldStopTest(exitLoopKey)) { - if (delay > 0) - { - await DoSpeedTest(downloadHandle, it); - } - else - { - await UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); - } + await UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); + return; + } + + if (delay > 0) + { + await DoSpeedTest(downloadHandle, it); + } + else + { + await UpdateFunc(it.IndexId, "", ResUI.SpeedtestingSkip); } } } From 0d307671d1111c1e7b37ca97504fc861557ff287 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:44:39 +0800 Subject: [PATCH 13/52] Bug fix https://github.com/2dust/v2rayN/issues/8267 --- v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs index 481e183b..2f31e827 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs @@ -4,7 +4,7 @@ namespace ServiceLib.Handler.Fmt; public class BaseFmt { - private static readonly string[] _allowInsecureArray = new[] { "insecure", "allowInsecure", "allow_insecure", "verify" }; + private static readonly string[] _allowInsecureArray = new[] { "insecure", "allowInsecure", "allow_insecure" }; protected static string GetIpv6(string address) { From 7f24f4a15f4d9fad4c004387a6cb57180e2e5bad Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Tue, 18 Nov 2025 16:00:02 +0800 Subject: [PATCH 14/52] Remove shortcut hints from menu translations Shortcut key hints (e.g., '(Ctrl+C)', '(Delete)') were removed from various menu item translations in resource files for all supported languages. This improves consistency and clarity in UI text across the application. --- v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 44 ++++++------- v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx | 34 +++++----- v2rayN/ServiceLib/Resx/ResUI.fr.resx | 36 +++++----- v2rayN/ServiceLib/Resx/ResUI.hu.resx | 42 ++++++------ v2rayN/ServiceLib/Resx/ResUI.resx | 42 ++++++------ v2rayN/ServiceLib/Resx/ResUI.ru.resx | 38 +++++------ v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 42 ++++++------ v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 44 ++++++------- .../Views/AddGroupServerWindow.axaml | 25 +++++-- .../Views/ClashProxiesView.axaml | 5 +- v2rayN/v2rayN.Desktop/Views/MainWindow.axaml | 10 ++- v2rayN/v2rayN.Desktop/Views/MsgView.axaml | 6 +- .../v2rayN.Desktop/Views/ProfilesView.axaml | 65 +++++++++++++++---- .../Views/RoutingRuleSettingWindow.axaml | 30 +++++++-- .../Views/RoutingSettingWindow.axaml | 15 ++++- v2rayN/v2rayN/Views/AddGroupServerWindow.xaml | 15 +++-- v2rayN/v2rayN/Views/ClashProxiesView.xaml | 5 +- v2rayN/v2rayN/Views/MainWindow.xaml | 6 +- v2rayN/v2rayN/Views/MsgView.xaml | 6 +- v2rayN/v2rayN/Views/ProfilesView.xaml | 39 +++++++---- .../Views/RoutingRuleSettingWindow.xaml | 18 +++-- v2rayN/v2rayN/Views/RoutingSettingWindow.xaml | 9 ++- 22 files changed, 351 insertions(+), 225 deletions(-) diff --git a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index 03c38114..4ac11d1c 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -19,7 +19,7 @@ namespace ServiceLib.Resx { // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen // (以 /str 作为命令选项),或重新生成 VS 项目。 - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] public class ResUI { @@ -799,7 +799,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Import Share Links from clipboard (Ctrl+V) 的本地化字符串。 + /// 查找类似 Import Share Links from clipboard 的本地化字符串。 /// public static string menuAddServerViaClipboard { get { @@ -817,7 +817,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Scan QR code on the screen (Ctrl+S) 的本地化字符串。 + /// 查找类似 Scan QR code on the screen 的本地化字符串。 /// public static string menuAddServerViaScan { get { @@ -970,7 +970,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Edit Configuration (Ctrl+D) 的本地化字符串。 + /// 查找类似 Edit Configuration 的本地化字符串。 /// public static string menuEditServer { get { @@ -1015,7 +1015,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Export Share Link to Clipboard (Ctrl+C) 的本地化字符串。 + /// 查找类似 Export Share Link to Clipboard 的本地化字符串。 /// public static string menuExport2ShareUrl { get { @@ -1249,7 +1249,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Move to bottom (B) 的本地化字符串。 + /// 查找类似 Move to bottom 的本地化字符串。 /// public static string menuMoveBottom { get { @@ -1258,7 +1258,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Down (D) 的本地化字符串。 + /// 查找类似 Down 的本地化字符串。 /// public static string menuMoveDown { get { @@ -1285,7 +1285,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Move to top (T) 的本地化字符串。 + /// 查找类似 Move to top 的本地化字符串。 /// public static string menuMoveTop { get { @@ -1294,7 +1294,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Up (U) 的本地化字符串。 + /// 查找类似 Up 的本地化字符串。 /// public static string menuMoveUp { get { @@ -1312,7 +1312,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Copy (Ctrl+C) 的本地化字符串。 + /// 查找类似 Copy 的本地化字符串。 /// public static string menuMsgViewCopy { get { @@ -1330,7 +1330,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Select all (Ctrl+A) 的本地化字符串。 + /// 查找类似 Select all 的本地化字符串。 /// public static string menuMsgViewSelectAll { get { @@ -1402,7 +1402,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Select active node (Enter) 的本地化字符串。 + /// 查找类似 Select active node 的本地化字符串。 /// public static string menuProxiesSelectActivity { get { @@ -1411,7 +1411,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Test Configurations real delay (Ctrl+R) 的本地化字符串。 + /// 查找类似 Test Configurations real delay 的本地化字符串。 /// public static string menuRealPingServer { get { @@ -1528,7 +1528,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Remove selected Configurations (Delete) 的本地化字符串。 + /// 查找类似 Remove selected Configurations 的本地化字符串。 /// public static string menuRemoveServer { get { @@ -1564,7 +1564,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Remove selected (Delete) 的本地化字符串。 + /// 查找类似 Remove selected 的本地化字符串。 /// public static string menuRoutingAdvancedRemove { get { @@ -1573,7 +1573,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Set as active rule (Enter) 的本地化字符串。 + /// 查找类似 Set as active rule 的本地化字符串。 /// public static string menuRoutingAdvancedSetDefault { get { @@ -1645,7 +1645,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Remove Rule (Delete) 的本地化字符串。 + /// 查找类似 Remove Rule 的本地化字符串。 /// public static string menuRuleRemove { get { @@ -1654,7 +1654,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Select all (Ctrl+A) 的本地化字符串。 + /// 查找类似 Select all 的本地化字符串。 /// public static string menuSelectAll { get { @@ -1681,7 +1681,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Set as active Configuration (Enter) 的本地化字符串。 + /// 查找类似 Set as active Configuration 的本地化字符串。 /// public static string menuSetDefaultServer { get { @@ -1699,7 +1699,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Share Configuration (Ctrl+F) 的本地化字符串。 + /// 查找类似 Share Configuration 的本地化字符串。 /// public static string menuShareServer { get { @@ -1726,7 +1726,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Test Configurations download speed (Ctrl+T) 的本地化字符串。 + /// 查找类似 Test Configurations download speed 的本地化字符串。 /// public static string menuSpeedServer { get { @@ -1870,7 +1870,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 Test Configurations with tcping (Ctrl+O) 的本地化字符串。 + /// 查找类似 Test Configurations with tcping 的本地化字符串。 /// public static string menuTcpingServer { get { diff --git a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index f495cebb..1872f674 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -472,10 +472,10 @@ زبان - وارد کردن URL انبوه از کلیپ بورد (Ctrl+V) + وارد کردن URL انبوه از کلیپ بورد - اسکن کد QR روی صفحه (Ctrl+S) + اسکن کد QR روی صفحه سرور انتخاب شده را شبیه سازی کنید @@ -484,31 +484,31 @@ سرورهای تکراری را حذف کنید - حذف سرورهای انتخابی (Delete) + حذف سرورهای انتخابی - به عنوان سرور فعال تنظیم کنید (Enter) + به عنوان سرور فعال تنظیم کنید تمام آمار خدمات را پاک کنید - آزمایش سرورها با تاخیر واقعی (Ctrl+R) + آزمایش سرورها با تاخیر واقعی مرتب سازی بر اساس نتیجه تست - تست سرعت دانلود سرورها (Ctrl+T) + تست سرعت دانلود سرورها - تست سرورها با tcping (Ctrl+O) + تست سرورها با tcping سرور انتخابی را برای پیکربندی کلاینت صادر کنید - URL های اشتراک گذاری را به کلیپ بورد صادر کنید (Ctrl+C) + URL های اشتراک گذاری را به کلیپ بورد صادر کنید یک سرور پیکربندی سفارشی اضافه شود @@ -529,19 +529,19 @@ سرور [VMess] را اضافه کنید - انتخاب همه (Ctrl+A) + انتخاب همه همه را پاک کن - کپی (Ctrl+C) + کپی کپی همه - انتخاب همه (Ctrl+A) + انتخاب همه اضافه کردن @@ -796,13 +796,13 @@ به پایین حرکت شود(B) - پایین (D) + پایین - حرکت به بالا (T) + حرکت به بالا - بالا (U) + بالا فیلتر، از عبارات منظم پشتیبانی می کند @@ -922,7 +922,7 @@ رد شدن از آزمون - ویرایش سرور (Ctrl+D) + ویرایش سرور دوبار کلیک کردن سرور باعث فعال شدن آن می شود @@ -1207,7 +1207,7 @@ تازه سازی پروکسی ها - انتخاب گره فعال (Enter) + انتخاب گره فعال استراتژی دامنه پیش فرض برای خروجی @@ -1638,4 +1638,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if macOS displays this in the Dock (requires restart) - \ No newline at end of file + diff --git a/v2rayN/ServiceLib/Resx/ResUI.fr.resx b/v2rayN/ServiceLib/Resx/ResUI.fr.resx index 32a2c585..47d23982 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.fr.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.fr.resx @@ -472,10 +472,10 @@ Langue (redémarrage requis) - Importer liens depuis le presse-papiers (Ctrl+V) + Importer liens depuis le presse-papiers - Scanner le QR code à l’écran (Ctrl+S) + Scanner le QR code à l’écran Cloner la sélection @@ -484,7 +484,7 @@ Supprimer les doublons - Supprimer la sélection (multi-sélection) (Delete) + Supprimer la sélection (multi-sélection) Définir comme actif (Entrée) @@ -493,22 +493,22 @@ Effacer toutes les statistiques de service - Tester la latence de connexion réelle (multi-sélect) (Ctrl+R) + Tester la latence de connexion réelle (multi-sélect) Trier selon les résultats de test - Tester la vitesse (multi-sélection) (Ctrl+T) + Tester la vitesse (multi-sélection) - Tester la latence Tcping (multi-sélection) (Ctrl+O) + Tester la latence Tcping (multi-sélection) Exporter la configuration complète sélectionnée - Exporter les liens de partage vers le presse-papiers (multi-sélection) (Ctrl+C) + Exporter les liens de partage vers le presse-papiers (multi-sélection) Ajouter une configuration personnalisée @@ -529,19 +529,19 @@ Ajouter [VMess] - Tout sélectionner (Ctrl+A) + Tout sélectionner Tout effacer - Copier (Ctrl+C) + Copier Tout copier - Tout sélect (Ctrl+A) + Tout sélect Ajouter @@ -781,7 +781,7 @@ Mode PAC - Partager (Ctrl+F) + Partager Routage @@ -793,16 +793,16 @@ Exécuter en tant qu’administrateur - Déplacer tout en bas (B) + Déplacer tout en bas - Descendre (D) + Descendre - Déplacer tout en haut (T) + Déplacer tout en haut - Monter (U) + Monter Filtre (regex pris en charge) @@ -817,7 +817,7 @@ Importer 1-clic du jeu de règles - Suppr. règles sélectionnées (Delete) + Suppr. règles sélectionnées Définir comme règles actives (Entrée) @@ -853,7 +853,7 @@ Liste des règles - Supprimer les règles sélectionnées (Delete) + Supprimer les règles sélectionnées Paramètres détaillés des règles de routage @@ -922,7 +922,7 @@ Ignorer le test - Éditer (Ctrl+D) + Éditer Double-cliquer sur l’interface principale pour activer diff --git a/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 4df5e94b..648bd2ad 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -472,10 +472,10 @@ Nyelv (Újraindítás) - Megosztási linkek importálása vágólapról (Ctrl+V) + Megosztási linkek importálása vágólapról - QR kód beolvasása a képernyőről (Ctrl+S) + QR kód beolvasása a képernyőről Kijelölt konfiguráció klónozása @@ -484,31 +484,31 @@ Ismétlődő konfigurációk eltávolítása - Kijelölt konfigurációk eltávolítása (Delete) + Kijelölt konfigurációk eltávolítása - Beállítás aktív konfigurációként (Enter) + Beállítás aktív konfigurációként Összes szolgáltatás statisztika törlése - Konfigurációk valós késleltetésének tesztelése (Ctrl+R) + Konfigurációk valós késleltetésének tesztelése Rendezés teszteredmény szerint - Konfigurációk letöltési sebességének tesztelése (Ctrl+T) + Konfigurációk letöltési sebességének tesztelése - Konfigurációk tesztelése tcpinggel (Ctrl+O) + Konfigurációk tesztelése tcpinggel Kijelölt konfiguráció exportálása teljes konfigurációként - Megosztási link exportálása vágólapra (Ctrl+C) + Megosztási link exportálása vágólapra Egyéni konfiguráció hozzáadása @@ -529,19 +529,19 @@ [VMess] konfiguráció hozzáadása - Összes kijelölése (Ctrl+A) + Összes kijelölése Összes törlése - Másolás (Ctrl+C) + Másolás Összes másolása - Összes kijelölése (Ctrl+A) + Összes kijelölése Hozzáadás @@ -781,7 +781,7 @@ PAC mód - Konfiguráció megosztása (Ctrl+F) + Konfiguráció megosztása Útválasztás @@ -793,16 +793,16 @@ Futtatás rendszergazdaként - Mozgatás alulra (B) + Mozgatás alulra - Le (D) + Le - Mozgatás felülre (T) + Mozgatás felülre - Fel (U) + Fel Szűrő, támogatja a reguláris kifejezéseket @@ -817,10 +817,10 @@ Szabályok importálása - Kijelölt eltávolítása (Delete) + Kijelölt eltávolítása - Beállítás aktív szabályként (Enter) + Beállítás aktív szabályként Tartomány stratégia @@ -853,7 +853,7 @@ Szabálylista - Szabály eltávolítása (Delete) + Szabály eltávolítása Útválasztási szabály részleteinek beállítása @@ -922,7 +922,7 @@ Teszt kihagyása - Konfiguráció szerkesztése (Ctrl+D) + Konfiguráció szerkesztése Dupla kattintás a konfigurációra aktiválja @@ -1207,7 +1207,7 @@ Proxyk frissítése - Aktív csomópont kiválasztása (Enter) + Aktív csomópont kiválasztása Alapértelmezett tartomány stratégia kimenő forgalomhoz diff --git a/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayN/ServiceLib/Resx/ResUI.resx index 785f13a3..9b1a0eb8 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.resx @@ -472,10 +472,10 @@ Language (Restart) - Import Share Links from clipboard (Ctrl+V) + Import Share Links from clipboard - Scan QR code on the screen (Ctrl+S) + Scan QR code on the screen Clone selected Configuration @@ -484,31 +484,31 @@ Remove duplicate Configurations - Remove selected Configurations (Delete) + Remove selected Configurations - Set as active Configuration (Enter) + Set as active Configuration Clear all service statistics - Test Configurations real delay (Ctrl+R) + Test Configurations real delay Sort by test result - Test Configurations download speed (Ctrl+T) + Test Configurations download speed - Test Configurations with tcping (Ctrl+O) + Test Configurations with tcping Export selected Configuration for complete configuration - Export Share Link to Clipboard (Ctrl+C) + Export Share Link to Clipboard Add a custom configuration Configuration @@ -529,19 +529,19 @@ Add [VMess] Configuration - Select all (Ctrl+A) + Select all Clear all - Copy (Ctrl+C) + Copy Copy all - Select all (Ctrl+A) + Select all Add @@ -781,7 +781,7 @@ PAC mode - Share Configuration (Ctrl+F) + Share Configuration Routing @@ -793,16 +793,16 @@ Run as Admin - Move to bottom (B) + Move to bottom - Down (D) + Down - Move to top (T) + Move to top - Up (U) + Up Filter, supports regular expressions @@ -817,10 +817,10 @@ Import Rules - Remove selected (Delete) + Remove selected - Set as active rule (Enter) + Set as active rule Domain strategy @@ -853,7 +853,7 @@ Rule List - Remove Rule (Delete) + Remove Rule Routing Rule Details Setting @@ -922,7 +922,7 @@ Skip test - Edit Configuration (Ctrl+D) + Edit Configuration Double-clicking Configuration makes it active @@ -1207,7 +1207,7 @@ Refresh Proxies - Select active node (Enter) + Select active node Default domain strategy for outbound diff --git a/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 4ba40e54..134c32f4 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -472,10 +472,10 @@ Язык (требуется перезапуск) - Импорт массива URL из буфера обмена (Ctrl+V) + Импорт массива URL из буфера обмена - Сканировать QR-код с экрана (Ctrl+S) + Сканировать QR-код с экрана Клонировать выбранный сервер @@ -484,31 +484,31 @@ Удалить дубликаты серверов - Удалить выбранные серверы (Delete) + Удалить выбранные серверы - Установить как активный сервер (Enter) + Установить как активный сервер Очистить всю статистику - Тест на реальную задержку сервера (Ctrl+R) + Тест на реальную задержку сервера Сортировать по результату теста - Тест на скорость загрузки сервера (Ctrl+T) + Тест на скорость загрузки сервера - Тест задержки с tcping (Ctrl+O) + Тест задержки с tcping Экспортировать выбранный сервер для клиента - Экспорт URL-адресов общего доступа в буфер обмена (Ctrl+C) + Экспорт URL-адресов общего доступа в буфер обмена Добавить сервер пользовательской конфигурации @@ -529,19 +529,19 @@ Добавить сервер [VMess] - Выбрать все (Ctrl+A) + Выбрать все Очистить все - Скопировать (Ctrl+C) + Скопировать Скопировать все - Выбрать все (Ctrl+A) + Выбрать все Добавить @@ -781,7 +781,7 @@ Режим PAC - Поделиться сервером (Ctrl+F) + Поделиться сервером Маршрутизация @@ -793,16 +793,16 @@ Администратор - Спуститься вниз (B) + Спуститься вниз - Вниз (D) + Вниз - Подняться наверх (T) + Подняться наверх - Вверх (U) + Вверх Фильтр, поддерживает regex @@ -853,7 +853,7 @@ Список правил - Удалить правила (Delete) + Удалить правила Детальные настройки правил маршрутизации @@ -922,7 +922,7 @@ Пропустить тест - Редактировать сервер (Ctrl+D) + Редактировать сервер Двойной клик чтобы сделать сервер активным @@ -1207,7 +1207,7 @@ Обновить прокси - Сделать узел активным (Enter) + Сделать узел активным Стратегия домена по умолчанию для исходящих diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index df77a6e8..1d5883fb 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -472,10 +472,10 @@ 语言 (需重启) - 从剪贴板导入分享链接 (Ctrl+V) + 从剪贴板导入分享链接 - 扫描屏幕上的二维码 (Ctrl+S) + 扫描屏幕上的二维码 克隆所选 @@ -484,31 +484,31 @@ 移除重复 - 移除所选 (多选) (Delete) + 移除所选 (多选) - 设为活动 (Enter) + 设为活动 清除所有服务统计数据 - 测试真连接延迟 (多选) (Ctrl+R) + 测试真连接延迟 (多选) 按测试结果排序 - 测试速度 (多选) (Ctrl+T) + 测试速度 (多选) - 测试延迟 Tcping (多选) (Ctrl+O) + 测试延迟 Tcping (多选) 导出所选完整配置 - 导出分享链接至剪贴板 (多选) (Ctrl+C) + 导出分享链接至剪贴板 (多选) 添加自定义配置 @@ -529,19 +529,19 @@ 添加 [VMess] - 全选 (Ctrl+A) + 全选 清除所有 - 复制 (Ctrl+C) + 复制 复制所有 - 全选 (Ctrl+A) + 全选 添加 @@ -781,7 +781,7 @@ Pac 模式 - 分享 (Ctrl+F) + 分享 路由 @@ -793,16 +793,16 @@ 以管理员身份运行 - 下移至底 (B) + 下移至底 - 下移 (D) + 下移 - 上移至顶 (T) + 上移至顶 - 上移 (U) + 上移 过滤器 (支持正则) @@ -817,10 +817,10 @@ 一键导入规则集 - 移除所选规则 (Delete) + 移除所选规则 - 设为活动规则 (Enter) + 设为活动规则 域名解析策略 @@ -853,7 +853,7 @@ 规则列表 - 移除所选规则 (Delete) + 移除所选规则 路由规则详情设置 @@ -922,7 +922,7 @@ 跳过测试 - 编辑 (Ctrl+D) + 编辑 主界面双击设为活动 @@ -1204,7 +1204,7 @@ 刷新 - 设为活动 (Enter) + 设为活动 Outbound 默认解析策略 diff --git a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index f69ff6ff..036e69d8 100644 --- a/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -472,10 +472,10 @@ 語言 (需重啟) - 從剪貼簿導入分享連結 (Ctrl+V) + 從剪貼簿導入分享連結 - 掃描螢幕上的二維碼 (Ctrl+S) + 掃描螢幕上的二維碼 複製所選 @@ -484,31 +484,31 @@ 移除重複 - 移除所選 (多選) (Delete) + 移除所選 (多選) - 設為活動 (Enter) + 設為活動 清除所有服務統計資料 - 測試真連線延遲 (多選) (Ctrl+R) + 測試真連線延遲 (多選) 按測試結果排序 - 測試速度 (多選) (Ctrl+T) + 測試速度 (多選) - 測試延遲 Tcping (多選) (Ctrl+O) + 測試延遲 Tcping (多選) 匯出所選完整設定 - 匯出分享連結至剪貼簿 (多選) (Ctrl+C) + 匯出分享連結至剪貼簿 (多選) 新增自訂節點 @@ -529,19 +529,19 @@ 新增 [VMess] 節點 - 全選 (Ctrl+A) + 全選 清除所有 - 複製 (Ctrl+C) + 複製 複製所有 - 全選 (Ctrl+A) + 全選 新增 @@ -781,7 +781,7 @@ PAC 模式 - 分享 (Ctrl+F) + 分享 路由 @@ -793,16 +793,16 @@ 以管理員身份執行 - 下移至底部 (B) + 下移至底部 - 下移 (D) + 下移 - 上移至頂部 (T) + 上移至頂部 - 上移 (U) + 上移 過濾 (允許正則) @@ -817,10 +817,10 @@ 一鍵匯入規則集 - 移除所選規則 (Delete) + 移除所選規則 - 設為活動規則 (Enter) + 設為活動規則 域名解析策略 @@ -853,7 +853,7 @@ 規則列表 - 移除所選規則 (Delete) + 移除所選規則 路由規則詳情設定 @@ -922,7 +922,7 @@ 跳過測試 - 編輯 (Ctrl+D) + 編輯 主介面輕按兩下設為活動 @@ -1204,7 +1204,7 @@ 重新整理 - 設為活動節點 (Enter) + 設為活動節點 Outbound 預設解析策略 @@ -1635,4 +1635,4 @@ macOS 在 Dock 欄顯示 (需重啟) - \ No newline at end of file + diff --git a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml index 8e49ad77..81e4c6aa 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml @@ -153,12 +153,27 @@ - + - - - - + + + + diff --git a/v2rayN/v2rayN.Desktop/Views/ClashProxiesView.axaml b/v2rayN/v2rayN.Desktop/Views/ClashProxiesView.axaml index a4ef8315..15a0741d 100644 --- a/v2rayN/v2rayN.Desktop/Views/ClashProxiesView.axaml +++ b/v2rayN/v2rayN.Desktop/Views/ClashProxiesView.axaml @@ -110,7 +110,10 @@ - + diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml index 4eb8392e..2fa4e9ea 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml @@ -26,8 +26,14 @@ - - + + diff --git a/v2rayN/v2rayN.Desktop/Views/MsgView.axaml b/v2rayN/v2rayN.Desktop/Views/MsgView.axaml index 8c2cc90c..90dcfeb7 100644 --- a/v2rayN/v2rayN.Desktop/Views/MsgView.axaml +++ b/v2rayN/v2rayN.Desktop/Views/MsgView.axaml @@ -72,18 +72,20 @@ VerticalScrollBarVisibility="Auto" WordWrap="True"> - + + Header="{x:Static resx:ResUI.menuMsgViewCopy}" + InputGesture="Ctrl+C" /> - - + + - + - - - + + + @@ -130,19 +148,40 @@ - - - - + + + + - + - + - + diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml index 8f50f883..8c84bc39 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml @@ -184,14 +184,32 @@ - - + + - - - - + + + + diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml index 69f17eca..0677f835 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml @@ -99,9 +99,18 @@ - - - + + + diff --git a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml index cb823229..8b0cd824 100644 --- a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml +++ b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml @@ -218,24 +218,29 @@ + Header="{x:Static resx:ResUI.menuSelectAll}" + InputGestureText="Ctrl+A" /> + Header="{x:Static resx:ResUI.menuMoveTop}" + InputGestureText="T" /> + Header="{x:Static resx:ResUI.menuMoveUp}" + InputGestureText="U" /> + Header="{x:Static resx:ResUI.menuMoveDown}" + InputGestureText="D" /> + Header="{x:Static resx:ResUI.menuMoveBottom}" + InputGestureText="B" /> diff --git a/v2rayN/v2rayN/Views/ClashProxiesView.xaml b/v2rayN/v2rayN/Views/ClashProxiesView.xaml index ca87e098..df8e739e 100644 --- a/v2rayN/v2rayN/Views/ClashProxiesView.xaml +++ b/v2rayN/v2rayN/Views/ClashProxiesView.xaml @@ -142,7 +142,10 @@ - + diff --git a/v2rayN/v2rayN/Views/MainWindow.xaml b/v2rayN/v2rayN/Views/MainWindow.xaml index 25b44106..5d6fc7f5 100644 --- a/v2rayN/v2rayN/Views/MainWindow.xaml +++ b/v2rayN/v2rayN/Views/MainWindow.xaml @@ -58,11 +58,13 @@ + Header="{x:Static resx:ResUI.menuAddServerViaClipboard}" + InputGestureText="Ctrl+V" /> + Header="{x:Static resx:ResUI.menuAddServerViaScan}" + InputGestureText="Ctrl+S" /> + Header="{x:Static resx:ResUI.menuMsgViewSelectAll}" + InputGestureText="Ctrl+A" /> + Header="{x:Static resx:ResUI.menuMsgViewCopy}" + InputGestureText="Ctrl+C" /> + Header="{x:Static resx:ResUI.menuSetDefaultServer}" + InputGestureText="Enter" /> + Header="{x:Static resx:ResUI.menuEditServer}" + InputGestureText="Ctrl+D" /> + Header="{x:Static resx:ResUI.menuRemoveServer}" + InputGestureText="Delete" /> + Header="{x:Static resx:ResUI.menuTcpingServer}" + InputGestureText="Ctrl+O" /> + Header="{x:Static resx:ResUI.menuRealPingServer}" + InputGestureText="Ctrl+R" /> + Header="{x:Static resx:ResUI.menuSpeedServer}" + InputGestureText="Ctrl+T" /> + Header="{x:Static resx:ResUI.menuMoveTop}" + InputGestureText="T" /> + Header="{x:Static resx:ResUI.menuMoveUp}" + InputGestureText="U" /> + Header="{x:Static resx:ResUI.menuMoveDown}" + InputGestureText="D" /> + Header="{x:Static resx:ResUI.menuMoveBottom}" + InputGestureText="B" /> + Header="{x:Static resx:ResUI.menuSelectAll}" + InputGestureText="Ctrl+A" /> + Header="{x:Static resx:ResUI.menuShareServer}" + InputGestureText="Ctrl+F" /> + Header="{x:Static resx:ResUI.menuExport2ShareUrl}" + InputGestureText="Ctrl+C" /> + Header="{x:Static resx:ResUI.menuRuleRemove}" + InputGestureText="Delete" /> + Header="{x:Static resx:ResUI.menuSelectAll}" + InputGestureText="Ctrl+A" /> + Header="{x:Static resx:ResUI.menuMoveTop}" + InputGestureText="T" /> + Header="{x:Static resx:ResUI.menuMoveUp}" + InputGestureText="U" /> + Header="{x:Static resx:ResUI.menuMoveDown}" + InputGestureText="D" /> + Header="{x:Static resx:ResUI.menuMoveBottom}" + InputGestureText="B" /> diff --git a/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml b/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml index c4595292..90bb09e4 100644 --- a/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml +++ b/v2rayN/v2rayN/Views/RoutingSettingWindow.xaml @@ -144,15 +144,18 @@ + Header="{x:Static resx:ResUI.menuRoutingAdvancedRemove}" + InputGestureText="Delete" /> + Header="{x:Static resx:ResUI.menuSelectAll}" + InputGestureText="Ctrl+A" /> + Header="{x:Static resx:ResUI.menuRoutingAdvancedSetDefault}" + InputGestureText="Enter" /> Date: Tue, 18 Nov 2025 16:15:19 +0800 Subject: [PATCH 15/52] Update Directory.Packages.props --- v2rayN/Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/v2rayN/Directory.Packages.props b/v2rayN/Directory.Packages.props index cd23d54f..33903afc 100644 --- a/v2rayN/Directory.Packages.props +++ b/v2rayN/Directory.Packages.props @@ -19,9 +19,9 @@ - + - + From 84f812c8eedfb86cad735c08d0ec30f4425b1b85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 16:15:59 +0800 Subject: [PATCH 16/52] Bump actions/checkout from 5.0.0 to 5.0.1 (#8341) Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 5.0.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5.0.0...v5.0.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 5.0.1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-linux.yml | 4 ++-- .github/workflows/build-osx.yml | 2 +- .github/workflows/build-windows-desktop.yml | 2 +- .github/workflows/build-windows.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index b67527a1..42a1a343 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v5.0.1 with: submodules: 'recursive' fetch-depth: '0' @@ -110,7 +110,7 @@ jobs: dnf -y install sudo git rpm-build rpmdevtools dnf-plugins-core rsync findutils tar gzip unzip which - name: Checkout repo (for scripts) - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v5.0.1 with: submodules: 'recursive' fetch-depth: '0' diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index 5825ac9d..9edbbf99 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v5.0.1 with: submodules: 'recursive' fetch-depth: '0' diff --git a/.github/workflows/build-windows-desktop.yml b/.github/workflows/build-windows-desktop.yml index 65b86126..ec857938 100644 --- a/.github/workflows/build-windows-desktop.yml +++ b/.github/workflows/build-windows-desktop.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v5.0.1 with: submodules: 'recursive' fetch-depth: '0' diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 31b5a90c..288f776c 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v5.0.1 - name: Setup uses: actions/setup-dotnet@v5.0.0 From 2ebd2b28a8101a9a66dbcc7c69ef3e214c3d32e9 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Tue, 18 Nov 2025 16:54:42 +0800 Subject: [PATCH 17/52] Support Backspace for remove actions in UI lists Changed key handling and menu input gestures to allow Backspace (in addition to Delete) for removing items in server, profile, and routing rule lists. This improves usability and consistency across both Avalonia and WPF views. --- .../Views/AddGroupServerWindow.axaml | 5 +- .../Views/AddGroupServerWindow.axaml.cs | 1 + .../v2rayN.Desktop/Views/ProfilesView.axaml | 2 +- .../Views/ProfilesView.axaml.cs | 56 ++++++++++--------- .../Views/RoutingRuleSettingWindow.axaml | 2 +- .../Views/RoutingRuleSettingWindow.axaml.cs | 39 +++++++------ .../Views/RoutingSettingWindow.axaml | 2 +- .../Views/RoutingSettingWindow.axaml.cs | 25 ++++++--- .../v2rayN/Views/AddGroupServerWindow.xaml.cs | 39 +++++++------ v2rayN/v2rayN/Views/ProfilesView.xaml | 2 +- v2rayN/v2rayN/Views/ProfilesView.xaml.cs | 56 ++++++++++--------- .../Views/RoutingRuleSettingWindow.xaml | 2 +- .../Views/RoutingRuleSettingWindow.xaml.cs | 39 +++++++------ v2rayN/v2rayN/Views/RoutingSettingWindow.xaml | 2 +- .../v2rayN/Views/RoutingSettingWindow.xaml.cs | 25 ++++++--- 15 files changed, 168 insertions(+), 129 deletions(-) diff --git a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml index 81e4c6aa..221a1b88 100644 --- a/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml @@ -152,7 +152,10 @@ - + break; case Key.Delete: + case Key.Back: ViewModel?.ChildRemoveAsync(); e.Handled = true; break; diff --git a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml index 371ade2d..c84a7151 100644 --- a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml +++ b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml @@ -115,7 +115,7 @@ + InputGesture="Back" /> diff --git a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs index 418d6d20..e019c5fd 100644 --- a/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs +++ b/v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs @@ -313,33 +313,37 @@ public partial class ProfilesView : ReactiveUserControl } else { - if (e.Key is Key.Enter or Key.Return) + switch (e.Key) { - ViewModel?.SetDefaultServer(); - } - else if (e.Key == Key.Delete) - { - ViewModel?.RemoveServerAsync(); - } - else if (e.Key == Key.T) - { - ViewModel?.MoveServer(EMove.Top); - } - else if (e.Key == Key.U) - { - ViewModel?.MoveServer(EMove.Up); - } - else if (e.Key == Key.D) - { - ViewModel?.MoveServer(EMove.Down); - } - else if (e.Key == Key.B) - { - ViewModel?.MoveServer(EMove.Bottom); - } - else if (e.Key == Key.Escape) - { - ViewModel?.ServerSpeedtestStop(); + case Key.Enter: + //case Key.Return: + ViewModel?.SetDefaultServer(); + break; + + case Key.Delete: + case Key.Back: + ViewModel?.RemoveServerAsync(); + break; + + case Key.T: + ViewModel?.MoveServer(EMove.Top); + break; + + case Key.U: + ViewModel?.MoveServer(EMove.Up); + break; + + case Key.D: + ViewModel?.MoveServer(EMove.Down); + break; + + case Key.B: + ViewModel?.MoveServer(EMove.Bottom); + break; + + case Key.Escape: + ViewModel?.ServerSpeedtestStop(); + break; } } } diff --git a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml index 8c84bc39..7d00b3cc 100644 --- a/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml @@ -187,7 +187,7 @@ + InputGesture="Back" /> + InputGesture="Back" /> { if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta) { - if (e.Key == Key.A) + switch (e.Key) { - lstRoutings.SelectAll(); + case Key.A: + lstRoutings.SelectAll(); + break; } } - else if (e.Key is Key.Enter or Key.Return) + else { - ViewModel?.RoutingAdvancedSetDefault(); - } - else if (e.Key == Key.Delete) - { - ViewModel?.RoutingAdvancedRemoveAsync(); + switch (e.Key) + { + case Key.Enter: + //case Key.Return: + ViewModel?.RoutingAdvancedSetDefault(); + break; + + case Key.Delete: + case Key.Back: + ViewModel?.RoutingAdvancedRemoveAsync(); + break; + } } } diff --git a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs index d7cf450c..14f5a7bf 100644 --- a/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs +++ b/v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs @@ -91,25 +91,28 @@ public partial class AddGroupServerWindow } else { - if (e.Key == Key.T) + switch (e.Key) { - ViewModel?.MoveServer(EMove.Top); - } - else if (e.Key == Key.U) - { - ViewModel?.MoveServer(EMove.Up); - } - else if (e.Key == Key.D) - { - ViewModel?.MoveServer(EMove.Down); - } - else if (e.Key == Key.B) - { - ViewModel?.MoveServer(EMove.Bottom); - } - else if (e.Key == Key.Delete) - { - ViewModel?.ChildRemoveAsync(); + case Key.T: + ViewModel?.MoveServer(EMove.Top); + break; + + case Key.U: + ViewModel?.MoveServer(EMove.Up); + break; + + case Key.D: + ViewModel?.MoveServer(EMove.Down); + break; + + case Key.B: + ViewModel?.MoveServer(EMove.Bottom); + break; + + case Key.Delete: + case Key.Back: + ViewModel?.ChildRemoveAsync(); + break; } } } diff --git a/v2rayN/v2rayN/Views/ProfilesView.xaml b/v2rayN/v2rayN/Views/ProfilesView.xaml index 8bbfb6b7..6cf0d159 100644 --- a/v2rayN/v2rayN/Views/ProfilesView.xaml +++ b/v2rayN/v2rayN/Views/ProfilesView.xaml @@ -138,7 +138,7 @@ x:Name="menuRemoveServer" Height="{StaticResource MenuItemHeight}" Header="{x:Static resx:ResUI.menuRemoveServer}" - InputGestureText="Delete" /> + InputGestureText="Back" /> + InputGestureText="Back" /> + InputGestureText="Back" /> Date: Wed, 19 Nov 2025 16:47:00 +0800 Subject: [PATCH 18/52] =?UTF-8?q?[PR]=E6=94=B9=E8=BF=9BEmoji=E5=AD=97?= =?UTF-8?q?=E4=BD=93=E5=85=BC=E5=AE=B9=E6=80=A7=20(#8346)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update AppBuilderExtension.cs * Update package-rhel.sh * Update package-debian.sh * Update AppBuilderExtension.cs * Update AppBuilderExtension.cs * Update AppBuilderExtension.cs * Withdraw * Update AppBuilderExtension.cs --- package-debian.sh | 2 +- package-rhel.sh | 3 ++- .../Common/AppBuilderExtension.cs | 25 ++++++++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/package-debian.sh b/package-debian.sh index 2c0ce9da..8b15bb06 100644 --- a/package-debian.sh +++ b/package-debian.sh @@ -28,7 +28,7 @@ Package: v2rayN Version: $Version Architecture: $Arch2 Maintainer: https://github.com/2dust/v2rayN -Depends: libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1) +Depends: libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1), libfreetype6 (>= 2.11) Description: A GUI client for Windows and Linux, support Xray core and sing-box-core and others EOF diff --git a/package-rhel.sh b/package-rhel.sh index 5ef75ab5..a3ea5406 100644 --- a/package-rhel.sh +++ b/package-rhel.sh @@ -631,13 +631,14 @@ ExclusiveArch: aarch64 x86_64 Source0: __PKGROOT__.tar.gz # Runtime dependencies (Avalonia / X11 / Fonts / GL) -Requires: freetype, cairo, pango, openssl, mesa-libEGL, mesa-libGL +Requires: cairo, pango, openssl, mesa-libEGL, mesa-libGL Requires: glibc >= 2.34 Requires: fontconfig >= 2.13.1 Requires: desktop-file-utils >= 0.26 Requires: xdg-utils >= 1.1.3 Requires: coreutils >= 8.32 Requires: bash >= 5.1 +Requires: freetype >= 2.10 %description v2rayN Linux for Red Hat Enterprise Linux diff --git a/v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs b/v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs index c0702938..5a3fca95 100644 --- a/v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs +++ b/v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs @@ -1,14 +1,31 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Avalonia; +using Avalonia.Media; + namespace v2rayN.Desktop.Common; public static class AppBuilderExtension { public static AppBuilder WithFontByDefault(this AppBuilder appBuilder) { - var uri = Path.Combine(Global.AvaAssets, "Fonts#Noto Sans SC"); - return appBuilder.With(new FontManagerOptions() + var fallbacks = new List(); + + var notoSansSc = new FontFamily(Path.Combine(Global.AvaAssets, "Fonts#Noto Sans SC")); + fallbacks.Add(new FontFallback { FontFamily = notoSansSc }); + + if (OperatingSystem.IsLinux()) { - //DefaultFamilyName = uri, - FontFallbacks = new[] { new FontFallback { FontFamily = new FontFamily(uri) } } + fallbacks.Add(new FontFallback + { + FontFamily = new FontFamily("Noto Color Emoji") + }); + } + + return appBuilder.With(new FontManagerOptions + { + FontFallbacks = fallbacks.ToArray() }); } } From 30e663cd4fa9b2d43b564155f6a3dfb20677bdfc Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Wed, 19 Nov 2025 17:15:35 +0800 Subject: [PATCH 19/52] up 7.16.3 --- v2rayN/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/v2rayN/Directory.Build.props b/v2rayN/Directory.Build.props index b3df5f80..ee1b516c 100644 --- a/v2rayN/Directory.Build.props +++ b/v2rayN/Directory.Build.props @@ -1,7 +1,7 @@ - 7.16.2 + 7.16.3 From d3e2e55ecf7ca1726248c99c1aa8ade81723dc7d Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 20 Nov 2025 10:12:44 +0800 Subject: [PATCH 20/52] Add global.json for SDK configuration Introduces a global.json file specifying the .NET SDK version (8.0.416) and disables rollForward to ensure consistent SDK usage across environments. --- v2rayN/global.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 v2rayN/global.json diff --git a/v2rayN/global.json b/v2rayN/global.json new file mode 100644 index 00000000..ce0f627c --- /dev/null +++ b/v2rayN/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.416", + "rollForward": "disable" + } +} From f61e6d8c630085ccaec8d03e948c4ff2a442d2df Mon Sep 17 00:00:00 2001 From: DHR60 Date: Thu, 20 Nov 2025 19:35:57 +0800 Subject: [PATCH 21/52] perf: Shadowsocks (#8352) * perf: Shadowsocks * stricter plugin name fix for SIP002 URI * Fix --- .../ServiceLib/Handler/Fmt/ShadowsocksFmt.cs | 145 +++++++++++++++-- .../Singbox/SingboxOutboundService.cs | 151 ++++++++++++------ 2 files changed, 232 insertions(+), 64 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs index adaeb954..04f52232 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs @@ -41,7 +41,68 @@ public class ShadowsocksFmt : BaseFmt //url = Utile.Base64Encode(url); //new Sip002 var pw = Utils.Base64Encode($"{item.Security}:{item.Id}", true); - return ToUri(EConfigType.Shadowsocks, item.Address, item.Port, pw, null, remark); + + // plugin + var plugin = string.Empty; + var pluginArgs = string.Empty; + + if (item.Network == nameof(ETransport.tcp) && item.HeaderType == Global.TcpHeaderHttp) + { + plugin = "obfs-local"; + pluginArgs = $"obfs=http;obfs-host={item.RequestHost};"; + } + else + { + if (item.Network == nameof(ETransport.ws)) + { + pluginArgs += "mode=websocket;"; + pluginArgs += $"host={item.RequestHost};"; + pluginArgs += $"path={item.Path};"; + } + else if (item.Network == nameof(ETransport.quic)) + { + pluginArgs += "mode=quic;"; + } + if (item.StreamSecurity == Global.StreamSecurity) + { + pluginArgs += "tls;"; + var certs = CertPemManager.ParsePemChain(item.Cert); + if (certs.Count > 0) + { + var cert = certs.First(); + const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; + const string endMarker = "\n-----END CERTIFICATE-----"; + + var base64Start = beginMarker.Length; + var endIndex = cert.IndexOf(endMarker, base64Start, StringComparison.Ordinal); + var base64Content = cert.Substring(base64Start, endIndex - base64Start); + + // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172 + // Equal signs and commas [and backslashes] must be escaped with a backslash. + base64Content = base64Content.Replace("\\", "\\\\").Replace("=", "\\=").Replace(",", "\\,"); + + pluginArgs += $"certRaw={base64Content};"; + } + } + if (pluginArgs.Length > 0) + { + plugin = "v2ray-plugin"; + } + } + + var dicQuery = new Dictionary(); + if (plugin.IsNotEmpty()) + { + var pluginStr = plugin + ";" + pluginArgs; + // pluginStr remove last ';' and url encode + if (pluginStr.EndsWith(';')) + { + pluginStr = pluginStr[..^1]; + } + dicQuery["plugin"] = Utils.UrlEncode(pluginStr); + } + + return ToUri(EConfigType.Shadowsocks, item.Address, item.Port, pw, dicQuery, remark); } private static readonly Regex UrlFinder = new(@"ss://(?[A-Za-z0-9+-/=_]+)(?:#(?\S+))?", RegexOptions.IgnoreCase | RegexOptions.Compiled); @@ -124,19 +185,81 @@ public class ShadowsocksFmt : BaseFmt var queryParameters = Utils.ParseQueryString(parsedUrl.Query); if (queryParameters["plugin"] != null) { - //obfs-host exists - var obfsHost = queryParameters["plugin"]?.Split(';').FirstOrDefault(t => t.Contains("obfs-host")); - if (queryParameters["plugin"].Contains("obfs=http") && obfsHost.IsNotEmpty()) - { - obfsHost = obfsHost?.Replace("obfs-host=", ""); - item.Network = Global.DefaultNetwork; - item.HeaderType = Global.TcpHeaderHttp; - item.RequestHost = obfsHost ?? ""; - } - else + var pluginStr = queryParameters["plugin"]; + var pluginParts = pluginStr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + + if (pluginParts.Length == 0) { return null; } + + var pluginName = pluginParts[0]; + + // A typo in https://github.com/shadowsocks/shadowsocks-org/blob/6b1c064db4129de99c516294960e731934841c94/docs/doc/sip002.md?plain=1#L15 + // "simple-obfs" should be "obfs-local" + if (pluginName == "simple-obfs") + { + pluginName = "obfs-local"; + } + + // Parse obfs-local plugin + if (pluginName == "obfs-local") + { + var obfsMode = pluginParts.FirstOrDefault(t => t.StartsWith("obfs=")); + var obfsHost = pluginParts.FirstOrDefault(t => t.StartsWith("obfs-host=")); + + if ((!obfsMode.IsNullOrEmpty()) && obfsMode.Contains("obfs=http") && obfsHost.IsNotEmpty()) + { + obfsHost = obfsHost.Replace("obfs-host=", ""); + item.Network = Global.DefaultNetwork; + item.HeaderType = Global.TcpHeaderHttp; + item.RequestHost = obfsHost; + } + } + // Parse v2ray-plugin + else if (pluginName == "v2ray-plugin") + { + var mode = pluginParts.FirstOrDefault(t => t.StartsWith("mode="), "websocket"); + var host = pluginParts.FirstOrDefault(t => t.StartsWith("host=")); + var path = pluginParts.FirstOrDefault(t => t.StartsWith("path=")); + var hasTls = pluginParts.Any(t => t == "tls"); + var certRaw = pluginParts.FirstOrDefault(t => t.StartsWith("certRaw=")); + + var modeValue = mode.Replace("mode=", ""); + if (modeValue == "websocket") + { + item.Network = nameof(ETransport.ws); + if (!host.IsNullOrEmpty()) + { + item.RequestHost = host.Replace("host=", ""); + } + if (!path.IsNullOrEmpty()) + { + item.Path = path.Replace("path=", ""); + } + } + else if (modeValue == "quic") + { + item.Network = nameof(ETransport.quic); + } + + if (hasTls) + { + item.StreamSecurity = Global.StreamSecurity; + + if (!certRaw.IsNullOrEmpty()) + { + var certBase64 = certRaw.Replace("certRaw=", ""); + + certBase64 = certBase64.Replace("\\=", "=").Replace("\\,", ",").Replace("\\\\", "\\"); + + const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; + const string endMarker = "\n-----END CERTIFICATE-----"; + var certPem = beginMarker + certBase64 + endMarker; + item.Cert = certPem; + } + } + } } return item; diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs index 9671dc77..1bda5981 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs @@ -26,6 +26,7 @@ public partial class CoreConfigSingboxService } await GenOutboundMux(node, outbound); + await GenOutboundTransport(node, outbound); break; } case EConfigType.Shadowsocks: @@ -33,6 +34,52 @@ public partial class CoreConfigSingboxService outbound.method = AppManager.Instance.GetShadowsocksSecurities(node).Contains(node.Security) ? node.Security : Global.None; outbound.password = node.Id; + if (node.Network == nameof(ETransport.tcp) && node.HeaderType == Global.TcpHeaderHttp) + { + outbound.plugin = "obfs-local"; + outbound.plugin_opts = $"obfs=http;obfs-host={node.RequestHost};"; + } + else + { + var pluginArgs = string.Empty; + if (node.Network == nameof(ETransport.ws)) + { + pluginArgs += "mode=websocket;"; + pluginArgs += $"host={node.RequestHost};"; + pluginArgs += $"path={node.Path};"; + } + else if (node.Network == nameof(ETransport.quic)) + { + pluginArgs += "mode=quic;"; + } + if (node.StreamSecurity == Global.StreamSecurity) + { + pluginArgs += "tls;"; + var certs = CertPemManager.ParsePemChain(node.Cert); + if (certs.Count > 0) + { + var cert = certs.First(); + const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; + const string endMarker = "\n-----END CERTIFICATE-----"; + + var base64Start = beginMarker.Length; + var endIndex = cert.IndexOf(endMarker, base64Start, StringComparison.Ordinal); + var base64Content = cert.Substring(base64Start, endIndex - base64Start); + + // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172 + // Equal signs and commas [and backslashes] must be escaped with a backslash. + base64Content = base64Content.Replace("\\", "\\\\").Replace("=", "\\=").Replace(",", "\\,"); + + pluginArgs += $"certRaw={base64Content};"; + } + } + if (pluginArgs.Length > 0) + { + outbound.plugin = "v2ray-plugin"; + outbound.plugin_opts = pluginArgs; + } + } + await GenOutboundMux(node, outbound); break; } @@ -71,6 +118,8 @@ public partial class CoreConfigSingboxService { outbound.flow = node.Flow; } + + await GenOutboundTransport(node, outbound); break; } case EConfigType.Trojan: @@ -78,6 +127,7 @@ public partial class CoreConfigSingboxService outbound.password = node.Id; await GenOutboundMux(node, outbound); + await GenOutboundTransport(node, outbound); break; } case EConfigType.Hysteria2: @@ -127,8 +177,6 @@ public partial class CoreConfigSingboxService } await GenOutboundTls(node, outbound); - - await GenOutboundTransport(node, outbound); } catch (Exception ex) { @@ -232,54 +280,59 @@ public partial class CoreConfigSingboxService { try { - if (node.StreamSecurity is Global.StreamSecurityReality or Global.StreamSecurity) + if (node.StreamSecurity is not (Global.StreamSecurityReality or Global.StreamSecurity)) { - var server_name = string.Empty; - if (node.Sni.IsNotEmpty()) - { - server_name = node.Sni; - } - else if (node.RequestHost.IsNotEmpty()) - { - server_name = Utils.String2List(node.RequestHost)?.First(); - } - var tls = new Tls4Sbox() + return await Task.FromResult(0); + } + if (node.ConfigType is EConfigType.Shadowsocks or EConfigType.SOCKS or EConfigType.WireGuard) + { + return await Task.FromResult(0); + } + var server_name = string.Empty; + if (node.Sni.IsNotEmpty()) + { + server_name = node.Sni; + } + else if (node.RequestHost.IsNotEmpty()) + { + server_name = Utils.String2List(node.RequestHost)?.First(); + } + var tls = new Tls4Sbox() + { + enabled = true, + record_fragment = _config.CoreBasicItem.EnableFragment ? true : null, + server_name = server_name, + insecure = Utils.ToBool(node.AllowInsecure.IsNullOrEmpty() ? _config.CoreBasicItem.DefAllowInsecure.ToString().ToLower() : node.AllowInsecure), + alpn = node.GetAlpn(), + }; + if (node.Fingerprint.IsNotEmpty()) + { + tls.utls = new Utls4Sbox() { enabled = true, - record_fragment = _config.CoreBasicItem.EnableFragment ? true : null, - server_name = server_name, - insecure = Utils.ToBool(node.AllowInsecure.IsNullOrEmpty() ? _config.CoreBasicItem.DefAllowInsecure.ToString().ToLower() : node.AllowInsecure), - alpn = node.GetAlpn(), + fingerprint = node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : node.Fingerprint }; - if (node.Fingerprint.IsNotEmpty()) + } + if (node.StreamSecurity == Global.StreamSecurity) + { + var certs = CertPemManager.ParsePemChain(node.Cert); + if (certs.Count > 0) { - tls.utls = new Utls4Sbox() - { - enabled = true, - fingerprint = node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : node.Fingerprint - }; - } - if (node.StreamSecurity == Global.StreamSecurity) - { - var certs = CertPemManager.ParsePemChain(node.Cert); - if (certs.Count > 0) - { - tls.certificate = certs; - tls.insecure = false; - } - } - else if (node.StreamSecurity == Global.StreamSecurityReality) - { - tls.reality = new Reality4Sbox() - { - enabled = true, - public_key = node.PublicKey, - short_id = node.ShortId - }; + tls.certificate = certs; tls.insecure = false; } - outbound.tls = tls; } + else if (node.StreamSecurity == Global.StreamSecurityReality) + { + tls.reality = new Reality4Sbox() + { + enabled = true, + public_key = node.PublicKey, + short_id = node.ShortId + }; + tls.insecure = false; + } + outbound.tls = tls; } catch (Exception ex) { @@ -305,17 +358,9 @@ public partial class CoreConfigSingboxService case nameof(ETransport.tcp): //http if (node.HeaderType == Global.TcpHeaderHttp) { - if (node.ConfigType == EConfigType.Shadowsocks) - { - outbound.plugin = "obfs-local"; - outbound.plugin_opts = $"obfs=http;obfs-host={node.RequestHost};"; - } - else - { - transport.type = nameof(ETransport.http); - transport.host = node.RequestHost.IsNullOrEmpty() ? null : Utils.String2List(node.RequestHost); - transport.path = node.Path.IsNullOrEmpty() ? null : node.Path; - } + transport.type = nameof(ETransport.http); + transport.host = node.RequestHost.IsNullOrEmpty() ? null : Utils.String2List(node.RequestHost); + transport.path = node.Path.IsNullOrEmpty() ? null : node.Path; } break; From 2ba896e17e402418a7b8cb612796649b52d1436c Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 20 Nov 2025 19:39:29 +0800 Subject: [PATCH 22/52] Update Directory.Packages.props --- v2rayN/Directory.Packages.props | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/v2rayN/Directory.Packages.props b/v2rayN/Directory.Packages.props index 33903afc..beb870f2 100644 --- a/v2rayN/Directory.Packages.props +++ b/v2rayN/Directory.Packages.props @@ -6,11 +6,11 @@ - - - + + + - + From c0fca0dddd30f73c079afb124e01984762b77186 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 20 Nov 2025 19:56:14 +0800 Subject: [PATCH 23/52] Update build script and remove global.json --- .github/workflows/build-windows.yml | 14 +++++++------- v2rayN/global.json | 6 ------ 2 files changed, 7 insertions(+), 13 deletions(-) delete mode 100644 v2rayN/global.json diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 288f776c..0ffe971a 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -37,12 +37,12 @@ jobs: - name: Build run: | cd v2rayN - dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=false -p:EnableWindowsTargeting=true -o $OutputPath64 - dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-arm64 --self-contained=false -p:EnableWindowsTargeting=true -o $OutputPathArm64 - dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 --self-contained=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=false -p:EnableWindowsTargeting=true -o $OutputPath64 - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=false -p:EnableWindowsTargeting=true -o $OutputPathArm64 - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64Sc + dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 -p:SelfContained=false -p:EnableWindowsTargeting=true -o $OutputPath64 + dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-arm64 -p:SelfContained=false -p:EnableWindowsTargeting=true -o $OutputPathArm64 + dotnet publish ./v2rayN/v2rayN.csproj -c Release -r win-x64 -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPath64Sc + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 -p:SelfContained=false -p:EnableWindowsTargeting=true -o $OutputPath64 + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 -p:SelfContained=false -p:EnableWindowsTargeting=true -o $OutputPathArm64 + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64Sc - name: Upload build artifacts @@ -68,4 +68,4 @@ jobs: file: ${{ github.workspace }}/v2rayN*.zip tag: ${{ github.event.inputs.release_tag }} file_glob: true - prerelease: true \ No newline at end of file + prerelease: true diff --git a/v2rayN/global.json b/v2rayN/global.json deleted file mode 100644 index ce0f627c..00000000 --- a/v2rayN/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "sdk": { - "version": "8.0.416", - "rollForward": "disable" - } -} From 20ce35bc30aebd9bd6e28e75ab00833d5d45f69a Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Thu, 20 Nov 2025 20:04:14 +0800 Subject: [PATCH 24/52] Update dotnet publish syntax in build workflows --- .github/workflows/build-linux.yml | 8 ++++---- .github/workflows/build-osx.yml | 8 ++++---- .github/workflows/build-windows-desktop.yml | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 42a1a343..8fe09d48 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -44,10 +44,10 @@ jobs: - name: Build run: | cd v2rayN - dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 --self-contained=true -o "$OutputPath64" - dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 --self-contained=true -o "$OutputPathArm64" - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 --self-contained=true -p:PublishTrimmed=true -o "$OutputPath64" - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishTrimmed=true -o "$OutputPathArm64" + dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64 -p:SelfContained=true -o "$OutputPath64" + dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 -p:SelfContained=true -o "$OutputPathArm64" + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-x64 -p:SelfContained=true -p:PublishTrimmed=true -o "$OutputPath64" + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 -p:SelfContained=true -p:PublishTrimmed=true -o "$OutputPathArm64" - name: Upload build artifacts uses: actions/upload-artifact@v5.0.0 diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index 9edbbf99..b8f3e202 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -39,10 +39,10 @@ jobs: - name: Build run: | cd v2rayN - dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 --self-contained=true -o $OutputPath64 - dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 --self-contained=true -o $OutputPathArm64 - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-x64 --self-contained=true -p:PublishTrimmed=true -o $OutputPath64 - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64 + dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64 -p:SelfContained=true -o $OutputPath64 + dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 -p:SelfContained=true -o $OutputPathArm64 + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-x64 -p:SelfContained=true -p:PublishTrimmed=true -o $OutputPath64 + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 -p:SelfContained=true -p:PublishTrimmed=true -o $OutputPathArm64 - name: Upload build artifacts uses: actions/upload-artifact@v5.0.0 diff --git a/.github/workflows/build-windows-desktop.yml b/.github/workflows/build-windows-desktop.yml index ec857938..73f679fe 100644 --- a/.github/workflows/build-windows-desktop.yml +++ b/.github/workflows/build-windows-desktop.yml @@ -39,10 +39,10 @@ jobs: - name: Build run: | cd v2rayN - dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-x64 --self-contained=true -p:EnableWindowsTargeting=true -o $OutputPath64 - dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -o $OutputPathArm64 - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64 - dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64 + dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-x64 -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPath64 + dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-arm64 -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPathArm64 + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64 -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64 + dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64 - name: Upload build artifacts uses: actions/upload-artifact@v5.0.0 From 5b82f1799582c19edfd2f0e8b6fe360e4f729ab8 Mon Sep 17 00:00:00 2001 From: DHR60 Date: Fri, 21 Nov 2025 15:56:42 +0800 Subject: [PATCH 25/52] Fix (#8363) * Fix * AI-optimized code --- .../ServiceLib/Handler/Fmt/ShadowsocksFmt.cs | 8 ++- .../Manager/ActionPrecheckManager.cs | 50 +++++++++++++------ .../Singbox/SingboxOutboundService.cs | 6 +-- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs b/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs index 04f52232..a17a8bd8 100644 --- a/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs +++ b/v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs @@ -73,13 +73,11 @@ public class ShadowsocksFmt : BaseFmt const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; const string endMarker = "\n-----END CERTIFICATE-----"; - var base64Start = beginMarker.Length; - var endIndex = cert.IndexOf(endMarker, base64Start, StringComparison.Ordinal); - var base64Content = cert.Substring(base64Start, endIndex - base64Start); + var base64Content = cert.Replace(beginMarker, "").Replace(endMarker, "").Trim(); // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172 // Equal signs and commas [and backslashes] must be escaped with a backslash. - base64Content = base64Content.Replace("\\", "\\\\").Replace("=", "\\=").Replace(",", "\\,"); + base64Content = base64Content.Replace("=", "\\="); pluginArgs += $"certRaw={base64Content};"; } @@ -251,7 +249,7 @@ public class ShadowsocksFmt : BaseFmt { var certBase64 = certRaw.Replace("certRaw=", ""); - certBase64 = certBase64.Replace("\\=", "=").Replace("\\,", ",").Replace("\\\\", "\\"); + certBase64 = certBase64.Replace("\\=", "="); const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; const string endMarker = "\n-----END CERTIFICATE-----"; diff --git a/v2rayN/ServiceLib/Manager/ActionPrecheckManager.cs b/v2rayN/ServiceLib/Manager/ActionPrecheckManager.cs index 75e3e00e..7b665816 100644 --- a/v2rayN/ServiceLib/Manager/ActionPrecheckManager.cs +++ b/v2rayN/ServiceLib/Manager/ActionPrecheckManager.cs @@ -10,6 +10,13 @@ public class ActionPrecheckManager(Config config) private readonly Config _config = config; + // sing-box supported transports for different protocol types + private static readonly HashSet SingboxUnsupportedTransports = [nameof(ETransport.kcp), nameof(ETransport.xhttp)]; + private static readonly HashSet SingboxTransportSupportedProtocols = + [EConfigType.VMess, EConfigType.VLESS, EConfigType.Trojan, EConfigType.Shadowsocks]; + private static readonly HashSet SingboxShadowsocksAllowedTransports = + [nameof(ETransport.tcp), nameof(ETransport.ws), nameof(ETransport.quic)]; + public async Task> Check(string? indexId) { if (indexId.IsNullOrEmpty()) @@ -174,26 +181,16 @@ public class ActionPrecheckManager(Config config) return errors; } - var net = item.GetNetwork() ?? item.Network; + var net = item.GetNetwork(); if (coreType == ECoreType.sing_box) { - // sing-box does not support xhttp / kcp - // sing-box does not support transports like ws/http/httpupgrade/etc. when the node is not vmess/trojan/vless - if (net is nameof(ETransport.kcp) or nameof(ETransport.xhttp)) + var transportError = ValidateSingboxTransport(item.ConfigType, net); + if (transportError != null) { - errors.Add(string.Format(ResUI.CoreNotSupportNetwork, nameof(ECoreType.sing_box), net)); + errors.Add(transportError); return errors; } - - if (item.ConfigType is not (EConfigType.VMess or EConfigType.VLESS or EConfigType.Trojan)) - { - if (net is nameof(ETransport.ws) or nameof(ETransport.http) or nameof(ETransport.h2) or nameof(ETransport.quic) or nameof(ETransport.httpupgrade)) - { - errors.Add(string.Format(ResUI.CoreNotSupportProtocolTransport, nameof(ECoreType.sing_box), item.ConfigType.ToString(), net)); - return errors; - } - } } else if (coreType is ECoreType.Xray) { @@ -209,6 +206,31 @@ public class ActionPrecheckManager(Config config) return errors; } + private static string? ValidateSingboxTransport(EConfigType configType, string net) + { + // sing-box does not support xhttp / kcp transports + if (SingboxUnsupportedTransports.Contains(net)) + { + return string.Format(ResUI.CoreNotSupportNetwork, nameof(ECoreType.sing_box), net); + } + + // sing-box does not support non-tcp transports for protocols other than vmess/trojan/vless/shadowsocks + if (!SingboxTransportSupportedProtocols.Contains(configType) && net != nameof(ETransport.tcp)) + { + return string.Format(ResUI.CoreNotSupportProtocolTransport, + nameof(ECoreType.sing_box), configType.ToString(), net); + } + + // sing-box shadowsocks only supports tcp/ws/quic transports + if (configType == EConfigType.Shadowsocks && !SingboxShadowsocksAllowedTransports.Contains(net)) + { + return string.Format(ResUI.CoreNotSupportProtocolTransport, + nameof(ECoreType.sing_box), configType.ToString(), net); + } + + return null; + } + private async Task> ValidateRelatedNodesExistAndValid(ProfileItem? item) { var errors = new List(); diff --git a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs index 1bda5981..5188d177 100644 --- a/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs +++ b/v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs @@ -62,13 +62,11 @@ public partial class CoreConfigSingboxService const string beginMarker = "-----BEGIN CERTIFICATE-----\n"; const string endMarker = "\n-----END CERTIFICATE-----"; - var base64Start = beginMarker.Length; - var endIndex = cert.IndexOf(endMarker, base64Start, StringComparison.Ordinal); - var base64Content = cert.Substring(base64Start, endIndex - base64Start); + var base64Content = cert.Replace(beginMarker, "").Replace(endMarker, "").Trim(); // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172 // Equal signs and commas [and backslashes] must be escaped with a backslash. - base64Content = base64Content.Replace("\\", "\\\\").Replace("=", "\\=").Replace(",", "\\,"); + base64Content = base64Content.Replace("=", "\\="); pluginArgs += $"certRaw={base64Content};"; } From 514d76953a763854b391f196595ef268786d671a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 15:57:37 +0800 Subject: [PATCH 26/52] Bump actions/checkout from 5.0.1 to 6.0.0 (#8359) Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.1 to 6.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5.0.1...v6.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build-linux.yml | 4 ++-- .github/workflows/build-osx.yml | 2 +- .github/workflows/build-windows-desktop.yml | 2 +- .github/workflows/build-windows.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 8fe09d48..1cf32d89 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -31,7 +31,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.1 + uses: actions/checkout@v6.0.0 with: submodules: 'recursive' fetch-depth: '0' @@ -110,7 +110,7 @@ jobs: dnf -y install sudo git rpm-build rpmdevtools dnf-plugins-core rsync findutils tar gzip unzip which - name: Checkout repo (for scripts) - uses: actions/checkout@v5.0.1 + uses: actions/checkout@v6.0.0 with: submodules: 'recursive' fetch-depth: '0' diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index b8f3e202..61f974c4 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.1 + uses: actions/checkout@v6.0.0 with: submodules: 'recursive' fetch-depth: '0' diff --git a/.github/workflows/build-windows-desktop.yml b/.github/workflows/build-windows-desktop.yml index 73f679fe..aa7d0c11 100644 --- a/.github/workflows/build-windows-desktop.yml +++ b/.github/workflows/build-windows-desktop.yml @@ -26,7 +26,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.1 + uses: actions/checkout@v6.0.0 with: submodules: 'recursive' fetch-depth: '0' diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 0ffe971a..e779e12c 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -27,7 +27,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v5.0.1 + uses: actions/checkout@v6.0.0 - name: Setup uses: actions/setup-dotnet@v5.0.0 From ad74b1584d3814e3e51adc52c3b82ff39da64b91 Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Fri, 21 Nov 2025 20:30:41 +0800 Subject: [PATCH 27/52] Refactor dialog layouts --- v2rayN/v2rayN.Desktop/Views/MainWindow.axaml | 4 +-- v2rayN/v2rayN/Views/BackupAndRestoreView.xaml | 13 ++----- v2rayN/v2rayN/Views/CheckUpdateView.xaml | 13 ++----- v2rayN/v2rayN/Views/MainWindow.xaml | 35 ++++++++++--------- v2rayN/v2rayN/Views/QrcodeView.xaml | 15 ++------ v2rayN/v2rayN/Views/SubSettingWindow.xaml | 1 + 6 files changed, 27 insertions(+), 54 deletions(-) diff --git a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml index 2fa4e9ea..52cf5c4f 100644 --- a/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml +++ b/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml @@ -90,13 +90,13 @@ - - + + diff --git a/v2rayN/v2rayN/Views/BackupAndRestoreView.xaml b/v2rayN/v2rayN/Views/BackupAndRestoreView.xaml index a803d524..3b50cfe4 100644 --- a/v2rayN/v2rayN/Views/BackupAndRestoreView.xaml +++ b/v2rayN/v2rayN/Views/BackupAndRestoreView.xaml @@ -1,4 +1,4 @@ - - - - - - - - - - - - - + + + + + + + + + + + 400 - - -