Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
95e3ebd815 | ||
|
|
dc2877d817 | ||
|
|
89d6af8fc9 | ||
|
|
dcc9c9fa14 | ||
|
|
a73906505c | ||
|
|
f45290eb3a | ||
|
|
0fb6b2e54b | ||
|
|
9cc99c5c63 | ||
|
|
46801ce339 | ||
|
|
4345c58b45 | ||
|
|
a2028623e7 | ||
|
|
8314ff3271 | ||
|
|
6a9408fe9b | ||
|
|
b5e0a77401 | ||
|
|
dffc6d9a9b | ||
|
|
c9989108bd | ||
|
|
386c86bfa6 | ||
|
|
925cf16c50 | ||
|
|
c561916b67 | ||
|
|
d41a73b44b | ||
|
|
7995bdd4df | ||
|
|
df95cc6af7 | ||
|
|
c669e72189 | ||
|
|
46db5efef3 | ||
|
|
610418b42b | ||
|
|
508eb24fc3 | ||
|
|
6973272dd0 | ||
|
|
d820c4367e | ||
|
|
96e1f85d6f | ||
|
|
6fa5ca5aa9 | ||
|
|
1d1f5641eb | ||
|
|
3f79df21d9 | ||
|
|
ac1231ad54 | ||
|
|
8662d94ab6 | ||
|
|
3d23f3e3a2 | ||
|
|
6715d7dce6 | ||
|
|
dad35f57d0 | ||
|
|
f779e311ed | ||
|
|
ce7c41e3ff | ||
|
|
74bb01d044 | ||
|
|
82f9698c0d | ||
|
|
6911883995 | ||
|
|
47c509faf6 | ||
|
|
8704942209 | ||
|
|
e8cdc29bb5 | ||
|
|
191a7a6574 | ||
|
|
ad5d21db5a | ||
|
|
569e939492 | ||
|
|
6a17c539d1 | ||
|
|
f8a4f946e4 | ||
|
|
0715fa85ce | ||
|
|
1360051f0c | ||
|
|
42c4f9a6c6 | ||
|
|
11691d0128 | ||
|
|
26fe9c63a3 |
2
.github/workflows/build-linux.yml
vendored
2
.github/workflows/build-linux.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
fetch-depth: '0'
|
||||
|
||||
2
.github/workflows/build-osx.yml
vendored
2
.github/workflows/build-osx.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
fetch-depth: '0'
|
||||
|
||||
2
.github/workflows/build-windows-desktop.yml
vendored
2
.github/workflows/build-windows-desktop.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
fetch-depth: '0'
|
||||
|
||||
2
.github/workflows/build-windows.yml
vendored
2
.github/workflows/build-windows.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
uses: actions/checkout@v5.0.0
|
||||
|
||||
- name: Setup
|
||||
uses: actions/setup-dotnet@v4.3.1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>7.13.0</Version>
|
||||
<Version>7.14.0</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
<CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.2" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.2" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.2" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.2" />
|
||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.3" />
|
||||
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.3.3" />
|
||||
<PackageVersion Include="CliWrap" Version="3.9.0" />
|
||||
<PackageVersion Include="Downloader" Version="3.3.4" />
|
||||
<PackageVersion Include="Downloader" Version="4.0.3" />
|
||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.0" />
|
||||
<PackageVersion Include="MaterialDesignThemes" Version="5.2.1" />
|
||||
<PackageVersion Include="MessageBox.Avalonia" Version="3.2.0" />
|
||||
@@ -27,4 +27,4 @@
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.14" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -26,7 +26,7 @@ public class DownloaderHelper
|
||||
var downloadOpt = new DownloadConfiguration()
|
||||
{
|
||||
Timeout = timeout * 1000,
|
||||
MaxTryAgainOnFailover = 2,
|
||||
MaxTryAgainOnFailure = 2,
|
||||
RequestConfiguration =
|
||||
{
|
||||
Headers = headers,
|
||||
@@ -64,7 +64,7 @@ public class DownloaderHelper
|
||||
var downloadOpt = new DownloadConfiguration()
|
||||
{
|
||||
Timeout = timeout * 1000,
|
||||
MaxTryAgainOnFailover = 2,
|
||||
MaxTryAgainOnFailure = 2,
|
||||
RequestConfiguration =
|
||||
{
|
||||
Timeout= timeout * 1000,
|
||||
@@ -135,7 +135,7 @@ public class DownloaderHelper
|
||||
var downloadOpt = new DownloadConfiguration()
|
||||
{
|
||||
Timeout = timeout * 1000,
|
||||
MaxTryAgainOnFailover = 2,
|
||||
MaxTryAgainOnFailure = 2,
|
||||
RequestConfiguration =
|
||||
{
|
||||
Timeout= timeout * 1000,
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ServiceLib.Common;
|
||||
|
||||
public static class StringEx
|
||||
public static class Extension
|
||||
{
|
||||
public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)
|
||||
{
|
||||
@@ -79,4 +79,9 @@ public static class StringEx
|
||||
{
|
||||
return int.TryParse(value, out var result) ? result : defaultValue;
|
||||
}
|
||||
|
||||
public static List<string> AppendEmpty(this IEnumerable<string> source)
|
||||
{
|
||||
return source.Concat(new[] { string.Empty }).ToList();
|
||||
}
|
||||
}
|
||||
@@ -223,4 +223,28 @@ public static class FileManager
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a Linux shell file with the specified contents.
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="contents"></param>
|
||||
/// <param name="overwrite"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<string> CreateLinuxShellFile(string fileName, string contents, bool overwrite)
|
||||
{
|
||||
var shFilePath = Utils.GetBinConfigPath(fileName);
|
||||
|
||||
// Check if the file already exists and if we should overwrite it
|
||||
if (!overwrite && File.Exists(shFilePath))
|
||||
{
|
||||
return shFilePath;
|
||||
}
|
||||
|
||||
File.Delete(shFilePath);
|
||||
await File.WriteAllTextAsync(shFilePath, contents);
|
||||
await Utils.SetLinuxChmod(shFilePath);
|
||||
|
||||
return shFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,5 +128,8 @@ public class JsonUtils
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public static JsonNode? SerializeToNode(object? obj) => JsonSerializer.SerializeToNode(obj);
|
||||
public static JsonNode? SerializeToNode(object? obj, JsonSerializerOptions? options = null)
|
||||
{
|
||||
return JsonSerializer.SerializeToNode(obj, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,6 +323,14 @@ public class Utils
|
||||
return text.Replace(",", ",").Replace(Environment.NewLine, ",");
|
||||
}
|
||||
|
||||
public static List<string> GetEnumNames<TEnum>() where TEnum : Enum
|
||||
{
|
||||
return Enum.GetValues(typeof(TEnum))
|
||||
.Cast<TEnum>()
|
||||
.Select(e => e.ToString())
|
||||
.ToList();
|
||||
}
|
||||
|
||||
#endregion 转换函数
|
||||
|
||||
#region 数据检查
|
||||
@@ -382,13 +390,44 @@ public class Utils
|
||||
{
|
||||
if (IPAddress.TryParse(ip, out var address))
|
||||
{
|
||||
// Loopback address check (127.0.0.1 for IPv4, ::1 for IPv6)
|
||||
if (IPAddress.IsLoopback(address))
|
||||
return true;
|
||||
|
||||
var ipBytes = address.GetAddressBytes();
|
||||
if (ipBytes[0] == 10)
|
||||
return true;
|
||||
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
|
||||
return true;
|
||||
if (ipBytes[0] == 192 && ipBytes[1] == 168)
|
||||
return true;
|
||||
if (address.AddressFamily == AddressFamily.InterNetwork)
|
||||
{
|
||||
// IPv4 private address check
|
||||
if (ipBytes[0] == 10)
|
||||
return true;
|
||||
if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)
|
||||
return true;
|
||||
if (ipBytes[0] == 192 && ipBytes[1] == 168)
|
||||
return true;
|
||||
}
|
||||
else if (address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||
{
|
||||
// IPv6 private address check
|
||||
// Link-local address fe80::/10
|
||||
if (ipBytes[0] == 0xfe && (ipBytes[1] & 0xc0) == 0x80)
|
||||
return true;
|
||||
|
||||
// Unique local address fc00::/7 (typically fd00::/8)
|
||||
if ((ipBytes[0] & 0xfe) == 0xfc)
|
||||
return true;
|
||||
|
||||
// Private portion in IPv4-mapped addresses ::ffff:0:0/96
|
||||
if (address.IsIPv4MappedToIPv6)
|
||||
{
|
||||
var ipv4Bytes = ipBytes.Skip(12).ToArray();
|
||||
if (ipv4Bytes[0] == 10)
|
||||
return true;
|
||||
if (ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31)
|
||||
return true;
|
||||
if (ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -427,11 +466,11 @@ public class Utils
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int GetFreePort(int defaultPort = 9090)
|
||||
public static int GetFreePort(int defaultPort = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Utils.PortInUse(defaultPort))
|
||||
if (!(defaultPort == 0 || Utils.PortInUse(defaultPort)))
|
||||
{
|
||||
return defaultPort;
|
||||
}
|
||||
|
||||
@@ -11,5 +11,6 @@ public enum EConfigType
|
||||
Hysteria2 = 7,
|
||||
TUIC = 8,
|
||||
WireGuard = 9,
|
||||
HTTP = 10
|
||||
HTTP = 10,
|
||||
Anytls = 11
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ public enum EViewAction
|
||||
DNSSettingWindow,
|
||||
RoutingSettingWindow,
|
||||
OptionSettingWindow,
|
||||
FullConfigTemplateWindow,
|
||||
GlobalHotkeySettingWindow,
|
||||
SubSettingWindow,
|
||||
DispatcherSpeedTest,
|
||||
|
||||
@@ -38,6 +38,8 @@ public class Global
|
||||
public const string PacFileName = NamespaceSample + "pac";
|
||||
public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
|
||||
public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
|
||||
public const string KillAsSudoOSXShellFileName = NamespaceSample + "kill_as_sudo_osx_sh";
|
||||
public const string KillAsSudoLinuxShellFileName = NamespaceSample + "kill_as_sudo_linux_sh";
|
||||
|
||||
public const string DefaultSecurity = "auto";
|
||||
public const string DefaultNetwork = "tcp";
|
||||
@@ -46,6 +48,7 @@ public class Global
|
||||
public const string ProxyTag = "proxy";
|
||||
public const string DirectTag = "direct";
|
||||
public const string BlockTag = "block";
|
||||
public const string DnsTag = "dns-module";
|
||||
public const string StreamSecurity = "tls";
|
||||
public const string StreamSecurityReality = "reality";
|
||||
public const string Loopback = "127.0.0.1";
|
||||
@@ -54,6 +57,9 @@ public class Global
|
||||
public const string HttpsProtocol = "https://";
|
||||
public const string SocksProtocol = "socks://";
|
||||
public const string Socks5Protocol = "socks5://";
|
||||
public const string AsIs = "AsIs";
|
||||
public const string IPIfNonMatch = "IPIfNonMatch";
|
||||
public const string IPOnDemand = "IPOnDemand";
|
||||
|
||||
public const string UserEMail = "t@t.tt";
|
||||
public const string AutoRunRegPath = @"Software\Microsoft\Windows\CurrentVersion\Run";
|
||||
@@ -74,6 +80,13 @@ public class Global
|
||||
public const int SpeedTestPageSize = 1000;
|
||||
public const string LinuxBash = "/bin/bash";
|
||||
|
||||
public const string SingboxDirectDNSTag = "direct_dns";
|
||||
public const string SingboxRemoteDNSTag = "remote_dns";
|
||||
public const string SingboxOutboundResolverTag = "outbound_resolver";
|
||||
public const string SingboxFinalResolverTag = "final_resolver";
|
||||
public const string SingboxHostsDNSTag = "hosts_dns";
|
||||
public const string SingboxFakeDNSTag = "fake_dns";
|
||||
|
||||
public static readonly List<string> IEProxyProtocols =
|
||||
[
|
||||
"{ip}:{http_port}",
|
||||
@@ -127,24 +140,24 @@ public class Global
|
||||
];
|
||||
|
||||
public static readonly List<string> SingboxRulesetSources =
|
||||
[
|
||||
"",
|
||||
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-rules-dat@release/sing-box/rule-set-{0}/{1}.srs",
|
||||
@"https://cdn.jsdelivr.net/gh/chocolate4u/Iran-sing-box-rules@rule-set/{1}.srs"
|
||||
];
|
||||
[
|
||||
"",
|
||||
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/release/sing-box/rule-set-{0}/{1}.srs",
|
||||
@"https://raw.githubusercontent.com/chocolate4u/Iran-sing-box-rules/rule-set/{1}.srs"
|
||||
];
|
||||
|
||||
public static readonly List<string> RoutingRulesSources =
|
||||
[
|
||||
"",
|
||||
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/template.json",
|
||||
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/template.json"
|
||||
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-custom-routing-list/main/v2rayN/template.json",
|
||||
@"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/main/v2rayN/template.json"
|
||||
];
|
||||
|
||||
public static readonly List<string> DNSTemplateSources =
|
||||
[
|
||||
"",
|
||||
@"https://cdn.jsdelivr.net/gh/runetfreedom/russia-v2ray-custom-routing-list@main/v2rayN/",
|
||||
@"https://cdn.jsdelivr.net/gh/Chocolate4U/Iran-v2ray-rules@main/v2rayN/"
|
||||
@"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-custom-routing-list/main/v2rayN/",
|
||||
@"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/main/v2rayN/"
|
||||
];
|
||||
|
||||
public static readonly Dictionary<string, string> UserAgentTexts = new()
|
||||
@@ -167,7 +180,8 @@ public class Global
|
||||
{ EConfigType.Trojan, "trojan://" },
|
||||
{ EConfigType.Hysteria2, "hysteria2://" },
|
||||
{ EConfigType.TUIC, "tuic://" },
|
||||
{ EConfigType.WireGuard, "wireguard://" }
|
||||
{ EConfigType.WireGuard, "wireguard://" },
|
||||
{ EConfigType.Anytls, "anytls://" }
|
||||
};
|
||||
|
||||
public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()
|
||||
@@ -180,7 +194,8 @@ public class Global
|
||||
{ EConfigType.Trojan, "trojan" },
|
||||
{ EConfigType.Hysteria2, "hysteria2" },
|
||||
{ EConfigType.TUIC, "tuic" },
|
||||
{ EConfigType.WireGuard, "wireguard" }
|
||||
{ EConfigType.WireGuard, "wireguard" },
|
||||
{ EConfigType.Anytls, "anytls" }
|
||||
};
|
||||
|
||||
public static readonly List<string> VmessSecurities =
|
||||
@@ -276,9 +291,9 @@ public class Global
|
||||
|
||||
public static readonly List<string> DomainStrategies =
|
||||
[
|
||||
"AsIs",
|
||||
"IPIfNonMatch",
|
||||
"IPOnDemand"
|
||||
AsIs,
|
||||
IPIfNonMatch,
|
||||
IPOnDemand
|
||||
];
|
||||
|
||||
public static readonly List<string> DomainStrategies4Singbox =
|
||||
@@ -347,25 +362,42 @@ public class Global
|
||||
|
||||
public static readonly List<string> SingboxDomainStrategy4Out =
|
||||
[
|
||||
"ipv4_only",
|
||||
"",
|
||||
"ipv4_only",
|
||||
"prefer_ipv4",
|
||||
"prefer_ipv6",
|
||||
"ipv6_only",
|
||||
""
|
||||
"ipv6_only"
|
||||
];
|
||||
|
||||
public static readonly List<string> DomainDNSAddress =
|
||||
public static readonly List<string> DomainDirectDNSAddress =
|
||||
[
|
||||
"223.5.5.5",
|
||||
"223.6.6.6",
|
||||
"https://dns.alidns.com/dns-query",
|
||||
"https://doh.pub/dns-query",
|
||||
"223.5.5.5",
|
||||
"119.29.29.29",
|
||||
"localhost"
|
||||
];
|
||||
|
||||
public static readonly List<string> SingboxDomainDNSAddress =
|
||||
public static readonly List<string> DomainRemoteDNSAddress =
|
||||
[
|
||||
"https://cloudflare-dns.com/dns-query",
|
||||
"https://dns.cloudflare.com/dns-query",
|
||||
"https://dns.google/dns-query",
|
||||
"https://doh.dns.sb/dns-query",
|
||||
"https://doh.opendns.com/dns-query",
|
||||
"https://common.dot.dns.yandex.net",
|
||||
"8.8.8.8",
|
||||
"1.1.1.1",
|
||||
"185.222.222.222",
|
||||
"208.67.222.222",
|
||||
"77.88.8.8"
|
||||
];
|
||||
|
||||
public static readonly List<string> DomainPureIPDNSAddress =
|
||||
[
|
||||
"223.5.5.5",
|
||||
"223.6.6.6",
|
||||
"dhcp://auto"
|
||||
"119.29.29.29",
|
||||
"localhost"
|
||||
];
|
||||
|
||||
public static readonly List<string> Languages =
|
||||
@@ -528,5 +560,37 @@ public class Global
|
||||
@""
|
||||
];
|
||||
|
||||
public static readonly List<string> OutboundTags =
|
||||
[
|
||||
ProxyTag,
|
||||
DirectTag,
|
||||
BlockTag
|
||||
];
|
||||
|
||||
public static readonly Dictionary<string, List<string>> PredefinedHosts = new()
|
||||
{
|
||||
{ "dns.google", new List<string> { "8.8.8.8", "8.8.4.4", "2001:4860:4860::8888", "2001:4860:4860::8844" } },
|
||||
{ "dns.alidns.com", new List<string> { "223.5.5.5", "223.6.6.6", "2400:3200::1", "2400:3200:baba::1" } },
|
||||
{ "one.one.one.one", new List<string> { "1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001" } },
|
||||
{ "1dot1dot1dot1.cloudflare-dns.com", new List<string> { "1.1.1.1", "1.0.0.1", "2606:4700:4700::1111", "2606:4700:4700::1001" } },
|
||||
{ "cloudflare-dns.com", new List<string> { "104.16.249.249", "104.16.248.249", "2606:4700::6810:f8f9", "2606:4700::6810:f9f9" } },
|
||||
{ "dns.cloudflare.com", new List<string> { "104.16.132.229", "104.16.133.229", "2606:4700::6810:84e5", "2606:4700::6810:85e5" } },
|
||||
{ "dot.pub", new List<string> { "1.12.12.12", "120.53.53.53" } },
|
||||
{ "dns.quad9.net", new List<string> { "9.9.9.9", "149.112.112.112", "2620:fe::fe", "2620:fe::9" } },
|
||||
{ "dns.yandex.net", new List<string> { "77.88.8.8", "77.88.8.1", "2a02:6b8::feed:0ff", "2a02:6b8:0:1::feed:0ff" } },
|
||||
{ "dns.sb", new List<string> { "185.222.222.222", "2a09::" } },
|
||||
{ "dns.umbrella.com", new List<string> { "208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53" } },
|
||||
{ "dns.sse.cisco.com", new List<string> { "208.67.220.220", "208.67.222.222", "2620:119:35::35", "2620:119:53::53" } },
|
||||
{ "engage.cloudflareclient.com", new List<string> { "162.159.192.1", "2606:4700:d0::a29f:c001" } }
|
||||
};
|
||||
|
||||
public static readonly List<string> ExpectedIPs =
|
||||
[
|
||||
"geoip:cn",
|
||||
"geoip:ir",
|
||||
"geoip:ru",
|
||||
""
|
||||
];
|
||||
|
||||
#endregion const
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ public sealed class AppHandler
|
||||
SQLiteHelper.Instance.CreateTable<RoutingItem>();
|
||||
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
|
||||
SQLiteHelper.Instance.CreateTable<DNSItem>();
|
||||
SQLiteHelper.Instance.CreateTable<FullConfigTemplateItem>();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -203,6 +204,16 @@ public sealed class AppHandler
|
||||
return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
|
||||
}
|
||||
|
||||
public async Task<List<FullConfigTemplateItem>?> FullConfigTemplateItem()
|
||||
{
|
||||
return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<FullConfigTemplateItem?> GetFullConfigTemplateItem(ECoreType eCoreType)
|
||||
{
|
||||
return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);
|
||||
}
|
||||
|
||||
#endregion SqliteHelper
|
||||
|
||||
#region Core Type
|
||||
|
||||
@@ -112,6 +112,8 @@ public class ConfigHandler
|
||||
|
||||
config.ConstItem ??= new ConstItem();
|
||||
|
||||
config.SimpleDNSItem ??= InitBuiltinSimpleDNS();
|
||||
|
||||
config.SpeedTestItem ??= new();
|
||||
if (config.SpeedTestItem.SpeedTestTimeout < 10)
|
||||
{
|
||||
@@ -246,6 +248,7 @@ public class ConfigHandler
|
||||
item.PublicKey = profileItem.PublicKey;
|
||||
item.ShortId = profileItem.ShortId;
|
||||
item.SpiderX = profileItem.SpiderX;
|
||||
item.Mldsa65Verify = profileItem.Mldsa65Verify;
|
||||
item.Extra = profileItem.Extra;
|
||||
item.MuxEnabled = profileItem.MuxEnabled;
|
||||
}
|
||||
@@ -261,6 +264,7 @@ public class ConfigHandler
|
||||
EConfigType.Hysteria2 => await AddHysteria2Server(config, item),
|
||||
EConfigType.TUIC => await AddTuicServer(config, item),
|
||||
EConfigType.WireGuard => await AddWireguardServer(config, item),
|
||||
EConfigType.Anytls => await AddAnytlsServer(config, item),
|
||||
_ => -1,
|
||||
};
|
||||
return ret;
|
||||
@@ -785,6 +789,35 @@ public class ConfigHandler
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add or edit a Anytls server
|
||||
/// Validates and processes Anytls-specific settings
|
||||
/// </summary>
|
||||
/// <param name="config">Current configuration</param>
|
||||
/// <param name="profileItem">Anytls profile to add</param>
|
||||
/// <param name="toFile">Whether to save to file</param>
|
||||
/// <returns>0 if successful, -1 if failed</returns>
|
||||
public static async Task<int> AddAnytlsServer(Config config, ProfileItem profileItem, bool toFile = true)
|
||||
{
|
||||
profileItem.ConfigType = EConfigType.Anytls;
|
||||
profileItem.CoreType = ECoreType.sing_box;
|
||||
|
||||
profileItem.Address = profileItem.Address.TrimEx();
|
||||
profileItem.Id = profileItem.Id.TrimEx();
|
||||
profileItem.Security = profileItem.Security.TrimEx();
|
||||
profileItem.Network = string.Empty;
|
||||
if (profileItem.StreamSecurity.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.StreamSecurity = Global.StreamSecurity;
|
||||
}
|
||||
if (profileItem.Id.IsNullOrEmpty())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
await AddServerCommon(config, profileItem, toFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sort the server list by the specified column
|
||||
/// Updates the sort order in the profile extension data
|
||||
@@ -1294,6 +1327,7 @@ public class ConfigHandler
|
||||
EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false),
|
||||
EConfigType.TUIC => await AddTuicServer(config, profileItem, false),
|
||||
EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false),
|
||||
EConfigType.Anytls => await AddAnytlsServer(config, profileItem, false),
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
@@ -1996,7 +2030,7 @@ public class ConfigHandler
|
||||
|
||||
if (!blImportAdvancedRules && items.Count > 0)
|
||||
{
|
||||
//migrate
|
||||
//migrate
|
||||
//TODO Temporary code to be removed later
|
||||
if (config.RoutingBasicItem.RoutingIndexId.IsNotEmpty())
|
||||
{
|
||||
@@ -2062,18 +2096,38 @@ public class ConfigHandler
|
||||
/// <summary>
|
||||
/// Initialize built-in DNS configurations
|
||||
/// Creates default DNS items for V2Ray and sing-box
|
||||
/// Also checks existing DNS items and disables those with empty NormalDNS
|
||||
/// </summary>
|
||||
/// <param name="config">Current configuration</param>
|
||||
/// <returns>0 if successful</returns>
|
||||
public static async Task<int> InitBuiltinDNS(Config config)
|
||||
{
|
||||
var items = await AppHandler.Instance.DNSItems();
|
||||
|
||||
// Check existing DNS items and disable those with empty NormalDNS
|
||||
var needsUpdate = false;
|
||||
foreach (var existingItem in items)
|
||||
{
|
||||
if (existingItem.NormalDNS.IsNullOrEmpty() && existingItem.Enabled)
|
||||
{
|
||||
existingItem.Enabled = false;
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Update items if any changes were made
|
||||
if (needsUpdate)
|
||||
{
|
||||
await SQLiteHelper.Instance.UpdateAllAsync(items);
|
||||
}
|
||||
|
||||
if (items.Count <= 0)
|
||||
{
|
||||
var item = new DNSItem()
|
||||
{
|
||||
Remarks = "V2ray",
|
||||
CoreType = ECoreType.Xray,
|
||||
Enabled = false,
|
||||
};
|
||||
await SaveDNSItems(config, item);
|
||||
|
||||
@@ -2081,6 +2135,7 @@ public class ConfigHandler
|
||||
{
|
||||
Remarks = "sing-box",
|
||||
CoreType = ECoreType.sing_box,
|
||||
Enabled = false,
|
||||
};
|
||||
await SaveDNSItems(config, item2);
|
||||
}
|
||||
@@ -2152,6 +2207,86 @@ public class ConfigHandler
|
||||
|
||||
#endregion DNS
|
||||
|
||||
#region Simple DNS
|
||||
|
||||
public static SimpleDNSItem InitBuiltinSimpleDNS()
|
||||
{
|
||||
return new SimpleDNSItem()
|
||||
{
|
||||
UseSystemHosts = false,
|
||||
AddCommonHosts = true,
|
||||
FakeIP = false,
|
||||
BlockBindingQuery = true,
|
||||
DirectDNS = Global.DomainDirectDNSAddress.FirstOrDefault(),
|
||||
RemoteDNS = Global.DomainRemoteDNSAddress.FirstOrDefault(),
|
||||
SingboxOutboundsResolveDNS = Global.DomainDirectDNSAddress.FirstOrDefault(),
|
||||
SingboxFinalResolveDNS = Global.DomainPureIPDNSAddress.FirstOrDefault()
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task<SimpleDNSItem> GetExternalSimpleDNSItem(string url)
|
||||
{
|
||||
var downloadHandle = new DownloadService();
|
||||
var templateContent = await downloadHandle.TryDownloadString(url, true, "");
|
||||
if (templateContent.IsNullOrEmpty())
|
||||
return null;
|
||||
var template = JsonUtils.Deserialize<SimpleDNSItem>(templateContent);
|
||||
if (template == null)
|
||||
return null;
|
||||
return template;
|
||||
}
|
||||
|
||||
#endregion Simple DNS
|
||||
|
||||
#region Custom Config
|
||||
|
||||
public static async Task<int> InitBuiltinFullConfigTemplate(Config config)
|
||||
{
|
||||
var items = await AppHandler.Instance.FullConfigTemplateItem();
|
||||
if (items.Count <= 0)
|
||||
{
|
||||
var item = new FullConfigTemplateItem()
|
||||
{
|
||||
Remarks = "V2ray",
|
||||
CoreType = ECoreType.Xray,
|
||||
};
|
||||
await SaveFullConfigTemplate(config, item);
|
||||
|
||||
var item2 = new FullConfigTemplateItem()
|
||||
{
|
||||
Remarks = "sing-box",
|
||||
CoreType = ECoreType.sing_box,
|
||||
};
|
||||
await SaveFullConfigTemplate(config, item2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static async Task<int> SaveFullConfigTemplate(Config config, FullConfigTemplateItem item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (item.Id.IsNullOrEmpty())
|
||||
{
|
||||
item.Id = Utils.GetGuid(false);
|
||||
}
|
||||
|
||||
if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Custom Config
|
||||
|
||||
#region Regional Presets
|
||||
|
||||
/// <summary>
|
||||
@@ -2173,7 +2308,8 @@ public class ConfigHandler
|
||||
await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>();
|
||||
await InitBuiltinDNS(config);
|
||||
|
||||
return true;
|
||||
config.SimpleDNSItem = InitBuiltinSimpleDNS();
|
||||
break;
|
||||
|
||||
case EPresetType.Russia:
|
||||
config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[1];
|
||||
@@ -2183,7 +2319,8 @@ public class ConfigHandler
|
||||
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json"));
|
||||
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json"));
|
||||
|
||||
return true;
|
||||
config.SimpleDNSItem = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[1] + "simple_dns.json") ?? InitBuiltinSimpleDNS();
|
||||
break;
|
||||
|
||||
case EPresetType.Iran:
|
||||
config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[2];
|
||||
@@ -2193,10 +2330,11 @@ public class ConfigHandler
|
||||
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json"));
|
||||
await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json"));
|
||||
|
||||
return true;
|
||||
config.SimpleDNSItem = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[2] + "simple_dns.json") ?? InitBuiltinSimpleDNS();
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion Regional Presets
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using CliWrap;
|
||||
using CliWrap.Buffered;
|
||||
|
||||
namespace ServiceLib.Handler;
|
||||
|
||||
@@ -11,6 +12,7 @@ public class CoreAdminHandler
|
||||
private Config _config;
|
||||
private Action<bool, string>? _updateFunc;
|
||||
private int _linuxSudoPid = -1;
|
||||
private const string _tag = "CoreAdminHandler";
|
||||
|
||||
public async Task Init(Config config, Action<bool, string> updateFunc)
|
||||
{
|
||||
@@ -20,6 +22,8 @@ public class CoreAdminHandler
|
||||
}
|
||||
_config = config;
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void UpdateFunc(bool notify, string msg)
|
||||
@@ -29,8 +33,11 @@ public class CoreAdminHandler
|
||||
|
||||
public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath)
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
sb.AppendLine("#!/bin/bash");
|
||||
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
||||
sb.AppendLine($"sudo -S {cmdLine}");
|
||||
var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);
|
||||
|
||||
Process proc = new()
|
||||
{
|
||||
@@ -44,33 +51,26 @@ public class CoreAdminHandler
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
CreateNoWindow = true,
|
||||
StandardInputEncoding = Encoding.UTF8,
|
||||
StandardOutputEncoding = Encoding.UTF8,
|
||||
StandardErrorEncoding = Encoding.UTF8,
|
||||
}
|
||||
};
|
||||
|
||||
proc.OutputDataReceived += (sender, e) =>
|
||||
void dataHandler(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (e.Data.IsNotEmpty())
|
||||
{
|
||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||
}
|
||||
};
|
||||
proc.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (e.Data.IsNotEmpty())
|
||||
{
|
||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
proc.OutputDataReceived += dataHandler;
|
||||
proc.ErrorDataReceived += dataHandler;
|
||||
|
||||
proc.Start();
|
||||
proc.BeginOutputReadLine();
|
||||
proc.BeginErrorReadLine();
|
||||
|
||||
await Task.Delay(10);
|
||||
await proc.StandardInput.WriteLineAsync();
|
||||
await Task.Delay(10);
|
||||
await proc.StandardInput.WriteLineAsync(AppHandler.Instance.LinuxSudoPwd);
|
||||
|
||||
@@ -92,35 +92,27 @@ public class CoreAdminHandler
|
||||
return;
|
||||
}
|
||||
|
||||
var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}";
|
||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh");
|
||||
try
|
||||
{
|
||||
var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName;
|
||||
var shFilePath = await FileManager.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true);
|
||||
if (shFilePath.Contains(' '))
|
||||
{
|
||||
shFilePath = shFilePath.AppendQuotes();
|
||||
}
|
||||
var arg = new List<string>() { "-c", $"sudo -S {shFilePath} {_linuxSudoPid}" };
|
||||
var result = await Cli.Wrap(Global.LinuxBash)
|
||||
.WithArguments(arg)
|
||||
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd))
|
||||
.ExecuteBufferedAsync();
|
||||
|
||||
await Cli.Wrap(shFilePath)
|
||||
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd))
|
||||
.ExecuteAsync();
|
||||
UpdateFunc(false, result.StandardOutput.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
|
||||
_linuxSudoPid = -1;
|
||||
}
|
||||
|
||||
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
|
||||
{
|
||||
var shFilePath = Utils.GetBinConfigPath(fileName);
|
||||
File.Delete(shFilePath);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("#!/bin/sh");
|
||||
if (Utils.IsAdministrator())
|
||||
{
|
||||
sb.AppendLine($"{cmdLine}");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.AppendLine($"sudo -S {cmdLine}");
|
||||
}
|
||||
|
||||
await File.WriteAllTextAsync(shFilePath, sb.ToString());
|
||||
await Utils.SetLinuxChmod(shFilePath);
|
||||
|
||||
return shFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public class CoreHandler
|
||||
|
||||
public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)
|
||||
{
|
||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC) ? ECoreType.sing_box : ECoreType.Xray;
|
||||
var coreType = selecteds.Exists(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls) ? ECoreType.sing_box : ECoreType.Xray;
|
||||
var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));
|
||||
var configPath = Utils.GetBinConfigPath(fileName);
|
||||
var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);
|
||||
@@ -280,20 +280,15 @@ public class CoreHandler
|
||||
|
||||
if (displayLog)
|
||||
{
|
||||
proc.OutputDataReceived += (sender, e) =>
|
||||
void dataHandler(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (e.Data.IsNotEmpty())
|
||||
{
|
||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||
}
|
||||
};
|
||||
proc.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (e.Data.IsNotEmpty())
|
||||
{
|
||||
UpdateFunc(false, e.Data + Environment.NewLine);
|
||||
}
|
||||
};
|
||||
}
|
||||
proc.OutputDataReceived += dataHandler;
|
||||
proc.ErrorDataReceived += dataHandler;
|
||||
}
|
||||
proc.Start();
|
||||
|
||||
|
||||
48
v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
Normal file
48
v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
namespace ServiceLib.Handler.Fmt;
|
||||
|
||||
public class AnytlsFmt : BaseFmt
|
||||
{
|
||||
public static ProfileItem? Resolve(string str, out string msg)
|
||||
{
|
||||
msg = ResUI.ConfigurationFormatIncorrect;
|
||||
|
||||
var parsedUrl = Utils.TryUri(str);
|
||||
if (parsedUrl == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ProfileItem item = new()
|
||||
{
|
||||
ConfigType = EConfigType.Anytls,
|
||||
Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),
|
||||
Address = parsedUrl.IdnHost,
|
||||
Port = parsedUrl.Port,
|
||||
};
|
||||
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
||||
item.Id = rawUserInfo;
|
||||
|
||||
var query = Utils.ParseQueryString(parsedUrl.Query);
|
||||
_ = ResolveStdTransport(query, ref item);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public static string? ToUri(ProfileItem? item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var remark = string.Empty;
|
||||
if (item.Remarks.IsNotEmpty())
|
||||
{
|
||||
remark = "#" + Utils.UrlEncode(item.Remarks);
|
||||
}
|
||||
var pw = item.Id;
|
||||
var dicQuery = new Dictionary<string, string>();
|
||||
_ = GetStdTransport(item, Global.None, ref dicQuery);
|
||||
|
||||
return ToUri(EConfigType.Anytls, item.Address, item.Port, pw, dicQuery, remark);
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,10 @@ public class BaseFmt
|
||||
{
|
||||
dicQuery.Add("spx", Utils.UrlEncode(item.SpiderX));
|
||||
}
|
||||
if (item.Mldsa65Verify.IsNotEmpty())
|
||||
{
|
||||
dicQuery.Add("pqv", Utils.UrlEncode(item.Mldsa65Verify));
|
||||
}
|
||||
if (item.AllowInsecure.Equals("true"))
|
||||
{
|
||||
dicQuery.Add("allowInsecure", "1");
|
||||
@@ -159,6 +163,7 @@ public class BaseFmt
|
||||
item.PublicKey = Utils.UrlDecode(query["pbk"] ?? "");
|
||||
item.ShortId = Utils.UrlDecode(query["sid"] ?? "");
|
||||
item.SpiderX = Utils.UrlDecode(query["spx"] ?? "");
|
||||
item.Mldsa65Verify = Utils.UrlDecode(query["pqv"] ?? "");
|
||||
item.AllowInsecure = (query["allowInsecure"] ?? "") == "1" ? "true" : "";
|
||||
|
||||
item.Network = query["type"] ?? nameof(ETransport.tcp);
|
||||
|
||||
@@ -18,6 +18,7 @@ public class FmtHandler
|
||||
EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),
|
||||
EConfigType.TUIC => TuicFmt.ToUri(item),
|
||||
EConfigType.WireGuard => WireguardFmt.ToUri(item),
|
||||
EConfigType.Anytls => AnytlsFmt.ToUri(item),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
@@ -75,6 +76,10 @@ public class FmtHandler
|
||||
{
|
||||
return WireguardFmt.Resolve(str, out msg);
|
||||
}
|
||||
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Anytls]))
|
||||
{
|
||||
return AnytlsFmt.Resolve(str, out msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = ResUI.NonvmessOrssProtocol;
|
||||
|
||||
@@ -24,7 +24,7 @@ public class Hysteria2Fmt : BaseFmt
|
||||
item.Path = Utils.UrlDecode(query["obfs-password"] ?? "");
|
||||
item.AllowInsecure = (query["insecure"] ?? "") == "1" ? "true" : "false";
|
||||
|
||||
item.Ports = Utils.UrlDecode(query["mport"] ?? "").Replace('-', ':');
|
||||
item.Ports = Utils.UrlDecode(query["mport"] ?? "");
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
133
v2rayN/ServiceLib/Handler/SubscriptionHandler.cs
Normal file
133
v2rayN/ServiceLib/Handler/SubscriptionHandler.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
namespace ServiceLib.Handler;
|
||||
|
||||
public class SubscriptionHandler
|
||||
{
|
||||
public static async Task UpdateProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
||||
{
|
||||
updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
||||
var subItem = await AppHandler.Instance.SubItems();
|
||||
|
||||
if (subItem is not { Count: > 0 })
|
||||
{
|
||||
updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in subItem)
|
||||
{
|
||||
var id = item.Id.TrimEx();
|
||||
var url = item.Url.TrimEx();
|
||||
var userAgent = item.UserAgent.TrimEx();
|
||||
var hashCode = $"{item.Remarks}->";
|
||||
if (id.IsNullOrEmpty() || url.IsNullOrEmpty() || (subId.IsNotEmpty() && item.Id != subId))
|
||||
{
|
||||
//_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
|
||||
continue;
|
||||
}
|
||||
if (!url.StartsWith(Global.HttpsProtocol) && !url.StartsWith(Global.HttpProtocol))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.Enabled == false)
|
||||
{
|
||||
updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var downloadHandle = new DownloadService();
|
||||
downloadHandle.Error += (sender2, args) =>
|
||||
{
|
||||
updateFunc?.Invoke(false, $"{hashCode}{args.GetException().Message}");
|
||||
};
|
||||
|
||||
updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
|
||||
|
||||
//one url
|
||||
url = Utils.GetPunycode(url);
|
||||
//convert
|
||||
if (item.ConvertTarget.IsNotEmpty())
|
||||
{
|
||||
var subConvertUrl = config.ConstItem.SubConvertUrl.IsNullOrEmpty() ? Global.SubConvertUrls.FirstOrDefault() : config.ConstItem.SubConvertUrl;
|
||||
url = string.Format(subConvertUrl!, Utils.UrlEncode(url));
|
||||
if (!url.Contains("target="))
|
||||
{
|
||||
url += string.Format("&target={0}", item.ConvertTarget);
|
||||
}
|
||||
if (!url.Contains("config="))
|
||||
{
|
||||
url += string.Format("&config={0}", Global.SubConvertConfig.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent);
|
||||
if (blProxy && result.IsNullOrEmpty())
|
||||
{
|
||||
result = await downloadHandle.TryDownloadString(url, false, userAgent);
|
||||
}
|
||||
|
||||
//more url
|
||||
if (item.ConvertTarget.IsNullOrEmpty() && item.MoreUrl.TrimEx().IsNotEmpty())
|
||||
{
|
||||
if (result.IsNotEmpty() && Utils.IsBase64String(result))
|
||||
{
|
||||
result = Utils.Base64Decode(result);
|
||||
}
|
||||
|
||||
var lstUrl = item.MoreUrl.TrimEx().Split(",") ?? [];
|
||||
foreach (var it in lstUrl)
|
||||
{
|
||||
var url2 = Utils.GetPunycode(it);
|
||||
if (url2.IsNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var result2 = await downloadHandle.TryDownloadString(url2, blProxy, userAgent);
|
||||
if (blProxy && result2.IsNullOrEmpty())
|
||||
{
|
||||
result2 = await downloadHandle.TryDownloadString(url2, false, userAgent);
|
||||
}
|
||||
if (result2.IsNotEmpty())
|
||||
{
|
||||
if (Utils.IsBase64String(result2))
|
||||
{
|
||||
result += Environment.NewLine + Utils.Base64Decode(result2);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += Environment.NewLine + result2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
|
||||
}
|
||||
else
|
||||
{
|
||||
updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
|
||||
if (result?.Length < 99)
|
||||
{
|
||||
updateFunc?.Invoke(false, $"{hashCode}{result}");
|
||||
}
|
||||
|
||||
var ret = await ConfigHandler.AddBatchServers(config, result, id, true);
|
||||
if (ret <= 0)
|
||||
{
|
||||
Logging.SaveLog("FailedImportSubscription");
|
||||
Logging.SaveLog(result);
|
||||
}
|
||||
updateFunc?.Invoke(false,
|
||||
ret > 0
|
||||
? $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}"
|
||||
: $"{hashCode}{ResUI.MsgFailedImportSubscription}");
|
||||
}
|
||||
updateFunc?.Invoke(false, "-------------------------------------------------------");
|
||||
|
||||
//await ConfigHandler.DedupServerList(config, id);
|
||||
}
|
||||
|
||||
updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||
}
|
||||
}
|
||||
@@ -18,14 +18,7 @@ public class ProxySettingLinux
|
||||
|
||||
private static async Task ExecCmd(List<string> args)
|
||||
{
|
||||
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
var contents = EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName);
|
||||
await File.AppendAllTextAsync(fileName, contents);
|
||||
|
||||
await Utils.SetLinuxChmod(fileName);
|
||||
}
|
||||
var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false);
|
||||
|
||||
await Utils.GetCliWrapOutput(fileName, args);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,7 @@ public class ProxySettingOSX
|
||||
|
||||
private static async Task ExecCmd(List<string> args)
|
||||
{
|
||||
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
|
||||
if (!File.Exists(fileName))
|
||||
{
|
||||
var contents = EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName);
|
||||
await File.AppendAllTextAsync(fileName, contents);
|
||||
|
||||
await Utils.SetLinuxChmod(fileName);
|
||||
}
|
||||
var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false);
|
||||
|
||||
await Utils.GetCliWrapOutput(fileName, args);
|
||||
}
|
||||
|
||||
@@ -63,11 +63,10 @@ public class TaskHandler
|
||||
}
|
||||
|
||||
Logging.SaveLog("Execute update subscription");
|
||||
var updateHandle = new UpdateService();
|
||||
|
||||
foreach (var item in lstSubs)
|
||||
{
|
||||
await updateHandle.UpdateSubscriptionProcess(config, item.Id, true, (bool success, string msg) =>
|
||||
await SubscriptionHandler.UpdateProcess(config, item.Id, true, (bool success, string msg) =>
|
||||
{
|
||||
updateFunc?.Invoke(success, msg);
|
||||
if (success)
|
||||
|
||||
@@ -48,6 +48,7 @@ public class Config
|
||||
public List<InItem> Inbound { get; set; }
|
||||
public List<KeyEventItem> GlobalHotkeys { get; set; }
|
||||
public List<CoreTypeItem> CoreTypeItem { get; set; }
|
||||
public SimpleDNSItem SimpleDNSItem { get; set; }
|
||||
|
||||
#endregion other entities
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@ public class CoreTypeItem
|
||||
public class TunModeItem
|
||||
{
|
||||
public bool EnableTun { get; set; }
|
||||
public bool AutoRoute { get; set; } = true;
|
||||
public bool StrictRoute { get; set; } = true;
|
||||
public string Stack { get; set; }
|
||||
public int Mtu { get; set; }
|
||||
@@ -253,3 +254,21 @@ public class WindowSizeItem
|
||||
public int Width { get; set; }
|
||||
public int Height { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class SimpleDNSItem
|
||||
{
|
||||
public bool? UseSystemHosts { get; set; }
|
||||
public bool? AddCommonHosts { get; set; }
|
||||
public bool? FakeIP { get; set; }
|
||||
public bool? BlockBindingQuery { get; set; }
|
||||
public string? DirectDNS { get; set; }
|
||||
public string? RemoteDNS { get; set; }
|
||||
public string? SingboxOutboundsResolveDNS { get; set; }
|
||||
public string? SingboxFinalResolveDNS { get; set; }
|
||||
public string? RayStrategy4Freedom { get; set; }
|
||||
public string? SingboxStrategy4Direct { get; set; }
|
||||
public string? SingboxStrategy4Proxy { get; set; }
|
||||
public string? Hosts { get; set; }
|
||||
public string? DirectExpectedIPs { get; set; }
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ public class DNSItem
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Remarks { get; set; }
|
||||
public bool Enabled { get; set; } = true;
|
||||
public bool Enabled { get; set; } = false;
|
||||
public ECoreType CoreType { get; set; }
|
||||
public bool UseSystemHosts { get; set; }
|
||||
public string? NormalDNS { get; set; }
|
||||
|
||||
18
v2rayN/ServiceLib/Models/FullConfigTemplateItem.cs
Normal file
18
v2rayN/ServiceLib/Models/FullConfigTemplateItem.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using SQLite;
|
||||
|
||||
namespace ServiceLib.Models;
|
||||
|
||||
[Serializable]
|
||||
public class FullConfigTemplateItem
|
||||
{
|
||||
[PrimaryKey]
|
||||
public string Id { get; set; }
|
||||
|
||||
public string Remarks { get; set; }
|
||||
public bool Enabled { get; set; } = false;
|
||||
public ECoreType CoreType { get; set; }
|
||||
public string? Config { get; set; }
|
||||
public string? TunConfig { get; set; }
|
||||
public bool? AddProxyOnly { get; set; } = false;
|
||||
public string? ProxyDetour { get; set; }
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class ProfileItem : ReactiveObject
|
||||
public string GetSummary()
|
||||
{
|
||||
var summary = $"[{(ConfigType).ToString()}] ";
|
||||
var arrAddr = Address.Split('.');
|
||||
var arrAddr = Address.Contains(':') ? Address.Split(':') : Address.Split('.');
|
||||
var addr = arrAddr.Length switch
|
||||
{
|
||||
> 2 => $"{arrAddr.First()}***{arrAddr.Last()}",
|
||||
@@ -93,6 +93,7 @@ public class ProfileItem : ReactiveObject
|
||||
public string PublicKey { get; set; }
|
||||
public string ShortId { get; set; }
|
||||
public string SpiderX { get; set; }
|
||||
public string Mldsa65Verify { get; set; }
|
||||
public string Extra { get; set; }
|
||||
public bool? MuxEnabled { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ServiceLib.Models;
|
||||
|
||||
public class SingboxConfig
|
||||
@@ -6,6 +8,7 @@ public class SingboxConfig
|
||||
public Dns4Sbox? dns { get; set; }
|
||||
public List<Inbound4Sbox> inbounds { get; set; }
|
||||
public List<Outbound4Sbox> outbounds { get; set; }
|
||||
public List<Endpoints4Sbox>? endpoints { get; set; }
|
||||
public Route4Sbox route { get; set; }
|
||||
public Experimental4Sbox? experimental { get; set; }
|
||||
}
|
||||
@@ -29,14 +32,15 @@ public class Dns4Sbox
|
||||
public bool? independent_cache { get; set; }
|
||||
public bool? reverse_mapping { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
public Fakeip4Sbox? fakeip { get; set; }
|
||||
}
|
||||
|
||||
public class Route4Sbox
|
||||
{
|
||||
public Rule4Sbox? default_domain_resolver { get; set; } // or string
|
||||
public bool? auto_detect_interface { get; set; }
|
||||
public List<Rule4Sbox> rules { get; set; }
|
||||
public List<Ruleset4Sbox>? rule_set { get; set; }
|
||||
public string? final { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -49,6 +53,7 @@ public class Rule4Sbox
|
||||
public string? mode { get; set; }
|
||||
public bool? ip_is_private { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
public int? rewrite_ttl { get; set; }
|
||||
public bool? invert { get; set; }
|
||||
public string? clash_mode { get; set; }
|
||||
public List<string>? inbound { get; set; }
|
||||
@@ -67,6 +72,27 @@ public class Rule4Sbox
|
||||
public List<string>? process_name { get; set; }
|
||||
public List<string>? rule_set { get; set; }
|
||||
public List<Rule4Sbox>? rules { get; set; }
|
||||
public string? action { get; set; }
|
||||
public string? strategy { get; set; }
|
||||
public List<string>? sniffer { get; set; }
|
||||
public string? rcode { get; set; }
|
||||
public List<int>? query_type { get; set; }
|
||||
public List<string>? answer { get; set; }
|
||||
public List<string>? ns { get; set; }
|
||||
public List<string>? extra { get; set; }
|
||||
public string? method { get; set; }
|
||||
public bool? no_drop { get; set; }
|
||||
public bool? source_ip_is_private { get; set; }
|
||||
public bool? ip_accept_any { get; set; }
|
||||
public int? source_port { get; set; }
|
||||
public List<string>? source_port_range { get; set; }
|
||||
public List<string>? network_type { get; set; }
|
||||
public bool? network_is_expensive { get; set; }
|
||||
public bool? network_is_constrained { get; set; }
|
||||
public List<string>? wifi_ssid { get; set; }
|
||||
public List<string>? wifi_bssid { get; set; }
|
||||
public bool? rule_set_ip_cidr_match_source { get; set; }
|
||||
public bool? rule_set_ip_cidr_accept_empty { get; set; }
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@@ -76,7 +102,6 @@ public class Inbound4Sbox
|
||||
public string tag { get; set; }
|
||||
public string listen { get; set; }
|
||||
public int? listen_port { get; set; }
|
||||
public string? domain_strategy { get; set; }
|
||||
public string interface_name { get; set; }
|
||||
public List<string>? address { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
@@ -84,8 +109,6 @@ public class Inbound4Sbox
|
||||
public bool? strict_route { get; set; }
|
||||
public bool? endpoint_independent_nat { get; set; }
|
||||
public string? stack { get; set; }
|
||||
public bool? sniff { get; set; }
|
||||
public bool? sniff_override_destination { get; set; }
|
||||
public List<User4Sbox> users { get; set; }
|
||||
}
|
||||
|
||||
@@ -95,10 +118,8 @@ public class User4Sbox
|
||||
public string password { get; set; }
|
||||
}
|
||||
|
||||
public class Outbound4Sbox
|
||||
public class Outbound4Sbox : BaseServer4Sbox
|
||||
{
|
||||
public string type { get; set; }
|
||||
public string tag { get; set; }
|
||||
public string? server { get; set; }
|
||||
public int? server_port { get; set; }
|
||||
public List<string>? server_ports { get; set; }
|
||||
@@ -113,7 +134,6 @@ public class Outbound4Sbox
|
||||
public int? recv_window_conn { get; set; }
|
||||
public int? recv_window { get; set; }
|
||||
public bool? disable_mtu_discovery { get; set; }
|
||||
public string? detour { get; set; }
|
||||
public string? method { get; set; }
|
||||
public string? username { get; set; }
|
||||
public string? password { get; set; }
|
||||
@@ -121,21 +141,36 @@ public class Outbound4Sbox
|
||||
public string? version { get; set; }
|
||||
public string? network { get; set; }
|
||||
public string? packet_encoding { get; set; }
|
||||
public List<string>? local_address { get; set; }
|
||||
public string? private_key { get; set; }
|
||||
public string? peer_public_key { get; set; }
|
||||
public List<int>? reserved { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
public string? plugin { get; set; }
|
||||
public string? plugin_opts { get; set; }
|
||||
public Tls4Sbox? tls { get; set; }
|
||||
public Multiplex4Sbox? multiplex { get; set; }
|
||||
public Transport4Sbox? transport { get; set; }
|
||||
public HyObfs4Sbox? obfs { get; set; }
|
||||
public List<string>? outbounds { get; set; }
|
||||
public bool? interrupt_exist_connections { get; set; }
|
||||
}
|
||||
|
||||
public class Endpoints4Sbox : BaseServer4Sbox
|
||||
{
|
||||
public bool? system { get; set; }
|
||||
public string? name { get; set; }
|
||||
public int? mtu { get; set; }
|
||||
public List<string> address { get; set; }
|
||||
public string private_key { get; set; }
|
||||
public int? listen_port { get; set; }
|
||||
public string? udp_timeout { get; set; }
|
||||
public int? workers { get; set; }
|
||||
public List<Peer4Sbox> peers { get; set; }
|
||||
}
|
||||
|
||||
public class Peer4Sbox
|
||||
{
|
||||
public string address { get; set; }
|
||||
public int port { get; set; }
|
||||
public string public_key { get; set; }
|
||||
public string? pre_shared_key { get; set; }
|
||||
public List<string> allowed_ips { get; set; }
|
||||
public int? persistent_keepalive_interval { get; set; }
|
||||
public List<int> reserved { get; set; }
|
||||
}
|
||||
|
||||
public class Tls4Sbox
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
@@ -144,6 +179,9 @@ public class Tls4Sbox
|
||||
public List<string>? alpn { get; set; }
|
||||
public Utls4Sbox? utls { get; set; }
|
||||
public Reality4Sbox? reality { get; set; }
|
||||
public bool? fragment { get; set; }
|
||||
public string? fragment_fallback_delay { get; set; }
|
||||
public bool? record_fragment { get; set; }
|
||||
}
|
||||
|
||||
public class Multiplex4Sbox
|
||||
@@ -191,15 +229,28 @@ public class HyObfs4Sbox
|
||||
public string? password { get; set; }
|
||||
}
|
||||
|
||||
public class Server4Sbox
|
||||
public class Server4Sbox : BaseServer4Sbox
|
||||
{
|
||||
public string? tag { get; set; }
|
||||
public string? inet4_range { get; set; }
|
||||
public string? inet6_range { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
public string? server { get; set; }
|
||||
public new string? domain_resolver { get; set; }
|
||||
[JsonPropertyName("interface")] public string? Interface { get; set; }
|
||||
public int? server_port { get; set; }
|
||||
public string? path { get; set; }
|
||||
public Headers4Sbox? headers { get; set; }
|
||||
|
||||
// public List<string>? path { get; set; } // hosts
|
||||
public Dictionary<string, List<string>>? predefined { get; set; }
|
||||
|
||||
// Deprecated
|
||||
public string? address { get; set; }
|
||||
|
||||
public string? address_resolver { get; set; }
|
||||
public string? address_strategy { get; set; }
|
||||
public string? strategy { get; set; }
|
||||
public string? detour { get; set; }
|
||||
public string? client_subnet { get; set; }
|
||||
// Deprecated End
|
||||
}
|
||||
|
||||
public class Experimental4Sbox
|
||||
@@ -229,13 +280,6 @@ public class Stats4Sbox
|
||||
public List<string>? users { get; set; }
|
||||
}
|
||||
|
||||
public class Fakeip4Sbox
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
public string inet4_range { get; set; }
|
||||
public string inet6_range { get; set; }
|
||||
}
|
||||
|
||||
public class CacheFile4Sbox
|
||||
{
|
||||
public bool enabled { get; set; }
|
||||
@@ -254,3 +298,33 @@ public class Ruleset4Sbox
|
||||
public string? download_detour { get; set; }
|
||||
public string? update_interval { get; set; }
|
||||
}
|
||||
|
||||
public abstract class DialFields4Sbox
|
||||
{
|
||||
public string? detour { get; set; }
|
||||
public string? bind_interface { get; set; }
|
||||
public string? inet4_bind_address { get; set; }
|
||||
public string? inet6_bind_address { get; set; }
|
||||
public int? routing_mark { get; set; }
|
||||
public bool? reuse_addr { get; set; }
|
||||
public string? netns { get; set; }
|
||||
public string? connect_timeout { get; set; }
|
||||
public bool? tcp_fast_open { get; set; }
|
||||
public bool? tcp_multi_path { get; set; }
|
||||
public bool? udp_fragment { get; set; }
|
||||
public Rule4Sbox? domain_resolver { get; set; } // or string
|
||||
public string? network_strategy { get; set; }
|
||||
public List<string>? network_type { get; set; }
|
||||
public List<string>? fallback_network_type { get; set; }
|
||||
public string? fallback_delay { get; set; }
|
||||
public Tls4Sbox? tls { get; set; }
|
||||
public Multiplex4Sbox? multiplex { get; set; }
|
||||
public Transport4Sbox? transport { get; set; }
|
||||
public HyObfs4Sbox? obfs { get; set; }
|
||||
}
|
||||
|
||||
public abstract class BaseServer4Sbox : DialFields4Sbox
|
||||
{
|
||||
public string type { get; set; }
|
||||
public string tag { get; set; }
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ServiceLib.Models;
|
||||
public class V2rayConfig
|
||||
{
|
||||
public Log4Ray log { get; set; }
|
||||
public object dns { get; set; }
|
||||
public Dns4Ray dns { get; set; }
|
||||
public List<Inbounds4Ray> inbounds { get; set; }
|
||||
public List<Outbounds4Ray> outbounds { get; set; }
|
||||
public Routing4Ray routing { get; set; }
|
||||
@@ -203,7 +203,15 @@ public class Response4Ray
|
||||
|
||||
public class Dns4Ray
|
||||
{
|
||||
public List<string> servers { get; set; }
|
||||
public Dictionary<string, object>? hosts { get; set; }
|
||||
public List<object> servers { get; set; }
|
||||
public string? clientIp { get; set; }
|
||||
public string? queryStrategy { get; set; }
|
||||
public bool? disableCache { get; set; }
|
||||
public bool? disableFallback { get; set; }
|
||||
public bool? disableFallbackIfMatch { get; set; }
|
||||
public bool? useSystemHosts { get; set; }
|
||||
public string? tag { get; set; }
|
||||
}
|
||||
|
||||
public class DnsServer4Ray
|
||||
@@ -211,6 +219,14 @@ public class DnsServer4Ray
|
||||
public string? address { get; set; }
|
||||
public List<string>? domains { get; set; }
|
||||
public bool? skipFallback { get; set; }
|
||||
public List<string>? expectedIPs { get; set; }
|
||||
public List<string>? unexpectedIPs { get; set; }
|
||||
public string? clientIp { get; set; }
|
||||
public string? queryStrategy { get; set; }
|
||||
public int? timeoutMs { get; set; }
|
||||
public bool? disableCache { get; set; }
|
||||
public bool? finalQuery { get; set; }
|
||||
public string? tag { get; set; }
|
||||
}
|
||||
|
||||
public class Routing4Ray
|
||||
@@ -340,6 +356,7 @@ public class TlsSettings4Ray
|
||||
public string? publicKey { get; set; }
|
||||
public string? shortId { get; set; }
|
||||
public string? spiderX { get; set; }
|
||||
public string? mldsa65Verify { get; set; }
|
||||
}
|
||||
|
||||
public class TcpSettings4Ray
|
||||
|
||||
319
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
319
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -186,6 +186,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please fill in the correct config template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string FillCorrectConfigTemplateText {
|
||||
get {
|
||||
return ResourceManager.GetString("FillCorrectConfigTemplateText", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Please fill in the correct custom DNS 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -654,6 +663,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add [Anytls] Configuration 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuAddAnytlsServer {
|
||||
get {
|
||||
return ResourceManager.GetString("menuAddAnytlsServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add a custom configuration Configuration 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -924,6 +942,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Full Config Template Setting 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string menuFullConfigTemplate {
|
||||
get {
|
||||
return ResourceManager.GetString("menuFullConfigTemplate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Global Hotkey Setting 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2202,6 +2229,33 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Incorrect password, please try again. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string SudoIncorrectPasswordTip {
|
||||
get {
|
||||
return ResourceManager.GetString("SudoIncorrectPasswordTip", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add Common DNS Hosts 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbAddCommonDNSHosts {
|
||||
get {
|
||||
return ResourceManager.GetString("TbAddCommonDNSHosts", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Do Not Add Non-Proxy Protocol Outbound 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbAddProxyProtocolOutboundOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("TbAddProxyProtocolOutboundOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Address 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2238,6 +2292,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Apply to Proxy Domains Only 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbApplyProxyDomainsOnly {
|
||||
get {
|
||||
return ResourceManager.GetString("TbApplyProxyDomainsOnly", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Auto refresh 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2265,6 +2328,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Block SVCB and HTTPS Queries 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbBlockSVCBHTTPSQueries {
|
||||
get {
|
||||
return ResourceManager.GetString("TbBlockSVCBHTTPSQueries", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Prevent domain-based routing rules from failing 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbBlockSVCBHTTPSQueriesTips {
|
||||
get {
|
||||
return ResourceManager.GetString("TbBlockSVCBHTTPSQueriesTips", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Browse 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2319,6 +2400,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable Custom DNS 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbCustomDNSEnable {
|
||||
get {
|
||||
return ResourceManager.GetString("TbCustomDNSEnable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Custom DNS Enabled, This Page's Settings Invalid 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbCustomDNSEnabledPageInvalid {
|
||||
get {
|
||||
return ResourceManager.GetString("TbCustomDNSEnabledPageInvalid", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Display GUI 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2337,6 +2436,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 DNS Hosts: ("domain1 ip1 ip2" per line) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbDNSHostsConfig {
|
||||
get {
|
||||
return ResourceManager.GetString("TbDNSHostsConfig", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2382,6 +2490,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Domestic DNS 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbDomesticDNS {
|
||||
get {
|
||||
return ResourceManager.GetString("TbDomesticDNS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Edit 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2400,6 +2517,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 FakeIP 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbFakeIP {
|
||||
get {
|
||||
return ResourceManager.GetString("TbFakeIP", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Fingerprint 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2418,6 +2544,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbFullConfigTemplateDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbFullConfigTemplateDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Enable Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbFullConfigTemplateEnable {
|
||||
get {
|
||||
return ResourceManager.GetString("TbFullConfigTemplateEnable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Global Hotkey Settings 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2508,6 +2652,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Mldsa65Verify 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbMldsa65Verify {
|
||||
get {
|
||||
return ResourceManager.GetString("TbMldsa65Verify", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Transport protocol(network) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2616,6 +2769,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 v2ray Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRayFullConfigTemplate {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRayFullConfigTemplate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRayFullConfigTemplateDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRayFullConfigTemplateDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Alias (remarks) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2625,6 +2796,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Remote DNS 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbRemoteDNS {
|
||||
get {
|
||||
return ResourceManager.GetString("TbRemoteDNS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Camouflage domain(host) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -2733,6 +2913,87 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box Direct Resolution Strategy 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBDirectResolveStrategy {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBDirectResolveStrategy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The sing-box DoH resolution server can be overwritten 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBDoHOverride {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBDoHOverride", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box DoH Resolver Server 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBDoHResolverServer {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBDoHResolverServer", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Fallback DNS Resolution, Suggest IP 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBFallbackDNSResolve {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBFallbackDNSResolve", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box Full Config Template 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBFullConfigTemplate {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBFullConfigTemplate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Add Outbound and Endpoint Config Only, Click to view the document 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBFullConfigTemplateDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBFullConfigTemplateDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Resolve Outbound Domains 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBOutboundDomainResolve {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBOutboundDomainResolve", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Outbound DNS Resolution (sing-box) 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBOutboundsResolverDNS {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBOutboundsResolverDNS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 sing-box Remote Resolution Strategy 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSBRemoteResolveStrategy {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSBRemoteResolveStrategy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Encryption method (security) 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3058,7 +3319,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Use Xray and enable non-Tun mode, which conflicts with the group previous proxy 的本地化字符串。
|
||||
/// 查找类似 which conflicts with the group previous proxy 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsEnableFragmentTips {
|
||||
get {
|
||||
@@ -3193,7 +3454,7 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart. 的本地化字符串。
|
||||
/// 查找类似 The password will be validated via the command line. If a validation error causes the application to malfunction, please restart the application. The password will not be stored and must be entered again after each restart. 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSettingsLinuxSudoPasswordTip {
|
||||
get {
|
||||
@@ -3516,6 +3777,15 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Set Upstream Proxy Tag 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbSetUpstreamProxyDetour {
|
||||
get {
|
||||
return ResourceManager.GetString("TbSetUpstreamProxyDetour", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Short Id 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3678,6 +3948,33 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Validate Regional Domain IPs 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbValidateDirectExpectedIPs {
|
||||
get {
|
||||
return ResourceManager.GetString("TbValidateDirectExpectedIPs", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbValidateDirectExpectedIPsDesc {
|
||||
get {
|
||||
return ResourceManager.GetString("TbValidateDirectExpectedIPsDesc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 xray Freedom Resolution Strategy 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string TbXrayFreedomResolveStrategy {
|
||||
get {
|
||||
return ResourceManager.GetString("TbXrayFreedomResolveStrategy", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 The delay: {0} ms, {1} 的本地化字符串。
|
||||
/// </summary>
|
||||
@@ -3687,6 +3984,24 @@ namespace ServiceLib.Resx {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Advanced DNS Settings 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string ThAdvancedDNSSettings {
|
||||
get {
|
||||
return ResourceManager.GetString("ThAdvancedDNSSettings", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Basic DNS Settings 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string ThBasicDNSSettings {
|
||||
get {
|
||||
return ResourceManager.GetString("ThBasicDNSSettings", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 Active 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
@@ -1105,7 +1105,7 @@
|
||||
<value>افزودن سرور [HTTP]</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>از Xray استفاده کنید و حالت non-Tun را فعال کنید، که با پراکسی قبلی گروه در تضاد است</value>
|
||||
<value>which conflicts with the group previous proxy</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>فعال کردن فرگمنت</value>
|
||||
@@ -1318,7 +1318,7 @@
|
||||
<value>رمز عبور sudo سیستم</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>رمز عبوری که وارد کرده اید تایید نمی شود، بنابراین مطمئن شوید که آن را به درستی وارد کرده اید. اگر برنامه به دلیل ورودی نادرست به درستی کار نمی کند، لطفاً برنامه را مجدداً راه اندازی کنید. رمز عبور ذخیره نمی شود و پس از هر بار راه اندازی مجدد باید آن را دوباره وارد کنید.</value>
|
||||
<value>The password will be validated via the command line. If a validation error causes the application to malfunction, please restart the application. The password will not be stored and must be entered again after each restart.</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*حالت xhttp</value>
|
||||
@@ -1395,4 +1395,109 @@
|
||||
<data name="TbRuleOutboundTagTip" xml:space="preserve">
|
||||
<value>Can fill in the configuration remarks, please make sure it exist and are unique</value>
|
||||
</data>
|
||||
<data name="SudoIncorrectPasswordTip" xml:space="preserve">
|
||||
<value>Incorrect password, please try again.</value>
|
||||
</data>
|
||||
<data name="TbMldsa65Verify" xml:space="preserve">
|
||||
<value>Mldsa65Verify</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Add [Anytls] Configuration</value>
|
||||
</data>
|
||||
<data name="TbRemoteDNS" xml:space="preserve">
|
||||
<value>Remote DNS</value>
|
||||
</data>
|
||||
<data name="TbDomesticDNS" xml:space="preserve">
|
||||
<value>Domestic DNS</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
|
||||
<value>Outbound DNS Resolution (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
|
||||
<value>Resolve Outbound Domains</value>
|
||||
</data>
|
||||
<data name="TbSBDoHResolverServer" xml:space="preserve">
|
||||
<value>sing-box DoH Resolver Server</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Fallback DNS Resolution, Suggest IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box Direct Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box Remote Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
|
||||
<value>Block SVCB and HTTPS Queries</value>
|
||||
</data>
|
||||
<data name="TbDNSHostsConfig" xml:space="preserve">
|
||||
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
|
||||
</data>
|
||||
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
|
||||
<value>Apply to Proxy Domains Only</value>
|
||||
</data>
|
||||
<data name="ThBasicDNSSettings" xml:space="preserve">
|
||||
<value>Basic DNS Settings</value>
|
||||
</data>
|
||||
<data name="ThAdvancedDNSSettings" xml:space="preserve">
|
||||
<value>Advanced DNS Settings</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPs" xml:space="preserve">
|
||||
<value>Validate Regional Domain IPs</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve">
|
||||
<value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnable" xml:space="preserve">
|
||||
<value>Enable Custom DNS</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueriesTips" xml:space="preserve">
|
||||
<value>Prevent domain-based routing rules from failing</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1105,7 +1105,7 @@
|
||||
<value>Add [HTTP] Configuration</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>Use Xray and enable non-Tun mode, which conflicts with the group previous proxy</value>
|
||||
<value>which conflicts with the group previous proxy</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>Enable fragment</value>
|
||||
@@ -1318,7 +1318,7 @@
|
||||
<value>System sudo password</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>The password you entered cannot be verified, so make sure you enter it correctly. If the application does not work properly due to an incorrect input, please restart the application. The password will not be stored and you will need to enter it again after each restart.</value>
|
||||
<value>The password will be validated via the command line. If a validation error causes the application to malfunction, please restart the application. The password will not be stored and must be entered again after each restart.</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp mode</value>
|
||||
@@ -1395,4 +1395,109 @@
|
||||
<data name="TbRuleOutboundTagTip" xml:space="preserve">
|
||||
<value>Can fill in the configuration remarks, please make sure it exist and are unique</value>
|
||||
</data>
|
||||
<data name="SudoIncorrectPasswordTip" xml:space="preserve">
|
||||
<value>Incorrect password, please try again.</value>
|
||||
</data>
|
||||
<data name="TbMldsa65Verify" xml:space="preserve">
|
||||
<value>Mldsa65Verify</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Add [Anytls] Configuration</value>
|
||||
</data>
|
||||
<data name="TbRemoteDNS" xml:space="preserve">
|
||||
<value>Remote DNS</value>
|
||||
</data>
|
||||
<data name="TbDomesticDNS" xml:space="preserve">
|
||||
<value>Domestic DNS</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
|
||||
<value>Outbound DNS Resolution (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
|
||||
<value>Resolve Outbound Domains</value>
|
||||
</data>
|
||||
<data name="TbSBDoHResolverServer" xml:space="preserve">
|
||||
<value>sing-box DoH Resolver Server</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Fallback DNS Resolution, Suggest IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box Direct Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box Remote Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
|
||||
<value>Block SVCB and HTTPS Queries</value>
|
||||
</data>
|
||||
<data name="TbDNSHostsConfig" xml:space="preserve">
|
||||
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
|
||||
</data>
|
||||
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
|
||||
<value>Apply to Proxy Domains Only</value>
|
||||
</data>
|
||||
<data name="ThBasicDNSSettings" xml:space="preserve">
|
||||
<value>Basic DNS Settings</value>
|
||||
</data>
|
||||
<data name="ThAdvancedDNSSettings" xml:space="preserve">
|
||||
<value>Advanced DNS Settings</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPs" xml:space="preserve">
|
||||
<value>Validate Regional Domain IPs</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve">
|
||||
<value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnable" xml:space="preserve">
|
||||
<value>Enable Custom DNS</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueriesTips" xml:space="preserve">
|
||||
<value>Prevent domain-based routing rules from failing</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -807,9 +807,6 @@
|
||||
<data name="menuMoveUp" xml:space="preserve">
|
||||
<value>Вверх (U)</value>
|
||||
</data>
|
||||
<data name="menuMoveTo" xml:space="preserve">
|
||||
<value>Переместить вверх/вниз</value>
|
||||
</data>
|
||||
<data name="MsgFilterTitle" xml:space="preserve">
|
||||
<value>Фильтр, поддерживает regex</value>
|
||||
</data>
|
||||
@@ -969,6 +966,9 @@
|
||||
<data name="TbSettingsSpeedTestUrl" xml:space="preserve">
|
||||
<value>URL для тестирования скорости</value>
|
||||
</data>
|
||||
<data name="menuMoveTo" xml:space="preserve">
|
||||
<value>Переместить вверх/вниз</value>
|
||||
</data>
|
||||
<data name="TbPublicKey" xml:space="preserve">
|
||||
<value>PublicKey</value>
|
||||
</data>
|
||||
@@ -1099,13 +1099,13 @@
|
||||
<value>Отмена тестирования...</value>
|
||||
</data>
|
||||
<data name="TransportRequestHostTip5" xml:space="preserve">
|
||||
<value>*gRPC Authority</value>
|
||||
<value>* gRPC Authority (HTTP/2 псевдозаголовок :authority)</value>
|
||||
</data>
|
||||
<data name="menuAddHttpServer" xml:space="preserve">
|
||||
<value>Добавить сервер [HTTP]</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>Используйте Xray и отключите режим TUN, так как он конфликтует с предыдущим прокси-сервером группы</value>
|
||||
<value>что конфликтует с предыдущим прокси группы</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>Включить фрагментацию (Fragment)</value>
|
||||
@@ -1318,13 +1318,13 @@
|
||||
<value>Пароль sudo системы</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>Введенный вами пароль не может быть подтвержден, поэтому убедитесь, что вы ввели его правильно. Если приложение не работает должным образом из-за неправильного ввода, то перезапустите его. Пароль не будет сохранен, и вам придется вводить его заново после каждого перезапуска</value>
|
||||
<value>Пароль sudo будет проверен в терминале. Если из-за ошибки проверки приложение начнёт работать некорректно, перезапустите его. Пароль не сохраняется — его нужно вводить после каждого перезапуска.</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*XHTTP-режим</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>Дополнительный XHTTP сырой JSON, формат: { XHTTPObject }</value>
|
||||
<value>Дополнительный „сырой“ JSON для XHTTP, формат: { XHTTP Object }</value>
|
||||
</data>
|
||||
<data name="TbSettingsHide2TrayWhenClose" xml:space="preserve">
|
||||
<value>Скрыть в трее при закрытии окна</value>
|
||||
@@ -1393,6 +1393,111 @@
|
||||
<value>URL для тестирования текущего соединения</value>
|
||||
</data>
|
||||
<data name="TbRuleOutboundTagTip" xml:space="preserve">
|
||||
<value>Can fill in the configuration remarks, please make sure it exist and are unique</value>
|
||||
<value>Можно указать название (Remarks) из конфигурации, убедитесь, что оно существует и уникально</value>
|
||||
</data>
|
||||
</root>
|
||||
<data name="SudoIncorrectPasswordTip" xml:space="preserve">
|
||||
<value>Неверный пароль, попробуйте ещё раз.</value>
|
||||
</data>
|
||||
<data name="TbMldsa65Verify" xml:space="preserve">
|
||||
<value>Mldsa65Verify</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>Добавить сервер [Anytls]</value>
|
||||
</data>
|
||||
<data name="TbRemoteDNS" xml:space="preserve">
|
||||
<value>Удалённый DNS</value>
|
||||
</data>
|
||||
<data name="TbDomesticDNS" xml:space="preserve">
|
||||
<value>Внутренний DNS</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
|
||||
<value>Резолвер DNS для исходящих (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
|
||||
<value>Разрешать домены для исходящих соединений</value>
|
||||
</data>
|
||||
<data name="TbSBDoHResolverServer" xml:space="preserve">
|
||||
<value>Сервер DoH-резолвера (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Резервное DNS-разрешение (рекомендуется указывать IP)</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>Стратегия резолвинга Freedom (Xray)</value>
|
||||
</data>
|
||||
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
|
||||
<value>Стратегия прямого резолвинга (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
|
||||
<value>Стратегия удалённого резолвинга (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Добавить стандартные записи hosts (DNS)</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>Сервер DoH-резолвера sing-box можно переопределить</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
|
||||
<value>Блокировать DNS-запросы SVCB и HTTPS</value>
|
||||
</data>
|
||||
<data name="TbDNSHostsConfig" xml:space="preserve">
|
||||
<value>DNS hosts: (каждая строка в формате "domain1 ip1 ip2")</value>
|
||||
</data>
|
||||
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
|
||||
<value>Применять только к доменам через прокси</value>
|
||||
</data>
|
||||
<data name="ThBasicDNSSettings" xml:space="preserve">
|
||||
<value>Базовые настройки DNS</value>
|
||||
</data>
|
||||
<data name="ThAdvancedDNSSettings" xml:space="preserve">
|
||||
<value>Расширенные настройки DNS</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPs" xml:space="preserve">
|
||||
<value>Проверять IP-адреса региональных доменов</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve">
|
||||
<value>При включении проверяет IP-адреса, возвращаемые для региональных доменов (например, geosite:cn), и оставляет только ожидаемые IP-адреса</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnable" xml:space="preserve">
|
||||
<value>Включить пользовательский DNS</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Включён пользовательский DNS — настройки на этой странице не применяются</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueriesTips" xml:space="preserve">
|
||||
<value>Предотвращает сбои доменных правил маршрутизации</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Пожалуйста, заполните корректный шаблон конфигурации</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Настройка полного шаблона конфигурации</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Включить полный шаблон конфигурации</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>Полный шаблон конфигурации v2ray</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Добавляет только конфигурацию исходящих (outbound), а также routing.balancers и routing.rules.outboundTag. Нажмите, чтобы открыть документ</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Не добавлять исходящие для непрокси-протоколов</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Задать тег верхнего прокси (upstream)</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>Полный шаблон конфигурации sing-box</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Добавляет только конфигурацию Outbound и Endpoint. Нажмите, чтобы открыть документ</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Эта функция предназначена для продвинутых пользователей и особых случаев. После включения игнорируются базовые настройки ядра, DNS и маршрутизации. Вы должны самостоятельно корректно задать порт системного прокси, учёт трафика и другие связанные параметры — всё настраивается вручную.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -703,7 +703,7 @@
|
||||
<value>例外:对于下列字符开头的地址,不使用代理配置文件。使用分号 (;) 分隔。</value>
|
||||
</data>
|
||||
<data name="TbSettingsDisplayRealTimeSpeed" xml:space="preserve">
|
||||
<value>显示实时速度(需重启)</value>
|
||||
<value>显示实时速度 (需重启)</value>
|
||||
</data>
|
||||
<data name="TbSettingsKeepOlderDedupl" xml:space="preserve">
|
||||
<value>去重时保留序号较小的项</value>
|
||||
@@ -739,7 +739,7 @@
|
||||
<value>开机启动 (可能会不成功)</value>
|
||||
</data>
|
||||
<data name="TbSettingsStatistics" xml:space="preserve">
|
||||
<value>启用流量统计(需重启)</value>
|
||||
<value>启用流量统计 (需重启)</value>
|
||||
</data>
|
||||
<data name="TbSettingsSubConvert" xml:space="preserve">
|
||||
<value>订阅转换网址 (可选)</value>
|
||||
@@ -886,7 +886,7 @@
|
||||
<value>仅限路由 (routeOnly)</value>
|
||||
</data>
|
||||
<data name="TbSettingsNotProxyLocalAddress" xml:space="preserve">
|
||||
<value>请勿将代理服务器用于本地(Intranet)地址</value>
|
||||
<value>请勿将代理服务器用于本地 (Intranet) 地址</value>
|
||||
</data>
|
||||
<data name="menuMixedTestServer" xml:space="preserve">
|
||||
<value>一键多线程测试延迟和速度 (Ctrl+E)</value>
|
||||
@@ -919,7 +919,7 @@
|
||||
<value>移至订阅分组</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableDragDropSort" xml:space="preserve">
|
||||
<value>启用配置文件拖放排序(需重启)</value>
|
||||
<value>启用配置文件拖放排序 (需重启)</value>
|
||||
</data>
|
||||
<data name="TbAutoRefresh" xml:space="preserve">
|
||||
<value>自动刷新</value>
|
||||
@@ -946,10 +946,10 @@
|
||||
<value>仅对 tcp/http、ws 协议生效</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamily" xml:space="preserve">
|
||||
<value>当前字体(需重启)</value>
|
||||
<value>当前字体 (需重启)</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyTip" xml:space="preserve">
|
||||
<value>拷贝字体 TTF/TTC 文件到目录 guiFonts,重启设置</value>
|
||||
<value>拷贝字体 TTF/TTC 文件到目录 guiFonts,重启生效</value>
|
||||
</data>
|
||||
<data name="TbSettingsSocksPortTip" xml:space="preserve">
|
||||
<value>Pac 端口 = +3;Xray API 端口 = +4;mihomo API 端口 = +5;</value>
|
||||
@@ -979,10 +979,10 @@
|
||||
<value>SpiderX</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableHWA" xml:space="preserve">
|
||||
<value>启用硬件加速(需重启)</value>
|
||||
<value>启用硬件加速 (需重启)</value>
|
||||
</data>
|
||||
<data name="SpeedtestingWait" xml:space="preserve">
|
||||
<value>等待测试中(按 ESC 终止)...</value>
|
||||
<value>等待测试中 (按 ESC 终止)...</value>
|
||||
</data>
|
||||
<data name="TipDisplayLog" xml:space="preserve">
|
||||
<value>当有异常断流时请关闭</value>
|
||||
@@ -1075,7 +1075,7 @@
|
||||
<value>Reserved (2,3,4)</value>
|
||||
</data>
|
||||
<data name="TbLocalAddress" xml:space="preserve">
|
||||
<value>Address (Ipv4,Ipv6)</value>
|
||||
<value>Address (IPv4,IPv6)</value>
|
||||
</data>
|
||||
<data name="TbPath7" xml:space="preserve">
|
||||
<value>混淆密码 (obfs password)</value>
|
||||
@@ -1102,13 +1102,13 @@
|
||||
<value>添加 [HTTP] 配置文件</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>使用 Xray 且非 Tun 模式启用,和分组前置代理冲突</value>
|
||||
<value>和分组前置代理冲突</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>启用分片(Fragment)</value>
|
||||
<value>启用分片 (Fragment)</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableCacheFile4Sbox" xml:space="preserve">
|
||||
<value>启用 sing-box(规则集文件)的缓存文件</value>
|
||||
<value>启用 sing-box (规则集文件) 的缓存文件</value>
|
||||
</data>
|
||||
<data name="LvCustomRulesetPath4Singbox" xml:space="preserve">
|
||||
<value>自定义 sing-box rule-set</value>
|
||||
@@ -1201,7 +1201,7 @@
|
||||
<value>Outbound 默认解析策略</value>
|
||||
</data>
|
||||
<data name="TbSettingsMainGirdOrientation" xml:space="preserve">
|
||||
<value>主界面布局方向(需重启)</value>
|
||||
<value>主界面布局方向 (需重启)</value>
|
||||
</data>
|
||||
<data name="TbSettingsDomainDNSAddress" xml:space="preserve">
|
||||
<value>Outbound 域名解析地址</value>
|
||||
@@ -1303,7 +1303,7 @@
|
||||
<value>请不要使用不安全的 HTTP 协议订阅地址</value>
|
||||
</data>
|
||||
<data name="TbSettingsCurrentFontFamilyLinuxTip" xml:space="preserve">
|
||||
<value>安装字体到系统中,选择或填入字体名称,重启设置</value>
|
||||
<value>安装字体到系统中,选择或填入字体名称,重启生效</value>
|
||||
</data>
|
||||
<data name="menuExitTips" xml:space="preserve">
|
||||
<value>是否确定退出?</value>
|
||||
@@ -1315,10 +1315,10 @@
|
||||
<value>系统的 sudo 密码</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>输入的密码无法校验,所以请确保输入正确。如果因为输入错误导致无法正常运行时,请重启本应用。 密码不会存储,每次重启后都需要再次输入。</value>
|
||||
<value>密码将调用命令行校验,如果因为校验错误导致无法正常运行时,请重启本应用。 密码不会存储,每次重启后都需要再次输入。</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp 模式</value>
|
||||
<value>*XHTTP 模式</value>
|
||||
</data>
|
||||
<data name="TransportExtraTip" xml:space="preserve">
|
||||
<value>XHTTP Extra 原始 JSON,格式: { XHTTPObject }</value>
|
||||
@@ -1339,7 +1339,7 @@
|
||||
<value>开启第二个本地监听端口</value>
|
||||
</data>
|
||||
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||
<value>socks:本地端口,socks2:第二个本地端口,socks3:局域网端口</value>
|
||||
<value>Socks:本地端口,Socks2:第二个本地端口,Socks3:局域网端口</value>
|
||||
</data>
|
||||
<data name="TbSettingsTheme" xml:space="preserve">
|
||||
<value>主题</value>
|
||||
@@ -1372,13 +1372,13 @@
|
||||
<value>多配置文件随机 Xray</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServerXrayRoundRobin" xml:space="preserve">
|
||||
<value>多配置文件负载均衡 Xray</value>
|
||||
<value>多配置文件负载均衡 Xray</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServerXrayLeastPing" xml:space="preserve">
|
||||
<value>多配置文件最低延迟 Xray</value>
|
||||
<value>多配置文件最低延迟 Xray</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServerXrayLeastLoad" xml:space="preserve">
|
||||
<value>多配置文件最稳定 Xray</value>
|
||||
<value>多配置文件最稳定 Xray</value>
|
||||
</data>
|
||||
<data name="menuSetDefaultMultipleServerSingBoxLeastPing" xml:space="preserve">
|
||||
<value>多配置文件最低延迟 sing-box</value>
|
||||
@@ -1392,4 +1392,109 @@
|
||||
<data name="TbRuleOutboundTagTip" xml:space="preserve">
|
||||
<value>可以填写配置文件别名,请确保存在并唯一</value>
|
||||
</data>
|
||||
<data name="SudoIncorrectPasswordTip" xml:space="preserve">
|
||||
<value>密码错误,请重试。</value>
|
||||
</data>
|
||||
<data name="TbMldsa65Verify" xml:space="preserve">
|
||||
<value>Mldsa65Verify</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>添加 [Anytls] 配置文件</value>
|
||||
</data>
|
||||
<data name="TbRemoteDNS" xml:space="preserve">
|
||||
<value>远程 DNS</value>
|
||||
</data>
|
||||
<data name="TbDomesticDNS" xml:space="preserve">
|
||||
<value>直连 DNS</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
|
||||
<value>出站 DNS 解析(sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
|
||||
<value>解析出站域名</value>
|
||||
</data>
|
||||
<data name="TbSBDoHResolverServer" xml:space="preserve">
|
||||
<value>sing-box DoH 解析服务器</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>兜底解析其他 DNS 域名,建议设为 ip</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray freedom 解析策略</value>
|
||||
</data>
|
||||
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box 直连解析策略</value>
|
||||
</data>
|
||||
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box 远程解析策略</value>
|
||||
</data>
|
||||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>添加常用 DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>开启后可覆盖 sing-box DoH 解析服务器</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
|
||||
<value>阻止 SVCB 和 HTTPS 查询</value>
|
||||
</data>
|
||||
<data name="TbDNSHostsConfig" xml:space="preserve">
|
||||
<value>DNS Hosts:(“域名1 ip1 ip2” 一行一个)</value>
|
||||
</data>
|
||||
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
|
||||
<value>仅对代理域名生效</value>
|
||||
</data>
|
||||
<data name="ThBasicDNSSettings" xml:space="preserve">
|
||||
<value>DNS 基础设置</value>
|
||||
</data>
|
||||
<data name="ThAdvancedDNSSettings" xml:space="preserve">
|
||||
<value>DNS 进阶设置</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPs" xml:space="preserve">
|
||||
<value>校验相应地区域名 IP</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve">
|
||||
<value>配置后,会对相应地区域名(如 geosite:cn)的返回 IP 进行校验,仅返回期望 IP</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnable" xml:space="preserve">
|
||||
<value>启用自定义 DNS</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>自定义 DNS 已启用,此页面配置将无效</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueriesTips" xml:space="preserve">
|
||||
<value>避免域名分流规则失效</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>请填写正确的配置模板</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>完整配置模板设置</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>启用完整配置模板</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray 完整配置模板</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>仅添加出站配置,routing.balancers 和 routing.rules.outboundTag,点击查看文档</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>不添加非代理协议出站</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>设置上游代理 tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box 完整配置模板</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>仅添加出站和端点配置,点击查看文档</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>此功能供高级用户和有特殊需求的用户使用。 启用此功能后,将忽略 Core 的基础设置,DNS 设置 ,路由设置。你需要保证系统代理的端口和流量统计等功能的配置正确,一切都由你来设置。</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1102,7 +1102,7 @@
|
||||
<value>新增 [HTTP] 設定檔</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragmentTips" xml:space="preserve">
|
||||
<value>使用 Xray 且非 Tun 模式啟用,和分組前置代理衝突</value>
|
||||
<value>和分組前置代理衝突</value>
|
||||
</data>
|
||||
<data name="TbSettingsEnableFragment" xml:space="preserve">
|
||||
<value>啟用分片(Fragment)</value>
|
||||
@@ -1315,7 +1315,7 @@
|
||||
<value>系統的 sudo 密碼</value>
|
||||
</data>
|
||||
<data name="TbSettingsLinuxSudoPasswordTip" xml:space="preserve">
|
||||
<value>輸入的密碼無法校驗,所以請確保輸入正確。如果因為輸入錯誤導致無法正常運作時,請重新啟動本應用。 密碼不會儲存,每次重啟後都需要再次輸入。</value>
|
||||
<value>密碼將調用命令行校驗,如果因為校驗錯誤導致無法正常運行時,請重啟本應用。密碼不會存儲,每次重啟後都需要再次輸入。</value>
|
||||
</data>
|
||||
<data name="TransportHeaderTypeTip5" xml:space="preserve">
|
||||
<value>*xhttp 模式</value>
|
||||
@@ -1392,4 +1392,109 @@
|
||||
<data name="TbRuleOutboundTagTip" xml:space="preserve">
|
||||
<value>可以填寫設定檔別名,請確保存在並唯一</value>
|
||||
</data>
|
||||
<data name="SudoIncorrectPasswordTip" xml:space="preserve">
|
||||
<value>密碼錯誤,請重試。</value>
|
||||
</data>
|
||||
<data name="TbMldsa65Verify" xml:space="preserve">
|
||||
<value>Mldsa65Verify</value>
|
||||
</data>
|
||||
<data name="menuAddAnytlsServer" xml:space="preserve">
|
||||
<value>新增 [Anytls] 設定檔</value>
|
||||
</data>
|
||||
<data name="TbRemoteDNS" xml:space="preserve">
|
||||
<value>Remote DNS</value>
|
||||
</data>
|
||||
<data name="TbDomesticDNS" xml:space="preserve">
|
||||
<value>Domestic DNS</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundsResolverDNS" xml:space="preserve">
|
||||
<value>Outbound DNS Resolution (sing-box)</value>
|
||||
</data>
|
||||
<data name="TbSBOutboundDomainResolve" xml:space="preserve">
|
||||
<value>Resolve Outbound Domains</value>
|
||||
</data>
|
||||
<data name="TbSBDoHResolverServer" xml:space="preserve">
|
||||
<value>sing-box DoH Resolver Server</value>
|
||||
</data>
|
||||
<data name="TbSBFallbackDNSResolve" xml:space="preserve">
|
||||
<value>Fallback DNS Resolution, Suggest IP</value>
|
||||
</data>
|
||||
<data name="TbXrayFreedomResolveStrategy" xml:space="preserve">
|
||||
<value>xray Freedom Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbSBDirectResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box Direct Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbSBRemoteResolveStrategy" xml:space="preserve">
|
||||
<value>sing-box Remote Resolution Strategy</value>
|
||||
</data>
|
||||
<data name="TbAddCommonDNSHosts" xml:space="preserve">
|
||||
<value>Add Common DNS Hosts</value>
|
||||
</data>
|
||||
<data name="TbSBDoHOverride" xml:space="preserve">
|
||||
<value>The sing-box DoH resolution server can be overwritten</value>
|
||||
</data>
|
||||
<data name="TbFakeIP" xml:space="preserve">
|
||||
<value>FakeIP</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueries" xml:space="preserve">
|
||||
<value>Block SVCB and HTTPS Queries</value>
|
||||
</data>
|
||||
<data name="TbDNSHostsConfig" xml:space="preserve">
|
||||
<value>DNS Hosts: ("domain1 ip1 ip2" per line)</value>
|
||||
</data>
|
||||
<data name="TbApplyProxyDomainsOnly" xml:space="preserve">
|
||||
<value>Apply to Proxy Domains Only</value>
|
||||
</data>
|
||||
<data name="ThBasicDNSSettings" xml:space="preserve">
|
||||
<value>Basic DNS Settings</value>
|
||||
</data>
|
||||
<data name="ThAdvancedDNSSettings" xml:space="preserve">
|
||||
<value>Advanced DNS Settings</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPs" xml:space="preserve">
|
||||
<value>Validate Regional Domain IPs</value>
|
||||
</data>
|
||||
<data name="TbValidateDirectExpectedIPsDesc" xml:space="preserve">
|
||||
<value>When configured, validates IPs returned for regional domains (e.g., geosite:cn), returning only expected IPs</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnable" xml:space="preserve">
|
||||
<value>Enable Custom DNS</value>
|
||||
</data>
|
||||
<data name="TbCustomDNSEnabledPageInvalid" xml:space="preserve">
|
||||
<value>Custom DNS Enabled, This Page's Settings Invalid</value>
|
||||
</data>
|
||||
<data name="TbBlockSVCBHTTPSQueriesTips" xml:space="preserve">
|
||||
<value>Prevent domain-based routing rules from failing</value>
|
||||
</data>
|
||||
<data name="FillCorrectConfigTemplateText" xml:space="preserve">
|
||||
<value>Please fill in the correct config template</value>
|
||||
</data>
|
||||
<data name="menuFullConfigTemplate" xml:space="preserve">
|
||||
<value>Full Config Template Setting</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateEnable" xml:space="preserve">
|
||||
<value>Enable Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplate" xml:space="preserve">
|
||||
<value>v2ray Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbRayFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve">
|
||||
<value>Do Not Add Non-Proxy Protocol Outbound</value>
|
||||
</data>
|
||||
<data name="TbSetUpstreamProxyDetour" xml:space="preserve">
|
||||
<value>Set Upstream Proxy Tag</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplate" xml:space="preserve">
|
||||
<value>sing-box Full Config Template</value>
|
||||
</data>
|
||||
<data name="TbSBFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>Add Outbound and Endpoint Config Only, Click to view the document</value>
|
||||
</data>
|
||||
<data name="TbFullConfigTemplateDesc" xml:space="preserve">
|
||||
<value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,4 +1,4 @@
|
||||
{
|
||||
{
|
||||
"log": {
|
||||
"level": "debug",
|
||||
"timestamp": true
|
||||
@@ -14,22 +14,10 @@
|
||||
{
|
||||
"type": "direct",
|
||||
"tag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "block",
|
||||
"tag": "block"
|
||||
},
|
||||
{
|
||||
"tag": "dns_out",
|
||||
"type": "dns"
|
||||
}
|
||||
],
|
||||
"route": {
|
||||
"rules": [
|
||||
{
|
||||
"protocol": [ "dns" ],
|
||||
"outbound": "dns_out"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -2,28 +2,33 @@
|
||||
"servers": [
|
||||
{
|
||||
"tag": "remote",
|
||||
"address": "tcp://8.8.8.8",
|
||||
"strategy": "prefer_ipv4",
|
||||
"type": "tcp",
|
||||
"server": "8.8.8.8",
|
||||
"detour": "proxy"
|
||||
},
|
||||
{
|
||||
"tag": "local",
|
||||
"address": "223.5.5.5",
|
||||
"strategy": "prefer_ipv4",
|
||||
"detour": "direct"
|
||||
},
|
||||
{
|
||||
"tag": "block",
|
||||
"address": "rcode://success"
|
||||
"type": "udp",
|
||||
"server": "223.5.5.5"
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"domain_suffix": [
|
||||
"googleapis.cn",
|
||||
"gstatic.com"
|
||||
],
|
||||
"server": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
},
|
||||
{
|
||||
"rule_set": [
|
||||
"geosite-cn"
|
||||
],
|
||||
"server": "local"
|
||||
"server": "local",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
],
|
||||
"final": "remote"
|
||||
"final": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
|
||||
61
v2rayN/ServiceLib/Sample/kill_as_sudo_linux_sh
Normal file
61
v2rayN/ServiceLib/Sample/kill_as_sudo_linux_sh
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Process Terminator Script for Linux
|
||||
# This script forcibly terminates a process and all its child processes
|
||||
#
|
||||
|
||||
# Check if PID argument is provided
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <PID>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PID=$1
|
||||
|
||||
# Validate that input is a valid PID (numeric)
|
||||
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
|
||||
echo "Error: The PID must be a numeric value"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the process exists
|
||||
if ! ps -p $PID > /dev/null; then
|
||||
echo "Warning: No process found with PID $PID"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Recursive function to find and kill all child processes
|
||||
kill_children() {
|
||||
local parent=$1
|
||||
local children=$(ps -o pid --no-headers --ppid "$parent")
|
||||
|
||||
# Output information about processes being terminated
|
||||
echo "Processing children of PID: $parent..."
|
||||
|
||||
# Process each child
|
||||
for child in $children; do
|
||||
# Recursively find and kill child's children first
|
||||
kill_children "$child"
|
||||
|
||||
# Force kill the child process
|
||||
echo "Terminating child process: $child"
|
||||
kill -9 "$child" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
echo "============================================"
|
||||
echo "Starting termination of process $PID and all its children"
|
||||
echo "============================================"
|
||||
|
||||
# Find and kill all child processes
|
||||
kill_children "$PID"
|
||||
|
||||
# Finally kill the main process
|
||||
echo "Terminating main process: $PID"
|
||||
kill -9 "$PID" 2>/dev/null || true
|
||||
|
||||
echo "============================================"
|
||||
echo "Process $PID and all its children have been terminated"
|
||||
echo "============================================"
|
||||
|
||||
exit 0
|
||||
56
v2rayN/ServiceLib/Sample/kill_as_sudo_osx_sh
Normal file
56
v2rayN/ServiceLib/Sample/kill_as_sudo_osx_sh
Normal file
@@ -0,0 +1,56 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Process Terminator Script for macOS
|
||||
# This script forcibly terminates a process and all its descendant processes
|
||||
#
|
||||
|
||||
# Check if PID argument is provided
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: $0 <PID>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PID=$1
|
||||
|
||||
# Validate that input is a valid PID (numeric)
|
||||
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
|
||||
echo "Error: The PID must be a numeric value"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the process exists - using kill -0 which is more reliable on macOS
|
||||
if ! kill -0 $PID 2>/dev/null; then
|
||||
echo "Warning: No process found with PID $PID"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Recursive function to find and kill all descendant processes
|
||||
kill_descendants() {
|
||||
local parent=$1
|
||||
# Use ps -axo for macOS to ensure all processes are included
|
||||
local children=$(ps -axo pid=,ppid= | awk -v ppid=$parent '$2==ppid {print $1}')
|
||||
|
||||
echo "Processing children of PID: $parent..."
|
||||
for child in $children; do
|
||||
kill_descendants "$child"
|
||||
echo "Terminating child process: $child"
|
||||
kill -9 "$child" 2>/dev/null || true
|
||||
done
|
||||
}
|
||||
|
||||
echo "============================================"
|
||||
echo "Starting termination of process $PID and all its descendants"
|
||||
echo "============================================"
|
||||
|
||||
# Find and kill all descendant processes
|
||||
kill_descendants "$PID"
|
||||
|
||||
# Finally kill the main process
|
||||
echo "Terminating main process: $PID"
|
||||
kill -9 "$PID" 2>/dev/null || true
|
||||
|
||||
echo "============================================"
|
||||
echo "Process $PID and all its descendants have been terminated"
|
||||
echo "============================================"
|
||||
|
||||
exit 0
|
||||
@@ -2,29 +2,33 @@
|
||||
"servers": [
|
||||
{
|
||||
"tag": "remote",
|
||||
"address": "tcp://8.8.8.8",
|
||||
"strategy": "prefer_ipv4",
|
||||
"type": "tcp",
|
||||
"server": "8.8.8.8",
|
||||
"detour": "proxy"
|
||||
},
|
||||
{
|
||||
"tag": "local",
|
||||
"address": "223.5.5.5",
|
||||
"strategy": "prefer_ipv4",
|
||||
"detour": "direct"
|
||||
},
|
||||
{
|
||||
"tag": "block",
|
||||
"address": "rcode://success"
|
||||
"type": "udp",
|
||||
"server": "223.5.5.5"
|
||||
}
|
||||
],
|
||||
"rules": [
|
||||
{
|
||||
"rule_set": [
|
||||
"geosite-cn",
|
||||
"geosite-geolocation-cn"
|
||||
"domain_suffix": [
|
||||
"googleapis.cn",
|
||||
"gstatic.com"
|
||||
],
|
||||
"server": "local"
|
||||
"server": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
},
|
||||
{
|
||||
"rule_set": [
|
||||
"geosite-cn"
|
||||
],
|
||||
"server": "local",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
],
|
||||
"final": "remote"
|
||||
}
|
||||
"final": "remote",
|
||||
"strategy": "prefer_ipv4"
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
139,
|
||||
5353
|
||||
],
|
||||
"outbound": "block"
|
||||
"action": "reject"
|
||||
},
|
||||
{
|
||||
"ip_cidr": [
|
||||
"224.0.0.0/3",
|
||||
"ff00::/8"
|
||||
],
|
||||
"outbound": "block"
|
||||
"action": "reject"
|
||||
}
|
||||
]
|
||||
@@ -28,6 +28,8 @@
|
||||
<EmbeddedResource Include="Sample\custom_routing_white" />
|
||||
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
||||
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
||||
<EmbeddedResource Include="Sample\kill_as_sudo_linux_sh" />
|
||||
<EmbeddedResource Include="Sample\kill_as_sudo_osx_sh" />
|
||||
<EmbeddedResource Include="Sample\pac" />
|
||||
<EmbeddedResource Include="Sample\proxy_set_linux_sh" />
|
||||
<EmbeddedResource Include="Sample\proxy_set_osx_sh" />
|
||||
|
||||
@@ -12,7 +12,7 @@ public class CoreConfigClashService
|
||||
{
|
||||
_config = config;
|
||||
}
|
||||
|
||||
|
||||
public async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName)
|
||||
{
|
||||
var ret = new RetResult();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,8 @@
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ServiceLib.Services.CoreConfig;
|
||||
|
||||
@@ -66,7 +68,7 @@ public class CoreConfigV2rayService
|
||||
|
||||
ret.Msg = string.Format(ResUI.SuccessfulConfiguration, "");
|
||||
ret.Success = true;
|
||||
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||
ret.Data = await ApplyFullConfigTemplate(v2rayConfig);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -120,7 +122,7 @@ public class CoreConfigV2rayService
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (it.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC)
|
||||
if (it.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -175,7 +177,7 @@ public class CoreConfigV2rayService
|
||||
rule.balancerTag = balancer.tag;
|
||||
}
|
||||
}
|
||||
if (v2rayConfig.routing.domainStrategy == "IPIfNonMatch")
|
||||
if (v2rayConfig.routing.domainStrategy == Global.IPIfNonMatch)
|
||||
{
|
||||
v2rayConfig.routing.rules.Add(new()
|
||||
{
|
||||
@@ -195,7 +197,8 @@ public class CoreConfigV2rayService
|
||||
}
|
||||
|
||||
ret.Success = true;
|
||||
ret.Data = JsonUtils.Serialize(v2rayConfig);
|
||||
|
||||
ret.Data = await ApplyFullConfigTemplate(v2rayConfig, true);
|
||||
return ret;
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -631,7 +634,7 @@ public class CoreConfigV2rayService
|
||||
|
||||
private async Task<string?> GenRoutingUserRuleOutbound(string outboundTag, V2rayConfig v2rayConfig)
|
||||
{
|
||||
if (outboundTag is Global.ProxyTag or Global.ProxyTag or Global.BlockTag)
|
||||
if (Global.OutboundTags.Contains(outboundTag))
|
||||
{
|
||||
return outboundTag;
|
||||
}
|
||||
@@ -640,7 +643,8 @@ public class CoreConfigV2rayService
|
||||
if (node == null
|
||||
|| node.ConfigType == EConfigType.Custom
|
||||
|| node.ConfigType == EConfigType.Hysteria2
|
||||
|| node.ConfigType == EConfigType.TUIC)
|
||||
|| node.ConfigType == EConfigType.TUIC
|
||||
|| node.ConfigType == EConfigType.Anytls)
|
||||
{
|
||||
return Global.ProxyTag;
|
||||
}
|
||||
@@ -944,6 +948,7 @@ public class CoreConfigV2rayService
|
||||
publicKey = node.PublicKey,
|
||||
shortId = node.ShortId,
|
||||
spiderX = node.SpiderX,
|
||||
mldsa65Verify = node.Mldsa65Verify,
|
||||
show = false,
|
||||
};
|
||||
|
||||
@@ -1132,6 +1137,293 @@ public class CoreConfigV2rayService
|
||||
}
|
||||
|
||||
private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
|
||||
if (item != null && item.Enabled == true)
|
||||
{
|
||||
var result = await GenDnsCompatible(node, v2rayConfig);
|
||||
|
||||
if (v2rayConfig.routing.domainStrategy == Global.IPIfNonMatch)
|
||||
{
|
||||
// DNS routing
|
||||
v2rayConfig.dns.tag = Global.DnsTag;
|
||||
v2rayConfig.routing.rules.Add(new RulesItem4Ray
|
||||
{
|
||||
type = "field",
|
||||
inboundTag = new List<string> { Global.DnsTag },
|
||||
outboundTag = Global.ProxyTag,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
var simpleDNSItem = _config.SimpleDNSItem;
|
||||
var domainStrategy4Freedom = simpleDNSItem?.RayStrategy4Freedom;
|
||||
|
||||
//Outbound Freedom domainStrategy
|
||||
if (domainStrategy4Freedom.IsNotEmpty())
|
||||
{
|
||||
var outbound = v2rayConfig.outbounds.FirstOrDefault(t => t is { protocol: "freedom", tag: Global.DirectTag });
|
||||
if (outbound != null)
|
||||
{
|
||||
outbound.settings = new()
|
||||
{
|
||||
domainStrategy = domainStrategy4Freedom,
|
||||
userLevel = 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
await GenDnsServers(node, v2rayConfig, simpleDNSItem);
|
||||
await GenDnsHosts(v2rayConfig, simpleDNSItem);
|
||||
|
||||
if (v2rayConfig.routing.domainStrategy == Global.IPIfNonMatch)
|
||||
{
|
||||
// DNS routing
|
||||
v2rayConfig.dns.tag = Global.DnsTag;
|
||||
v2rayConfig.routing.rules.Add(new RulesItem4Ray
|
||||
{
|
||||
type = "field",
|
||||
inboundTag = new List<string> { Global.DnsTag },
|
||||
outboundTag = Global.ProxyTag,
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog(_tag, ex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private async Task<int> GenDnsServers(ProfileItem? node, V2rayConfig v2rayConfig, SimpleDNSItem simpleDNSItem)
|
||||
{
|
||||
static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress)
|
||||
{
|
||||
var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';')
|
||||
.Select(addr => addr.Trim())
|
||||
.Where(addr => !string.IsNullOrEmpty(addr))
|
||||
.Select(addr => addr.StartsWith("dhcp", StringComparison.OrdinalIgnoreCase) ? "localhost" : addr)
|
||||
.Distinct()
|
||||
.ToList() ?? new List<string> { defaultAddress };
|
||||
return addresses.Count > 0 ? addresses : new List<string> { defaultAddress };
|
||||
}
|
||||
|
||||
static object CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null)
|
||||
{
|
||||
var dnsServer = new DnsServer4Ray
|
||||
{
|
||||
address = dnsAddress,
|
||||
skipFallback = true,
|
||||
domains = domains.Count > 0 ? domains : null,
|
||||
expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null
|
||||
};
|
||||
return JsonUtils.SerializeToNode(dnsServer, new JsonSerializerOptions
|
||||
{
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
|
||||
});
|
||||
}
|
||||
|
||||
var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.FirstOrDefault());
|
||||
var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.FirstOrDefault());
|
||||
|
||||
var directDomainList = new List<string>();
|
||||
var directGeositeList = new List<string>();
|
||||
var proxyDomainList = new List<string>();
|
||||
var proxyGeositeList = new List<string>();
|
||||
var expectedDomainList = new List<string>();
|
||||
var expectedIPs = new List<string>();
|
||||
var regionNames = new HashSet<string>();
|
||||
|
||||
if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs))
|
||||
{
|
||||
expectedIPs = simpleDNSItem.DirectExpectedIPs
|
||||
.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.Trim())
|
||||
.Where(s => !string.IsNullOrEmpty(s))
|
||||
.ToList();
|
||||
|
||||
foreach (var ip in expectedIPs)
|
||||
{
|
||||
if (ip.StartsWith("geoip:", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var region = ip["geoip:".Length..];
|
||||
if (!string.IsNullOrEmpty(region))
|
||||
{
|
||||
regionNames.Add($"geosite:{region}");
|
||||
regionNames.Add($"geosite:geolocation-{region}");
|
||||
regionNames.Add($"geosite:tld-{region}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var routing = await ConfigHandler.GetDefaultRouting(_config);
|
||||
List<RulesItem>? rules = null;
|
||||
if (routing != null)
|
||||
{
|
||||
rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];
|
||||
foreach (var item in rules)
|
||||
{
|
||||
if (!item.Enabled || item.Domain is null || item.Domain.Count == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var domain in item.Domain)
|
||||
{
|
||||
if (domain.StartsWith('#'))
|
||||
continue;
|
||||
var normalizedDomain = domain.Replace(Global.RoutingRuleComma, ",");
|
||||
|
||||
if (item.OutboundTag == Global.DirectTag)
|
||||
{
|
||||
if (normalizedDomain.StartsWith("geosite:"))
|
||||
{
|
||||
(regionNames.Contains(normalizedDomain) ? expectedDomainList : directGeositeList).Add(normalizedDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
directDomainList.Add(normalizedDomain);
|
||||
}
|
||||
}
|
||||
else if (item.OutboundTag != Global.BlockTag)
|
||||
{
|
||||
if (normalizedDomain.StartsWith("geosite:"))
|
||||
{
|
||||
proxyGeositeList.Add(normalizedDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyDomainList.Add(normalizedDomain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Utils.IsDomain(node?.Address))
|
||||
{
|
||||
directDomainList.Add(node.Address);
|
||||
}
|
||||
|
||||
if (node?.Subid is not null)
|
||||
{
|
||||
var subItem = await AppHandler.Instance.GetSubItem(node.Subid);
|
||||
if (subItem is not null)
|
||||
{
|
||||
foreach (var profile in new[] { subItem.PrevProfile, subItem.NextProfile })
|
||||
{
|
||||
var profileNode = await AppHandler.Instance.GetProfileItemViaRemarks(profile);
|
||||
if (profileNode is not null &&
|
||||
profileNode.ConfigType is not (EConfigType.Custom or EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls) &&
|
||||
Utils.IsDomain(profileNode.Address))
|
||||
{
|
||||
directDomainList.Add(profileNode.Address);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
v2rayConfig.dns ??= new Dns4Ray();
|
||||
v2rayConfig.dns.servers ??= new List<object>();
|
||||
|
||||
void AddDnsServers(List<string> dnsAddresses, List<string> domains, List<string>? expectedIPs = null)
|
||||
{
|
||||
if (domains.Count > 0)
|
||||
{
|
||||
foreach (var dnsAddress in dnsAddresses)
|
||||
{
|
||||
v2rayConfig.dns.servers.Add(CreateDnsServer(dnsAddress, domains, expectedIPs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
||||
AddDnsServers(directDNSAddress, directDomainList);
|
||||
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
||||
AddDnsServers(directDNSAddress, directGeositeList);
|
||||
AddDnsServers(directDNSAddress, expectedDomainList, expectedIPs);
|
||||
|
||||
var useDirectDns = rules?.LastOrDefault() is { } lastRule &&
|
||||
lastRule.OutboundTag == Global.DirectTag &&
|
||||
(lastRule.Port == "0-65535" ||
|
||||
lastRule.Network == "tcp,udp" ||
|
||||
lastRule.Ip?.Contains("0.0.0.0/0") == true);
|
||||
|
||||
var defaultDnsServers = useDirectDns ? directDNSAddress : remoteDNSAddress;
|
||||
v2rayConfig.dns.servers.AddRange(defaultDnsServers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private async Task<int> GenDnsHosts(V2rayConfig v2rayConfig, SimpleDNSItem simpleDNSItem)
|
||||
{
|
||||
if (simpleDNSItem.AddCommonHosts == false && simpleDNSItem.UseSystemHosts == false && simpleDNSItem.Hosts.IsNullOrEmpty())
|
||||
{
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
v2rayConfig.dns ??= new Dns4Ray();
|
||||
v2rayConfig.dns.hosts ??= new Dictionary<string, object>();
|
||||
if (simpleDNSItem.AddCommonHosts == true)
|
||||
{
|
||||
v2rayConfig.dns.hosts = Global.PredefinedHosts.ToDictionary(
|
||||
kvp => kvp.Key,
|
||||
kvp => (object)kvp.Value
|
||||
);
|
||||
}
|
||||
|
||||
if (simpleDNSItem.UseSystemHosts == true)
|
||||
{
|
||||
var systemHosts = Utils.GetSystemHosts();
|
||||
if (systemHosts.Count > 0)
|
||||
{
|
||||
var normalHost = v2rayConfig.dns.hosts;
|
||||
if (normalHost != null)
|
||||
{
|
||||
foreach (var host in systemHosts)
|
||||
{
|
||||
if (normalHost[host.Key] != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
normalHost[host.Key] = new List<string> { host.Value };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var userHostsMap = simpleDNSItem.Hosts?
|
||||
.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(line => !string.IsNullOrWhiteSpace(line))
|
||||
.Where(line => line.Contains(' '))
|
||||
.ToDictionary(
|
||||
line =>
|
||||
{
|
||||
var parts = line.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return parts[0];
|
||||
},
|
||||
line =>
|
||||
{
|
||||
var parts = line.Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
var values = parts.Skip(1).ToList();
|
||||
return values;
|
||||
}
|
||||
);
|
||||
|
||||
if (userHostsMap != null)
|
||||
{
|
||||
foreach (var kvp in userHostsMap)
|
||||
{
|
||||
v2rayConfig.dns.hosts[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<int> GenDnsCompatible(ProfileItem? node, V2rayConfig v2rayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1174,22 +1466,33 @@ public class CoreConfigV2rayService
|
||||
var systemHosts = Utils.GetSystemHosts();
|
||||
if (systemHosts.Count > 0)
|
||||
{
|
||||
var normalHost = obj["hosts"];
|
||||
if (normalHost != null)
|
||||
var normalHost1 = obj["hosts"];
|
||||
if (normalHost1 != null)
|
||||
{
|
||||
foreach (var host in systemHosts)
|
||||
{
|
||||
if (normalHost[host.Key] != null)
|
||||
if (normalHost1[host.Key] != null)
|
||||
continue;
|
||||
normalHost[host.Key] = host.Value;
|
||||
normalHost1[host.Key] = host.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var normalHost = obj["hosts"];
|
||||
if (normalHost != null)
|
||||
{
|
||||
foreach (var hostProp in normalHost.AsObject().ToList())
|
||||
{
|
||||
if (hostProp.Value is JsonValue value && value.TryGetValue<string>(out var ip))
|
||||
{
|
||||
normalHost[hostProp.Key] = new JsonArray(ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await GenDnsDomains(node, obj, item);
|
||||
await GenDnsDomainsCompatible(node, obj, item);
|
||||
|
||||
v2rayConfig.dns = obj;
|
||||
v2rayConfig.dns = JsonUtils.Deserialize<Dns4Ray>(JsonUtils.Serialize(obj));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -1198,7 +1501,7 @@ public class CoreConfigV2rayService
|
||||
return 0;
|
||||
}
|
||||
|
||||
private async Task<int> GenDnsDomains(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
|
||||
private async Task<int> GenDnsDomainsCompatible(ProfileItem? node, JsonNode dns, DNSItem? dNSItem)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
@@ -1241,7 +1544,7 @@ public class CoreConfigV2rayService
|
||||
{
|
||||
var dnsServer = new DnsServer4Ray()
|
||||
{
|
||||
address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress,
|
||||
address = string.IsNullOrEmpty(dNSItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dNSItem?.DomainDNSAddress,
|
||||
skipFallback = true,
|
||||
domains = domainList
|
||||
};
|
||||
@@ -1349,7 +1652,8 @@ public class CoreConfigV2rayService
|
||||
if (prevNode is not null
|
||||
&& prevNode.ConfigType != EConfigType.Custom
|
||||
&& prevNode.ConfigType != EConfigType.Hysteria2
|
||||
&& prevNode.ConfigType != EConfigType.TUIC)
|
||||
&& prevNode.ConfigType != EConfigType.TUIC
|
||||
&& prevNode.ConfigType != EConfigType.Anytls)
|
||||
{
|
||||
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||
await GenOutbound(prevNode, prevOutbound);
|
||||
@@ -1424,7 +1728,8 @@ public class CoreConfigV2rayService
|
||||
if (prevNode is not null
|
||||
&& prevNode.ConfigType != EConfigType.Custom
|
||||
&& prevNode.ConfigType != EConfigType.Hysteria2
|
||||
&& prevNode.ConfigType != EConfigType.TUIC)
|
||||
&& prevNode.ConfigType != EConfigType.TUIC
|
||||
&& prevNode.ConfigType != EConfigType.Anytls)
|
||||
{
|
||||
var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);
|
||||
await GenOutbound(prevNode, prevOutbound);
|
||||
@@ -1493,7 +1798,8 @@ public class CoreConfigV2rayService
|
||||
if (nextNode is not null
|
||||
&& nextNode.ConfigType != EConfigType.Custom
|
||||
&& nextNode.ConfigType != EConfigType.Hysteria2
|
||||
&& nextNode.ConfigType != EConfigType.TUIC)
|
||||
&& nextNode.ConfigType != EConfigType.TUIC
|
||||
&& nextNode.ConfigType != EConfigType.Anytls)
|
||||
{
|
||||
if (nextOutbound == null)
|
||||
{
|
||||
@@ -1563,5 +1869,85 @@ public class CoreConfigV2rayService
|
||||
return await Task.FromResult(0);
|
||||
}
|
||||
|
||||
private async Task<string> ApplyFullConfigTemplate(V2rayConfig v2rayConfig, bool handleBalancerAndRules = false)
|
||||
{
|
||||
var fullConfigTemplate = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
if (fullConfigTemplate == null || !fullConfigTemplate.Enabled || fullConfigTemplate.Config.IsNullOrEmpty())
|
||||
{
|
||||
return JsonUtils.Serialize(v2rayConfig);
|
||||
}
|
||||
|
||||
var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplate.Config);
|
||||
if (fullConfigTemplateNode == null)
|
||||
{
|
||||
return JsonUtils.Serialize(v2rayConfig);
|
||||
}
|
||||
|
||||
// Handle balancer and rules modifications (for multiple load scenarios)
|
||||
if (handleBalancerAndRules && v2rayConfig.routing?.balancers?.Count > 0)
|
||||
{
|
||||
var balancer = v2rayConfig.routing.balancers.First();
|
||||
|
||||
// Modify existing rules in custom config
|
||||
var rulesNode = fullConfigTemplateNode["routing"]?["rules"];
|
||||
if (rulesNode != null)
|
||||
{
|
||||
foreach (var rule in rulesNode.AsArray())
|
||||
{
|
||||
if (rule["outboundTag"]?.GetValue<string>() == Global.ProxyTag)
|
||||
{
|
||||
rule.AsObject().Remove("outboundTag");
|
||||
rule["balancerTag"] = balancer.tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure routing node exists
|
||||
if (fullConfigTemplateNode["routing"] == null)
|
||||
{
|
||||
fullConfigTemplateNode["routing"] = new JsonObject();
|
||||
}
|
||||
|
||||
// Handle balancers - append instead of override
|
||||
if (fullConfigTemplateNode["routing"]["balancers"] is JsonArray customBalancersNode)
|
||||
{
|
||||
if (JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.routing.balancers)) is JsonArray newBalancers)
|
||||
{
|
||||
foreach (var balancerNode in newBalancers)
|
||||
{
|
||||
customBalancersNode.Add(balancerNode?.DeepClone());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullConfigTemplateNode["routing"]["balancers"] = JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.routing.balancers));
|
||||
}
|
||||
}
|
||||
|
||||
// Handle outbounds - append instead of override
|
||||
var customOutboundsNode = fullConfigTemplateNode["outbounds"] is JsonArray outbounds ? outbounds : new JsonArray();
|
||||
foreach (var outbound in v2rayConfig.outbounds)
|
||||
{
|
||||
if (outbound.protocol.ToLower() is "blackhole" or "dns" or "freedom")
|
||||
{
|
||||
if (fullConfigTemplate.AddProxyOnly == true)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if ((outbound.streamSettings?.sockopt?.dialerProxy.IsNullOrEmpty() == true) && (!fullConfigTemplate.ProxyDetour.IsNullOrEmpty()) && !(Utils.IsPrivateNetwork(outbound.settings?.servers?.FirstOrDefault()?.address ?? string.Empty) || Utils.IsPrivateNetwork(outbound.settings?.vnext?.FirstOrDefault()?.address ?? string.Empty)))
|
||||
{
|
||||
outbound.streamSettings ??= new StreamSettings4Ray();
|
||||
outbound.streamSettings.sockopt ??= new Sockopt4Ray();
|
||||
outbound.streamSettings.sockopt.dialerProxy = fullConfigTemplate.ProxyDetour;
|
||||
}
|
||||
customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));
|
||||
}
|
||||
fullConfigTemplateNode["outbounds"] = customOutboundsNode;
|
||||
|
||||
return await Task.FromResult(JsonUtils.Serialize(fullConfigTemplateNode));
|
||||
}
|
||||
|
||||
#endregion private gen function
|
||||
}
|
||||
|
||||
@@ -358,8 +358,8 @@ public class SpeedtestService
|
||||
private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)
|
||||
{
|
||||
List<List<ServerTestItem>> lstTest = new();
|
||||
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC)).ToList();
|
||||
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC).ToList();
|
||||
var lst1 = lstSelected.Where(t => t.ConfigType is not (EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls)).ToList();
|
||||
var lst2 = lstSelected.Where(t => t.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls).ToList();
|
||||
|
||||
for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace ServiceLib.Services;
|
||||
public class UpdateService
|
||||
{
|
||||
private Action<bool, string>? _updateFunc;
|
||||
private int _timeout = 30;
|
||||
private readonly int _timeout = 30;
|
||||
private static readonly string _tag = "UpdateService";
|
||||
|
||||
public async Task CheckUpdateGuiN(Config config, Action<bool, string> updateFunc, bool preRelease)
|
||||
@@ -104,137 +104,6 @@ public class UpdateService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateSubscriptionProcess(Config config, string subId, bool blProxy, Action<bool, string> updateFunc)
|
||||
{
|
||||
_updateFunc = updateFunc;
|
||||
|
||||
_updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);
|
||||
var subItem = await AppHandler.Instance.SubItems();
|
||||
|
||||
if (subItem is not { Count: > 0 })
|
||||
{
|
||||
_updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var item in subItem)
|
||||
{
|
||||
var id = item.Id.TrimEx();
|
||||
var url = item.Url.TrimEx();
|
||||
var userAgent = item.UserAgent.TrimEx();
|
||||
var hashCode = $"{item.Remarks}->";
|
||||
if (id.IsNullOrEmpty() || url.IsNullOrEmpty() || (subId.IsNotEmpty() && item.Id != subId))
|
||||
{
|
||||
//_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgNoValidSubscription}");
|
||||
continue;
|
||||
}
|
||||
if (!url.StartsWith(Global.HttpsProtocol) && !url.StartsWith(Global.HttpProtocol))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (item.Enabled == false)
|
||||
{
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}");
|
||||
continue;
|
||||
}
|
||||
|
||||
var downloadHandle = new DownloadService();
|
||||
downloadHandle.Error += (sender2, args) =>
|
||||
{
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{args.GetException().Message}");
|
||||
};
|
||||
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgStartGettingSubscriptions}");
|
||||
|
||||
//one url
|
||||
url = Utils.GetPunycode(url);
|
||||
//convert
|
||||
if (item.ConvertTarget.IsNotEmpty())
|
||||
{
|
||||
var subConvertUrl = config.ConstItem.SubConvertUrl.IsNullOrEmpty() ? Global.SubConvertUrls.FirstOrDefault() : config.ConstItem.SubConvertUrl;
|
||||
url = string.Format(subConvertUrl!, Utils.UrlEncode(url));
|
||||
if (!url.Contains("target="))
|
||||
{
|
||||
url += string.Format("&target={0}", item.ConvertTarget);
|
||||
}
|
||||
if (!url.Contains("config="))
|
||||
{
|
||||
url += string.Format("&config={0}", Global.SubConvertConfig.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent);
|
||||
if (blProxy && result.IsNullOrEmpty())
|
||||
{
|
||||
result = await downloadHandle.TryDownloadString(url, false, userAgent);
|
||||
}
|
||||
|
||||
//more url
|
||||
if (item.ConvertTarget.IsNullOrEmpty() && item.MoreUrl.TrimEx().IsNotEmpty())
|
||||
{
|
||||
if (result.IsNotEmpty() && Utils.IsBase64String(result))
|
||||
{
|
||||
result = Utils.Base64Decode(result);
|
||||
}
|
||||
|
||||
var lstUrl = item.MoreUrl.TrimEx().Split(",") ?? [];
|
||||
foreach (var it in lstUrl)
|
||||
{
|
||||
var url2 = Utils.GetPunycode(it);
|
||||
if (url2.IsNullOrEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var result2 = await downloadHandle.TryDownloadString(url2, blProxy, userAgent);
|
||||
if (blProxy && result2.IsNullOrEmpty())
|
||||
{
|
||||
result2 = await downloadHandle.TryDownloadString(url2, false, userAgent);
|
||||
}
|
||||
if (result2.IsNotEmpty())
|
||||
{
|
||||
if (Utils.IsBase64String(result2))
|
||||
{
|
||||
result += Environment.NewLine + Utils.Base64Decode(result2);
|
||||
}
|
||||
else
|
||||
{
|
||||
result += Environment.NewLine + result2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}");
|
||||
if (result?.Length < 99)
|
||||
{
|
||||
_updateFunc?.Invoke(false, $"{hashCode}{result}");
|
||||
}
|
||||
|
||||
var ret = await ConfigHandler.AddBatchServers(config, result, id, true);
|
||||
if (ret <= 0)
|
||||
{
|
||||
Logging.SaveLog("FailedImportSubscription");
|
||||
Logging.SaveLog(result);
|
||||
}
|
||||
_updateFunc?.Invoke(false,
|
||||
ret > 0
|
||||
? $"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}"
|
||||
: $"{hashCode}{ResUI.MsgFailedImportSubscription}");
|
||||
}
|
||||
_updateFunc?.Invoke(false, "-------------------------------------------------------");
|
||||
|
||||
//await ConfigHandler.DedupServerList(config, id);
|
||||
}
|
||||
|
||||
_updateFunc?.Invoke(true, $"{ResUI.MsgUpdateSubscriptionEnd}");
|
||||
}
|
||||
|
||||
public async Task UpdateGeoFileAll(Config config, Action<bool, string> updateFunc)
|
||||
{
|
||||
await UpdateGeoFiles(config, updateFunc);
|
||||
@@ -536,6 +405,11 @@ public class UpdateService
|
||||
}
|
||||
}
|
||||
|
||||
//append dns items TODO
|
||||
geoSiteFiles.Add("cn");
|
||||
geoSiteFiles.Add("geolocation-cn");
|
||||
geoSiteFiles.Add("category-ads-all");
|
||||
|
||||
var path = Utils.GetBinPath("srss");
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
|
||||
@@ -234,7 +234,7 @@ public class ClashProxiesViewModel : MyReactiveObject
|
||||
else
|
||||
{
|
||||
SelectedGroup = _proxyGroups.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -6,39 +6,52 @@ namespace ServiceLib.ViewModels;
|
||||
|
||||
public class DNSSettingViewModel : MyReactiveObject
|
||||
{
|
||||
[Reactive] public bool UseSystemHosts { get; set; }
|
||||
[Reactive] public string DomainStrategy4Freedom { get; set; }
|
||||
[Reactive] public string DomainDNSAddress { get; set; }
|
||||
[Reactive] public string NormalDNS { get; set; }
|
||||
[Reactive] public bool? UseSystemHosts { get; set; }
|
||||
[Reactive] public bool? AddCommonHosts { get; set; }
|
||||
[Reactive] public bool? FakeIP { get; set; }
|
||||
[Reactive] public bool? BlockBindingQuery { get; set; }
|
||||
[Reactive] public string? DirectDNS { get; set; }
|
||||
[Reactive] public string? RemoteDNS { get; set; }
|
||||
[Reactive] public string? SingboxOutboundsResolveDNS { get; set; }
|
||||
[Reactive] public string? SingboxFinalResolveDNS { get; set; }
|
||||
[Reactive] public string? RayStrategy4Freedom { get; set; }
|
||||
[Reactive] public string? SingboxStrategy4Direct { get; set; }
|
||||
[Reactive] public string? SingboxStrategy4Proxy { get; set; }
|
||||
[Reactive] public string? Hosts { get; set; }
|
||||
[Reactive] public string? DirectExpectedIPs { get; set; }
|
||||
|
||||
[Reactive] public string DomainStrategy4Freedom2 { get; set; }
|
||||
[Reactive] public string DomainDNSAddress2 { get; set; }
|
||||
[Reactive] public string NormalDNS2 { get; set; }
|
||||
[Reactive] public string TunDNS2 { get; set; }
|
||||
[Reactive] public bool UseSystemHostsCompatible { get; set; }
|
||||
[Reactive] public string DomainStrategy4FreedomCompatible { get; set; }
|
||||
[Reactive] public string DomainDNSAddressCompatible { get; set; }
|
||||
[Reactive] public string NormalDNSCompatible { get; set; }
|
||||
|
||||
[Reactive] public string DomainStrategy4Freedom2Compatible { get; set; }
|
||||
[Reactive] public string DomainDNSAddress2Compatible { get; set; }
|
||||
[Reactive] public string NormalDNS2Compatible { get; set; }
|
||||
[Reactive] public string TunDNS2Compatible { get; set; }
|
||||
[Reactive] public bool RayCustomDNSEnableCompatible { get; set; }
|
||||
[Reactive] public bool SBCustomDNSEnableCompatible { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCompatibleCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCompatibleCmd { get; }
|
||||
|
||||
public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||
{
|
||||
_config = AppHandler.Instance.Config;
|
||||
_updateView = updateView;
|
||||
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await SaveSettingAsync();
|
||||
});
|
||||
SaveCmd = ReactiveCommand.CreateFromTask(SaveSettingAsync);
|
||||
|
||||
ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
ImportDefConfig4V2rayCompatibleCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
NormalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
||||
NormalDNSCompatible = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
ImportDefConfig4SingboxCompatibleCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
NormalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);
|
||||
TunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);
|
||||
NormalDNS2Compatible = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);
|
||||
TunDNS2Compatible = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);
|
||||
await Task.CompletedTask;
|
||||
});
|
||||
|
||||
@@ -47,48 +60,80 @@ public class DNSSettingViewModel : MyReactiveObject
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
|
||||
_config = AppHandler.Instance.Config;
|
||||
var item = _config.SimpleDNSItem;
|
||||
UseSystemHosts = item.UseSystemHosts;
|
||||
DomainStrategy4Freedom = item?.DomainStrategy4Freedom ?? string.Empty;
|
||||
DomainDNSAddress = item?.DomainDNSAddress ?? string.Empty;
|
||||
NormalDNS = item?.NormalDNS ?? string.Empty;
|
||||
AddCommonHosts = item.AddCommonHosts;
|
||||
FakeIP = item.FakeIP;
|
||||
BlockBindingQuery = item.BlockBindingQuery;
|
||||
DirectDNS = item.DirectDNS;
|
||||
RemoteDNS = item.RemoteDNS;
|
||||
RayStrategy4Freedom = item.RayStrategy4Freedom;
|
||||
SingboxOutboundsResolveDNS = item.SingboxOutboundsResolveDNS;
|
||||
SingboxFinalResolveDNS = item.SingboxFinalResolveDNS;
|
||||
SingboxStrategy4Direct = item.SingboxStrategy4Direct;
|
||||
SingboxStrategy4Proxy = item.SingboxStrategy4Proxy;
|
||||
Hosts = item.Hosts;
|
||||
DirectExpectedIPs = item.DirectExpectedIPs;
|
||||
|
||||
var item1 = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
|
||||
RayCustomDNSEnableCompatible = item1.Enabled;
|
||||
UseSystemHostsCompatible = item1.UseSystemHosts;
|
||||
DomainStrategy4FreedomCompatible = item1?.DomainStrategy4Freedom ?? string.Empty;
|
||||
DomainDNSAddressCompatible = item1?.DomainDNSAddress ?? string.Empty;
|
||||
NormalDNSCompatible = item1?.NormalDNS ?? string.Empty;
|
||||
|
||||
var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
|
||||
DomainStrategy4Freedom2 = item2?.DomainStrategy4Freedom ?? string.Empty;
|
||||
DomainDNSAddress2 = item2?.DomainDNSAddress ?? string.Empty;
|
||||
NormalDNS2 = item2?.NormalDNS ?? string.Empty;
|
||||
TunDNS2 = item2?.TunDNS ?? string.Empty;
|
||||
SBCustomDNSEnableCompatible = item2.Enabled;
|
||||
DomainStrategy4Freedom2Compatible = item2?.DomainStrategy4Freedom ?? string.Empty;
|
||||
DomainDNSAddress2Compatible = item2?.DomainDNSAddress ?? string.Empty;
|
||||
NormalDNS2Compatible = item2?.NormalDNS ?? string.Empty;
|
||||
TunDNS2Compatible = item2?.TunDNS ?? string.Empty;
|
||||
}
|
||||
|
||||
private async Task SaveSettingAsync()
|
||||
{
|
||||
if (NormalDNS.IsNotEmpty())
|
||||
_config.SimpleDNSItem.UseSystemHosts = UseSystemHosts;
|
||||
_config.SimpleDNSItem.AddCommonHosts = AddCommonHosts;
|
||||
_config.SimpleDNSItem.FakeIP = FakeIP;
|
||||
_config.SimpleDNSItem.BlockBindingQuery = BlockBindingQuery;
|
||||
_config.SimpleDNSItem.DirectDNS = DirectDNS;
|
||||
_config.SimpleDNSItem.RemoteDNS = RemoteDNS;
|
||||
_config.SimpleDNSItem.RayStrategy4Freedom = RayStrategy4Freedom;
|
||||
_config.SimpleDNSItem.SingboxOutboundsResolveDNS = SingboxOutboundsResolveDNS;
|
||||
_config.SimpleDNSItem.SingboxFinalResolveDNS = SingboxFinalResolveDNS;
|
||||
_config.SimpleDNSItem.SingboxStrategy4Direct = SingboxStrategy4Direct;
|
||||
_config.SimpleDNSItem.SingboxStrategy4Proxy = SingboxStrategy4Proxy;
|
||||
_config.SimpleDNSItem.Hosts = Hosts;
|
||||
_config.SimpleDNSItem.DirectExpectedIPs = DirectExpectedIPs;
|
||||
|
||||
if (NormalDNSCompatible.IsNotEmpty())
|
||||
{
|
||||
var obj = JsonUtils.ParseJson(NormalDNS);
|
||||
var obj = JsonUtils.ParseJson(NormalDNSCompatible);
|
||||
if (obj != null && obj["servers"] != null)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NormalDNS.Contains('{') || NormalDNS.Contains('}'))
|
||||
if (NormalDNSCompatible.Contains('{') || NormalDNSCompatible.Contains('}'))
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NormalDNS2.IsNotEmpty())
|
||||
if (NormalDNS2Compatible.IsNotEmpty())
|
||||
{
|
||||
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2);
|
||||
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2Compatible);
|
||||
if (obj2 == null)
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (TunDNS2.IsNotEmpty())
|
||||
if (TunDNS2Compatible.IsNotEmpty())
|
||||
{
|
||||
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2);
|
||||
var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2Compatible);
|
||||
if (obj2 == null)
|
||||
{
|
||||
NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText);
|
||||
@@ -96,21 +141,26 @@ public class DNSSettingViewModel : MyReactiveObject
|
||||
}
|
||||
}
|
||||
|
||||
var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
|
||||
item.DomainStrategy4Freedom = DomainStrategy4Freedom;
|
||||
item.DomainDNSAddress = DomainDNSAddress;
|
||||
item.UseSystemHosts = UseSystemHosts;
|
||||
item.NormalDNS = NormalDNS;
|
||||
await ConfigHandler.SaveDNSItems(_config, item);
|
||||
var item1 = await AppHandler.Instance.GetDNSItem(ECoreType.Xray);
|
||||
item1.Enabled = RayCustomDNSEnableCompatible;
|
||||
item1.DomainStrategy4Freedom = DomainStrategy4FreedomCompatible;
|
||||
item1.DomainDNSAddress = DomainDNSAddressCompatible;
|
||||
item1.UseSystemHosts = UseSystemHostsCompatible;
|
||||
item1.NormalDNS = NormalDNSCompatible;
|
||||
await ConfigHandler.SaveDNSItems(_config, item1);
|
||||
|
||||
var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box);
|
||||
item2.DomainStrategy4Freedom = DomainStrategy4Freedom2;
|
||||
item2.DomainDNSAddress = DomainDNSAddress2;
|
||||
item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2));
|
||||
item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2));
|
||||
item2.Enabled = SBCustomDNSEnableCompatible;
|
||||
item2.DomainStrategy4Freedom = DomainStrategy4Freedom2Compatible;
|
||||
item2.DomainDNSAddress = DomainDNSAddress2Compatible;
|
||||
item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2Compatible));
|
||||
item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2Compatible));
|
||||
await ConfigHandler.SaveDNSItems(_config, item2);
|
||||
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
_ = _updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
if (_updateView != null)
|
||||
{
|
||||
await _updateView(EViewAction.CloseWindow, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
113
v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs
Normal file
113
v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System.Reactive;
|
||||
using ReactiveUI;
|
||||
using ReactiveUI.Fody.Helpers;
|
||||
|
||||
namespace ServiceLib.ViewModels;
|
||||
|
||||
public class FullConfigTemplateViewModel : MyReactiveObject
|
||||
{
|
||||
#region Reactive
|
||||
|
||||
[Reactive]
|
||||
public bool EnableFullConfigTemplate4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool EnableFullConfigTemplate4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string FullConfigTemplate4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string FullConfigTemplate4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string FullTunConfigTemplate4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool AddProxyOnly4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public bool AddProxyOnly4Singbox { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string ProxyDetour4Ray { get; set; }
|
||||
|
||||
[Reactive]
|
||||
public string ProxyDetour4Singbox { get; set; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SaveCmd { get; }
|
||||
|
||||
#endregion Reactive
|
||||
|
||||
public FullConfigTemplateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||
{
|
||||
_config = AppHandler.Instance.Config;
|
||||
_updateView = updateView;
|
||||
SaveCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await SaveSettingAsync();
|
||||
});
|
||||
|
||||
_ = Init();
|
||||
}
|
||||
|
||||
private async Task Init()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
EnableFullConfigTemplate4Ray = item?.Enabled ?? false;
|
||||
FullConfigTemplate4Ray = item?.Config ?? string.Empty;
|
||||
AddProxyOnly4Ray = item?.AddProxyOnly ?? false;
|
||||
ProxyDetour4Ray = item?.ProxyDetour ?? string.Empty;
|
||||
|
||||
var item2 = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
|
||||
EnableFullConfigTemplate4Singbox = item2?.Enabled ?? false;
|
||||
FullConfigTemplate4Singbox = item2?.Config ?? string.Empty;
|
||||
FullTunConfigTemplate4Singbox = item2?.TunConfig ?? string.Empty;
|
||||
AddProxyOnly4Singbox = item2?.AddProxyOnly ?? false;
|
||||
ProxyDetour4Singbox = item2?.ProxyDetour ?? string.Empty;
|
||||
}
|
||||
|
||||
private async Task SaveSettingAsync()
|
||||
{
|
||||
if (!await SaveXrayConfigAsync())
|
||||
return;
|
||||
|
||||
if (!await SaveSingboxConfigAsync())
|
||||
return;
|
||||
|
||||
NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);
|
||||
_ = _updateView?.Invoke(EViewAction.CloseWindow, null);
|
||||
}
|
||||
|
||||
private async Task<bool> SaveXrayConfigAsync()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.Xray);
|
||||
item.Enabled = EnableFullConfigTemplate4Ray;
|
||||
item.Config = null;
|
||||
|
||||
item.Config = FullConfigTemplate4Ray;
|
||||
|
||||
item.AddProxyOnly = AddProxyOnly4Ray;
|
||||
item.ProxyDetour = ProxyDetour4Ray;
|
||||
|
||||
await ConfigHandler.SaveFullConfigTemplate(_config, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> SaveSingboxConfigAsync()
|
||||
{
|
||||
var item = await AppHandler.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);
|
||||
item.Enabled = EnableFullConfigTemplate4Singbox;
|
||||
item.Config = null;
|
||||
item.TunConfig = null;
|
||||
|
||||
item.Config = FullConfigTemplate4Singbox;
|
||||
item.TunConfig = FullTunConfigTemplate4Singbox;
|
||||
|
||||
item.AddProxyOnly = AddProxyOnly4Singbox;
|
||||
item.ProxyDetour = ProxyDetour4Singbox;
|
||||
|
||||
await ConfigHandler.SaveFullConfigTemplate(_config, item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
public ReactiveCommand<Unit, Unit> AddHysteria2ServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddAnytlsServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }
|
||||
@@ -38,6 +39,7 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
|
||||
public ReactiveCommand<Unit, Unit> RoutingSettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> DNSSettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> FullConfigTemplateCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> GlobalHotkeySettingCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> RebootAsAdminCmd { get; }
|
||||
public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }
|
||||
@@ -111,6 +113,10 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
{
|
||||
await AddServerAsync(true, EConfigType.WireGuard);
|
||||
});
|
||||
AddAnytlsServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await AddServerAsync(true, EConfigType.Anytls);
|
||||
});
|
||||
AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await AddServerAsync(true, EConfigType.Custom);
|
||||
@@ -164,6 +170,10 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
{
|
||||
await DNSSettingAsync();
|
||||
});
|
||||
FullConfigTemplateCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await FullConfigTemplateAsync();
|
||||
});
|
||||
GlobalHotkeySettingCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
if (await _updateView?.Invoke(EViewAction.GlobalHotkeySettingWindow, null) == true)
|
||||
@@ -215,6 +225,7 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
|
||||
await ConfigHandler.InitBuiltinRouting(_config);
|
||||
await ConfigHandler.InitBuiltinDNS(_config);
|
||||
await ConfigHandler.InitBuiltinFullConfigTemplate(_config);
|
||||
await ProfileExHandler.Instance.Init();
|
||||
await CoreHandler.Instance.Init(_config, UpdateHandler);
|
||||
TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler);
|
||||
@@ -466,7 +477,7 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
|
||||
public async Task UpdateSubscriptionProcess(string subId, bool blProxy)
|
||||
{
|
||||
await (new UpdateService()).UpdateSubscriptionProcess(_config, subId, blProxy, UpdateTaskHandler);
|
||||
await SubscriptionHandler.UpdateProcess(_config, subId, blProxy, UpdateTaskHandler);
|
||||
}
|
||||
|
||||
#endregion Subscription
|
||||
@@ -503,6 +514,15 @@ public class MainWindowViewModel : MyReactiveObject
|
||||
}
|
||||
}
|
||||
|
||||
private async Task FullConfigTemplateAsync()
|
||||
{
|
||||
var ret = await _updateView?.Invoke(EViewAction.FullConfigTemplateWindow, null);
|
||||
if (ret == true)
|
||||
{
|
||||
await Reload();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RebootAsAdmin()
|
||||
{
|
||||
ProcUtils.RebootAsAdmin();
|
||||
|
||||
@@ -84,6 +84,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||
|
||||
#region Tun mode
|
||||
|
||||
[Reactive] public bool TunAutoRoute { get; set; }
|
||||
[Reactive] public bool TunStrictRoute { get; set; }
|
||||
[Reactive] public string TunStack { get; set; }
|
||||
[Reactive] public int TunMtu { get; set; }
|
||||
@@ -201,6 +202,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||
|
||||
#region Tun mode
|
||||
|
||||
TunAutoRoute = _config.TunModeItem.AutoRoute;
|
||||
TunStrictRoute = _config.TunModeItem.StrictRoute;
|
||||
TunStack = _config.TunModeItem.Stack;
|
||||
TunMtu = _config.TunModeItem.Mtu;
|
||||
@@ -354,6 +356,7 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||
_config.SystemProxyItem.SystemProxyAdvancedProtocol = systemProxyAdvancedProtocol;
|
||||
|
||||
//tun mode
|
||||
_config.TunModeItem.AutoRoute = TunAutoRoute;
|
||||
_config.TunModeItem.StrictRoute = TunStrictRoute;
|
||||
_config.TunModeItem.Stack = TunStack;
|
||||
_config.TunModeItem.Mtu = TunMtu;
|
||||
|
||||
@@ -436,30 +436,34 @@ public class StatusBarViewModel : MyReactiveObject
|
||||
|
||||
private async Task DoEnableTun(bool c)
|
||||
{
|
||||
if (_config.TunModeItem.EnableTun != EnableTun)
|
||||
if (_config.TunModeItem.EnableTun == EnableTun)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_config.TunModeItem.EnableTun = EnableTun;
|
||||
|
||||
if (EnableTun && AllowEnableTun() == false)
|
||||
{
|
||||
_config.TunModeItem.EnableTun = EnableTun;
|
||||
// When running as a non-administrator, reboot to administrator mode
|
||||
if (EnableTun && AllowEnableTun() == false)
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
if (Utils.IsWindows())
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool? passwordResult = await _updateView?.Invoke(EViewAction.PasswordInput, null);
|
||||
if (passwordResult == false)
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (await _updateView?.Invoke(EViewAction.PasswordInput, null) == false)
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||
}
|
||||
await ConfigHandler.SaveConfig(_config);
|
||||
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
|
||||
}
|
||||
|
||||
private bool AllowEnableTun()
|
||||
|
||||
@@ -61,11 +61,7 @@ internal class Program
|
||||
//.WithInterFont()
|
||||
.WithFontByDefault()
|
||||
.LogToTrace()
|
||||
#if OS_OSX
|
||||
.UseReactiveUI()
|
||||
.With(new MacOSPlatformOptions { ShowInDock = AppHandler.Instance.Config.UiItem.MacOSShowInDock });
|
||||
#else
|
||||
.UseReactiveUI();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ public class ThemeSettingViewModel : MyReactiveObject
|
||||
x.OfType<Button>(),
|
||||
x.OfType<TextBox>(),
|
||||
x.OfType<TextBlock>(),
|
||||
x.OfType<SelectableTextBlock>(),
|
||||
x.OfType<Menu>(),
|
||||
x.OfType<ContextMenu>(),
|
||||
x.OfType<DataGridRow>(),
|
||||
@@ -146,6 +147,7 @@ public class ThemeSettingViewModel : MyReactiveObject
|
||||
x.OfType<Button>(),
|
||||
x.OfType<TextBox>(),
|
||||
x.OfType<TextBlock>(),
|
||||
x.OfType<SelectableTextBlock>(),
|
||||
x.OfType<Menu>(),
|
||||
x.OfType<ContextMenu>(),
|
||||
x.OfType<DataGridRow>(),
|
||||
|
||||
@@ -21,13 +21,7 @@ public partial class AddServer2Window : WindowBase<AddServer2ViewModel>
|
||||
btnCancel.Click += (s, e) => this.Close();
|
||||
ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);
|
||||
|
||||
foreach (ECoreType it in Enum.GetValues(typeof(ECoreType)))
|
||||
{
|
||||
if (it == ECoreType.v2rayN)
|
||||
continue;
|
||||
cmbCoreType.Items.Add(it.ToString());
|
||||
}
|
||||
cmbCoreType.Items.Add(string.Empty);
|
||||
cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
@@ -533,6 +533,26 @@
|
||||
HorizontalAlignment="Left"
|
||||
Watermark="1500" />
|
||||
</Grid>
|
||||
<Grid
|
||||
x:Name="gridAnytls"
|
||||
Grid.Row="2"
|
||||
ColumnDefinitions="180,Auto"
|
||||
IsVisible="False"
|
||||
RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbId3}" />
|
||||
<TextBox
|
||||
x:Name="txtId10"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</Grid>
|
||||
|
||||
<Separator
|
||||
x:Name="sepa2"
|
||||
@@ -753,7 +773,7 @@
|
||||
Grid.Row="7"
|
||||
ColumnDefinitions="180,Auto"
|
||||
IsVisible="False"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto">
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
@@ -823,6 +843,20 @@
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbMldsa65Verify}" />
|
||||
<TextBox
|
||||
x:Name="txtMldsa65Verify"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</Grid>
|
||||
<Separator Grid.Row="8" Margin="{StaticResource MarginTb8}" />
|
||||
</Grid>
|
||||
|
||||
@@ -26,41 +26,22 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
|
||||
ViewModel = new AddServerViewModel(profileItem, UpdateViewHandler);
|
||||
|
||||
Global.CoreTypes.ForEach(it =>
|
||||
{
|
||||
cmbCoreType.Items.Add(it);
|
||||
});
|
||||
cmbCoreType.Items.Add(string.Empty);
|
||||
cmbCoreType.ItemsSource = Global.CoreTypes.AppendEmpty();
|
||||
cmbNetwork.ItemsSource = Global.Networks;
|
||||
cmbFingerprint.ItemsSource = Global.Fingerprints;
|
||||
cmbFingerprint2.ItemsSource = Global.Fingerprints;
|
||||
cmbAllowInsecure.ItemsSource = Global.AllowInsecure;
|
||||
cmbAlpn.ItemsSource = Global.Alpns;
|
||||
|
||||
cmbStreamSecurity.Items.Add(string.Empty);
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurity);
|
||||
|
||||
Global.Networks.ForEach(it =>
|
||||
{
|
||||
cmbNetwork.Items.Add(it);
|
||||
});
|
||||
Global.Fingerprints.ForEach(it =>
|
||||
{
|
||||
cmbFingerprint.Items.Add(it);
|
||||
cmbFingerprint2.Items.Add(it);
|
||||
});
|
||||
Global.AllowInsecure.ForEach(it =>
|
||||
{
|
||||
cmbAllowInsecure.Items.Add(it);
|
||||
});
|
||||
Global.Alpns.ForEach(it =>
|
||||
{
|
||||
cmbAlpn.Items.Add(it);
|
||||
});
|
||||
var lstStreamSecurity = new List<string>();
|
||||
lstStreamSecurity.Add(string.Empty);
|
||||
lstStreamSecurity.Add(Global.StreamSecurity);
|
||||
|
||||
switch (profileItem.ConfigType)
|
||||
{
|
||||
case EConfigType.VMess:
|
||||
gridVMess.IsVisible = true;
|
||||
Global.VmessSecurities.ForEach(it =>
|
||||
{
|
||||
cmbSecurity.Items.Add(it);
|
||||
});
|
||||
cmbSecurity.ItemsSource = Global.VmessSecurities;
|
||||
if (profileItem.Security.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.Security = Global.DefaultSecurity;
|
||||
@@ -69,10 +50,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
|
||||
case EConfigType.Shadowsocks:
|
||||
gridSs.IsVisible = true;
|
||||
AppHandler.Instance.GetShadowsocksSecurities(profileItem).ForEach(it =>
|
||||
{
|
||||
cmbSecurity3.Items.Add(it);
|
||||
});
|
||||
cmbSecurity3.ItemsSource = AppHandler.Instance.GetShadowsocksSecurities(profileItem);
|
||||
break;
|
||||
|
||||
case EConfigType.SOCKS:
|
||||
@@ -82,11 +60,8 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
|
||||
case EConfigType.VLESS:
|
||||
gridVLESS.IsVisible = true;
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityReality);
|
||||
Global.Flows.ForEach(it =>
|
||||
{
|
||||
cmbFlow5.Items.Add(it);
|
||||
});
|
||||
lstStreamSecurity.Add(Global.StreamSecurityReality);
|
||||
cmbFlow5.ItemsSource = Global.Flows;
|
||||
if (profileItem.Security.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.Security = Global.None;
|
||||
@@ -95,11 +70,8 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
|
||||
case EConfigType.Trojan:
|
||||
gridTrojan.IsVisible = true;
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityReality);
|
||||
Global.Flows.ForEach(it =>
|
||||
{
|
||||
cmbFlow6.Items.Add(it);
|
||||
});
|
||||
lstStreamSecurity.Add(Global.StreamSecurityReality);
|
||||
cmbFlow6.ItemsSource = Global.Flows;
|
||||
break;
|
||||
|
||||
case EConfigType.Hysteria2:
|
||||
@@ -119,10 +91,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
cmbFingerprint.IsEnabled = false;
|
||||
cmbFingerprint.SelectedValue = string.Empty;
|
||||
|
||||
Global.TuicCongestionControls.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType8.Items.Add(it);
|
||||
});
|
||||
cmbHeaderType8.ItemsSource = Global.TuicCongestionControls;
|
||||
break;
|
||||
|
||||
case EConfigType.WireGuard:
|
||||
@@ -133,7 +102,14 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
gridTls.IsVisible = false;
|
||||
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
gridAnytls.IsVisible = true;
|
||||
lstStreamSecurity.Add(Global.StreamSecurityReality);
|
||||
cmbCoreType.IsEnabled = false;
|
||||
break;
|
||||
}
|
||||
cmbStreamSecurity.ItemsSource = lstStreamSecurity;
|
||||
|
||||
gridTlsMore.IsVisible = false;
|
||||
|
||||
@@ -197,6 +173,10 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables);
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Id, v => v.txtId10.Text).DisposeWith(disposables);
|
||||
break;
|
||||
}
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables);
|
||||
@@ -215,6 +195,7 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.PublicKey, v => v.txtPublicKey.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
@@ -272,44 +253,41 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
||||
|
||||
private void SetHeaderType()
|
||||
{
|
||||
cmbHeaderType.Items.Clear();
|
||||
var lstHeaderType = new List<string>();
|
||||
|
||||
var network = cmbNetwork.SelectedItem.ToString();
|
||||
if (network.IsNullOrEmpty())
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
lstHeaderType.Add(Global.None);
|
||||
cmbHeaderType.ItemsSource = lstHeaderType;
|
||||
cmbHeaderType.SelectedIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (network == nameof(ETransport.tcp))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
cmbHeaderType.Items.Add(Global.TcpHeaderHttp);
|
||||
lstHeaderType.Add(Global.None);
|
||||
lstHeaderType.Add(Global.TcpHeaderHttp);
|
||||
}
|
||||
else if (network is nameof(ETransport.kcp) or nameof(ETransport.quic))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
Global.KcpHeaderTypes.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
lstHeaderType.Add(Global.None);
|
||||
lstHeaderType.AddRange(Global.KcpHeaderTypes);
|
||||
}
|
||||
else if (network is nameof(ETransport.xhttp))
|
||||
{
|
||||
Global.XhttpMode.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
lstHeaderType.AddRange(Global.XhttpMode);
|
||||
}
|
||||
else if (network == nameof(ETransport.grpc))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.GrpcGunMode);
|
||||
cmbHeaderType.Items.Add(Global.GrpcMultiMode);
|
||||
lstHeaderType.Add(Global.GrpcGunMode);
|
||||
lstHeaderType.Add(Global.GrpcMultiMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
lstHeaderType.Add(Global.None);
|
||||
}
|
||||
cmbHeaderType.ItemsSource = lstHeaderType;
|
||||
cmbHeaderType.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
x:Class="v2rayN.Desktop.Views.DNSSettingWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ctrls="clr-namespace:v2rayN.Desktop.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
@@ -35,25 +36,305 @@
|
||||
</StackPanel>
|
||||
|
||||
<TabControl HorizontalContentAlignment="Stretch">
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
|
||||
<TabItem Header="{x:Static resx:ResUI.ThBasicDNSSettings}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Visible">
|
||||
<Grid
|
||||
Margin="{StaticResource Margin8}"
|
||||
ColumnDefinitions="Auto,Auto,*"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
x:Name="txtBasicDNSSettingsInvalid"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" />
|
||||
|
||||
<TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkDnsObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4V2ray"
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand" />
|
||||
</StackPanel>
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbDomesticDNS}" />
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbDirectDNS"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding DirectDNS, Mode=TwoWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbRemoteDNS}" />
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbRemoteDNS"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding RemoteDNS, Mode=TwoWay}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" />
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbSBResolverDNS"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding SingboxOutboundsResolveDNS, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBOutboundDomainResolve}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBDoHResolverServer}" />
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbSBFinalResolverDNS"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding SingboxFinalResolveDNS, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbXrayFreedomResolveStrategy}" />
|
||||
<ComboBox
|
||||
x:Name="cmbRayFreedomDNSStrategy"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
PlaceholderText="Default" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBDirectResolveStrategy}" />
|
||||
<ComboBox
|
||||
x:Name="cmbSBDirectDNSStrategy"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
PlaceholderText="Default" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBRemoteResolveStrategy}" />
|
||||
<ComboBox
|
||||
x:Name="cmbSBRemoteDNSStrategy"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
PlaceholderText="Default" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAddCommonHosts"
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSBDoHOverride}"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{x:Static resx:ResUI.ThAdvancedDNSSettings}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Visible">
|
||||
<Grid
|
||||
Margin="{StaticResource Margin8}"
|
||||
ColumnDefinitions="Auto,Auto,*"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,*">
|
||||
|
||||
<TextBlock
|
||||
x:Name="txtAdvancedDNSSettingsInvalid"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togUseSystemHosts"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFakeIP}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togFakeIP"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbApplyProxyDomainsOnly}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togBlockBindingQuery"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueriesTips}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPs}" />
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbDirectExpectedIPs"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding DirectExpectedIPs, Mode=TwoWay}" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbDNSHostsConfig}" />
|
||||
|
||||
<TextBox
|
||||
x:Name="txtHosts"
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderThickness="1"
|
||||
Classes="TextArea"
|
||||
TextWrapping="Wrap"
|
||||
Watermark="{x:Static resx:ResUI.TbDNSHostsConfig}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnable}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togRayCustomDNSEnableCompatible"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
|
||||
|
||||
<TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkDnsObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4V2rayCompatible"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -62,7 +343,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togUseSystemHosts"
|
||||
x:Name="togUseSystemHostsCompatible"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
@@ -73,7 +354,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainStrategy4Freedom"
|
||||
x:Name="cmbdomainStrategy4FreedomCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</StackPanel>
|
||||
@@ -83,10 +364,11 @@
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainDNSAddress"
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbdomainDNSAddressCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding DomainDNSAddressCompatible, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
@@ -96,7 +378,7 @@
|
||||
BorderThickness="1"
|
||||
Header="HTTP/SOCKS">
|
||||
<TextBox
|
||||
Name="txtnormalDNS"
|
||||
Name="txtnormalDNSCompatible"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
@@ -107,18 +389,36 @@
|
||||
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
|
||||
<TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4Singbox"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand" />
|
||||
</StackPanel>
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnable}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togSBCustomDNSEnableCompatible"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4SingboxCompatible"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -127,7 +427,7 @@
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainStrategy4Out"
|
||||
x:Name="cmbdomainStrategy4OutCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</StackPanel>
|
||||
@@ -137,10 +437,11 @@
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainDNSAddress2"
|
||||
<ctrls:AutoCompleteBox
|
||||
x:Name="cmbdomainDNSAddress2Compatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
Margin="{StaticResource Margin4}"
|
||||
Text="{Binding DomainDNSAddress2Compatible, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
@@ -152,7 +453,7 @@
|
||||
BorderThickness="1"
|
||||
Header="HTTP/SOCKS">
|
||||
<TextBox
|
||||
Name="txtnormalDNS2"
|
||||
Name="txtnormalDNS2Compatible"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
@@ -167,7 +468,7 @@
|
||||
BorderThickness="1"
|
||||
Header="{x:Static resx:ResUI.TbSettingsTunMode}">
|
||||
<TextBox
|
||||
Name="txttunDNS2"
|
||||
Name="txttunDNS2Compatible"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using ReactiveUI;
|
||||
using v2rayN.Desktop.Base;
|
||||
@@ -17,38 +18,64 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
||||
btnCancel.Click += (s, e) => this.Close();
|
||||
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
|
||||
|
||||
Global.DomainStrategy4Freedoms.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Freedom.Items.Add(it);
|
||||
});
|
||||
Global.SingboxDomainStrategy4Out.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Out.Items.Add(it);
|
||||
});
|
||||
Global.DomainDNSAddress.ForEach(it =>
|
||||
{
|
||||
cmbdomainDNSAddress.Items.Add(it);
|
||||
});
|
||||
Global.SingboxDomainDNSAddress.ForEach(it =>
|
||||
{
|
||||
cmbdomainDNSAddress2.Items.Add(it);
|
||||
});
|
||||
cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms;
|
||||
cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
|
||||
cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
|
||||
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
|
||||
cmbSBResolverDNS.ItemsSource = Global.DomainDirectDNSAddress.Concat(new[] { "dhcp://auto,localhost" });
|
||||
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
|
||||
cmbSBFinalResolverDNS.ItemsSource = Global.DomainPureIPDNSAddress.Concat(new[] { "dhcp://auto,localhost" });
|
||||
cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;
|
||||
|
||||
cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy4Freedoms;
|
||||
cmbdomainStrategy4OutCompatible.ItemsSource = Global.SingboxDomainStrategy4Out;
|
||||
cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress;
|
||||
cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RayStrategy4Freedom, v => v.cmbRayFreedomDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxStrategy4Direct, v => v.cmbSBDirectDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxStrategy4Proxy, v => v.cmbSBRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.RayCustomDNSEnableCompatible, v => v.togRayCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SBCustomDNSEnableCompatible, v => v.togSBCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.SelectedItem).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.SelectedItem).DisposeWith(disposables);
|
||||
//this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(
|
||||
x => x.ViewModel.RayCustomDNSEnableCompatible,
|
||||
x => x.ViewModel.SBCustomDNSEnableCompatible,
|
||||
(ray, sb) => ray && sb
|
||||
).BindTo(this.FindControl<TextBlock>("txtBasicDNSSettingsInvalid"), t => t.IsVisible);
|
||||
this.WhenAnyValue(
|
||||
x => x.ViewModel.RayCustomDNSEnableCompatible,
|
||||
x => x.ViewModel.SBCustomDNSEnableCompatible,
|
||||
(ray, sb) => ray && sb
|
||||
).BindTo(this.FindControl<TextBlock>("txtAdvancedDNSSettingsInvalid"), t => t.IsVisible);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
198
v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml
Normal file
198
v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml
Normal file
@@ -0,0 +1,198 @@
|
||||
<Window
|
||||
x:Class="v2rayN.Desktop.Views.FullConfigTemplateWindow"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuFullConfigTemplate}"
|
||||
Width="900"
|
||||
Height="600"
|
||||
x:DataType="vms:FullConfigTemplateViewModel"
|
||||
ShowInTaskbar="False"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbConfirm}"
|
||||
Cursor="Hand"
|
||||
IsDefault="True" />
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
Width="100"
|
||||
Margin="{StaticResource MarginLr8}"
|
||||
Content="{x:Static resx:ResUI.TbCancel}"
|
||||
Cursor="Hand"
|
||||
IsCancel="True" />
|
||||
</StackPanel>
|
||||
|
||||
<TabControl HorizontalContentAlignment="Stretch">
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbRayFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin4}">
|
||||
<Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbRayFullConfigTemplateDesc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleSwitch
|
||||
x:Name="rayFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Ray"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Ray"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<HeaderedContentControl
|
||||
Margin="{StaticResource Margin4}"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Header="xray config template json">
|
||||
<TextBox
|
||||
x:Name="rayFullConfigTemplate"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
TextWrapping="Wrap" />
|
||||
</HeaderedContentControl>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbSBFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin4}">
|
||||
<Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center">
|
||||
<HyperlinkButton Classes="WithIcon" Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbSBFullConfigTemplateDesc}" />
|
||||
</HyperlinkButton>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleSwitch
|
||||
x:Name="sbFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Singbox"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Singbox"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Margin="{StaticResource Margin4}" ColumnDefinitions="*,10,*">
|
||||
|
||||
<HeaderedContentControl
|
||||
Grid.Column="0"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Header="sing-box config template json">
|
||||
<TextBox
|
||||
x:Name="sbFullConfigTemplate"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
TextWrapping="Wrap" />
|
||||
</HeaderedContentControl>
|
||||
|
||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
||||
|
||||
<HeaderedContentControl
|
||||
Grid.Column="2"
|
||||
BorderBrush="Gray"
|
||||
BorderThickness="1"
|
||||
Header="sing-box tun config template json">
|
||||
<TextBox
|
||||
x:Name="sbFullTunConfigTemplate"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
MinLines="10"
|
||||
TextWrapping="Wrap" />
|
||||
</HeaderedContentControl>
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
</Window>
|
||||
@@ -0,0 +1,51 @@
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia.Interactivity;
|
||||
using ReactiveUI;
|
||||
using v2rayN.Desktop.Base;
|
||||
|
||||
namespace v2rayN.Desktop.Views;
|
||||
|
||||
public partial class FullConfigTemplateWindow : WindowBase<FullConfigTemplateViewModel>
|
||||
{
|
||||
private static Config _config;
|
||||
|
||||
public FullConfigTemplateWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_config = AppHandler.Instance.Config;
|
||||
btnCancel.Click += (s, e) => this.Close();
|
||||
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Singbox, v => v.sbFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Singbox, v => v.sbFullTunConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Singbox, v => v.togAddProxyProtocolOutboundOnly4Singbox.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Singbox, v => v.txtProxyDetour4Singbox.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
this.Close(true);
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void linkFullConfigTemplateDoc_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProcUtils.ProcessStart("https://github.com/2dust/v2rayN/wiki/Description-of-some-ui#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E8%AE%BE%E7%BD%AE");
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
<Separator />
|
||||
<MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" />
|
||||
<MenuItem x:Name="menuAddTuicServer" Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
||||
<MenuItem x:Name="menuAddAnytlsServer" Header="{x:Static resx:ResUI.menuAddAnytlsServer}" />
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem Padding="8,0">
|
||||
@@ -71,6 +72,7 @@
|
||||
<MenuItem x:Name="menuOptionSetting" Header="{x:Static resx:ResUI.menuOptionSetting}" />
|
||||
<MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" />
|
||||
<MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" />
|
||||
<MenuItem x:Name="menuFullConfigTemplate" Header="{x:Static resx:ResUI.menuFullConfigTemplate}" />
|
||||
<MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" />
|
||||
<Separator />
|
||||
<MenuItem x:Name="menuRebootAsAdmin" Header="{x:Static resx:ResUI.menuRebootAsAdmin}" />
|
||||
|
||||
@@ -83,6 +83,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||
@@ -99,6 +100,7 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.FullConfigTemplateCmd, v => v.menuFullConfigTemplate).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||
@@ -134,7 +136,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (Utils.IsWindows())
|
||||
{
|
||||
@@ -190,6 +191,9 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||
case EViewAction.DNSSettingWindow:
|
||||
return await new DNSSettingWindow().ShowDialog<bool>(this);
|
||||
|
||||
case EViewAction.FullConfigTemplateWindow:
|
||||
return await new FullConfigTemplateWindow().ShowDialog<bool>(this);
|
||||
|
||||
case EViewAction.RoutingSettingWindow:
|
||||
return await new RoutingSettingWindow().ShowDialog<bool>(this);
|
||||
|
||||
|
||||
@@ -69,34 +69,36 @@
|
||||
IsChecked="True"
|
||||
Theme="{DynamicResource SimpleToggleSwitch}" />
|
||||
</WrapPanel>
|
||||
<TextBox
|
||||
Name="txtMsg"
|
||||
VerticalAlignment="Stretch"
|
||||
BorderThickness="0"
|
||||
Classes="TextArea"
|
||||
IsReadOnly="True"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap">
|
||||
<TextBox.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewSelectAll"
|
||||
Click="menuMsgViewSelectAll_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewSelectAll}" />
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewCopy"
|
||||
Click="menuMsgViewCopy_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewCopy}" />
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewCopyAll"
|
||||
Click="menuMsgViewCopyAll_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewCopyAll}" />
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewClear"
|
||||
Click="menuMsgViewClear_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewClear}" />
|
||||
</ContextMenu>
|
||||
</TextBox.ContextMenu>
|
||||
</TextBox>
|
||||
|
||||
<ScrollViewer x:Name="msgScrollViewer" VerticalScrollBarVisibility="Auto">
|
||||
<SelectableTextBlock
|
||||
Name="txtMsg"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="TextArea"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap">
|
||||
<SelectableTextBlock.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewSelectAll"
|
||||
Click="menuMsgViewSelectAll_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewSelectAll}" />
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewCopy"
|
||||
Click="menuMsgViewCopy_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewCopy}" />
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewCopyAll"
|
||||
Click="menuMsgViewCopyAll_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewCopyAll}" />
|
||||
<MenuItem
|
||||
x:Name="menuMsgViewClear"
|
||||
Click="menuMsgViewClear_Click"
|
||||
Header="{x:Static resx:ResUI.menuMsgViewClear}" />
|
||||
</ContextMenu>
|
||||
</SelectableTextBlock.ContextMenu>
|
||||
</SelectableTextBlock>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reactive.Disposables;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Threading;
|
||||
@@ -9,9 +10,12 @@ namespace v2rayN.Desktop.Views;
|
||||
|
||||
public partial class MsgView : ReactiveUserControl<MsgViewModel>
|
||||
{
|
||||
private readonly ScrollViewer _scrollViewer;
|
||||
|
||||
public MsgView()
|
||||
{
|
||||
InitializeComponent();
|
||||
_scrollViewer = this.FindControl<ScrollViewer>("msgScrollViewer");
|
||||
|
||||
ViewModel = new MsgViewModel(UpdateViewHandler);
|
||||
|
||||
@@ -43,14 +47,14 @@ public partial class MsgView : ReactiveUserControl<MsgViewModel>
|
||||
txtMsg.Text = msg.ToString();
|
||||
if (togScrollToEnd.IsChecked ?? true)
|
||||
{
|
||||
txtMsg.CaretIndex = int.MaxValue;
|
||||
_scrollViewer?.ScrollToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearMsg()
|
||||
{
|
||||
ViewModel?.ClearMsg();
|
||||
txtMsg.Clear();
|
||||
txtMsg.Text = "";
|
||||
}
|
||||
|
||||
private void menuMsgViewSelectAll_Click(object? sender, RoutedEventArgs e)
|
||||
|
||||
@@ -729,71 +729,84 @@
|
||||
Margin="{StaticResource Margin4}"
|
||||
ColumnDefinitions="Auto,Auto,Auto"
|
||||
DockPanel.Dock="Top"
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="Auto Route" />
|
||||
<ToggleSwitch
|
||||
x:Name="togAutoRoute"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="Strict Route" />
|
||||
<ToggleSwitch
|
||||
x:Name="togStrictRoute"
|
||||
Grid.Row="2"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="Stack" />
|
||||
<ComboBox
|
||||
x:Name="cmbStack"
|
||||
Grid.Row="3"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="Mtu" />
|
||||
<ComboBox
|
||||
x:Name="cmbMtu"
|
||||
Grid.Row="4"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togEnableExInbound"
|
||||
Grid.Row="5"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
|
||||
<ToggleSwitch
|
||||
x:Name="togEnableIPv6Address"
|
||||
Grid.Row="6"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
@@ -19,87 +19,39 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
||||
|
||||
clbdestOverride.SelectionChanged += ClbdestOverride_SelectionChanged;
|
||||
Global.destOverrideProtocols.ForEach(it =>
|
||||
{
|
||||
clbdestOverride.Items.Add(it);
|
||||
});
|
||||
clbdestOverride.ItemsSource = Global.destOverrideProtocols;
|
||||
_config.Inbound.First().DestOverride?.ForEach(it =>
|
||||
{
|
||||
clbdestOverride.SelectedItems.Add(it);
|
||||
});
|
||||
Global.IEProxyProtocols.ForEach(it =>
|
||||
{
|
||||
cmbsystemProxyAdvancedProtocol.Items.Add(it);
|
||||
});
|
||||
Global.LogLevels.ForEach(it =>
|
||||
{
|
||||
cmbloglevel.Items.Add(it);
|
||||
});
|
||||
Global.Fingerprints.ForEach(it =>
|
||||
{
|
||||
cmbdefFingerprint.Items.Add(it);
|
||||
});
|
||||
Global.UserAgent.ForEach(it =>
|
||||
{
|
||||
cmbdefUserAgent.Items.Add(it);
|
||||
});
|
||||
Global.SingboxMuxs.ForEach(it =>
|
||||
{
|
||||
cmbmux4SboxProtocol.Items.Add(it);
|
||||
});
|
||||
|
||||
Global.TunMtus.ForEach(it =>
|
||||
{
|
||||
cmbMtu.Items.Add(it);
|
||||
});
|
||||
Global.TunStacks.ForEach(it =>
|
||||
{
|
||||
cmbStack.Items.Add(it);
|
||||
});
|
||||
Global.CoreTypes.ForEach(it =>
|
||||
{
|
||||
cmbCoreType1.Items.Add(it);
|
||||
cmbCoreType2.Items.Add(it);
|
||||
cmbCoreType3.Items.Add(it);
|
||||
cmbCoreType4.Items.Add(it);
|
||||
cmbCoreType5.Items.Add(it);
|
||||
cmbCoreType6.Items.Add(it);
|
||||
cmbCoreType9.Items.Add(it);
|
||||
});
|
||||
cmbsystemProxyAdvancedProtocol.ItemsSource = Global.IEProxyProtocols;
|
||||
cmbloglevel.ItemsSource = Global.LogLevels;
|
||||
cmbdefFingerprint.ItemsSource = Global.Fingerprints;
|
||||
cmbdefUserAgent.ItemsSource = Global.UserAgent;
|
||||
cmbmux4SboxProtocol.ItemsSource = Global.SingboxMuxs;
|
||||
cmbMtu.ItemsSource = Global.TunMtus;
|
||||
cmbStack.ItemsSource = Global.TunStacks;
|
||||
|
||||
for (var i = 2; i <= 8; i++)
|
||||
{
|
||||
cmbMixedConcurrencyCount.Items.Add(i);
|
||||
}
|
||||
for (var i = 2; i <= 6; i++)
|
||||
{
|
||||
cmbSpeedTestTimeout.Items.Add(i * 5);
|
||||
}
|
||||
cmbCoreType1.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType2.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType3.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType4.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType5.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType6.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType9.ItemsSource = Global.CoreTypes;
|
||||
|
||||
cmbMixedConcurrencyCount.ItemsSource = Enumerable.Range(2, 7).ToList();
|
||||
cmbSpeedTestTimeout.ItemsSource = Enumerable.Range(2, 5).Select(i => i * 5).ToList();
|
||||
cmbSpeedTestUrl.ItemsSource = Global.SpeedTestUrls;
|
||||
cmbSpeedPingTestUrl.ItemsSource = Global.SpeedPingTestUrls;
|
||||
cmbSubConvertUrl.ItemsSource = Global.SubConvertUrls;
|
||||
cmbGetFilesSourceUrl.ItemsSource = Global.GeoFilesSources;
|
||||
cmbSrsFilesSourceUrl.ItemsSource = Global.SingboxRulesetSources;
|
||||
cmbRoutingRulesSourceUrl.ItemsSource = Global.RoutingRulesSources;
|
||||
cmbIPAPIUrl.ItemsSource = Global.IPAPIUrls;
|
||||
|
||||
Global.GeoFilesSources.ForEach(it =>
|
||||
{
|
||||
cmbGetFilesSourceUrl.Items.Add(it);
|
||||
});
|
||||
Global.SingboxRulesetSources.ForEach(it =>
|
||||
{
|
||||
cmbSrsFilesSourceUrl.Items.Add(it);
|
||||
});
|
||||
Global.RoutingRulesSources.ForEach(it =>
|
||||
{
|
||||
cmbRoutingRulesSourceUrl.Items.Add(it);
|
||||
});
|
||||
Global.IPAPIUrls.ForEach(it =>
|
||||
{
|
||||
cmbIPAPIUrl.Items.Add(it);
|
||||
});
|
||||
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
|
||||
{
|
||||
cmbMainGirdOrientation.Items.Add(it.ToString());
|
||||
}
|
||||
cmbMainGirdOrientation.ItemsSource = Utils.GetEnumNames<EGirdOrientation>();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
@@ -153,6 +105,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.SelectedValue).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
||||
|
||||
@@ -23,19 +23,11 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
||||
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;
|
||||
|
||||
ViewModel = new RoutingRuleDetailsViewModel(rulesItem, UpdateViewHandler);
|
||||
cmbOutboundTag.ItemsSource = new List<string> { Global.ProxyTag, Global.DirectTag, Global.BlockTag };
|
||||
Global.RuleProtocols.ForEach(it =>
|
||||
{
|
||||
clbProtocol.Items.Add(it);
|
||||
});
|
||||
Global.InboundTags.ForEach(it =>
|
||||
{
|
||||
clbInboundTag.Items.Add(it);
|
||||
});
|
||||
Global.RuleNetworks.ForEach(it =>
|
||||
{
|
||||
cmbNetwork.Items.Add(it);
|
||||
});
|
||||
|
||||
cmbOutboundTag.ItemsSource = Global.OutboundTags;
|
||||
clbProtocol.ItemsSource = Global.RuleProtocols;
|
||||
clbInboundTag.ItemsSource = Global.InboundTags;
|
||||
cmbNetwork.ItemsSource = Global.RuleNetworks;
|
||||
|
||||
if (!rulesItem.Id.IsNullOrEmpty())
|
||||
{
|
||||
|
||||
@@ -30,15 +30,9 @@ public partial class RoutingRuleSettingWindow : WindowBase<RoutingRuleSettingVie
|
||||
btnBrowseCustomRulesetPath4Singbox.Click += btnBrowseCustomRulesetPath4Singbox_ClickAsync;
|
||||
|
||||
ViewModel = new RoutingRuleSettingViewModel(routingItem, UpdateViewHandler);
|
||||
Global.DomainStrategies.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy.Items.Add(it);
|
||||
});
|
||||
cmbdomainStrategy.Items.Add(string.Empty);
|
||||
Global.DomainStrategies4Singbox.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Singbox.Items.Add(it);
|
||||
});
|
||||
|
||||
cmbdomainStrategy.ItemsSource = Global.DomainStrategies.AppendEmpty();
|
||||
cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
@@ -26,18 +26,9 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
|
||||
|
||||
ViewModel = new RoutingSettingViewModel(UpdateViewHandler);
|
||||
|
||||
Global.DomainStrategies.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy.Items.Add(it);
|
||||
});
|
||||
Global.DomainMatchers.ForEach(it =>
|
||||
{
|
||||
cmbdomainMatcher.Items.Add(it);
|
||||
});
|
||||
Global.DomainStrategies4Singbox.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Singbox.Items.Add(it);
|
||||
});
|
||||
cmbdomainStrategy.ItemsSource = Global.DomainStrategies;
|
||||
cmbdomainMatcher.ItemsSource = Global.DomainMatchers;
|
||||
cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
@@ -126,7 +117,7 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>
|
||||
|
||||
private void linkdomainStrategy4Singbox_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
ProcUtils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/shared/listen/#domain_strategy");
|
||||
ProcUtils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/route/rule_action/#strategy");
|
||||
}
|
||||
|
||||
private void btnCancel_Click(object? sender, RoutedEventArgs e)
|
||||
|
||||
@@ -104,13 +104,15 @@ public partial class StatusBarView : ReactiveUserControl<StatusBarViewModel>
|
||||
{
|
||||
var dialog = new SudoPasswordInputView();
|
||||
var obj = await DialogHost.Show(dialog);
|
||||
if (obj == null)
|
||||
|
||||
var password = obj?.ToString();
|
||||
if (password.IsNullOrEmpty())
|
||||
{
|
||||
togEnableTun.IsChecked = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
AppHandler.Instance.LinuxSudoPwd = obj.ToString() ?? string.Empty;
|
||||
AppHandler.Instance.LinuxSudoPwd = password;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,7 @@ public partial class SubEditWindow : WindowBase<SubEditViewModel>
|
||||
|
||||
ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);
|
||||
|
||||
Global.SubConvertTargets.ForEach(it =>
|
||||
{
|
||||
cmbConvertTarget.Items.Add(it);
|
||||
});
|
||||
cmbConvertTarget.ItemsSource = Global.SubConvertTargets;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using CliWrap.Buffered;
|
||||
using DialogHostAvalonia;
|
||||
|
||||
namespace v2rayN.Desktop.Views;
|
||||
@@ -12,22 +13,70 @@ public partial class SudoPasswordInputView : UserControl
|
||||
|
||||
this.Loaded += (s, e) => txtPassword.Focus();
|
||||
|
||||
btnSave.Click += (_, _) =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(txtPassword.Text))
|
||||
{
|
||||
txtPassword.Focus();
|
||||
return;
|
||||
}
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
DialogHost.Close(null, txtPassword.Text);
|
||||
});
|
||||
};
|
||||
btnSave.Click += async (_, _) => await SavePasswordAsync();
|
||||
|
||||
btnCancel.Click += (_, _) =>
|
||||
{
|
||||
DialogHost.Close(null);
|
||||
};
|
||||
}
|
||||
|
||||
private async Task SavePasswordAsync()
|
||||
{
|
||||
if (txtPassword.Text.IsNullOrEmpty())
|
||||
{
|
||||
txtPassword.Focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var password = txtPassword.Text;
|
||||
btnSave.IsEnabled = false;
|
||||
|
||||
try
|
||||
{
|
||||
// Verify if the password is correct
|
||||
if (await CheckSudoPasswordAsync(password))
|
||||
{
|
||||
// Password verification successful, return password and close dialog
|
||||
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
DialogHost.Close(null, password);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Password verification failed, display error and let user try again
|
||||
NoticeHandler.Instance.Enqueue(ResUI.SudoIncorrectPasswordTip);
|
||||
txtPassword.Focus();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog("SudoPassword", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
btnSave.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> CheckSudoPasswordAsync(string password)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Use sudo echo command to verify password
|
||||
var arg = new List<string>() { "-c", "sudo -S echo SUDO_CHECK" };
|
||||
var result = await CliWrap.Cli.Wrap(Global.LinuxBash)
|
||||
.WithArguments(arg)
|
||||
.WithStandardInputPipe(CliWrap.PipeSource.FromString(password))
|
||||
.ExecuteBufferedAsync();
|
||||
|
||||
return result.ExitCode == 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog("CheckSudoPassword", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,9 @@ public partial class ThemeSettingView : ReactiveUserControl<ThemeSettingViewMode
|
||||
InitializeComponent();
|
||||
ViewModel = new ThemeSettingViewModel();
|
||||
|
||||
foreach (ETheme it in Enum.GetValues(typeof(ETheme)))
|
||||
{
|
||||
cmbCurrentTheme.Items.Add(it.ToString());
|
||||
}
|
||||
|
||||
for (int i = Global.MinFontSize; i <= Global.MinFontSize + 10; i++)
|
||||
{
|
||||
cmbCurrentFontSize.Items.Add(i);
|
||||
}
|
||||
|
||||
Global.Languages.ForEach(it =>
|
||||
{
|
||||
cmbCurrentLanguage.Items.Add(it);
|
||||
});
|
||||
cmbCurrentTheme.ItemsSource = Utils.GetEnumNames<ETheme>();
|
||||
cmbCurrentFontSize.ItemsSource = Enumerable.Range(Global.MinFontSize, 11).ToList();
|
||||
cmbCurrentLanguage.ItemsSource = Global.Languages;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
<EmbeddedResource Include="Assets\v2rayN.ico">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
<Compile Update="Views\FullConfigTemplateWindow.axaml.cs">
|
||||
<DependentUpon>FullConfigTemplateWindow.axaml</DependentUpon>
|
||||
</Compile>
|
||||
<None Update="v2rayN.png">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
|
||||
@@ -14,13 +14,7 @@ public partial class AddServer2Window
|
||||
this.Loaded += Window_Loaded;
|
||||
ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);
|
||||
|
||||
foreach (ECoreType it in Enum.GetValues(typeof(ECoreType)))
|
||||
{
|
||||
if (it == ECoreType.v2rayN)
|
||||
continue;
|
||||
cmbCoreType.Items.Add(it.ToString());
|
||||
}
|
||||
cmbCoreType.Items.Add(string.Empty);
|
||||
cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
@@ -707,6 +707,35 @@
|
||||
materialDesign:HintAssist.Hint="1500"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</Grid>
|
||||
<Grid
|
||||
x:Name="gridAnytls"
|
||||
Grid.Row="2"
|
||||
Visibility="Hidden">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbId3}" />
|
||||
<TextBox
|
||||
x:Name="txtId10"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</Grid>
|
||||
|
||||
<Separator
|
||||
x:Name="sepa2"
|
||||
@@ -979,6 +1008,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="180" />
|
||||
@@ -1064,6 +1094,22 @@
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin4}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbMldsa65Verify}" />
|
||||
<TextBox
|
||||
x:Name="txtMldsa65Verify"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="400"
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Left"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</Grid>
|
||||
<Separator
|
||||
Grid.Row="8"
|
||||
|
||||
@@ -20,41 +20,22 @@ public partial class AddServerWindow
|
||||
|
||||
ViewModel = new AddServerViewModel(profileItem, UpdateViewHandler);
|
||||
|
||||
Global.CoreTypes.ForEach(it =>
|
||||
{
|
||||
cmbCoreType.Items.Add(it);
|
||||
});
|
||||
cmbCoreType.Items.Add(string.Empty);
|
||||
cmbCoreType.ItemsSource = Global.CoreTypes.AppendEmpty();
|
||||
cmbNetwork.ItemsSource = Global.Networks;
|
||||
cmbFingerprint.ItemsSource = Global.Fingerprints;
|
||||
cmbFingerprint2.ItemsSource = Global.Fingerprints;
|
||||
cmbAllowInsecure.ItemsSource = Global.AllowInsecure;
|
||||
cmbAlpn.ItemsSource = Global.Alpns;
|
||||
|
||||
cmbStreamSecurity.Items.Add(string.Empty);
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurity);
|
||||
|
||||
Global.Networks.ForEach(it =>
|
||||
{
|
||||
cmbNetwork.Items.Add(it);
|
||||
});
|
||||
Global.Fingerprints.ForEach(it =>
|
||||
{
|
||||
cmbFingerprint.Items.Add(it);
|
||||
cmbFingerprint2.Items.Add(it);
|
||||
});
|
||||
Global.AllowInsecure.ForEach(it =>
|
||||
{
|
||||
cmbAllowInsecure.Items.Add(it);
|
||||
});
|
||||
Global.Alpns.ForEach(it =>
|
||||
{
|
||||
cmbAlpn.Items.Add(it);
|
||||
});
|
||||
var lstStreamSecurity = new List<string>();
|
||||
lstStreamSecurity.Add(string.Empty);
|
||||
lstStreamSecurity.Add(Global.StreamSecurity);
|
||||
|
||||
switch (profileItem.ConfigType)
|
||||
{
|
||||
case EConfigType.VMess:
|
||||
gridVMess.Visibility = Visibility.Visible;
|
||||
Global.VmessSecurities.ForEach(it =>
|
||||
{
|
||||
cmbSecurity.Items.Add(it);
|
||||
});
|
||||
cmbSecurity.ItemsSource = Global.VmessSecurities;
|
||||
if (profileItem.Security.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.Security = Global.DefaultSecurity;
|
||||
@@ -63,10 +44,7 @@ public partial class AddServerWindow
|
||||
|
||||
case EConfigType.Shadowsocks:
|
||||
gridSs.Visibility = Visibility.Visible;
|
||||
AppHandler.Instance.GetShadowsocksSecurities(profileItem).ForEach(it =>
|
||||
{
|
||||
cmbSecurity3.Items.Add(it);
|
||||
});
|
||||
cmbSecurity3.ItemsSource = AppHandler.Instance.GetShadowsocksSecurities(profileItem);
|
||||
break;
|
||||
|
||||
case EConfigType.SOCKS:
|
||||
@@ -76,11 +54,8 @@ public partial class AddServerWindow
|
||||
|
||||
case EConfigType.VLESS:
|
||||
gridVLESS.Visibility = Visibility.Visible;
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityReality);
|
||||
Global.Flows.ForEach(it =>
|
||||
{
|
||||
cmbFlow5.Items.Add(it);
|
||||
});
|
||||
lstStreamSecurity.Add(Global.StreamSecurityReality);
|
||||
cmbFlow5.ItemsSource = Global.Flows;
|
||||
if (profileItem.Security.IsNullOrEmpty())
|
||||
{
|
||||
profileItem.Security = Global.None;
|
||||
@@ -89,11 +64,8 @@ public partial class AddServerWindow
|
||||
|
||||
case EConfigType.Trojan:
|
||||
gridTrojan.Visibility = Visibility.Visible;
|
||||
cmbStreamSecurity.Items.Add(Global.StreamSecurityReality);
|
||||
Global.Flows.ForEach(it =>
|
||||
{
|
||||
cmbFlow6.Items.Add(it);
|
||||
});
|
||||
lstStreamSecurity.Add(Global.StreamSecurityReality);
|
||||
cmbFlow6.ItemsSource = Global.Flows;
|
||||
break;
|
||||
|
||||
case EConfigType.Hysteria2:
|
||||
@@ -113,10 +85,7 @@ public partial class AddServerWindow
|
||||
cmbFingerprint.IsEnabled = false;
|
||||
cmbFingerprint.Text = string.Empty;
|
||||
|
||||
Global.TuicCongestionControls.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType8.Items.Add(it);
|
||||
});
|
||||
cmbHeaderType8.ItemsSource = Global.TuicCongestionControls;
|
||||
break;
|
||||
|
||||
case EConfigType.WireGuard:
|
||||
@@ -127,7 +96,14 @@ public partial class AddServerWindow
|
||||
gridTls.Visibility = Visibility.Collapsed;
|
||||
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
gridAnytls.Visibility = Visibility.Visible;
|
||||
cmbCoreType.IsEnabled = false;
|
||||
lstStreamSecurity.Add(Global.StreamSecurityReality);
|
||||
break;
|
||||
}
|
||||
cmbStreamSecurity.ItemsSource = lstStreamSecurity;
|
||||
|
||||
gridTlsMore.Visibility = Visibility.Hidden;
|
||||
|
||||
@@ -191,6 +167,10 @@ public partial class AddServerWindow
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables);
|
||||
break;
|
||||
|
||||
case EConfigType.Anytls:
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Id, v => v.txtId10.Text).DisposeWith(disposables);
|
||||
break;
|
||||
}
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables);
|
||||
@@ -209,6 +189,7 @@ public partial class AddServerWindow
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.PublicKey, v => v.txtPublicKey.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
@@ -267,44 +248,41 @@ public partial class AddServerWindow
|
||||
|
||||
private void SetHeaderType()
|
||||
{
|
||||
cmbHeaderType.Items.Clear();
|
||||
var lstHeaderType = new List<string>();
|
||||
|
||||
var network = cmbNetwork.SelectedItem.ToString();
|
||||
if (network.IsNullOrEmpty())
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
lstHeaderType.Add(Global.None);
|
||||
cmbHeaderType.ItemsSource = lstHeaderType;
|
||||
cmbHeaderType.SelectedIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (network == nameof(ETransport.tcp))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
cmbHeaderType.Items.Add(Global.TcpHeaderHttp);
|
||||
lstHeaderType.Add(Global.None);
|
||||
lstHeaderType.Add(Global.TcpHeaderHttp);
|
||||
}
|
||||
else if (network is nameof(ETransport.kcp) or nameof(ETransport.quic))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
Global.KcpHeaderTypes.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
lstHeaderType.Add(Global.None);
|
||||
lstHeaderType.AddRange(Global.KcpHeaderTypes);
|
||||
}
|
||||
else if (network is nameof(ETransport.xhttp))
|
||||
{
|
||||
Global.XhttpMode.ForEach(it =>
|
||||
{
|
||||
cmbHeaderType.Items.Add(it);
|
||||
});
|
||||
lstHeaderType.AddRange(Global.XhttpMode);
|
||||
}
|
||||
else if (network == nameof(ETransport.grpc))
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.GrpcGunMode);
|
||||
cmbHeaderType.Items.Add(Global.GrpcMultiMode);
|
||||
lstHeaderType.Add(Global.GrpcGunMode);
|
||||
lstHeaderType.Add(Global.GrpcMultiMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
cmbHeaderType.Items.Add(Global.None);
|
||||
lstHeaderType.Add(Global.None);
|
||||
}
|
||||
cmbHeaderType.ItemsSource = lstHeaderType;
|
||||
cmbHeaderType.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<reactiveui:ReactiveUserControl
|
||||
x:Class="v2rayN.Views.ClashConnectionsView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
d:DesignHeight="450"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<reactiveui:ReactiveUserControl
|
||||
x:Class="v2rayN.Views.ClashProxiesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
xmlns:converters="clr-namespace:v2rayN.Converters"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:TypeArguments="vms:ClashProxiesViewModel"
|
||||
|
||||
@@ -41,31 +41,365 @@
|
||||
</StackPanel>
|
||||
|
||||
<TabControl HorizontalContentAlignment="Left">
|
||||
<TabItem Header="{x:Static resx:ResUI.ThBasicDNSSettings}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Visible">
|
||||
<Grid Margin="{StaticResource Margin8}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
x:Name="txtBasicDNSSettingsInvalid"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkDnsObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4V2ray"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbDomesticDNS}" />
|
||||
<ComboBox
|
||||
x:Name="cmbDirectDNS"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
IsEditable="True"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbRemoteDNS}" />
|
||||
<ComboBox
|
||||
x:Name="cmbRemoteDNS"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
IsEditable="True"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBOutboundsResolverDNS}" />
|
||||
<ComboBox
|
||||
x:Name="cmbSBResolverDNS"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
IsEditable="True"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBOutboundDomainResolve}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBDoHResolverServer}" />
|
||||
<ComboBox
|
||||
x:Name="cmbSBFinalResolverDNS"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
IsEditable="True"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbXrayFreedomResolveStrategy}" />
|
||||
<ComboBox
|
||||
x:Name="cmbRayFreedomDNSStrategy"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
materialDesign:HintAssist.Hint="Default"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBDirectResolveStrategy}" />
|
||||
<ComboBox
|
||||
x:Name="cmbSBDirectDNSStrategy"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
materialDesign:HintAssist.Hint="Default"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBRemoteResolveStrategy}" />
|
||||
<ComboBox
|
||||
x:Name="cmbSBRemoteDNSStrategy"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
materialDesign:HintAssist.Hint="Default"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAddCommonDNSHosts}" />
|
||||
<ToggleButton
|
||||
x:Name="togAddCommonHosts"
|
||||
Grid.Row="8"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="8"
|
||||
Grid.Column="3"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSBDoHOverride}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
<TabItem Header="{x:Static resx:ResUI.ThAdvancedDNSSettings}">
|
||||
<ScrollViewer VerticalScrollBarVisibility="Visible">
|
||||
<Grid Margin="{StaticResource Margin8}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock
|
||||
x:Name="txtAdvancedDNSSettingsInvalid"
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
|
||||
<ToggleButton
|
||||
x:Name="togUseSystemHosts"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFakeIP}" />
|
||||
<ToggleButton
|
||||
x:Name="togFakeIP"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbApplyProxyDomainsOnly}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}" />
|
||||
<ToggleButton
|
||||
x:Name="togBlockBindingQuery"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
<TextBlock
|
||||
Grid.Row="3"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbBlockSVCBHTTPSQueriesTips}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPs}" />
|
||||
<ComboBox
|
||||
x:Name="cmbDirectExpectedIPs"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
IsEditable="True"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="2"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbDNSHostsConfig}" />
|
||||
<TextBox
|
||||
x:Name="txtHosts"
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbDNSHostsConfig}"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</TabItem>
|
||||
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnable}" />
|
||||
<ToggleButton
|
||||
x:Name="togRayCustomDNSEnableCompatible"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkDnsObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4V2rayCompatible"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -75,7 +409,7 @@
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
|
||||
<ToggleButton
|
||||
x:Name="togUseSystemHosts"
|
||||
x:Name="togUseSystemHostsCompatible"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
@@ -87,7 +421,7 @@
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainStrategy4Freedom"
|
||||
x:Name="cmbdomainStrategy4FreedomCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
@@ -100,7 +434,7 @@
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainDNSAddress"
|
||||
x:Name="cmbdomainDNSAddressCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin8}"
|
||||
IsEditable="True"
|
||||
@@ -109,7 +443,7 @@
|
||||
</WrapPanel>
|
||||
|
||||
<TextBox
|
||||
x:Name="txtnormalDNS"
|
||||
x:Name="txtnormalDNSCompatible"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="HTTP/SOCKS"
|
||||
@@ -123,23 +457,42 @@
|
||||
|
||||
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkDnsSingboxObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4Singbox"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbCustomDNSEnable}" />
|
||||
<ToggleButton
|
||||
x:Name="togSBCustomDNSEnableCompatible"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkDnsSingboxObjectDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
<Button
|
||||
x:Name="btnImportDefConfig4SingboxCompatible"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
|
||||
Cursor="Hand"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -149,7 +502,7 @@
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainStrategy4Out"
|
||||
x:Name="cmbdomainStrategy4OutCompatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
@@ -162,7 +515,7 @@
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
|
||||
<ComboBox
|
||||
x:Name="cmbdomainDNSAddress2"
|
||||
x:Name="cmbdomainDNSAddress2Compatible"
|
||||
Width="150"
|
||||
Margin="{StaticResource Margin8}"
|
||||
IsEditable="True"
|
||||
@@ -178,7 +531,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
x:Name="txtnormalDNS2"
|
||||
x:Name="txtnormalDNS2Compatible"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="HTTP/SOCKS"
|
||||
@@ -191,7 +544,7 @@
|
||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
||||
|
||||
<TextBox
|
||||
x:Name="txttunDNS2"
|
||||
x:Name="txttunDNS2Compatible"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsTunMode}"
|
||||
|
||||
@@ -17,38 +17,66 @@ public partial class DNSSettingWindow
|
||||
|
||||
ViewModel = new DNSSettingViewModel(UpdateViewHandler);
|
||||
|
||||
Global.DomainStrategy4Freedoms.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Freedom.Items.Add(it);
|
||||
});
|
||||
Global.SingboxDomainStrategy4Out.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Out.Items.Add(it);
|
||||
});
|
||||
Global.DomainDNSAddress.ForEach(it =>
|
||||
{
|
||||
cmbdomainDNSAddress.Items.Add(it);
|
||||
});
|
||||
Global.SingboxDomainDNSAddress.ForEach(it =>
|
||||
{
|
||||
cmbdomainDNSAddress2.Items.Add(it);
|
||||
});
|
||||
cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms;
|
||||
cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
|
||||
cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out;
|
||||
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
|
||||
cmbSBResolverDNS.ItemsSource = Global.DomainDirectDNSAddress.Concat(new[] { "dhcp://auto,localhost" });
|
||||
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
|
||||
cmbSBFinalResolverDNS.ItemsSource = Global.DomainPureIPDNSAddress.Concat(new[] { "dhcp://auto,localhost" });
|
||||
cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;
|
||||
|
||||
cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy4Freedoms;
|
||||
cmbdomainStrategy4OutCompatible.ItemsSource = Global.SingboxDomainStrategy4Out;
|
||||
cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress;
|
||||
cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom, v => v.cmbdomainStrategy4Freedom.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.RayStrategy4Freedom, v => v.cmbRayFreedomDNSStrategy.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxStrategy4Direct, v => v.cmbSBDirectDNSStrategy.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SingboxStrategy4Proxy, v => v.cmbSBRemoteDNSStrategy.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCmd, v => v.btnImportDefConfig4V2ray).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCmd, v => v.btnImportDefConfig4Singbox).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.RayCustomDNSEnableCompatible, v => v.togRayCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.SBCustomDNSEnableCompatible, v => v.togSBCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables);
|
||||
|
||||
this.WhenAnyValue(
|
||||
x => x.ViewModel.RayCustomDNSEnableCompatible,
|
||||
x => x.ViewModel.SBCustomDNSEnableCompatible,
|
||||
(ray, sb) => ray && sb ? Visibility.Visible : Visibility.Collapsed)
|
||||
.BindTo(this, x => x.txtBasicDNSSettingsInvalid.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
this.WhenAnyValue(
|
||||
x => x.ViewModel.RayCustomDNSEnableCompatible,
|
||||
x => x.ViewModel.SBCustomDNSEnableCompatible,
|
||||
(ray, sb) => ray && sb ? Visibility.Visible : Visibility.Collapsed)
|
||||
.BindTo(this, x => x.txtAdvancedDNSSettingsInvalid.Visibility)
|
||||
.DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
|
||||
}
|
||||
|
||||
227
v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml
Normal file
227
v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml
Normal file
@@ -0,0 +1,227 @@
|
||||
<base:WindowBase
|
||||
x:Class="v2rayN.Views.FullConfigTemplateWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:base="clr-namespace:v2rayN.Base"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:reactiveui="http://reactiveui.net"
|
||||
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
|
||||
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
|
||||
Title="{x:Static resx:ResUI.menuFullConfigTemplate}"
|
||||
Width="1000"
|
||||
Height="700"
|
||||
x:TypeArguments="vms:FullConfigTemplateViewModel"
|
||||
ShowInTaskbar="False"
|
||||
Style="{StaticResource WindowGlobal}"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
mc:Ignorable="d">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<StackPanel
|
||||
Margin="{StaticResource Margin4}"
|
||||
HorizontalAlignment="Center"
|
||||
DockPanel.Dock="Bottom"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
x:Name="btnSave"
|
||||
Width="100"
|
||||
Content="{x:Static resx:ResUI.TbConfirm}"
|
||||
Cursor="Hand"
|
||||
IsDefault="True"
|
||||
Style="{StaticResource DefButton}" />
|
||||
<Button
|
||||
x:Name="btnCancel"
|
||||
Width="100"
|
||||
Margin="{StaticResource MarginLeftRight8}"
|
||||
Content="{x:Static resx:ResUI.TbCancel}"
|
||||
Cursor="Hand"
|
||||
IsCancel="true"
|
||||
Style="{StaticResource DefButton}" />
|
||||
</StackPanel>
|
||||
|
||||
<TabControl HorizontalContentAlignment="Left">
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbRayFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbRayFullConfigTemplateDesc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleButton
|
||||
x:Name="rayFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleButton
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Ray"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Ray"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<TextBox
|
||||
x:Name="rayFullConfigTemplate"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="xray config template json"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
<TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbSBFullConfigTemplate}">
|
||||
<DockPanel Margin="{StaticResource Margin8}">
|
||||
<Grid DockPanel.Dock="Top">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateDesc}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}">
|
||||
<Hyperlink Click="linkFullConfigTemplateDoc_Click">
|
||||
<TextBlock Text="{x:Static resx:ResUI.TbSBFullConfigTemplateDesc}" />
|
||||
<materialDesign:PackIcon Kind="Link" />
|
||||
</Hyperlink>
|
||||
</TextBlock>
|
||||
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbFullConfigTemplateEnable}" />
|
||||
<ToggleButton
|
||||
x:Name="sbFullConfigTemplateEnable"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}" />
|
||||
<ToggleButton
|
||||
x:Name="togAddProxyProtocolOutboundOnly4Singbox"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="{x:Static resx:ResUI.TbSetUpstreamProxyDetour}" />
|
||||
<TextBox
|
||||
x:Name="txtProxyDetour4Singbox"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
Style="{StaticResource DefTextBox}" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
|
||||
<Grid Margin="{StaticResource Margin8}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="1*" />
|
||||
<ColumnDefinition Width="10" />
|
||||
<ColumnDefinition Width="1*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
x:Name="sbFullConfigTemplate"
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="sing-box config template json"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
|
||||
<GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" />
|
||||
|
||||
<TextBox
|
||||
x:Name="sbFullTunConfigTemplate"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Stretch"
|
||||
materialDesign:HintAssist.Hint="sing-box tun config template json"
|
||||
AcceptsReturn="True"
|
||||
BorderThickness="1"
|
||||
Style="{StaticResource MaterialDesignOutlinedTextBox}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</Grid>
|
||||
</DockPanel>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</DockPanel>
|
||||
</base:WindowBase>
|
||||
52
v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs
Normal file
52
v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Reactive.Disposables;
|
||||
using System.Windows;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace v2rayN.Views;
|
||||
|
||||
public partial class FullConfigTemplateWindow
|
||||
{
|
||||
private static Config _config;
|
||||
|
||||
public FullConfigTemplateWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.Owner = Application.Current.MainWindow;
|
||||
_config = AppHandler.Instance.Config;
|
||||
|
||||
ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullConfigTemplate4Singbox, v => v.sbFullConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Singbox, v => v.sbFullTunConfigTemplate.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.AddProxyOnly4Singbox, v => v.togAddProxyProtocolOutboundOnly4Singbox.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.ProxyDetour4Singbox, v => v.txtProxyDetour4Singbox.Text).DisposeWith(disposables);
|
||||
|
||||
this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);
|
||||
});
|
||||
WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme);
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case EViewAction.CloseWindow:
|
||||
this.DialogResult = true;
|
||||
break;
|
||||
}
|
||||
return await Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void linkFullConfigTemplateDoc_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProcUtils.ProcessStart("https://github.com/2dust/v2rayN/wiki/Description-of-some-ui#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E8%AE%BE%E7%BD%AE");
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,10 @@
|
||||
x:Name="menuAddTuicServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAddTuicServer}" />
|
||||
<MenuItem
|
||||
x:Name="menuAddAnytlsServer"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuAddAnytlsServer}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<Separator />
|
||||
@@ -169,6 +173,10 @@
|
||||
x:Name="menuDNSSetting"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuDNSSetting}" />
|
||||
<MenuItem
|
||||
x:Name="menuFullConfigTemplate"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
Header="{x:Static resx:ResUI.menuFullConfigTemplate}" />
|
||||
<MenuItem
|
||||
x:Name="menuGlobalHotkeySetting"
|
||||
Height="{StaticResource MenuItemHeight}"
|
||||
|
||||
@@ -80,6 +80,7 @@ public partial class MainWindow
|
||||
this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);
|
||||
@@ -96,6 +97,7 @@ public partial class MainWindow
|
||||
this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.FullConfigTemplateCmd, v => v.menuFullConfigTemplate).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);
|
||||
this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);
|
||||
@@ -185,6 +187,9 @@ public partial class MainWindow
|
||||
case EViewAction.OptionSettingWindow:
|
||||
return (new OptionSettingWindow().ShowDialog() ?? false);
|
||||
|
||||
case EViewAction.FullConfigTemplateWindow:
|
||||
return (new FullConfigTemplateWindow().ShowDialog() ?? false);
|
||||
|
||||
case EViewAction.GlobalHotkeySettingWindow:
|
||||
return (new GlobalHotkeySettingWindow().ShowDialog() ?? false);
|
||||
|
||||
|
||||
@@ -26,10 +26,7 @@ public partial class MsgView
|
||||
menuMsgViewCopyAll.Click += menuMsgViewCopyAll_Click;
|
||||
menuMsgViewClear.Click += menuMsgViewClear_Click;
|
||||
|
||||
Global.PresetMsgFilters.ForEach(it =>
|
||||
{
|
||||
cmbMsgFilter.Items.Add(it);
|
||||
});
|
||||
cmbMsgFilter.ItemsSource = Global.PresetMsgFilters;
|
||||
}
|
||||
|
||||
private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)
|
||||
|
||||
@@ -1023,6 +1023,7 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -1036,9 +1037,9 @@
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="Strict Route" />
|
||||
Text="Auto Route" />
|
||||
<ToggleButton
|
||||
x:Name="togStrictRoute"
|
||||
x:Name="togAutoRoute"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
@@ -1050,10 +1051,24 @@
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="Strict Route" />
|
||||
<ToggleButton
|
||||
x:Name="togStrictRoute"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource ToolbarTextBlock}"
|
||||
Text="Stack" />
|
||||
<ComboBox
|
||||
x:Name="cmbStack"
|
||||
Grid.Row="3"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
@@ -1061,7 +1076,7 @@
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="4"
|
||||
Grid.Row="5"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -1069,7 +1084,7 @@
|
||||
Text="Mtu" />
|
||||
<ComboBox
|
||||
x:Name="cmbMtu"
|
||||
Grid.Row="4"
|
||||
Grid.Row="5"
|
||||
Grid.Column="1"
|
||||
Width="200"
|
||||
Margin="{StaticResource Margin8}"
|
||||
@@ -1077,7 +1092,7 @@
|
||||
Style="{StaticResource DefComboBox}" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="5"
|
||||
Grid.Row="6"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -1085,13 +1100,13 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableExInbound}" />
|
||||
<ToggleButton
|
||||
x:Name="togEnableExInbound"
|
||||
Grid.Row="5"
|
||||
Grid.Row="6"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="6"
|
||||
Grid.Row="7"
|
||||
Grid.Column="0"
|
||||
Margin="{StaticResource Margin8}"
|
||||
VerticalAlignment="Center"
|
||||
@@ -1099,7 +1114,7 @@
|
||||
Text="{x:Static resx:ResUI.TbSettingsEnableIPv6Address}" />
|
||||
<ToggleButton
|
||||
x:Name="togEnableIPv6Address"
|
||||
Grid.Row="6"
|
||||
Grid.Row="7"
|
||||
Grid.Column="1"
|
||||
Margin="{StaticResource Margin8}"
|
||||
HorizontalAlignment="Left" />
|
||||
|
||||
@@ -21,94 +21,39 @@ public partial class OptionSettingWindow
|
||||
ViewModel = new OptionSettingViewModel(UpdateViewHandler);
|
||||
|
||||
clbdestOverride.SelectionChanged += ClbdestOverride_SelectionChanged;
|
||||
Global.destOverrideProtocols.ForEach(it =>
|
||||
{
|
||||
clbdestOverride.Items.Add(it);
|
||||
});
|
||||
clbdestOverride.ItemsSource = Global.destOverrideProtocols;
|
||||
_config.Inbound.First().DestOverride?.ForEach(it =>
|
||||
{
|
||||
clbdestOverride.SelectedItems.Add(it);
|
||||
});
|
||||
Global.IEProxyProtocols.ForEach(it =>
|
||||
{
|
||||
cmbsystemProxyAdvancedProtocol.Items.Add(it);
|
||||
});
|
||||
Global.LogLevels.ForEach(it =>
|
||||
{
|
||||
cmbloglevel.Items.Add(it);
|
||||
});
|
||||
Global.Fingerprints.ForEach(it =>
|
||||
{
|
||||
cmbdefFingerprint.Items.Add(it);
|
||||
});
|
||||
Global.UserAgent.ForEach(it =>
|
||||
{
|
||||
cmbdefUserAgent.Items.Add(it);
|
||||
});
|
||||
Global.SingboxMuxs.ForEach(it =>
|
||||
{
|
||||
cmbmux4SboxProtocol.Items.Add(it);
|
||||
});
|
||||
|
||||
Global.TunMtus.ForEach(it =>
|
||||
{
|
||||
cmbMtu.Items.Add(it);
|
||||
});
|
||||
Global.TunStacks.ForEach(it =>
|
||||
{
|
||||
cmbStack.Items.Add(it);
|
||||
});
|
||||
Global.CoreTypes.ForEach(it =>
|
||||
{
|
||||
cmbCoreType1.Items.Add(it);
|
||||
cmbCoreType2.Items.Add(it);
|
||||
cmbCoreType3.Items.Add(it);
|
||||
cmbCoreType4.Items.Add(it);
|
||||
cmbCoreType5.Items.Add(it);
|
||||
cmbCoreType6.Items.Add(it);
|
||||
cmbCoreType9.Items.Add(it);
|
||||
});
|
||||
cmbsystemProxyAdvancedProtocol.ItemsSource = Global.IEProxyProtocols;
|
||||
cmbloglevel.ItemsSource = Global.LogLevels;
|
||||
cmbdefFingerprint.ItemsSource = Global.Fingerprints;
|
||||
cmbdefUserAgent.ItemsSource = Global.UserAgent;
|
||||
cmbmux4SboxProtocol.ItemsSource = Global.SingboxMuxs;
|
||||
cmbMtu.ItemsSource = Global.TunMtus;
|
||||
cmbStack.ItemsSource = Global.TunStacks;
|
||||
|
||||
for (var i = 2; i <= 8; i++)
|
||||
{
|
||||
cmbMixedConcurrencyCount.Items.Add(i);
|
||||
}
|
||||
for (var i = 2; i <= 6; i++)
|
||||
{
|
||||
cmbSpeedTestTimeout.Items.Add(i * 5);
|
||||
}
|
||||
Global.SpeedTestUrls.ForEach(it =>
|
||||
{
|
||||
cmbSpeedTestUrl.Items.Add(it);
|
||||
});
|
||||
Global.SpeedPingTestUrls.ForEach(it =>
|
||||
{
|
||||
cmbSpeedPingTestUrl.Items.Add(it);
|
||||
});
|
||||
Global.SubConvertUrls.ForEach(it =>
|
||||
{
|
||||
cmbSubConvertUrl.Items.Add(it);
|
||||
});
|
||||
Global.GeoFilesSources.ForEach(it =>
|
||||
{
|
||||
cmbGetFilesSourceUrl.Items.Add(it);
|
||||
});
|
||||
Global.SingboxRulesetSources.ForEach(it =>
|
||||
{
|
||||
cmbSrsFilesSourceUrl.Items.Add(it);
|
||||
});
|
||||
Global.RoutingRulesSources.ForEach(it =>
|
||||
{
|
||||
cmbRoutingRulesSourceUrl.Items.Add(it);
|
||||
});
|
||||
Global.IPAPIUrls.ForEach(it =>
|
||||
{
|
||||
cmbIPAPIUrl.Items.Add(it);
|
||||
});
|
||||
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
|
||||
{
|
||||
cmbMainGirdOrientation.Items.Add(it.ToString());
|
||||
}
|
||||
cmbCoreType1.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType2.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType3.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType4.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType5.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType6.ItemsSource = Global.CoreTypes;
|
||||
cmbCoreType9.ItemsSource = Global.CoreTypes;
|
||||
|
||||
cmbMixedConcurrencyCount.ItemsSource = Enumerable.Range(2, 7).ToList();
|
||||
cmbSpeedTestTimeout.ItemsSource = Enumerable.Range(2, 5).Select(i => i * 5).ToList();
|
||||
cmbSpeedTestUrl.ItemsSource = Global.SpeedTestUrls;
|
||||
cmbSpeedPingTestUrl.ItemsSource = Global.SpeedPingTestUrls;
|
||||
cmbSubConvertUrl.ItemsSource = Global.SubConvertUrls;
|
||||
cmbGetFilesSourceUrl.ItemsSource = Global.GeoFilesSources;
|
||||
cmbSrsFilesSourceUrl.ItemsSource = Global.SingboxRulesetSources;
|
||||
cmbRoutingRulesSourceUrl.ItemsSource = Global.RoutingRulesSources;
|
||||
cmbIPAPIUrl.ItemsSource = Global.IPAPIUrls;
|
||||
|
||||
cmbMainGirdOrientation.ItemsSource = Utils.GetEnumNames<EGirdOrientation>();
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
@@ -172,6 +117,7 @@ public partial class OptionSettingWindow
|
||||
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
|
||||
|
||||
this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);
|
||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
|
||||
@@ -209,8 +155,7 @@ public partial class OptionSettingWindow
|
||||
private async Task InitSettingFont()
|
||||
{
|
||||
var lstFonts = await GetFonts(Utils.GetFontsPath());
|
||||
lstFonts.ForEach(it => { cmbcurrentFontFamily.Items.Add(it); });
|
||||
cmbcurrentFontFamily.Items.Add(string.Empty);
|
||||
cmbcurrentFontFamily.ItemsSource = lstFonts.AppendEmpty();
|
||||
}
|
||||
|
||||
private async Task<List<string>> GetFonts(string path)
|
||||
|
||||
@@ -16,21 +16,11 @@ public partial class RoutingRuleDetailsWindow
|
||||
clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;
|
||||
|
||||
ViewModel = new RoutingRuleDetailsViewModel(rulesItem, UpdateViewHandler);
|
||||
cmbOutboundTag.Items.Add(Global.ProxyTag);
|
||||
cmbOutboundTag.Items.Add(Global.DirectTag);
|
||||
cmbOutboundTag.Items.Add(Global.BlockTag);
|
||||
Global.RuleProtocols.ForEach(it =>
|
||||
{
|
||||
clbProtocol.Items.Add(it);
|
||||
});
|
||||
Global.InboundTags.ForEach(it =>
|
||||
{
|
||||
clbInboundTag.Items.Add(it);
|
||||
});
|
||||
Global.RuleNetworks.ForEach(it =>
|
||||
{
|
||||
cmbNetwork.Items.Add(it);
|
||||
});
|
||||
|
||||
cmbOutboundTag.ItemsSource = Global.OutboundTags;
|
||||
clbProtocol.ItemsSource = Global.RuleProtocols;
|
||||
clbInboundTag.ItemsSource = Global.InboundTags;
|
||||
cmbNetwork.ItemsSource = Global.RuleNetworks;
|
||||
|
||||
if (!rulesItem.Id.IsNullOrEmpty())
|
||||
{
|
||||
|
||||
@@ -21,15 +21,9 @@ public partial class RoutingRuleSettingWindow
|
||||
btnBrowseCustomRulesetPath4Singbox.Click += btnBrowseCustomRulesetPath4Singbox_Click;
|
||||
|
||||
ViewModel = new RoutingRuleSettingViewModel(routingItem, UpdateViewHandler);
|
||||
Global.DomainStrategies.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy.Items.Add(it);
|
||||
});
|
||||
cmbdomainStrategy.Items.Add(string.Empty);
|
||||
Global.DomainStrategies4Singbox.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Singbox.Items.Add(it);
|
||||
});
|
||||
|
||||
cmbdomainStrategy.ItemsSource = Global.DomainStrategies.AppendEmpty();
|
||||
cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
@@ -21,18 +21,9 @@ public partial class RoutingSettingWindow
|
||||
|
||||
ViewModel = new RoutingSettingViewModel(UpdateViewHandler);
|
||||
|
||||
Global.DomainStrategies.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy.Items.Add(it);
|
||||
});
|
||||
Global.DomainMatchers.ForEach(it =>
|
||||
{
|
||||
cmbdomainMatcher.Items.Add(it);
|
||||
});
|
||||
Global.DomainStrategies4Singbox.ForEach(it =>
|
||||
{
|
||||
cmbdomainStrategy4Singbox.Items.Add(it);
|
||||
});
|
||||
cmbdomainStrategy.ItemsSource = Global.DomainStrategies;
|
||||
cmbdomainMatcher.ItemsSource = Global.DomainMatchers;
|
||||
cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Singbox;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
@@ -131,7 +122,7 @@ public partial class RoutingSettingWindow
|
||||
|
||||
private void linkdomainStrategy4Singbox_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ProcUtils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/shared/listen/#domain_strategy");
|
||||
ProcUtils.ProcessStart("https://sing-box.sagernet.org/zh/configuration/route/rule_action/#strategy");
|
||||
}
|
||||
|
||||
private void btnCancel_Click(object sender, System.Windows.RoutedEventArgs e)
|
||||
|
||||
@@ -92,8 +92,7 @@
|
||||
AutomationProperties.Name="{x:Static resx:ResUI.menuRouting}"
|
||||
DisplayMemberPath="Remarks"
|
||||
FontSize="{DynamicResource StdFontSize}"
|
||||
Style="{StaticResource MaterialDesignFloatingHintComboBox}">
|
||||
</ComboBox>
|
||||
Style="{StaticResource MaterialDesignFloatingHintComboBox}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Margin="{StaticResource MarginLeftRight8}" VerticalAlignment="Center">
|
||||
@@ -185,8 +184,7 @@
|
||||
AutomationProperties.Name="{x:Static resx:ResUI.menuRouting}"
|
||||
DisplayMemberPath="Remarks"
|
||||
FontSize="{DynamicResource StdFontSize}"
|
||||
Style="{StaticResource MaterialDesignFilledComboBox}">
|
||||
</ComboBox>
|
||||
Style="{StaticResource MaterialDesignFilledComboBox}" />
|
||||
</DockPanel>
|
||||
</MenuItem.Header>
|
||||
</MenuItem>
|
||||
@@ -200,8 +198,7 @@
|
||||
AutomationProperties.Name="{x:Static resx:ResUI.menuServers}"
|
||||
DisplayMemberPath="Text"
|
||||
FontSize="{DynamicResource StdFontSize}"
|
||||
Style="{StaticResource MaterialDesignFilledComboBox}">
|
||||
</ComboBox>
|
||||
Style="{StaticResource MaterialDesignFilledComboBox}" />
|
||||
</DockPanel>
|
||||
</MenuItem.Header>
|
||||
</MenuItem>
|
||||
|
||||
@@ -15,10 +15,7 @@ public partial class SubEditWindow
|
||||
|
||||
ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);
|
||||
|
||||
Global.SubConvertTargets.ForEach(it =>
|
||||
{
|
||||
cmbConvertTarget.Items.Add(it);
|
||||
});
|
||||
cmbConvertTarget.ItemsSource = Global.SubConvertTargets;
|
||||
|
||||
this.WhenActivated(disposables =>
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user