mirror of
				https://github.com/2dust/v2rayN.git
				synced 2025-10-30 12:02:53 +00:00 
			
		
		
		
	Merge 9886c52e89 into 6fa5ca5aa9
				
					
				
			This commit is contained in:
		
						commit
						a1041628cd
					
				
					 51 changed files with 4115 additions and 406 deletions
				
			
		|  | @ -128,5 +128,8 @@ public class JsonUtils | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="obj"></param> |     /// <param name="obj"></param> | ||||||
|     /// <returns></returns> |     /// <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); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -466,11 +466,11 @@ public class Utils | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static int GetFreePort(int defaultPort = 9090) |     public static int GetFreePort(int defaultPort = 0) | ||||||
|     { |     { | ||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             if (!Utils.PortInUse(defaultPort)) |             if (!(defaultPort == 0 || Utils.PortInUse(defaultPort))) | ||||||
|             { |             { | ||||||
|                 return defaultPort; |                 return defaultPort; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  | @ -11,5 +11,6 @@ public enum EConfigType | ||||||
|     Hysteria2 = 7, |     Hysteria2 = 7, | ||||||
|     TUIC = 8, |     TUIC = 8, | ||||||
|     WireGuard = 9, |     WireGuard = 9, | ||||||
|     HTTP = 10 |     HTTP = 10, | ||||||
|  |     Anytls = 11 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ public enum EViewAction | ||||||
|     DNSSettingWindow, |     DNSSettingWindow, | ||||||
|     RoutingSettingWindow, |     RoutingSettingWindow, | ||||||
|     OptionSettingWindow, |     OptionSettingWindow, | ||||||
|  |     CustomConfigWindow, | ||||||
|     GlobalHotkeySettingWindow, |     GlobalHotkeySettingWindow, | ||||||
|     SubSettingWindow, |     SubSettingWindow, | ||||||
|     DispatcherSpeedTest, |     DispatcherSpeedTest, | ||||||
|  |  | ||||||
|  | @ -76,6 +76,13 @@ public class Global | ||||||
|     public const int SpeedTestPageSize = 1000; |     public const int SpeedTestPageSize = 1000; | ||||||
|     public const string LinuxBash = "/bin/bash"; |     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 = |     public static readonly List<string> IEProxyProtocols = | ||||||
|     [ |     [ | ||||||
|         "{ip}:{http_port}", |         "{ip}:{http_port}", | ||||||
|  | @ -169,7 +176,8 @@ public class Global | ||||||
|             { EConfigType.Trojan, "trojan://" }, |             { EConfigType.Trojan, "trojan://" }, | ||||||
|             { EConfigType.Hysteria2, "hysteria2://" }, |             { EConfigType.Hysteria2, "hysteria2://" }, | ||||||
|             { EConfigType.TUIC, "tuic://" }, |             { EConfigType.TUIC, "tuic://" }, | ||||||
|             { EConfigType.WireGuard, "wireguard://" } |             { EConfigType.WireGuard, "wireguard://" }, | ||||||
|  |             { EConfigType.Anytls, "anytls://" } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|     public static readonly Dictionary<EConfigType, string> ProtocolTypes = new() |     public static readonly Dictionary<EConfigType, string> ProtocolTypes = new() | ||||||
|  | @ -182,7 +190,8 @@ public class Global | ||||||
|             { EConfigType.Trojan, "trojan" }, |             { EConfigType.Trojan, "trojan" }, | ||||||
|             { EConfigType.Hysteria2, "hysteria2" }, |             { EConfigType.Hysteria2, "hysteria2" }, | ||||||
|             { EConfigType.TUIC, "tuic" }, |             { EConfigType.TUIC, "tuic" }, | ||||||
|             { EConfigType.WireGuard, "wireguard" } |             { EConfigType.WireGuard, "wireguard" }, | ||||||
|  |             { EConfigType.Anytls, "anytls" } | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|     public static readonly List<string> VmessSecurities = |     public static readonly List<string> VmessSecurities = | ||||||
|  | @ -349,25 +358,42 @@ public class Global | ||||||
| 
 | 
 | ||||||
|     public static readonly List<string> SingboxDomainStrategy4Out = |     public static readonly List<string> SingboxDomainStrategy4Out = | ||||||
|     [ |     [ | ||||||
|         "ipv4_only", |         "", | ||||||
|  |             "ipv4_only", | ||||||
|             "prefer_ipv4", |             "prefer_ipv4", | ||||||
|             "prefer_ipv6", |             "prefer_ipv6", | ||||||
|             "ipv6_only", |             "ipv6_only" | ||||||
|             "" |  | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     public static readonly List<string> DomainDNSAddress = |     public static readonly List<string> DomainDirectDNSAddress = | ||||||
|     [ |     [ | ||||||
|         "223.5.5.5", |         "https://dns.alidns.com/dns-query", | ||||||
|             "223.6.6.6", |             "https://doh.pub/dns-query", | ||||||
|  |             "223.5.5.5", | ||||||
|  |             "119.29.29.29", | ||||||
|             "localhost" |             "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.5.5.5", | ||||||
|             "223.6.6.6", |             "119.29.29.29", | ||||||
|             "dhcp://auto" |             "localhost" | ||||||
|     ]; |     ]; | ||||||
| 
 | 
 | ||||||
|     public static readonly List<string> Languages = |     public static readonly List<string> Languages = | ||||||
|  | @ -537,5 +563,30 @@ public class Global | ||||||
|         BlockTag |         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 |     #endregion const | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -64,6 +64,7 @@ public sealed class AppHandler | ||||||
|         SQLiteHelper.Instance.CreateTable<RoutingItem>(); |         SQLiteHelper.Instance.CreateTable<RoutingItem>(); | ||||||
|         SQLiteHelper.Instance.CreateTable<ProfileExItem>(); |         SQLiteHelper.Instance.CreateTable<ProfileExItem>(); | ||||||
|         SQLiteHelper.Instance.CreateTable<DNSItem>(); |         SQLiteHelper.Instance.CreateTable<DNSItem>(); | ||||||
|  |         SQLiteHelper.Instance.CreateTable<CustomConfigItem>(); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -203,6 +204,16 @@ public sealed class AppHandler | ||||||
|         return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType); |         return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public async Task<List<CustomConfigItem>?> CustomConfigItem() | ||||||
|  |     { | ||||||
|  |         return await SQLiteHelper.Instance.TableAsync<CustomConfigItem>().ToListAsync(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public async Task<CustomConfigItem?> GetCustomConfigItem(ECoreType eCoreType) | ||||||
|  |     { | ||||||
|  |         return await SQLiteHelper.Instance.TableAsync<CustomConfigItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     #endregion SqliteHelper |     #endregion SqliteHelper | ||||||
| 
 | 
 | ||||||
|     #region Core Type |     #region Core Type | ||||||
|  |  | ||||||
|  | @ -112,6 +112,11 @@ public class ConfigHandler | ||||||
| 
 | 
 | ||||||
|         config.ConstItem ??= new ConstItem(); |         config.ConstItem ??= new ConstItem(); | ||||||
| 
 | 
 | ||||||
|  |         if (config.SimpleDNSItem == null) | ||||||
|  |         { | ||||||
|  |             InitBuiltinSimpleDNS(config); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         config.SpeedTestItem ??= new(); |         config.SpeedTestItem ??= new(); | ||||||
|         if (config.SpeedTestItem.SpeedTestTimeout < 10) |         if (config.SpeedTestItem.SpeedTestTimeout < 10) | ||||||
|         { |         { | ||||||
|  | @ -261,6 +266,7 @@ public class ConfigHandler | ||||||
|             EConfigType.Hysteria2 => await AddHysteria2Server(config, item), |             EConfigType.Hysteria2 => await AddHysteria2Server(config, item), | ||||||
|             EConfigType.TUIC => await AddTuicServer(config, item), |             EConfigType.TUIC => await AddTuicServer(config, item), | ||||||
|             EConfigType.WireGuard => await AddWireguardServer(config, item), |             EConfigType.WireGuard => await AddWireguardServer(config, item), | ||||||
|  |             EConfigType.Anytls => await AddAnytlsServer(config, item), | ||||||
|             _ => -1, |             _ => -1, | ||||||
|         }; |         }; | ||||||
|         return ret; |         return ret; | ||||||
|  | @ -785,6 +791,35 @@ public class ConfigHandler | ||||||
|         return 0; |         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> |     /// <summary> | ||||||
|     /// Sort the server list by the specified column |     /// Sort the server list by the specified column | ||||||
|     /// Updates the sort order in the profile extension data |     /// Updates the sort order in the profile extension data | ||||||
|  | @ -1294,6 +1329,7 @@ public class ConfigHandler | ||||||
|                 EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false), |                 EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false), | ||||||
|                 EConfigType.TUIC => await AddTuicServer(config, profileItem, false), |                 EConfigType.TUIC => await AddTuicServer(config, profileItem, false), | ||||||
|                 EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false), |                 EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false), | ||||||
|  |                 EConfigType.Anytls => await AddAnytlsServer(config, profileItem, false), | ||||||
|                 _ => -1, |                 _ => -1, | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|  | @ -2062,18 +2098,38 @@ public class ConfigHandler | ||||||
|     /// <summary> |     /// <summary> | ||||||
|     /// Initialize built-in DNS configurations |     /// Initialize built-in DNS configurations | ||||||
|     /// Creates default DNS items for V2Ray and sing-box |     /// Creates default DNS items for V2Ray and sing-box | ||||||
|  |     /// Also checks existing DNS items and disables those with empty NormalDNS | ||||||
|     /// </summary> |     /// </summary> | ||||||
|     /// <param name="config">Current configuration</param> |     /// <param name="config">Current configuration</param> | ||||||
|     /// <returns>0 if successful</returns> |     /// <returns>0 if successful</returns> | ||||||
|     public static async Task<int> InitBuiltinDNS(Config config) |     public static async Task<int> InitBuiltinDNS(Config config) | ||||||
|     { |     { | ||||||
|         var items = await AppHandler.Instance.DNSItems(); |         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) |         if (items.Count <= 0) | ||||||
|         { |         { | ||||||
|             var item = new DNSItem() |             var item = new DNSItem() | ||||||
|             { |             { | ||||||
|                 Remarks = "V2ray", |                 Remarks = "V2ray", | ||||||
|                 CoreType = ECoreType.Xray, |                 CoreType = ECoreType.Xray, | ||||||
|  |                 Enabled = false, | ||||||
|             }; |             }; | ||||||
|             await SaveDNSItems(config, item); |             await SaveDNSItems(config, item); | ||||||
| 
 | 
 | ||||||
|  | @ -2081,6 +2137,7 @@ public class ConfigHandler | ||||||
|             { |             { | ||||||
|                 Remarks = "sing-box", |                 Remarks = "sing-box", | ||||||
|                 CoreType = ECoreType.sing_box, |                 CoreType = ECoreType.sing_box, | ||||||
|  |                 Enabled = false, | ||||||
|             }; |             }; | ||||||
|             await SaveDNSItems(config, item2); |             await SaveDNSItems(config, item2); | ||||||
|         } |         } | ||||||
|  | @ -2152,6 +2209,86 @@ public class ConfigHandler | ||||||
| 
 | 
 | ||||||
|     #endregion DNS |     #endregion DNS | ||||||
| 
 | 
 | ||||||
|  |     #region Simple DNS | ||||||
|  | 
 | ||||||
|  |     public static int InitBuiltinSimpleDNS(Config config) | ||||||
|  |     { | ||||||
|  |         config.SimpleDNSItem = 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() | ||||||
|  |         }; | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     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> InitBuiltinCustomConfig(Config config) | ||||||
|  |     { | ||||||
|  |         var items = await AppHandler.Instance.CustomConfigItem(); | ||||||
|  |         if (items.Count <= 0) | ||||||
|  |         { | ||||||
|  |             var item = new CustomConfigItem() | ||||||
|  |             { | ||||||
|  |                 Remarks = "V2ray", | ||||||
|  |                 CoreType = ECoreType.Xray, | ||||||
|  |             }; | ||||||
|  |             await SaveCustomConfigItem(config, item); | ||||||
|  | 
 | ||||||
|  |             var item2 = new CustomConfigItem() | ||||||
|  |             { | ||||||
|  |                 Remarks = "sing-box", | ||||||
|  |                 CoreType = ECoreType.sing_box, | ||||||
|  |             }; | ||||||
|  |             await SaveCustomConfigItem(config, item2); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |     public static async Task<int> SaveCustomConfigItem(Config config, CustomConfigItem 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 |     #region Regional Presets | ||||||
| 
 | 
 | ||||||
|     /// <summary> |     /// <summary> | ||||||
|  | @ -2173,6 +2310,8 @@ public class ConfigHandler | ||||||
|                 await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>(); |                 await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>(); | ||||||
|                 await InitBuiltinDNS(config); |                 await InitBuiltinDNS(config); | ||||||
| 
 | 
 | ||||||
|  |                 InitBuiltinSimpleDNS(config); | ||||||
|  | 
 | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
|             case EPresetType.Russia: |             case EPresetType.Russia: | ||||||
|  | @ -2183,6 +2322,8 @@ public class ConfigHandler | ||||||
|                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + "v2ray.json")); |                 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")); |                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + "sing_box.json")); | ||||||
| 
 | 
 | ||||||
|  |                 config.SimpleDNSItem = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[1] + "simple_dns.json"); | ||||||
|  | 
 | ||||||
|                 return true; |                 return true; | ||||||
| 
 | 
 | ||||||
|             case EPresetType.Iran: |             case EPresetType.Iran: | ||||||
|  | @ -2193,6 +2334,8 @@ public class ConfigHandler | ||||||
|                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + "v2ray.json")); |                 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")); |                 await SaveDNSItems(config, await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + "sing_box.json")); | ||||||
| 
 | 
 | ||||||
|  |                 config.SimpleDNSItem = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[2] + "simple_dns.json"); | ||||||
|  | 
 | ||||||
|                 return true; |                 return true; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -101,7 +101,7 @@ public class CoreHandler | ||||||
| 
 | 
 | ||||||
|     public async Task<int> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds) |     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 fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false)); | ||||||
|         var configPath = Utils.GetBinConfigPath(fileName); |         var configPath = Utils.GetBinConfigPath(fileName); | ||||||
|         var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType); |         var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType); | ||||||
|  |  | ||||||
							
								
								
									
										49
									
								
								v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | using static QRCoder.PayloadGenerator; | ||||||
|  | 
 | ||||||
|  | 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); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -18,6 +18,7 @@ public class FmtHandler | ||||||
|                 EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item), |                 EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item), | ||||||
|                 EConfigType.TUIC => TuicFmt.ToUri(item), |                 EConfigType.TUIC => TuicFmt.ToUri(item), | ||||||
|                 EConfigType.WireGuard => WireguardFmt.ToUri(item), |                 EConfigType.WireGuard => WireguardFmt.ToUri(item), | ||||||
|  |                 EConfigType.Anytls => AnytlsFmt.ToUri(item), | ||||||
|                 _ => null, |                 _ => null, | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|  | @ -75,6 +76,10 @@ public class FmtHandler | ||||||
|             { |             { | ||||||
|                 return WireguardFmt.Resolve(str, out msg); |                 return WireguardFmt.Resolve(str, out msg); | ||||||
|             } |             } | ||||||
|  |             else if (str.StartsWith(Global.ProtocolShares[EConfigType.Anytls])) | ||||||
|  |             { | ||||||
|  |                 return AnytlsFmt.Resolve(str, out msg); | ||||||
|  |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 msg = ResUI.NonvmessOrssProtocol; |                 msg = ResUI.NonvmessOrssProtocol; | ||||||
|  |  | ||||||
|  | @ -48,6 +48,7 @@ public class Config | ||||||
|     public List<InItem> Inbound { get; set; } |     public List<InItem> Inbound { get; set; } | ||||||
|     public List<KeyEventItem> GlobalHotkeys { get; set; } |     public List<KeyEventItem> GlobalHotkeys { get; set; } | ||||||
|     public List<CoreTypeItem> CoreTypeItem { get; set; } |     public List<CoreTypeItem> CoreTypeItem { get; set; } | ||||||
|  |     public SimpleDNSItem SimpleDNSItem { get; set; } | ||||||
| 
 | 
 | ||||||
|     #endregion other entities |     #endregion other entities | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -253,3 +253,21 @@ public class WindowSizeItem | ||||||
|     public int Width { get; set; } |     public int Width { get; set; } | ||||||
|     public int Height { 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; } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										18
									
								
								v2rayN/ServiceLib/Models/CustomConfigItem.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								v2rayN/ServiceLib/Models/CustomConfigItem.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | using SQLite; | ||||||
|  | 
 | ||||||
|  | namespace ServiceLib.Models; | ||||||
|  | 
 | ||||||
|  | [Serializable] | ||||||
|  | public class CustomConfigItem | ||||||
|  | { | ||||||
|  |     [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; } | ||||||
|  | } | ||||||
|  | @ -9,7 +9,7 @@ public class DNSItem | ||||||
|     public string Id { get; set; } |     public string Id { get; set; } | ||||||
| 
 | 
 | ||||||
|     public string Remarks { 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 ECoreType CoreType { get; set; } | ||||||
|     public bool UseSystemHosts { get; set; } |     public bool UseSystemHosts { get; set; } | ||||||
|     public string? NormalDNS { get; set; } |     public string? NormalDNS { get; set; } | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | using System.Text.Json.Serialization; | ||||||
|  | 
 | ||||||
| namespace ServiceLib.Models; | namespace ServiceLib.Models; | ||||||
| 
 | 
 | ||||||
| public class SingboxConfig | public class SingboxConfig | ||||||
|  | @ -6,6 +8,7 @@ public class SingboxConfig | ||||||
|     public Dns4Sbox? dns { get; set; } |     public Dns4Sbox? dns { get; set; } | ||||||
|     public List<Inbound4Sbox> inbounds { get; set; } |     public List<Inbound4Sbox> inbounds { get; set; } | ||||||
|     public List<Outbound4Sbox> outbounds { get; set; } |     public List<Outbound4Sbox> outbounds { get; set; } | ||||||
|  |     public List<Endpoints4Sbox>? endpoints { get; set; } | ||||||
|     public Route4Sbox route { get; set; } |     public Route4Sbox route { get; set; } | ||||||
|     public Experimental4Sbox? experimental { get; set; } |     public Experimental4Sbox? experimental { get; set; } | ||||||
| } | } | ||||||
|  | @ -29,14 +32,15 @@ public class Dns4Sbox | ||||||
|     public bool? independent_cache { get; set; } |     public bool? independent_cache { get; set; } | ||||||
|     public bool? reverse_mapping { get; set; } |     public bool? reverse_mapping { get; set; } | ||||||
|     public string? client_subnet { get; set; } |     public string? client_subnet { get; set; } | ||||||
|     public Fakeip4Sbox? fakeip { get; set; } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class Route4Sbox | public class Route4Sbox | ||||||
| { | { | ||||||
|  |     public Rule4Sbox? default_domain_resolver { get; set; } // or string | ||||||
|     public bool? auto_detect_interface { get; set; } |     public bool? auto_detect_interface { get; set; } | ||||||
|     public List<Rule4Sbox> rules { get; set; } |     public List<Rule4Sbox> rules { get; set; } | ||||||
|     public List<Ruleset4Sbox>? rule_set { get; set; } |     public List<Ruleset4Sbox>? rule_set { get; set; } | ||||||
|  |     public string? final { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [Serializable] | [Serializable] | ||||||
|  | @ -49,6 +53,7 @@ public class Rule4Sbox | ||||||
|     public string? mode { get; set; } |     public string? mode { get; set; } | ||||||
|     public bool? ip_is_private { get; set; } |     public bool? ip_is_private { get; set; } | ||||||
|     public string? client_subnet { get; set; } |     public string? client_subnet { get; set; } | ||||||
|  |     public int? rewrite_ttl { get; set; } | ||||||
|     public bool? invert { get; set; } |     public bool? invert { get; set; } | ||||||
|     public string? clash_mode { get; set; } |     public string? clash_mode { get; set; } | ||||||
|     public List<string>? inbound { 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>? process_name { get; set; } | ||||||
|     public List<string>? rule_set { get; set; } |     public List<string>? rule_set { get; set; } | ||||||
|     public List<Rule4Sbox>? rules { 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] | [Serializable] | ||||||
|  | @ -76,7 +102,6 @@ public class Inbound4Sbox | ||||||
|     public string tag { get; set; } |     public string tag { get; set; } | ||||||
|     public string listen { get; set; } |     public string listen { get; set; } | ||||||
|     public int? listen_port { get; set; } |     public int? listen_port { get; set; } | ||||||
|     public string? domain_strategy { get; set; } |  | ||||||
|     public string interface_name { get; set; } |     public string interface_name { get; set; } | ||||||
|     public List<string>? address { get; set; } |     public List<string>? address { get; set; } | ||||||
|     public int? mtu { get; set; } |     public int? mtu { get; set; } | ||||||
|  | @ -84,8 +109,6 @@ public class Inbound4Sbox | ||||||
|     public bool? strict_route { get; set; } |     public bool? strict_route { get; set; } | ||||||
|     public bool? endpoint_independent_nat { get; set; } |     public bool? endpoint_independent_nat { get; set; } | ||||||
|     public string? stack { 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; } |     public List<User4Sbox> users { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -95,10 +118,8 @@ public class User4Sbox | ||||||
|     public string password { get; set; } |     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 string? server { get; set; } | ||||||
|     public int? server_port { get; set; } |     public int? server_port { get; set; } | ||||||
|     public List<string>? server_ports { 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_conn { get; set; } | ||||||
|     public int? recv_window { get; set; } |     public int? recv_window { get; set; } | ||||||
|     public bool? disable_mtu_discovery { get; set; } |     public bool? disable_mtu_discovery { get; set; } | ||||||
|     public string? detour { get; set; } |  | ||||||
|     public string? method { get; set; } |     public string? method { get; set; } | ||||||
|     public string? username { get; set; } |     public string? username { get; set; } | ||||||
|     public string? password { get; set; } |     public string? password { get; set; } | ||||||
|  | @ -121,21 +141,36 @@ public class Outbound4Sbox | ||||||
|     public string? version { get; set; } |     public string? version { get; set; } | ||||||
|     public string? network { get; set; } |     public string? network { get; set; } | ||||||
|     public string? packet_encoding { 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 { get; set; } | ||||||
|     public string? plugin_opts { 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 List<string>? outbounds { get; set; } | ||||||
|     public bool? interrupt_exist_connections { 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 class Tls4Sbox | ||||||
| { | { | ||||||
|     public bool enabled { get; set; } |     public bool enabled { get; set; } | ||||||
|  | @ -191,15 +226,25 @@ public class HyObfs4Sbox | ||||||
|     public string? password { get; set; } |     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 { get; set; } | ||||||
|     public string? address_resolver { get; set; } |     public string? address_resolver { get; set; } | ||||||
|     public string? address_strategy { get; set; } |     public string? address_strategy { get; set; } | ||||||
|     public string? strategy { get; set; } |     public string? strategy { get; set; } | ||||||
|     public string? detour { get; set; } |     // Deprecated End | ||||||
|     public string? client_subnet { get; set; } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class Experimental4Sbox | public class Experimental4Sbox | ||||||
|  | @ -229,13 +274,6 @@ public class Stats4Sbox | ||||||
|     public List<string>? users { get; set; } |     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 class CacheFile4Sbox | ||||||
| { | { | ||||||
|     public bool enabled { get; set; } |     public bool enabled { get; set; } | ||||||
|  | @ -254,3 +292,33 @@ public class Ruleset4Sbox | ||||||
|     public string? download_detour { get; set; } |     public string? download_detour { get; set; } | ||||||
|     public string? update_interval { 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 class V2rayConfig | ||||||
| { | { | ||||||
|     public Log4Ray log { get; set; } |     public Log4Ray log { get; set; } | ||||||
|     public object dns { get; set; } |     public Dns4Ray dns { get; set; } | ||||||
|     public List<Inbounds4Ray> inbounds { get; set; } |     public List<Inbounds4Ray> inbounds { get; set; } | ||||||
|     public List<Outbounds4Ray> outbounds { get; set; } |     public List<Outbounds4Ray> outbounds { get; set; } | ||||||
|     public Routing4Ray routing { get; set; } |     public Routing4Ray routing { get; set; } | ||||||
|  | @ -203,7 +203,8 @@ public class Response4Ray | ||||||
| 
 | 
 | ||||||
| public class Dns4Ray | public class Dns4Ray | ||||||
| { | { | ||||||
|     public List<string> servers { get; set; } |     public Dictionary<string, List<string>>? hosts { get; set; } | ||||||
|  |     public List<object> servers { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class DnsServer4Ray | public class DnsServer4Ray | ||||||
|  | @ -211,6 +212,8 @@ public class DnsServer4Ray | ||||||
|     public string? address { get; set; } |     public string? address { get; set; } | ||||||
|     public List<string>? domains { get; set; } |     public List<string>? domains { get; set; } | ||||||
|     public bool? skipFallback { get; set; } |     public bool? skipFallback { get; set; } | ||||||
|  |     public List<string>? expectedIPs { get; set; } | ||||||
|  |     public List<string>? unexpectedIPs { get; set; } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| public class Routing4Ray | public class Routing4Ray | ||||||
|  |  | ||||||
							
								
								
									
										288
									
								
								v2rayN/ServiceLib/Resx/ResUI.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										288
									
								
								v2rayN/ServiceLib/Resx/ResUI.Designer.cs
									
									
									
										generated
									
									
									
								
							|  | @ -186,6 +186,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Please fill in the correct custom config 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string FillCorrectConfigText { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("FillCorrectConfigText", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Please fill in the correct custom DNS 的本地化字符串。 |         ///   查找类似 Please fill in the correct custom DNS 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -654,6 +663,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Add [Anytls] Configuration 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string menuAddAnytlsServer { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("menuAddAnytlsServer", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Add a custom configuration Configuration 的本地化字符串。 |         ///   查找类似 Add a custom configuration Configuration 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -843,6 +861,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Custom Config 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string menuCustomConfig { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("menuCustomConfig", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 DNS Settings 的本地化字符串。 |         ///   查找类似 DNS Settings 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2211,6 +2238,24 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <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> |         /// <summary> | ||||||
|         ///   查找类似 Address 的本地化字符串。 |         ///   查找类似 Address 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2247,6 +2292,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Apply to Proxy Domains Only 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbApplyProxyDomainsOnly { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbApplyProxyDomainsOnly", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Auto refresh 的本地化字符串。 |         ///   查找类似 Auto refresh 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2274,6 +2328,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Block SVCB and HTTPS Queries 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbBlockSVCBHTTPSQueries { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbBlockSVCBHTTPSQueries", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Browse 的本地化字符串。 |         ///   查找类似 Browse 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2328,6 +2391,42 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Enable Custom Config 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbCustomConfigEnable { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbCustomConfigEnable", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 sing-box Custom Config 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbCustomConfigSingbox { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbCustomConfigSingbox", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <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> |         /// <summary> | ||||||
|         ///   查找类似 Display GUI 的本地化字符串。 |         ///   查找类似 Display GUI 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2346,6 +2445,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 DNS Hosts: ("domain1 ip1 ip2" per line) 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbDNSHostsConfig { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbDNSHostsConfig", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。 |         ///   查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2391,6 +2499,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Domestic DNS 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbDomesticDNS { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbDomesticDNS", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Edit 的本地化字符串。 |         ///   查找类似 Edit 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2409,6 +2526,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 FakeIP 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbFakeIP { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbFakeIP", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Fingerprint 的本地化字符串。 |         ///   查找类似 Fingerprint 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2598,6 +2724,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Prevent DNS Leaks 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbPreventDNSLeaks { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbPreventDNSLeaks", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Private Key 的本地化字符串。 |         ///   查找类似 Private Key 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2625,6 +2760,24 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 v2ray Custom Config 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbRayCustomConfig { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbRayCustomConfig", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Add Outbound Config Only, routing.balancers and routing.rules.outboundTag 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbRayCustomConfigDesc { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbRayCustomConfigDesc", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Alias (remarks) 的本地化字符串。 |         ///   查找类似 Alias (remarks) 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2634,6 +2787,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Remote DNS 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbRemoteDNS { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbRemoteDNS", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Camouflage domain(host) 的本地化字符串。 |         ///   查找类似 Camouflage domain(host) 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -2742,6 +2904,78 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Add Outbound and Endpoint Config Only 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbSBCustomConfigDesc { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbSBCustomConfigDesc", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         /// <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> | ||||||
|  |         ///   查找类似 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> |         /// <summary> | ||||||
|         ///   查找类似 Encryption method (security) 的本地化字符串。 |         ///   查找类似 Encryption method (security) 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -3525,6 +3759,15 @@ namespace ServiceLib.Resx { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|          |          | ||||||
|  |         /// <summary> | ||||||
|  |         ///   查找类似 Set Upstream Proxy Tag 的本地化字符串。 | ||||||
|  |         /// </summary> | ||||||
|  |         public static string TbSetUpstreamProxyDetour { | ||||||
|  |             get { | ||||||
|  |                 return ResourceManager.GetString("TbSetUpstreamProxyDetour", resourceCulture); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |          | ||||||
|         /// <summary> |         /// <summary> | ||||||
|         ///   查找类似 Short Id 的本地化字符串。 |         ///   查找类似 Short Id 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -3687,6 +3930,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> |         /// <summary> | ||||||
|         ///   查找类似 The delay: {0} ms, {1} 的本地化字符串。 |         ///   查找类似 The delay: {0} ms, {1} 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  | @ -3696,6 +3966,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> |         /// <summary> | ||||||
|         ///   查找类似 Active 的本地化字符串。 |         ///   查找类似 Active 的本地化字符串。 | ||||||
|         /// </summary> |         /// </summary> | ||||||
|  |  | ||||||
|  | @ -1398,4 +1398,100 @@ | ||||||
|   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> |   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> | ||||||
|     <value>Incorrect password, please try again.</value> |     <value>Incorrect password, please try again.</value> | ||||||
|   </data> |   </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="TbPreventDNSLeaks" xml:space="preserve"> | ||||||
|  |     <value>Prevent DNS Leaks</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="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>v2ray Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigSingbox" xml:space="preserve"> | ||||||
|  |     <value>sing-box Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSBCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound and Endpoint Config Only</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> | ||||||
| </root> | </root> | ||||||
|  | @ -1398,4 +1398,100 @@ | ||||||
|   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> |   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> | ||||||
|     <value>Incorrect password, please try again.</value> |     <value>Incorrect password, please try again.</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="menuAddAnytlsServer" xml:space="preserve"> | ||||||
|  |     <value>[Anytls] szerver hozzáadása</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="TbPreventDNSLeaks" xml:space="preserve"> | ||||||
|  |     <value>Prevent DNS Leaks</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="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>v2ray Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigSingbox" xml:space="preserve"> | ||||||
|  |     <value>sing-box Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSBCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound and Endpoint Config Only</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> | ||||||
| </root> | </root> | ||||||
|  | @ -1398,4 +1398,100 @@ | ||||||
|   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> |   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> | ||||||
|     <value>Incorrect password, please try again.</value> |     <value>Incorrect password, please try again.</value> | ||||||
|   </data> |   </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="TbPreventDNSLeaks" xml:space="preserve"> | ||||||
|  |     <value>Prevent DNS Leaks</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="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>v2ray Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigSingbox" xml:space="preserve"> | ||||||
|  |     <value>sing-box Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSBCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound and Endpoint Config Only</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> | ||||||
| </root> | </root> | ||||||
|  | @ -1,17 +1,17 @@ | ||||||
| <?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||||||
| <root> | <root> | ||||||
|   <!-- |   <!--  | ||||||
|     Microsoft ResX Schema |     Microsoft ResX Schema  | ||||||
| 
 |      | ||||||
|     Version 2.0 |     Version 2.0 | ||||||
| 
 |      | ||||||
|     The primary goals of this format is to allow a simple XML format |     The primary goals of this format is to allow a simple XML format  | ||||||
|     that is mostly human readable. The generation and parsing of the |     that is mostly human readable. The generation and parsing of the  | ||||||
|     various data types are done through the TypeConverter classes |     various data types are done through the TypeConverter classes  | ||||||
|     associated with the data types. |     associated with the data types. | ||||||
| 
 |      | ||||||
|     Example: |     Example: | ||||||
| 
 |      | ||||||
|     ... ado.net/XML headers & schema ... |     ... ado.net/XML headers & schema ... | ||||||
|     <resheader name="resmimetype">text/microsoft-resx</resheader> |     <resheader name="resmimetype">text/microsoft-resx</resheader> | ||||||
|     <resheader name="version">2.0</resheader> |     <resheader name="version">2.0</resheader> | ||||||
|  | @ -26,36 +26,36 @@ | ||||||
|         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> |         <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> | ||||||
|         <comment>This is a comment</comment> |         <comment>This is a comment</comment> | ||||||
|     </data> |     </data> | ||||||
| 
 |                  | ||||||
|     There are any number of "resheader" rows that contain simple |     There are any number of "resheader" rows that contain simple  | ||||||
|     name/value pairs. |     name/value pairs. | ||||||
| 
 |      | ||||||
|     Each data row contains a name, and value. The row also contains a |     Each data row contains a name, and value. The row also contains a  | ||||||
|     type or mimetype. Type corresponds to a .NET class that support |     type or mimetype. Type corresponds to a .NET class that support  | ||||||
|     text/value conversion through the TypeConverter architecture. |     text/value conversion through the TypeConverter architecture.  | ||||||
|     Classes that don't support this are serialized and stored with the |     Classes that don't support this are serialized and stored with the  | ||||||
|     mimetype set. |     mimetype set. | ||||||
| 
 |      | ||||||
|     The mimetype is used for serialized objects, and tells the |     The mimetype is used for serialized objects, and tells the  | ||||||
|     ResXResourceReader how to depersist the object. This is currently not |     ResXResourceReader how to depersist the object. This is currently not  | ||||||
|     extensible. For a given mimetype the value must be set accordingly: |     extensible. For a given mimetype the value must be set accordingly: | ||||||
| 
 |      | ||||||
|     Note - application/x-microsoft.net.object.binary.base64 is the format |     Note - application/x-microsoft.net.object.binary.base64 is the format  | ||||||
|     that the ResXResourceWriter will generate, however the reader can |     that the ResXResourceWriter will generate, however the reader can  | ||||||
|     read any of the formats listed below. |     read any of the formats listed below. | ||||||
| 
 |      | ||||||
|     mimetype: application/x-microsoft.net.object.binary.base64 |     mimetype: application/x-microsoft.net.object.binary.base64 | ||||||
|     value   : The object must be serialized with |     value   : The object must be serialized with  | ||||||
|             : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter |             : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter | ||||||
|             : and then encoded with base64 encoding. |             : and then encoded with base64 encoding. | ||||||
| 
 |      | ||||||
|     mimetype: application/x-microsoft.net.object.soap.base64 |     mimetype: application/x-microsoft.net.object.soap.base64 | ||||||
|     value   : The object must be serialized with |     value   : The object must be serialized with  | ||||||
|             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter |             : System.Runtime.Serialization.Formatters.Soap.SoapFormatter | ||||||
|             : and then encoded with base64 encoding. |             : and then encoded with base64 encoding. | ||||||
| 
 | 
 | ||||||
|     mimetype: application/x-microsoft.net.object.bytearray.base64 |     mimetype: application/x-microsoft.net.object.bytearray.base64 | ||||||
|     value   : The object must be serialized into a byte array |     value   : The object must be serialized into a byte array  | ||||||
|             : using a System.ComponentModel.TypeConverter |             : using a System.ComponentModel.TypeConverter | ||||||
|             : and then encoded with base64 encoding. |             : and then encoded with base64 encoding. | ||||||
|     --> |     --> | ||||||
|  | @ -807,9 +807,6 @@ | ||||||
|   <data name="menuMoveUp" xml:space="preserve"> |   <data name="menuMoveUp" xml:space="preserve"> | ||||||
|     <value>Вверх (U)</value> |     <value>Вверх (U)</value> | ||||||
|   </data> |   </data> | ||||||
|   <data name="menuMoveTo" xml:space="preserve"> |  | ||||||
|     <value>Переместить вверх/вниз</value> |  | ||||||
|   </data> |  | ||||||
|   <data name="MsgFilterTitle" xml:space="preserve"> |   <data name="MsgFilterTitle" xml:space="preserve"> | ||||||
|     <value>Фильтр, поддерживает regex</value> |     <value>Фильтр, поддерживает regex</value> | ||||||
|   </data> |   </data> | ||||||
|  | @ -969,6 +966,9 @@ | ||||||
|   <data name="TbSettingsSpeedTestUrl" xml:space="preserve"> |   <data name="TbSettingsSpeedTestUrl" xml:space="preserve"> | ||||||
|     <value>URL для тестирования скорости</value> |     <value>URL для тестирования скорости</value> | ||||||
|   </data> |   </data> | ||||||
|  |   <data name="menuMoveTo" xml:space="preserve"> | ||||||
|  |     <value>Переместить вверх/вниз</value> | ||||||
|  |   </data> | ||||||
|   <data name="TbPublicKey" xml:space="preserve"> |   <data name="TbPublicKey" xml:space="preserve"> | ||||||
|     <value>PublicKey</value> |     <value>PublicKey</value> | ||||||
|   </data> |   </data> | ||||||
|  | @ -1398,4 +1398,100 @@ | ||||||
|   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> |   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> | ||||||
|     <value>Incorrect password, please try again.</value> |     <value>Incorrect password, please try again.</value> | ||||||
|   </data> |   </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="TbPreventDNSLeaks" xml:space="preserve"> | ||||||
|  |     <value>Prevent DNS Leaks</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="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>v2ray Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigSingbox" xml:space="preserve"> | ||||||
|  |     <value>sing-box Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSBCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound and Endpoint Config Only</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> | ||||||
| </root> | </root> | ||||||
|  | @ -1395,4 +1395,100 @@ | ||||||
|   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> |   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> | ||||||
|     <value>密码错误,请重试。</value> |     <value>密码错误,请重试。</value> | ||||||
|   </data> |   </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="TbPreventDNSLeaks" xml:space="preserve"> | ||||||
|  |     <value>避免 DNS 泄漏</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="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>请填写正确的自定义配置</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>自定义配置</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigEnable" xml:space="preserve"> | ||||||
|  |     <value>启用自定义配置</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>v2ray 自定义配置</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigSingbox" xml:space="preserve"> | ||||||
|  |     <value>sing-box 自定义配置</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>仅添加出站配置,routing.balancers 和 routing.rules.outboundTag</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSBCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>仅添加出站和端点配置</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbAddProxyProtocolOutboundOnly" xml:space="preserve"> | ||||||
|  |     <value>不添加非代理协议出站</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSetUpstreamProxyDetour" xml:space="preserve"> | ||||||
|  |     <value>设置上游代理 tag</value> | ||||||
|  |   </data> | ||||||
| </root> | </root> | ||||||
|  | @ -1395,4 +1395,100 @@ | ||||||
|   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> |   <data name="SudoIncorrectPasswordTip" xml:space="preserve"> | ||||||
|     <value>密碼錯誤,請重試。</value> |     <value>密碼錯誤,請重試。</value> | ||||||
|   </data> |   </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="TbPreventDNSLeaks" xml:space="preserve"> | ||||||
|  |     <value>Prevent DNS Leaks</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="FillCorrectConfigText" xml:space="preserve"> | ||||||
|  |     <value>Please fill in the correct custom config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="menuCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigEnable" xml:space="preserve"> | ||||||
|  |     <value>Enable Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfig" xml:space="preserve"> | ||||||
|  |     <value>v2ray Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbCustomConfigSingbox" xml:space="preserve"> | ||||||
|  |     <value>sing-box Custom Config</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbRayCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag</value> | ||||||
|  |   </data> | ||||||
|  |   <data name="TbSBCustomConfigDesc" xml:space="preserve"> | ||||||
|  |     <value>Add Outbound and Endpoint Config Only</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> | ||||||
| </root> | </root> | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| { | { | ||||||
| 	"log": { | 	"log": { | ||||||
| 		"level": "debug", | 		"level": "debug", | ||||||
| 		"timestamp": true | 		"timestamp": true | ||||||
|  | @ -14,22 +14,10 @@ | ||||||
| 		{ | 		{ | ||||||
| 			"type": "direct", | 			"type": "direct", | ||||||
| 			"tag": "direct" | 			"tag": "direct" | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"type": "block", |  | ||||||
| 			"tag": "block" |  | ||||||
| 		}, |  | ||||||
| 		{ |  | ||||||
| 			"tag": "dns_out", |  | ||||||
| 			"type": "dns" |  | ||||||
| 		} | 		} | ||||||
| 	], | 	], | ||||||
| 	"route": { | 	"route": { | ||||||
| 		"rules": [ | 		"rules": [ | ||||||
| 			{ |  | ||||||
| 				"protocol": [ "dns" ], |  | ||||||
| 				"outbound": "dns_out" |  | ||||||
| 			} |  | ||||||
| 		] | 		] | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -2,28 +2,33 @@ | ||||||
|   "servers": [ |   "servers": [ | ||||||
|     { |     { | ||||||
|       "tag": "remote", |       "tag": "remote", | ||||||
|       "address": "tcp://8.8.8.8", |       "type": "tcp", | ||||||
|       "strategy": "prefer_ipv4", |       "server": "8.8.8.8", | ||||||
|       "detour": "proxy" |       "detour": "proxy" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "tag": "local", |       "tag": "local", | ||||||
|       "address": "223.5.5.5", |       "type": "udp", | ||||||
|       "strategy": "prefer_ipv4", |       "server": "223.5.5.5" | ||||||
|       "detour": "direct" |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "tag": "block", |  | ||||||
|       "address": "rcode://success" |  | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "rules": [ |   "rules": [ | ||||||
|  |     { | ||||||
|  |       "domain_suffix": [ | ||||||
|  |         "googleapis.cn", | ||||||
|  |         "gstatic.com" | ||||||
|  |       ], | ||||||
|  |       "server": "remote", | ||||||
|  |       "strategy": "prefer_ipv4" | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|       "rule_set": [ |       "rule_set": [ | ||||||
|         "geosite-cn" |         "geosite-cn" | ||||||
|       ], |       ], | ||||||
|       "server": "local" |       "server": "local", | ||||||
|  |       "strategy": "prefer_ipv4" | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "final": "remote" |   "final": "remote", | ||||||
|  |   "strategy": "prefer_ipv4" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,29 +2,33 @@ | ||||||
|   "servers": [ |   "servers": [ | ||||||
|     { |     { | ||||||
|       "tag": "remote", |       "tag": "remote", | ||||||
|       "address": "tcp://8.8.8.8", |       "type": "tcp", | ||||||
|       "strategy": "prefer_ipv4", |       "server": "8.8.8.8", | ||||||
|       "detour": "proxy" |       "detour": "proxy" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       "tag": "local", |       "tag": "local", | ||||||
|       "address": "223.5.5.5", |       "type": "udp", | ||||||
|       "strategy": "prefer_ipv4", |       "server": "223.5.5.5" | ||||||
|       "detour": "direct" |  | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|       "tag": "block", |  | ||||||
|       "address": "rcode://success" |  | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "rules": [ |   "rules": [ | ||||||
|     { |     { | ||||||
|       "rule_set": [ |       "domain_suffix": [ | ||||||
|         "geosite-cn", |         "googleapis.cn", | ||||||
|         "geosite-geolocation-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, |       139, | ||||||
|       5353 |       5353 | ||||||
|     ], |     ], | ||||||
|     "outbound": "block" |     "action": "reject" | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     "ip_cidr": [ |     "ip_cidr": [ | ||||||
|       "224.0.0.0/3", |       "224.0.0.0/3", | ||||||
|       "ff00::/8" |       "ff00::/8" | ||||||
|     ], |     ], | ||||||
|     "outbound": "block" |     "action": "reject" | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,6 +1,9 @@ | ||||||
| using System.Net; | using System.Net; | ||||||
| using System.Net.NetworkInformation; | using System.Net.NetworkInformation; | ||||||
|  | using System.Text.Json; | ||||||
| using System.Text.Json.Nodes; | using System.Text.Json.Nodes; | ||||||
|  | using System.Text.Json.Serialization; | ||||||
|  | using ServiceLib.Models; | ||||||
| 
 | 
 | ||||||
| namespace ServiceLib.Services.CoreConfig; | namespace ServiceLib.Services.CoreConfig; | ||||||
| 
 | 
 | ||||||
|  | @ -66,7 +69,9 @@ public class CoreConfigV2rayService | ||||||
| 
 | 
 | ||||||
|             ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); |             ret.Msg = string.Format(ResUI.SuccessfulConfiguration, ""); | ||||||
|             ret.Success = true; |             ret.Success = true; | ||||||
|             ret.Data = JsonUtils.Serialize(v2rayConfig); | 
 | ||||||
|  |             var customConfig = await AppHandler.Instance.GetCustomConfigItem(ECoreType.Xray); | ||||||
|  |             ret.Data = await ApplyCustomConfig(customConfig, v2rayConfig); | ||||||
|             return ret; |             return ret; | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|  | @ -120,7 +125,7 @@ public class CoreConfigV2rayService | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 if (it.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC) |                 if (it.ConfigType is EConfigType.Hysteria2 or EConfigType.TUIC or EConfigType.Anytls) | ||||||
|                 { |                 { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|  | @ -195,7 +200,9 @@ public class CoreConfigV2rayService | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             ret.Success = true; |             ret.Success = true; | ||||||
|             ret.Data = JsonUtils.Serialize(v2rayConfig); | 
 | ||||||
|  |             var customConfig = await AppHandler.Instance.GetCustomConfigItem(ECoreType.Xray); | ||||||
|  |             ret.Data = await ApplyCustomConfig(customConfig, v2rayConfig, true); | ||||||
|             return ret; |             return ret; | ||||||
|         } |         } | ||||||
|         catch (Exception ex) |         catch (Exception ex) | ||||||
|  | @ -640,7 +647,8 @@ public class CoreConfigV2rayService | ||||||
|         if (node == null |         if (node == null | ||||||
|             || node.ConfigType == EConfigType.Custom |             || node.ConfigType == EConfigType.Custom | ||||||
|             || node.ConfigType == EConfigType.Hysteria2 |             || node.ConfigType == EConfigType.Hysteria2 | ||||||
|             || node.ConfigType == EConfigType.TUIC) |             || node.ConfigType == EConfigType.TUIC | ||||||
|  |             || node.ConfigType == EConfigType.Anytls) | ||||||
|         { |         { | ||||||
|             return Global.ProxyTag; |             return Global.ProxyTag; | ||||||
|         } |         } | ||||||
|  | @ -1132,6 +1140,264 @@ public class CoreConfigV2rayService | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig) |     private async Task<int> GenDns(ProfileItem? node, V2rayConfig v2rayConfig) | ||||||
|  |     { | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|  |             if (item != null && item.Enabled == true) | ||||||
|  |             { | ||||||
|  |                 return await GenDnsCompatible(node, v2rayConfig); | ||||||
|  |             } | ||||||
|  |             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); | ||||||
|  |         } | ||||||
|  |         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.ProxyTag) | ||||||
|  |                     { | ||||||
|  |                         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, List<string>>(); | ||||||
|  |         if (simpleDNSItem.AddCommonHosts == true) | ||||||
|  |         { | ||||||
|  |             v2rayConfig.dns.hosts = Global.PredefinedHosts; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         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 |         try | ||||||
|         { |         { | ||||||
|  | @ -1174,22 +1440,33 @@ public class CoreConfigV2rayService | ||||||
|                 var systemHosts = Utils.GetSystemHosts(); |                 var systemHosts = Utils.GetSystemHosts(); | ||||||
|                 if (systemHosts.Count > 0) |                 if (systemHosts.Count > 0) | ||||||
|                 { |                 { | ||||||
|                     var normalHost = obj["hosts"]; |                     var normalHost1 = obj["hosts"]; | ||||||
|                     if (normalHost != null) |                     if (normalHost1 != null) | ||||||
|                     { |                     { | ||||||
|                         foreach (var host in systemHosts) |                         foreach (var host in systemHosts) | ||||||
|                         { |                         { | ||||||
|                             if (normalHost[host.Key] != null) |                             if (normalHost1[host.Key] != null) | ||||||
|                                 continue; |                                 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) |         catch (Exception ex) | ||||||
|         { |         { | ||||||
|  | @ -1198,7 +1475,7 @@ public class CoreConfigV2rayService | ||||||
|         return 0; |         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) |         if (node == null) | ||||||
|         { |         { | ||||||
|  | @ -1241,7 +1518,7 @@ public class CoreConfigV2rayService | ||||||
|             { |             { | ||||||
|                 var dnsServer = new DnsServer4Ray() |                 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, |                     skipFallback = true, | ||||||
|                     domains = domainList |                     domains = domainList | ||||||
|                 }; |                 }; | ||||||
|  | @ -1349,7 +1626,8 @@ public class CoreConfigV2rayService | ||||||
|             if (prevNode is not null |             if (prevNode is not null | ||||||
|                 && prevNode.ConfigType != EConfigType.Custom |                 && prevNode.ConfigType != EConfigType.Custom | ||||||
|                 && prevNode.ConfigType != EConfigType.Hysteria2 |                 && prevNode.ConfigType != EConfigType.Hysteria2 | ||||||
|                 && prevNode.ConfigType != EConfigType.TUIC) |                 && prevNode.ConfigType != EConfigType.TUIC | ||||||
|  |                 && prevNode.ConfigType != EConfigType.Anytls) | ||||||
|             { |             { | ||||||
|                 var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); |                 var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); | ||||||
|                 await GenOutbound(prevNode, prevOutbound); |                 await GenOutbound(prevNode, prevOutbound); | ||||||
|  | @ -1424,7 +1702,8 @@ public class CoreConfigV2rayService | ||||||
|                         if (prevNode is not null |                         if (prevNode is not null | ||||||
|                             && prevNode.ConfigType != EConfigType.Custom |                             && prevNode.ConfigType != EConfigType.Custom | ||||||
|                             && prevNode.ConfigType != EConfigType.Hysteria2 |                             && prevNode.ConfigType != EConfigType.Hysteria2 | ||||||
|                             && prevNode.ConfigType != EConfigType.TUIC) |                             && prevNode.ConfigType != EConfigType.TUIC | ||||||
|  |                             && prevNode.ConfigType != EConfigType.Anytls) | ||||||
|                         { |                         { | ||||||
|                             var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); |                             var prevOutbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound); | ||||||
|                             await GenOutbound(prevNode, prevOutbound); |                             await GenOutbound(prevNode, prevOutbound); | ||||||
|  | @ -1493,7 +1772,8 @@ public class CoreConfigV2rayService | ||||||
|             if (nextNode is not null |             if (nextNode is not null | ||||||
|                 && nextNode.ConfigType != EConfigType.Custom |                 && nextNode.ConfigType != EConfigType.Custom | ||||||
|                 && nextNode.ConfigType != EConfigType.Hysteria2 |                 && nextNode.ConfigType != EConfigType.Hysteria2 | ||||||
|                 && nextNode.ConfigType != EConfigType.TUIC) |                 && nextNode.ConfigType != EConfigType.TUIC | ||||||
|  |                 && nextNode.ConfigType != EConfigType.Anytls) | ||||||
|             { |             { | ||||||
|                 if (nextOutbound == null) |                 if (nextOutbound == null) | ||||||
|                 { |                 { | ||||||
|  | @ -1563,5 +1843,83 @@ public class CoreConfigV2rayService | ||||||
|         return await Task.FromResult(0); |         return await Task.FromResult(0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private async Task<string> ApplyCustomConfig(CustomConfigItem customConfig, V2rayConfig v2rayConfig, bool handleBalancerAndRules = false) | ||||||
|  |     { | ||||||
|  |         if (!customConfig.Enabled || customConfig.Config.IsNullOrEmpty()) | ||||||
|  |         { | ||||||
|  |             return JsonUtils.Serialize(v2rayConfig); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         var customConfigNode = JsonNode.Parse(customConfig.Config); | ||||||
|  |         if (customConfigNode == 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 = customConfigNode["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 (customConfigNode["routing"] == null) | ||||||
|  |             { | ||||||
|  |                 customConfigNode["routing"] = new JsonObject(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Handle balancers - append instead of override | ||||||
|  |             if (customConfigNode["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 | ||||||
|  |             { | ||||||
|  |                 customConfigNode["routing"]["balancers"] = JsonNode.Parse(JsonUtils.Serialize(v2rayConfig.routing.balancers)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Handle outbounds - append instead of override | ||||||
|  |         var customOutboundsNode = customConfigNode["outbounds"] is JsonArray outbounds ? outbounds : new JsonArray(); | ||||||
|  |         foreach (var outbound in v2rayConfig.outbounds) | ||||||
|  |         { | ||||||
|  |             if (outbound.protocol.ToLower() is "blackhole" or "dns" or "freedom") | ||||||
|  |             { | ||||||
|  |                 if (customConfig.AddProxyOnly == true) | ||||||
|  |                 { | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else if ((outbound.streamSettings?.sockopt?.dialerProxy.IsNullOrEmpty() == true) && (!customConfig.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 = customConfig.ProxyDetour; | ||||||
|  |             } | ||||||
|  |             customOutboundsNode.Add(JsonUtils.DeepCopy(outbound)); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return await Task.FromResult(JsonUtils.Serialize(customConfigNode)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     #endregion private gen function |     #endregion private gen function | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -358,8 +358,8 @@ public class SpeedtestService | ||||||
|     private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize) |     private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize) | ||||||
|     { |     { | ||||||
|         List<List<ServerTestItem>> lstTest = new(); |         List<List<ServerTestItem>> lstTest = new(); | ||||||
|         var lst1 = lstSelected.Where(t => t.ConfigType is not (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).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++) |         for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++) | ||||||
|         { |         { | ||||||
|  |  | ||||||
							
								
								
									
										110
									
								
								v2rayN/ServiceLib/ViewModels/CustomConfigViewModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								v2rayN/ServiceLib/ViewModels/CustomConfigViewModel.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,110 @@ | ||||||
|  | using System.Reactive; | ||||||
|  | using DynamicData.Binding; | ||||||
|  | using ReactiveUI; | ||||||
|  | using ReactiveUI.Fody.Helpers; | ||||||
|  | 
 | ||||||
|  | namespace ServiceLib.ViewModels; | ||||||
|  | public class CustomConfigViewModel : MyReactiveObject | ||||||
|  | { | ||||||
|  |     #region Reactive | ||||||
|  |     [Reactive] | ||||||
|  |     public bool EnableCustomConfig4Ray { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Reactive] | ||||||
|  |     public bool EnableCustomConfig4Singbox { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Reactive] | ||||||
|  |     public string CustomConfig4Ray { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Reactive] | ||||||
|  |     public string CustomConfig4Singbox { get; set; } | ||||||
|  | 
 | ||||||
|  |     [Reactive] | ||||||
|  |     public string CustomTunConfig4Singbox { 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 CustomConfigViewModel(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.GetCustomConfigItem(ECoreType.Xray); | ||||||
|  |         EnableCustomConfig4Ray = item?.Enabled ?? false; | ||||||
|  |         CustomConfig4Ray = item?.Config ?? string.Empty; | ||||||
|  |         AddProxyOnly4Ray = item?.AddProxyOnly ?? false; | ||||||
|  |         ProxyDetour4Ray = item?.ProxyDetour ?? string.Empty; | ||||||
|  | 
 | ||||||
|  |         var item2 = await AppHandler.Instance.GetCustomConfigItem(ECoreType.sing_box); | ||||||
|  |         EnableCustomConfig4Singbox = item2?.Enabled ?? false; | ||||||
|  |         CustomConfig4Singbox = item2?.Config ?? string.Empty; | ||||||
|  |         CustomTunConfig4Singbox = 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.GetCustomConfigItem(ECoreType.Xray); | ||||||
|  |         item.Enabled = EnableCustomConfig4Ray; | ||||||
|  |         item.Config = null; | ||||||
|  | 
 | ||||||
|  |         item.Config = CustomConfig4Ray; | ||||||
|  | 
 | ||||||
|  |         item.AddProxyOnly = AddProxyOnly4Ray; | ||||||
|  |         item.ProxyDetour = ProxyDetour4Ray; | ||||||
|  | 
 | ||||||
|  |         await ConfigHandler.SaveCustomConfigItem(_config, item); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async Task<bool> SaveSingboxConfigAsync() | ||||||
|  |     { | ||||||
|  |         var item = await AppHandler.Instance.GetCustomConfigItem(ECoreType.sing_box); | ||||||
|  |         item.Enabled = EnableCustomConfig4Singbox; | ||||||
|  |         item.Config = null; | ||||||
|  |         item.TunConfig = null; | ||||||
|  | 
 | ||||||
|  |         item.Config = CustomConfig4Singbox; | ||||||
|  |         item.TunConfig = CustomTunConfig4Singbox; | ||||||
|  | 
 | ||||||
|  |         item.AddProxyOnly = AddProxyOnly4Singbox; | ||||||
|  |         item.ProxyDetour = ProxyDetour4Singbox; | ||||||
|  | 
 | ||||||
|  |         await ConfigHandler.SaveCustomConfigItem(_config, item); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -6,39 +6,52 @@ namespace ServiceLib.ViewModels; | ||||||
| 
 | 
 | ||||||
| public class DNSSettingViewModel : MyReactiveObject | public class DNSSettingViewModel : MyReactiveObject | ||||||
| { | { | ||||||
|     [Reactive] public bool UseSystemHosts { get; set; } |     [Reactive] public bool? UseSystemHosts { get; set; } | ||||||
|     [Reactive] public string DomainStrategy4Freedom { get; set; } |     [Reactive] public bool? AddCommonHosts { get; set; } | ||||||
|     [Reactive] public string DomainDNSAddress { get; set; } |     [Reactive] public bool? FakeIP { get; set; } | ||||||
|     [Reactive] public string NormalDNS { 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 bool UseSystemHostsCompatible { get; set; } | ||||||
|     [Reactive] public string DomainDNSAddress2 { get; set; } |     [Reactive] public string DomainStrategy4FreedomCompatible { get; set; } | ||||||
|     [Reactive] public string NormalDNS2 { get; set; } |     [Reactive] public string DomainDNSAddressCompatible { get; set; } | ||||||
|     [Reactive] public string TunDNS2 { 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> SaveCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCmd { get; } |     public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCompatibleCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCmd { get; } |     public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCompatibleCmd { get; } | ||||||
| 
 | 
 | ||||||
|     public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView) |     public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView) | ||||||
|     { |     { | ||||||
|         _config = AppHandler.Instance.Config; |         _config = AppHandler.Instance.Config; | ||||||
|         _updateView = updateView; |         _updateView = updateView; | ||||||
|         SaveCmd = ReactiveCommand.CreateFromTask(async () => |         SaveCmd = ReactiveCommand.CreateFromTask(SaveSettingAsync); | ||||||
|         { |  | ||||||
|             await SaveSettingAsync(); |  | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         ImportDefConfig4V2rayCmd = ReactiveCommand.CreateFromTask(async () => |         ImportDefConfig4V2rayCompatibleCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|         { |         { | ||||||
|             NormalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); |             NormalDNSCompatible = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName); | ||||||
|             await Task.CompletedTask; |             await Task.CompletedTask; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         ImportDefConfig4SingboxCmd = ReactiveCommand.CreateFromTask(async () => |         ImportDefConfig4SingboxCompatibleCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|         { |         { | ||||||
|             NormalDNS2 = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName); |             NormalDNS2Compatible = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName); | ||||||
|             TunDNS2 = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName); |             TunDNS2Compatible = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName); | ||||||
|             await Task.CompletedTask; |             await Task.CompletedTask; | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  | @ -47,48 +60,80 @@ public class DNSSettingViewModel : MyReactiveObject | ||||||
| 
 | 
 | ||||||
|     private async Task Init() |     private async Task Init() | ||||||
|     { |     { | ||||||
|         var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |         _config = AppHandler.Instance.Config; | ||||||
|  |         var item = _config.SimpleDNSItem; | ||||||
|         UseSystemHosts = item.UseSystemHosts; |         UseSystemHosts = item.UseSystemHosts; | ||||||
|         DomainStrategy4Freedom = item?.DomainStrategy4Freedom ?? string.Empty; |         AddCommonHosts = item.AddCommonHosts; | ||||||
|         DomainDNSAddress = item?.DomainDNSAddress ?? string.Empty; |         FakeIP = item.FakeIP; | ||||||
|         NormalDNS = item?.NormalDNS ?? string.Empty; |         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); |         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|         DomainStrategy4Freedom2 = item2?.DomainStrategy4Freedom ?? string.Empty; |         SBCustomDNSEnableCompatible = item2.Enabled; | ||||||
|         DomainDNSAddress2 = item2?.DomainDNSAddress ?? string.Empty; |         DomainStrategy4Freedom2Compatible = item2?.DomainStrategy4Freedom ?? string.Empty; | ||||||
|         NormalDNS2 = item2?.NormalDNS ?? string.Empty; |         DomainDNSAddress2Compatible = item2?.DomainDNSAddress ?? string.Empty; | ||||||
|         TunDNS2 = item2?.TunDNS ?? string.Empty; |         NormalDNS2Compatible = item2?.NormalDNS ?? string.Empty; | ||||||
|  |         TunDNS2Compatible = item2?.TunDNS ?? string.Empty; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private async Task SaveSettingAsync() |     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) |             if (obj != null && obj["servers"] != null) | ||||||
|             { |             { | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 if (NormalDNS.Contains('{') || NormalDNS.Contains('}')) |                 if (NormalDNSCompatible.Contains('{') || NormalDNSCompatible.Contains('}')) | ||||||
|                 { |                 { | ||||||
|                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                     NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (NormalDNS2.IsNotEmpty()) |         if (NormalDNS2Compatible.IsNotEmpty()) | ||||||
|         { |         { | ||||||
|             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2); |             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2Compatible); | ||||||
|             if (obj2 == null) |             if (obj2 == null) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         if (TunDNS2.IsNotEmpty()) |         if (TunDNS2Compatible.IsNotEmpty()) | ||||||
|         { |         { | ||||||
|             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2); |             var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2Compatible); | ||||||
|             if (obj2 == null) |             if (obj2 == null) | ||||||
|             { |             { | ||||||
|                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); |                 NoticeHandler.Instance.Enqueue(ResUI.FillCorrectDNSText); | ||||||
|  | @ -96,21 +141,26 @@ public class DNSSettingViewModel : MyReactiveObject | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         var item = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); |         var item1 = await AppHandler.Instance.GetDNSItem(ECoreType.Xray); | ||||||
|         item.DomainStrategy4Freedom = DomainStrategy4Freedom; |         item1.Enabled = RayCustomDNSEnableCompatible; | ||||||
|         item.DomainDNSAddress = DomainDNSAddress; |         item1.DomainStrategy4Freedom = DomainStrategy4FreedomCompatible; | ||||||
|         item.UseSystemHosts = UseSystemHosts; |         item1.DomainDNSAddress = DomainDNSAddressCompatible; | ||||||
|         item.NormalDNS = NormalDNS; |         item1.UseSystemHosts = UseSystemHostsCompatible; | ||||||
|         await ConfigHandler.SaveDNSItems(_config, item); |         item1.NormalDNS = NormalDNSCompatible; | ||||||
|  |         await ConfigHandler.SaveDNSItems(_config, item1); | ||||||
| 
 | 
 | ||||||
|         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); |         var item2 = await AppHandler.Instance.GetDNSItem(ECoreType.sing_box); | ||||||
|         item2.DomainStrategy4Freedom = DomainStrategy4Freedom2; |         item2.Enabled = RayCustomDNSEnableCompatible; | ||||||
|         item2.DomainDNSAddress = DomainDNSAddress2; |         item2.DomainStrategy4Freedom = DomainStrategy4Freedom2Compatible; | ||||||
|         item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2)); |         item2.DomainDNSAddress = DomainDNSAddress2Compatible; | ||||||
|         item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2)); |         item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2Compatible)); | ||||||
|  |         item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2Compatible)); | ||||||
|         await ConfigHandler.SaveDNSItems(_config, item2); |         await ConfigHandler.SaveDNSItems(_config, item2); | ||||||
| 
 | 
 | ||||||
|         NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess); |         await ConfigHandler.SaveConfig(_config); | ||||||
|         _ = _updateView?.Invoke(EViewAction.CloseWindow, null); |         if (_updateView != null) | ||||||
|  |         { | ||||||
|  |             await _updateView(EViewAction.CloseWindow, null); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ public class MainWindowViewModel : MyReactiveObject | ||||||
|     public ReactiveCommand<Unit, Unit> AddHysteria2ServerCmd { get; } |     public ReactiveCommand<Unit, Unit> AddHysteria2ServerCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; } |     public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; } |     public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; } | ||||||
|  |     public ReactiveCommand<Unit, Unit> AddAnytlsServerCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; } |     public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; } |     public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { 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> RoutingSettingCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> DNSSettingCmd { get; } |     public ReactiveCommand<Unit, Unit> DNSSettingCmd { get; } | ||||||
|  |     public ReactiveCommand<Unit, Unit> CustomConfigCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> GlobalHotkeySettingCmd { get; } |     public ReactiveCommand<Unit, Unit> GlobalHotkeySettingCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> RebootAsAdminCmd { get; } |     public ReactiveCommand<Unit, Unit> RebootAsAdminCmd { get; } | ||||||
|     public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; } |     public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; } | ||||||
|  | @ -111,6 +113,10 @@ public class MainWindowViewModel : MyReactiveObject | ||||||
|         { |         { | ||||||
|             await AddServerAsync(true, EConfigType.WireGuard); |             await AddServerAsync(true, EConfigType.WireGuard); | ||||||
|         }); |         }); | ||||||
|  |         AddAnytlsServerCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|  |         { | ||||||
|  |             await AddServerAsync(true, EConfigType.Anytls); | ||||||
|  |         }); | ||||||
|         AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () => |         AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|         { |         { | ||||||
|             await AddServerAsync(true, EConfigType.Custom); |             await AddServerAsync(true, EConfigType.Custom); | ||||||
|  | @ -164,6 +170,10 @@ public class MainWindowViewModel : MyReactiveObject | ||||||
|         { |         { | ||||||
|             await DNSSettingAsync(); |             await DNSSettingAsync(); | ||||||
|         }); |         }); | ||||||
|  |         CustomConfigCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|  |         { | ||||||
|  |             await CustomConfigAsync(); | ||||||
|  |         }); | ||||||
|         GlobalHotkeySettingCmd = ReactiveCommand.CreateFromTask(async () => |         GlobalHotkeySettingCmd = ReactiveCommand.CreateFromTask(async () => | ||||||
|         { |         { | ||||||
|             if (await _updateView?.Invoke(EViewAction.GlobalHotkeySettingWindow, null) == true) |             if (await _updateView?.Invoke(EViewAction.GlobalHotkeySettingWindow, null) == true) | ||||||
|  | @ -215,6 +225,7 @@ public class MainWindowViewModel : MyReactiveObject | ||||||
| 
 | 
 | ||||||
|         await ConfigHandler.InitBuiltinRouting(_config); |         await ConfigHandler.InitBuiltinRouting(_config); | ||||||
|         await ConfigHandler.InitBuiltinDNS(_config); |         await ConfigHandler.InitBuiltinDNS(_config); | ||||||
|  |         await ConfigHandler.InitBuiltinCustomConfig(_config); | ||||||
|         await ProfileExHandler.Instance.Init(); |         await ProfileExHandler.Instance.Init(); | ||||||
|         await CoreHandler.Instance.Init(_config, UpdateHandler); |         await CoreHandler.Instance.Init(_config, UpdateHandler); | ||||||
|         TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler); |         TaskHandler.Instance.RegUpdateTask(_config, UpdateTaskHandler); | ||||||
|  | @ -503,6 +514,15 @@ public class MainWindowViewModel : MyReactiveObject | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     private async Task CustomConfigAsync() | ||||||
|  |     { | ||||||
|  |         var ret = await _updateView?.Invoke(EViewAction.CustomConfigWindow, null); | ||||||
|  |         if (ret == true) | ||||||
|  |         { | ||||||
|  |             await Reload(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public async Task RebootAsAdmin() |     public async Task RebootAsAdmin() | ||||||
|     { |     { | ||||||
|         ProcUtils.RebootAsAdmin(); |         ProcUtils.RebootAsAdmin(); | ||||||
|  |  | ||||||
|  | @ -533,6 +533,26 @@ | ||||||
|                         HorizontalAlignment="Left" |                         HorizontalAlignment="Left" | ||||||
|                         Watermark="1500" /> |                         Watermark="1500" /> | ||||||
|                 </Grid> |                 </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 |                 <Separator | ||||||
|                     x:Name="sepa2" |                     x:Name="sepa2" | ||||||
|  |  | ||||||
|  | @ -102,6 +102,12 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel> | ||||||
|                 gridTls.IsVisible = false; |                 gridTls.IsVisible = false; | ||||||
| 
 | 
 | ||||||
|                 break; |                 break; | ||||||
|  | 
 | ||||||
|  |             case EConfigType.Anytls: | ||||||
|  |                 gridAnytls.IsVisible = true; | ||||||
|  |                 lstStreamSecurity.Add(Global.StreamSecurityReality); | ||||||
|  |                 cmbCoreType.IsEnabled = false; | ||||||
|  |                 break; | ||||||
|         } |         } | ||||||
|         cmbStreamSecurity.ItemsSource = lstStreamSecurity; |         cmbStreamSecurity.ItemsSource = lstStreamSecurity; | ||||||
| 
 | 
 | ||||||
|  | @ -167,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.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables); | ||||||
|                     this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables); |                     this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables); | ||||||
|                     break; |                     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.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables); | ||||||
|  |  | ||||||
							
								
								
									
										182
									
								
								v2rayN/v2rayN.Desktop/Views/CustomConfigWindow.axaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								v2rayN/v2rayN.Desktop/Views/CustomConfigWindow.axaml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,182 @@ | ||||||
|  | <Window | ||||||
|  |     x:Class="v2rayN.Desktop.Views.CustomConfigWindow" | ||||||
|  |     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.menuCustomConfig}" | ||||||
|  |     Width="900" | ||||||
|  |     Height="600" | ||||||
|  |     x:DataType="vms:CustomConfigViewModel" | ||||||
|  |     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.TbRayCustomConfig}"> | ||||||
|  |                 <DockPanel Margin="{StaticResource Margin4}"> | ||||||
|  |                     <Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto"> | ||||||
|  | 
 | ||||||
|  |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Grid.Row="0" | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbRayCustomConfigDesc}" /> | ||||||
|  |                         </StackPanel> | ||||||
|  | 
 | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbCustomConfigEnable}" /> | ||||||
|  |                             <ToggleSwitch | ||||||
|  |                                 x:Name="rayCustomConfigEnable" | ||||||
|  |                                 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 json config"> | ||||||
|  |                         <TextBox | ||||||
|  |                             x:Name="rayCustomConfig" | ||||||
|  |                             VerticalAlignment="Stretch" | ||||||
|  |                             Classes="TextArea" | ||||||
|  |                             MinLines="10" | ||||||
|  |                             TextWrapping="Wrap" /> | ||||||
|  |                     </HeaderedContentControl> | ||||||
|  |                 </DockPanel> | ||||||
|  |             </TabItem> | ||||||
|  |             <TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbCustomConfigSingbox}"> | ||||||
|  |                 <DockPanel Margin="{StaticResource Margin4}"> | ||||||
|  |                     <Grid DockPanel.Dock="Top" RowDefinitions="Auto,Auto"> | ||||||
|  | 
 | ||||||
|  |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Grid.Row="0" | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbSBCustomConfigDesc}" /> | ||||||
|  |                         </StackPanel> | ||||||
|  | 
 | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbCustomConfigEnable}" /> | ||||||
|  |                             <ToggleSwitch | ||||||
|  |                                 x:Name="sbCustomConfigEnable" | ||||||
|  |                                 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 json config"> | ||||||
|  |                             <TextBox | ||||||
|  |                                 x:Name="sbCustomConfig" | ||||||
|  |                                 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 json tun config"> | ||||||
|  |                             <TextBox | ||||||
|  |                                 x:Name="sbCustomTunConfig" | ||||||
|  |                                 VerticalAlignment="Stretch" | ||||||
|  |                                 Classes="TextArea" | ||||||
|  |                                 MinLines="10" | ||||||
|  |                                 TextWrapping="Wrap" /> | ||||||
|  |                         </HeaderedContentControl> | ||||||
|  |                     </Grid> | ||||||
|  |                 </DockPanel> | ||||||
|  |             </TabItem> | ||||||
|  |         </TabControl> | ||||||
|  |     </DockPanel> | ||||||
|  | </Window> | ||||||
							
								
								
									
										46
									
								
								v2rayN/v2rayN.Desktop/Views/CustomConfigWindow.axaml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								v2rayN/v2rayN.Desktop/Views/CustomConfigWindow.axaml.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | using System.Reactive.Disposables; | ||||||
|  | using Avalonia.Interactivity; | ||||||
|  | using ReactiveUI; | ||||||
|  | using v2rayN.Desktop.Base; | ||||||
|  | 
 | ||||||
|  | namespace v2rayN.Desktop.Views; | ||||||
|  | 
 | ||||||
|  | public partial class CustomConfigWindow : WindowBase<CustomConfigViewModel> | ||||||
|  | { | ||||||
|  |     private static Config _config; | ||||||
|  | 
 | ||||||
|  |     public CustomConfigWindow() | ||||||
|  |     { | ||||||
|  |         InitializeComponent(); | ||||||
|  | 
 | ||||||
|  |         _config = AppHandler.Instance.Config; | ||||||
|  |         btnCancel.Click += (s, e) => this.Close(); | ||||||
|  |         ViewModel = new CustomConfigViewModel(UpdateViewHandler); | ||||||
|  | 
 | ||||||
|  |         this.WhenActivated(disposables => | ||||||
|  |         { | ||||||
|  |             this.Bind(ViewModel, vm => vm.EnableCustomConfig4Ray, v => v.rayCustomConfigEnable.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.CustomConfig4Ray, v => v.rayCustomConfig.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.EnableCustomConfig4Singbox, v => v.sbCustomConfigEnable.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.CustomConfig4Singbox, v => v.sbCustomConfig.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.CustomTunConfig4Singbox, v => v.sbCustomTunConfig.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); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
|     x:Class="v2rayN.Desktop.Views.DNSSettingWindow" |     x:Class="v2rayN.Desktop.Views.DNSSettingWindow" | ||||||
|     xmlns="https://github.com/avaloniaui" |     xmlns="https://github.com/avaloniaui" | ||||||
|     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |     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:d="http://schemas.microsoft.com/expression/blend/2008" | ||||||
|     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||||
|     xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" |     xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" | ||||||
|  | @ -35,25 +36,298 @@ | ||||||
|         </StackPanel> |         </StackPanel> | ||||||
| 
 | 
 | ||||||
|         <TabControl HorizontalContentAlignment="Stretch"> |         <TabControl HorizontalContentAlignment="Stretch"> | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}"> |             <TabItem Header="{x:Static resx:ResUI.ThBasicDNSSettings}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <ScrollViewer VerticalScrollBarVisibility="Visible"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         ColumnDefinitions="Auto,Auto,*" | ||||||
|  |                         RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto"> | ||||||
|  | 
 | ||||||
|                         <TextBlock |                         <TextBlock | ||||||
|  |                             x:Name="txtBasicDNSSettingsInvalid" | ||||||
|  |                             Grid.Row="0" | ||||||
|  |                             Grid.Column="0" | ||||||
|                             Margin="{StaticResource Margin4}" |                             Margin="{StaticResource Margin4}" | ||||||
|                             VerticalAlignment="Center" |                             VerticalAlignment="Center" | ||||||
|                             Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" /> |                             Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" /> | ||||||
| 
 |                          | ||||||
|                         <TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center"> |                         <TextBlock | ||||||
|                             <HyperlinkButton Classes="WithIcon" Click="linkDnsObjectDoc_Click"> |                             Grid.Row="1" | ||||||
|                                 <TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" /> |                             Grid.Column="0" | ||||||
|                             </HyperlinkButton> |  | ||||||
|                         </TextBlock> |  | ||||||
|                         <Button |  | ||||||
|                             x:Name="btnImportDefConfig4V2ray" |  | ||||||
|                             Margin="{StaticResource Margin4}" |                             Margin="{StaticResource Margin4}" | ||||||
|                             Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                             VerticalAlignment="Center" | ||||||
|                             Cursor="Hand" /> |                             Text="{x:Static resx:ResUI.TbDomesticDNS}" /> | ||||||
|                     </StackPanel> |                         <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}" /> | ||||||
|  | 
 | ||||||
|  |                         <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}" /> | ||||||
|  | 
 | ||||||
|  |                         <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}" /> | ||||||
|  |                     </Grid> | ||||||
|  |                 </ScrollViewer> | ||||||
|  |             </TabItem> | ||||||
|  | 
 | ||||||
|  |             <TabItem Header="{x:Static resx:ResUI.ThAdvancedDNSSettings}"> | ||||||
|  |                 <ScrollViewer VerticalScrollBarVisibility="Visible"> | ||||||
|  |                     <Grid | ||||||
|  |                         Margin="{StaticResource Margin4}" | ||||||
|  |                         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}" /> | ||||||
|  | 
 | ||||||
|  |                         <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.TbPreventDNSLeaks}" /> | ||||||
|  | 
 | ||||||
|  |                         <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}" /> | ||||||
|  | 
 | ||||||
|  |                         <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" | ||||||
|  |                             Watermark="{x:Static resx:ResUI.TbDNSHostsConfig}" | ||||||
|  |                             BorderThickness="1" | ||||||
|  |                             Classes="TextArea" | ||||||
|  |                             TextWrapping="Wrap" /> | ||||||
|  |                     </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"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -62,7 +336,7 @@ | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> | ||||||
|                             <ToggleSwitch |                             <ToggleSwitch | ||||||
|                                 x:Name="togUseSystemHosts" |                                 x:Name="togUseSystemHostsCompatible" | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 HorizontalAlignment="Left" /> |                                 HorizontalAlignment="Left" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -73,7 +347,7 @@ | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Freedom" |                                 x:Name="cmbdomainStrategy4FreedomCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -83,10 +357,11 @@ | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ctrls:AutoCompleteBox | ||||||
|                                 x:Name="cmbdomainDNSAddress" |                                 x:Name="cmbdomainDNSAddressCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 Text="{Binding DomainDNSAddressCompatible, Mode=TwoWay}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|                     </WrapPanel> |                     </WrapPanel> | ||||||
| 
 | 
 | ||||||
|  | @ -96,7 +371,7 @@ | ||||||
|                         BorderThickness="1" |                         BorderThickness="1" | ||||||
|                         Header="HTTP/SOCKS"> |                         Header="HTTP/SOCKS"> | ||||||
|                         <TextBox |                         <TextBox | ||||||
|                             Name="txtnormalDNS" |                             Name="txtnormalDNSCompatible" | ||||||
|                             VerticalAlignment="Stretch" |                             VerticalAlignment="Stretch" | ||||||
|                             Classes="TextArea" |                             Classes="TextArea" | ||||||
|                             MinLines="10" |                             MinLines="10" | ||||||
|  | @ -107,18 +382,36 @@ | ||||||
| 
 | 
 | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> |             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <DockPanel Margin="{StaticResource Margin8}"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid DockPanel.Dock="Top"> | ||||||
|                         <TextBlock Margin="{StaticResource Margin4}" VerticalAlignment="Center"> |                         <Grid.RowDefinitions> | ||||||
|                             <HyperlinkButton Classes="WithIcon" Click="linkDnsSingboxObjectDoc_Click"> |                             <RowDefinition Height="Auto" /> | ||||||
|                                 <TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" /> |                             <RowDefinition Height="Auto" /> | ||||||
|                             </HyperlinkButton> |                         </Grid.RowDefinitions> | ||||||
|                         </TextBlock> |                          | ||||||
|                         <Button |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|                             x:Name="btnImportDefConfig4Singbox" |                             <TextBlock | ||||||
|                             Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                             Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                                 VerticalAlignment="Center" | ||||||
|                             Cursor="Hand" /> |                                 Text="{x:Static resx:ResUI.TbCustomDNSEnable}" /> | ||||||
|                     </StackPanel> |                             <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"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -127,7 +420,7 @@ | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Out" |                                 x:Name="cmbdomainStrategy4OutCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -137,10 +430,11 @@ | ||||||
|                                 Margin="{StaticResource Margin4}" |                                 Margin="{StaticResource Margin4}" | ||||||
|                                 VerticalAlignment="Center" |                                 VerticalAlignment="Center" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ctrls:AutoCompleteBox | ||||||
|                                 x:Name="cmbdomainDNSAddress2" |                                 x:Name="cmbdomainDNSAddress2Compatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin4}" /> |                                 Margin="{StaticResource Margin4}" | ||||||
|  |                                 Text="{Binding DomainDNSAddress2Compatible, Mode=TwoWay}" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|                     </WrapPanel> |                     </WrapPanel> | ||||||
| 
 | 
 | ||||||
|  | @ -152,7 +446,7 @@ | ||||||
|                             BorderThickness="1" |                             BorderThickness="1" | ||||||
|                             Header="HTTP/SOCKS"> |                             Header="HTTP/SOCKS"> | ||||||
|                             <TextBox |                             <TextBox | ||||||
|                                 Name="txtnormalDNS2" |                                 Name="txtnormalDNS2Compatible" | ||||||
|                                 VerticalAlignment="Stretch" |                                 VerticalAlignment="Stretch" | ||||||
|                                 Classes="TextArea" |                                 Classes="TextArea" | ||||||
|                                 MinLines="10" |                                 MinLines="10" | ||||||
|  | @ -167,7 +461,7 @@ | ||||||
|                             BorderThickness="1" |                             BorderThickness="1" | ||||||
|                             Header="{x:Static resx:ResUI.TbSettingsTunMode}"> |                             Header="{x:Static resx:ResUI.TbSettingsTunMode}"> | ||||||
|                             <TextBox |                             <TextBox | ||||||
|                                 Name="txttunDNS2" |                                 Name="txttunDNS2Compatible" | ||||||
|                                 VerticalAlignment="Stretch" |                                 VerticalAlignment="Stretch" | ||||||
|                                 Classes="TextArea" |                                 Classes="TextArea" | ||||||
|                                 MinLines="10" |                                 MinLines="10" | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| using System.Reactive.Disposables; | using System.Reactive.Disposables; | ||||||
|  | using Avalonia.Controls; | ||||||
| using Avalonia.Interactivity; | using Avalonia.Interactivity; | ||||||
| using ReactiveUI; | using ReactiveUI; | ||||||
| using v2rayN.Desktop.Base; | using v2rayN.Desktop.Base; | ||||||
|  | @ -17,26 +18,64 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel> | ||||||
|         btnCancel.Click += (s, e) => this.Close(); |         btnCancel.Click += (s, e) => this.Close(); | ||||||
|         ViewModel = new DNSSettingViewModel(UpdateViewHandler); |         ViewModel = new DNSSettingViewModel(UpdateViewHandler); | ||||||
| 
 | 
 | ||||||
|         cmbdomainStrategy4Freedom.ItemsSource = Global.DomainStrategy4Freedoms; |         cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms; | ||||||
|         cmbdomainStrategy4Out.ItemsSource = Global.SingboxDomainStrategy4Out; |         cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress.ItemsSource = Global.DomainDNSAddress; |         cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress2.ItemsSource = Global.SingboxDomainDNSAddress; |         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.WhenActivated(disposables => | ||||||
|         { |         { | ||||||
|             this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(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.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.SelectedValue).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).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.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.SelectedValue).DisposeWith(disposables); |             //this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.SelectedValue).DisposeWith(disposables); |             //this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); |             //this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.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.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); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -46,6 +46,7 @@ | ||||||
|                         <Separator /> |                         <Separator /> | ||||||
|                         <MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" /> |                         <MenuItem x:Name="menuAddHysteria2Server" Header="{x:Static resx:ResUI.menuAddHysteria2Server}" /> | ||||||
|                         <MenuItem x:Name="menuAddTuicServer" Header="{x:Static resx:ResUI.menuAddTuicServer}" /> |                         <MenuItem x:Name="menuAddTuicServer" Header="{x:Static resx:ResUI.menuAddTuicServer}" /> | ||||||
|  |                         <MenuItem x:Name="menuAddAnytlsServer" Header="{x:Static resx:ResUI.menuAddAnytlsServer}" /> | ||||||
|                     </MenuItem> |                     </MenuItem> | ||||||
| 
 | 
 | ||||||
|                     <MenuItem Padding="8,0"> |                     <MenuItem Padding="8,0"> | ||||||
|  | @ -71,6 +72,7 @@ | ||||||
|                         <MenuItem x:Name="menuOptionSetting" Header="{x:Static resx:ResUI.menuOptionSetting}" /> |                         <MenuItem x:Name="menuOptionSetting" Header="{x:Static resx:ResUI.menuOptionSetting}" /> | ||||||
|                         <MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" /> |                         <MenuItem x:Name="menuRoutingSetting" Header="{x:Static resx:ResUI.menuRoutingSetting}" /> | ||||||
|                         <MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" /> |                         <MenuItem x:Name="menuDNSSetting" Header="{x:Static resx:ResUI.menuDNSSetting}" /> | ||||||
|  |                         <MenuItem x:Name="menuCustomConfig" Header="{x:Static resx:ResUI.menuCustomConfig}" /> | ||||||
|                         <MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" /> |                         <MenuItem x:Name="menuGlobalHotkeySetting" Header="{x:Static resx:ResUI.menuGlobalHotkeySetting}" /> | ||||||
|                         <Separator /> |                         <Separator /> | ||||||
|                         <MenuItem x:Name="menuRebootAsAdmin" Header="{x:Static resx:ResUI.menuRebootAsAdmin}" /> |                         <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.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).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.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.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables); |             this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).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.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).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.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables); | ||||||
|  |             this.BindCommand(ViewModel, vm => vm.CustomConfigCmd, v => v.menuCustomConfig).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).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.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables); |             this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables); | ||||||
|  | @ -189,6 +191,9 @@ public partial class MainWindow : WindowBase<MainWindowViewModel> | ||||||
|             case EViewAction.DNSSettingWindow: |             case EViewAction.DNSSettingWindow: | ||||||
|                 return await new DNSSettingWindow().ShowDialog<bool>(this); |                 return await new DNSSettingWindow().ShowDialog<bool>(this); | ||||||
| 
 | 
 | ||||||
|  |             case EViewAction.CustomConfigWindow: | ||||||
|  |                 return await new CustomConfigWindow().ShowDialog<bool>(this); | ||||||
|  | 
 | ||||||
|             case EViewAction.RoutingSettingWindow: |             case EViewAction.RoutingSettingWindow: | ||||||
|                 return await new RoutingSettingWindow().ShowDialog<bool>(this); |                 return await new RoutingSettingWindow().ShowDialog<bool>(this); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -117,7 +117,7 @@ public partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel> | ||||||
| 
 | 
 | ||||||
|     private void linkdomainStrategy4Singbox_Click(object? sender, RoutedEventArgs e) |     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) |     private void btnCancel_Click(object? sender, RoutedEventArgs e) | ||||||
|  |  | ||||||
|  | @ -707,6 +707,35 @@ | ||||||
|                         materialDesign:HintAssist.Hint="1500" |                         materialDesign:HintAssist.Hint="1500" | ||||||
|                         Style="{StaticResource DefTextBox}" /> |                         Style="{StaticResource DefTextBox}" /> | ||||||
|                 </Grid> |                 </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 |                 <Separator | ||||||
|                     x:Name="sepa2" |                     x:Name="sepa2" | ||||||
|  |  | ||||||
|  | @ -96,6 +96,12 @@ public partial class AddServerWindow | ||||||
|                 gridTls.Visibility = Visibility.Collapsed; |                 gridTls.Visibility = Visibility.Collapsed; | ||||||
| 
 | 
 | ||||||
|                 break; |                 break; | ||||||
|  | 
 | ||||||
|  |             case EConfigType.Anytls: | ||||||
|  |                 gridAnytls.Visibility = Visibility.Visible; | ||||||
|  |                 cmbCoreType.IsEnabled = false; | ||||||
|  |                 lstStreamSecurity.Add(Global.StreamSecurityReality); | ||||||
|  |                 break; | ||||||
|         } |         } | ||||||
|         cmbStreamSecurity.ItemsSource = lstStreamSecurity; |         cmbStreamSecurity.ItemsSource = lstStreamSecurity; | ||||||
| 
 | 
 | ||||||
|  | @ -161,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.RequestHost, v => v.txtRequestHost9.Text).DisposeWith(disposables); | ||||||
|                     this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables); |                     this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId9.Text).DisposeWith(disposables); | ||||||
|                     break; |                     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.Network, v => v.cmbNetwork.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables); | ||||||
|  |  | ||||||
							
								
								
									
										205
									
								
								v2rayN/v2rayN/Views/CustomConfigWindow.xaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								v2rayN/v2rayN/Views/CustomConfigWindow.xaml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,205 @@ | ||||||
|  | <base:WindowBase | ||||||
|  |     x:Class="v2rayN.Views.CustomConfigWindow" | ||||||
|  |     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.menuCustomConfig}" | ||||||
|  |     Width="1000" | ||||||
|  |     Height="700" | ||||||
|  |     x:TypeArguments="vms:CustomConfigViewModel" | ||||||
|  |     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.TbRayCustomConfig}"> | ||||||
|  |                 <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 | ||||||
|  |                                 Grid.Row="0" | ||||||
|  |                                 Margin="{StaticResource Margin8}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbRayCustomConfigDesc}" /> | ||||||
|  |                         </StackPanel> | ||||||
|  | 
 | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Margin="{StaticResource Margin8}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbCustomConfigEnable}" /> | ||||||
|  |                             <ToggleButton | ||||||
|  |                                 x:Name="rayCustomConfigEnable" | ||||||
|  |                                 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="rayCustomConfig" | ||||||
|  |                         Margin="{StaticResource Margin8}" | ||||||
|  |                         VerticalAlignment="Stretch" | ||||||
|  |                         materialDesign:HintAssist.Hint="xray json config" | ||||||
|  |                         AcceptsReturn="True" | ||||||
|  |                         BorderThickness="1" | ||||||
|  |                         Style="{StaticResource MaterialDesignOutlinedTextBox}" | ||||||
|  |                         TextWrapping="Wrap" | ||||||
|  |                         VerticalScrollBarVisibility="Auto" /> | ||||||
|  |                 </DockPanel> | ||||||
|  |             </TabItem> | ||||||
|  |             <TabItem HorizontalAlignment="Left" Header="{x:Static resx:ResUI.TbCustomConfigSingbox}"> | ||||||
|  |                 <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 | ||||||
|  |                                 Grid.Row="0" | ||||||
|  |                                 Margin="{StaticResource Margin8}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbSBCustomConfigDesc}" /> | ||||||
|  |                         </StackPanel> | ||||||
|  | 
 | ||||||
|  |                         <StackPanel Grid.Row="1" Orientation="Horizontal"> | ||||||
|  |                             <TextBlock | ||||||
|  |                                 Margin="{StaticResource Margin8}" | ||||||
|  |                                 VerticalAlignment="Center" | ||||||
|  |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                                 Text="{x:Static resx:ResUI.TbCustomConfigEnable}" /> | ||||||
|  |                             <ToggleButton | ||||||
|  |                                 x:Name="sbCustomConfigEnable" | ||||||
|  |                                 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="sbCustomConfig" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             VerticalAlignment="Stretch" | ||||||
|  |                             materialDesign:HintAssist.Hint="sing-box json config" | ||||||
|  |                             AcceptsReturn="True" | ||||||
|  |                             BorderThickness="1" | ||||||
|  |                             Style="{StaticResource MaterialDesignOutlinedTextBox}" | ||||||
|  |                             TextWrapping="Wrap" | ||||||
|  |                             VerticalScrollBarVisibility="Auto" /> | ||||||
|  | 
 | ||||||
|  |                         <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> | ||||||
|  | 
 | ||||||
|  |                         <TextBox | ||||||
|  |                             x:Name="sbCustomTunConfig" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             VerticalAlignment="Stretch" | ||||||
|  |                             materialDesign:HintAssist.Hint="sing-box json tun config" | ||||||
|  |                             AcceptsReturn="True" | ||||||
|  |                             BorderThickness="1" | ||||||
|  |                             Style="{StaticResource MaterialDesignOutlinedTextBox}" | ||||||
|  |                             TextWrapping="Wrap" | ||||||
|  |                             VerticalScrollBarVisibility="Auto" /> | ||||||
|  |                     </Grid> | ||||||
|  |                 </DockPanel> | ||||||
|  |             </TabItem> | ||||||
|  |         </TabControl> | ||||||
|  |     </DockPanel> | ||||||
|  | </base:WindowBase> | ||||||
							
								
								
									
										47
									
								
								v2rayN/v2rayN/Views/CustomConfigWindow.xaml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								v2rayN/v2rayN/Views/CustomConfigWindow.xaml.cs
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | using System.Reactive.Disposables; | ||||||
|  | using System.Windows; | ||||||
|  | using ReactiveUI; | ||||||
|  | 
 | ||||||
|  | namespace v2rayN.Views; | ||||||
|  | 
 | ||||||
|  | public partial class CustomConfigWindow | ||||||
|  | { | ||||||
|  |     private static Config _config; | ||||||
|  | 
 | ||||||
|  |     public CustomConfigWindow() | ||||||
|  |     { | ||||||
|  |         InitializeComponent(); | ||||||
|  | 
 | ||||||
|  |         this.Owner = Application.Current.MainWindow; | ||||||
|  |         _config = AppHandler.Instance.Config; | ||||||
|  | 
 | ||||||
|  |         ViewModel = new CustomConfigViewModel(UpdateViewHandler); | ||||||
|  | 
 | ||||||
|  |         this.WhenActivated(disposables => | ||||||
|  |         { | ||||||
|  |             this.Bind(ViewModel, vm => vm.EnableCustomConfig4Ray, v => v.rayCustomConfigEnable.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.CustomConfig4Ray, v => v.rayCustomConfig.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.EnableCustomConfig4Singbox, v => v.sbCustomConfigEnable.IsChecked).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.CustomConfig4Singbox, v => v.sbCustomConfig.Text).DisposeWith(disposables); | ||||||
|  |             this.Bind(ViewModel, vm => vm.CustomTunConfig4Singbox, v => v.sbCustomTunConfig.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); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -41,31 +41,361 @@ | ||||||
|         </StackPanel> |         </StackPanel> | ||||||
| 
 | 
 | ||||||
|         <TabControl HorizontalContentAlignment="Left"> |         <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 |                         <TextBlock | ||||||
|  |                             x:Name="txtBasicDNSSettingsInvalid" | ||||||
|  |                             Grid.Row="0" | ||||||
|  |                             Grid.Column="0" | ||||||
|  |                             Grid.ColumnSpan="3" | ||||||
|                             Margin="{StaticResource Margin8}" |                             Margin="{StaticResource Margin8}" | ||||||
|                             VerticalAlignment="Center" |                             VerticalAlignment="Center" | ||||||
|                             Style="{StaticResource ToolbarTextBlock}" |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|                             Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" /> |                             Text="{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}" /> | ||||||
|  | 
 | ||||||
|                         <TextBlock |                         <TextBlock | ||||||
|  |                             Grid.Row="1" | ||||||
|  |                             Grid.Column="0" | ||||||
|                             Margin="{StaticResource Margin8}" |                             Margin="{StaticResource Margin8}" | ||||||
|                             VerticalAlignment="Center" |                             VerticalAlignment="Center" | ||||||
|                             Style="{StaticResource ToolbarTextBlock}"> |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|                             <Hyperlink Click="linkDnsObjectDoc_Click"> |                             Text="{x:Static resx:ResUI.TbDomesticDNS}" /> | ||||||
|                                 <TextBlock Text="{x:Static resx:ResUI.TbDnsObjectDoc}" /> |                         <ComboBox | ||||||
|                                 <materialDesign:PackIcon Kind="Link" /> |                             x:Name="cmbDirectDNS" | ||||||
|                             </Hyperlink> |                             Grid.Row="1" | ||||||
|                         </TextBlock> |                             Grid.Column="1" | ||||||
|                         <Button |                             Width="200" | ||||||
|                             x:Name="btnImportDefConfig4V2ray" |                             IsEditable="True" | ||||||
|                             Margin="{StaticResource Margin8}" |                             Margin="{StaticResource Margin8}" | ||||||
|                             Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                             Style="{StaticResource DefComboBox}" /> | ||||||
|                             Cursor="Hand" | 
 | ||||||
|                             Style="{StaticResource DefButton}" /> |                         <TextBlock | ||||||
|                     </StackPanel> |                             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" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             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" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="3" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBOutboundDomainResolve}" /> | ||||||
|  | 
 | ||||||
|  |                         <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" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbSBFallbackDNSResolve}" /> | ||||||
|  | 
 | ||||||
|  |                         <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}" /> | ||||||
|  | 
 | ||||||
|  |                         <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.TbPreventDNSLeaks}" /> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                         <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" | ||||||
|  |                             IsEditable="True" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             Style="{StaticResource DefComboBox}" /> | ||||||
|  |                         <TextBlock | ||||||
|  |                             Grid.Row="4" | ||||||
|  |                             Grid.Column="2" | ||||||
|  |                             Margin="{StaticResource Margin8}" | ||||||
|  |                             VerticalAlignment="Center" | ||||||
|  |                             Style="{StaticResource ToolbarTextBlock}" | ||||||
|  |                             Text="{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}" /> | ||||||
|  | 
 | ||||||
|  |                         <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"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -75,7 +405,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" /> | ||||||
|                             <ToggleButton |                             <ToggleButton | ||||||
|                                 x:Name="togUseSystemHosts" |                                 x:Name="togUseSystemHostsCompatible" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 HorizontalAlignment="Left" /> |                                 HorizontalAlignment="Left" /> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|  | @ -87,7 +417,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Freedom" |                                 x:Name="cmbdomainStrategy4FreedomCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 Style="{StaticResource DefComboBox}" /> |                                 Style="{StaticResource DefComboBox}" /> | ||||||
|  | @ -100,7 +430,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainDNSAddress" |                                 x:Name="cmbdomainDNSAddressCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 IsEditable="True" |                                 IsEditable="True" | ||||||
|  | @ -109,7 +439,7 @@ | ||||||
|                     </WrapPanel> |                     </WrapPanel> | ||||||
| 
 | 
 | ||||||
|                     <TextBox |                     <TextBox | ||||||
|                         x:Name="txtnormalDNS" |                         x:Name="txtnormalDNSCompatible" | ||||||
|                         Margin="{StaticResource Margin8}" |                         Margin="{StaticResource Margin8}" | ||||||
|                         VerticalAlignment="Stretch" |                         VerticalAlignment="Stretch" | ||||||
|                         materialDesign:HintAssist.Hint="HTTP/SOCKS" |                         materialDesign:HintAssist.Hint="HTTP/SOCKS" | ||||||
|  | @ -123,23 +453,42 @@ | ||||||
| 
 | 
 | ||||||
|             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> |             <TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}"> | ||||||
|                 <DockPanel Margin="{StaticResource Margin8}"> |                 <DockPanel Margin="{StaticResource Margin8}"> | ||||||
|                     <StackPanel DockPanel.Dock="Top" Orientation="Horizontal"> |                     <Grid DockPanel.Dock="Top"> | ||||||
|                         <TextBlock |                         <Grid.RowDefinitions> | ||||||
|                             Margin="{StaticResource Margin8}" |                             <RowDefinition Height="Auto" /> | ||||||
|                             VerticalAlignment="Center" |                             <RowDefinition Height="Auto" /> | ||||||
|                             Style="{StaticResource ToolbarTextBlock}"> |                         </Grid.RowDefinitions> | ||||||
|                             <Hyperlink Click="linkDnsSingboxObjectDoc_Click"> |                          | ||||||
|                                 <TextBlock Text="{x:Static resx:ResUI.TbDnsSingboxObjectDoc}" /> |                         <StackPanel Grid.Row="0" Orientation="Horizontal"> | ||||||
|                                 <materialDesign:PackIcon Kind="Link" /> |                             <TextBlock | ||||||
|                             </Hyperlink> |                                     Margin="{StaticResource Margin8}" | ||||||
|                         </TextBlock> |                                     VerticalAlignment="Center" | ||||||
|                         <Button |                                     Style="{StaticResource ToolbarTextBlock}" | ||||||
|                             x:Name="btnImportDefConfig4Singbox" |                                     Text="{x:Static resx:ResUI.TbCustomDNSEnable}" /> | ||||||
|                             Margin="{StaticResource Margin8}" |                             <ToggleButton | ||||||
|                             Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}" |                                     x:Name="togSBCustomDNSEnableCompatible" | ||||||
|                             Cursor="Hand" |                                     Margin="{StaticResource Margin8}" | ||||||
|                             Style="{StaticResource DefButton}" /> |                                     HorizontalAlignment="Left" /> | ||||||
|                     </StackPanel> |                         </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"> |                     <WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal"> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|  | @ -149,7 +498,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainStrategy4Out" |                                 x:Name="cmbdomainStrategy4OutCompatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 Style="{StaticResource DefComboBox}" /> |                                 Style="{StaticResource DefComboBox}" /> | ||||||
|  | @ -162,7 +511,7 @@ | ||||||
|                                 Style="{StaticResource ToolbarTextBlock}" |                                 Style="{StaticResource ToolbarTextBlock}" | ||||||
|                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> |                                 Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" /> | ||||||
|                             <ComboBox |                             <ComboBox | ||||||
|                                 x:Name="cmbdomainDNSAddress2" |                                 x:Name="cmbdomainDNSAddress2Compatible" | ||||||
|                                 Width="150" |                                 Width="150" | ||||||
|                                 Margin="{StaticResource Margin8}" |                                 Margin="{StaticResource Margin8}" | ||||||
|                                 IsEditable="True" |                                 IsEditable="True" | ||||||
|  | @ -178,7 +527,7 @@ | ||||||
|                         </Grid.ColumnDefinitions> |                         </Grid.ColumnDefinitions> | ||||||
| 
 | 
 | ||||||
|                         <TextBox |                         <TextBox | ||||||
|                             x:Name="txtnormalDNS2" |                             x:Name="txtnormalDNS2Compatible" | ||||||
|                             Grid.Column="0" |                             Grid.Column="0" | ||||||
|                             VerticalAlignment="Stretch" |                             VerticalAlignment="Stretch" | ||||||
|                             materialDesign:HintAssist.Hint="HTTP/SOCKS" |                             materialDesign:HintAssist.Hint="HTTP/SOCKS" | ||||||
|  | @ -191,7 +540,7 @@ | ||||||
|                         <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> |                         <GridSplitter Grid.Column="1" HorizontalAlignment="Stretch" /> | ||||||
| 
 | 
 | ||||||
|                         <TextBox |                         <TextBox | ||||||
|                             x:Name="txttunDNS2" |                             x:Name="txttunDNS2Compatible" | ||||||
|                             Grid.Column="2" |                             Grid.Column="2" | ||||||
|                             VerticalAlignment="Stretch" |                             VerticalAlignment="Stretch" | ||||||
|                             materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsTunMode}" |                             materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbSettingsTunMode}" | ||||||
|  |  | ||||||
|  | @ -17,26 +17,66 @@ public partial class DNSSettingWindow | ||||||
| 
 | 
 | ||||||
|         ViewModel = new DNSSettingViewModel(UpdateViewHandler); |         ViewModel = new DNSSettingViewModel(UpdateViewHandler); | ||||||
| 
 | 
 | ||||||
|         cmbdomainStrategy4Freedom.ItemsSource = Global.DomainStrategy4Freedoms; |         cmbRayFreedomDNSStrategy.ItemsSource = Global.DomainStrategy4Freedoms; | ||||||
|         cmbdomainStrategy4Out.ItemsSource = Global.SingboxDomainStrategy4Out; |         cmbSBDirectDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress.ItemsSource = Global.DomainDNSAddress; |         cmbSBRemoteDNSStrategy.ItemsSource = Global.SingboxDomainStrategy4Out; | ||||||
|         cmbdomainDNSAddress2.ItemsSource = Global.SingboxDomainDNSAddress; |         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.WhenActivated(disposables => | ||||||
|         { |         { | ||||||
|             this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(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.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress, v => v.cmbdomainDNSAddress.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS, v => v.txtnormalDNS.Text).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.DomainStrategy4Freedom2, v => v.cmbdomainStrategy4Out.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.DomainDNSAddress2, v => v.cmbdomainDNSAddress2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SingboxOutboundsResolveDNS, v => v.cmbSBResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.NormalDNS2, v => v.txtnormalDNS2.Text).DisposeWith(disposables); |             this.Bind(ViewModel, vm => vm.SingboxFinalResolveDNS, v => v.cmbSBFinalResolverDNS.Text).DisposeWith(disposables); | ||||||
|             this.Bind(ViewModel, vm => vm.TunDNS2, v => v.txttunDNS2.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.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); |         WindowsUtils.SetDarkBorder(this, AppHandler.Instance.Config.UiItem.CurrentTheme); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -108,6 +108,10 @@ | ||||||
|                                     x:Name="menuAddTuicServer" |                                     x:Name="menuAddTuicServer" | ||||||
|                                     Height="{StaticResource MenuItemHeight}" |                                     Height="{StaticResource MenuItemHeight}" | ||||||
|                                     Header="{x:Static resx:ResUI.menuAddTuicServer}" /> |                                     Header="{x:Static resx:ResUI.menuAddTuicServer}" /> | ||||||
|  |                                 <MenuItem | ||||||
|  |                                     x:Name="menuAddAnytlsServer" | ||||||
|  |                                     Height="{StaticResource MenuItemHeight}" | ||||||
|  |                                     Header="{x:Static resx:ResUI.menuAddAnytlsServer}" /> | ||||||
|                             </MenuItem> |                             </MenuItem> | ||||||
|                         </Menu> |                         </Menu> | ||||||
|                         <Separator /> |                         <Separator /> | ||||||
|  | @ -169,6 +173,10 @@ | ||||||
|                                     x:Name="menuDNSSetting" |                                     x:Name="menuDNSSetting" | ||||||
|                                     Height="{StaticResource MenuItemHeight}" |                                     Height="{StaticResource MenuItemHeight}" | ||||||
|                                     Header="{x:Static resx:ResUI.menuDNSSetting}" /> |                                     Header="{x:Static resx:ResUI.menuDNSSetting}" /> | ||||||
|  |                                 <MenuItem | ||||||
|  |                                     x:Name="menuCustomConfig" | ||||||
|  |                                     Height="{StaticResource MenuItemHeight}" | ||||||
|  |                                     Header="{x:Static resx:ResUI.menuCustomConfig}" /> | ||||||
|                                 <MenuItem |                                 <MenuItem | ||||||
|                                     x:Name="menuGlobalHotkeySetting" |                                     x:Name="menuGlobalHotkeySetting" | ||||||
|                                     Height="{StaticResource MenuItemHeight}" |                                     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.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).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.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.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables); |             this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).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.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).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.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables); | ||||||
|  |             this.BindCommand(ViewModel, vm => vm.CustomConfigCmd, v => v.menuCustomConfig).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).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.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables); | ||||||
|             this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables); |             this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables); | ||||||
|  | @ -185,6 +187,9 @@ public partial class MainWindow | ||||||
|             case EViewAction.OptionSettingWindow: |             case EViewAction.OptionSettingWindow: | ||||||
|                 return (new OptionSettingWindow().ShowDialog() ?? false); |                 return (new OptionSettingWindow().ShowDialog() ?? false); | ||||||
| 
 | 
 | ||||||
|  |             case EViewAction.CustomConfigWindow: | ||||||
|  |                 return (new CustomConfigWindow().ShowDialog() ?? false); | ||||||
|  | 
 | ||||||
|             case EViewAction.GlobalHotkeySettingWindow: |             case EViewAction.GlobalHotkeySettingWindow: | ||||||
|                 return (new GlobalHotkeySettingWindow().ShowDialog() ?? false); |                 return (new GlobalHotkeySettingWindow().ShowDialog() ?? false); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -122,7 +122,7 @@ public partial class RoutingSettingWindow | ||||||
| 
 | 
 | ||||||
|     private void linkdomainStrategy4Singbox_Click(object sender, RoutedEventArgs e) |     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) |     private void btnCancel_Click(object sender, System.Windows.RoutedEventArgs e) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 DHR60
						DHR60