mirror of
https://github.com/2dust/v2rayN.git
synced 2026-07-26 09:52:05 +03:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b01476d147 | ||
|
|
cf8dd45abe | ||
|
|
9bba6f53f8 | ||
|
|
cd77f1d882 | ||
|
|
0427037638 | ||
|
|
e749b81ecf | ||
|
|
fd2c942231 | ||
|
|
fa42eb670f | ||
|
|
0d42996573 | ||
|
|
a37772f12b | ||
|
|
531e0e9443 |
@@ -13,8 +13,8 @@ PKGROOT="v2rayN-publish"
|
|||||||
PROJECT_HINT="v2rayN.Desktop/v2rayN.Desktop.csproj"
|
PROJECT_HINT="v2rayN.Desktop/v2rayN.Desktop.csproj"
|
||||||
OUTPUT_DIR="${HOME}/debbuild"
|
OUTPUT_DIR="${HOME}/debbuild"
|
||||||
DOTNET_TFM="net10.0"
|
DOTNET_TFM="net10.0"
|
||||||
DOTNET_LOONGARCH_VERSION="10.0.109"
|
DOTNET_LOONGARCH_VERSION="10.0.110"
|
||||||
DOTNET_LOONGARCH_TAG="v10.0.109-loongarch64"
|
DOTNET_LOONGARCH_TAG="v10.0.110-loongarch64"
|
||||||
DOTNET_LOONGARCH_BASE="https://github.com/loongson/dotnet/releases/download"
|
DOTNET_LOONGARCH_BASE="https://github.com/loongson/dotnet/releases/download"
|
||||||
DOTNET_LOONGARCH_FILE="dotnet-sdk-${DOTNET_LOONGARCH_VERSION}-linux-loongarch64.tar.gz"
|
DOTNET_LOONGARCH_FILE="dotnet-sdk-${DOTNET_LOONGARCH_VERSION}-linux-loongarch64.tar.gz"
|
||||||
DOTNET_SDK_URL="${DOTNET_LOONGARCH_BASE}/${DOTNET_LOONGARCH_TAG}/${DOTNET_LOONGARCH_FILE}"
|
DOTNET_SDK_URL="${DOTNET_LOONGARCH_BASE}/${DOTNET_LOONGARCH_TAG}/${DOTNET_LOONGARCH_FILE}"
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ MIN_KERNEL="6.12"
|
|||||||
PKGROOT="v2rayN-publish"
|
PKGROOT="v2rayN-publish"
|
||||||
PROJECT_HINT="v2rayN.Desktop/v2rayN.Desktop.csproj"
|
PROJECT_HINT="v2rayN.Desktop/v2rayN.Desktop.csproj"
|
||||||
RPM_TOPDIR="${HOME}/rpmbuild"
|
RPM_TOPDIR="${HOME}/rpmbuild"
|
||||||
DOTNET_LOONGARCH_VERSION="10.0.109"
|
DOTNET_LOONGARCH_VERSION="10.0.110"
|
||||||
DOTNET_LOONGARCH_TAG="v10.0.109-loongarch64"
|
DOTNET_LOONGARCH_TAG="v10.0.110-loongarch64"
|
||||||
DOTNET_LOONGARCH_BASE="https://github.com/loongson/dotnet/releases/download"
|
DOTNET_LOONGARCH_BASE="https://github.com/loongson/dotnet/releases/download"
|
||||||
DOTNET_LOONGARCH_FILE="dotnet-sdk-${DOTNET_LOONGARCH_VERSION}-linux-loongarch64.tar.gz"
|
DOTNET_LOONGARCH_FILE="dotnet-sdk-${DOTNET_LOONGARCH_VERSION}-linux-loongarch64.tar.gz"
|
||||||
DOTNET_SDK_URL="${DOTNET_LOONGARCH_BASE}/${DOTNET_LOONGARCH_TAG}/${DOTNET_LOONGARCH_FILE}"
|
DOTNET_SDK_URL="${DOTNET_LOONGARCH_BASE}/${DOTNET_LOONGARCH_TAG}/${DOTNET_LOONGARCH_FILE}"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>7.24.1</Version>
|
<Version>7.24.2</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="12.1.0" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="12.1.0" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="12.1.0" />
|
<PackageVersion Include="Avalonia.Desktop" Version="12.1.0" />
|
||||||
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
<PackageVersion Include="AvaloniaUI.DiagnosticsSupport" Version="2.2.3" />
|
||||||
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
<PackageVersion Include="AwesomeAssertions" Version="9.5.0" />
|
||||||
<PackageVersion Include="DialogHost.Avalonia" Version="0.12.2" />
|
<PackageVersion Include="DialogHost.Avalonia" Version="0.12.3" />
|
||||||
<PackageVersion Include="IPNetwork2" Version="4.3.0" />
|
<PackageVersion Include="IPNetwork2" Version="4.3.0" />
|
||||||
<PackageVersion Include="ReactiveUI.Avalonia" Version="12.0.3" />
|
<PackageVersion Include="ReactiveUI.Avalonia" Version="12.0.3" />
|
||||||
<PackageVersion Include="CliWrap" Version="3.10.2" />
|
<PackageVersion Include="CliWrap" Version="3.10.2" />
|
||||||
<PackageVersion Include="Downloader" Version="5.9.4" />
|
<PackageVersion Include="Downloader" Version="5.9.5" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.7.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
|
||||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.4.1" />
|
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.4.1" />
|
||||||
<PackageVersion Include="MaterialDesignThemes" Version="5.3.2" />
|
<PackageVersion Include="MaterialDesignThemes" Version="5.3.2" />
|
||||||
<PackageVersion Include="QRCoder" Version="1.8.0" />
|
<PackageVersion Include="QRCoder" Version="1.8.0" />
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="12.1.0" />
|
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="12.1.0" />
|
||||||
<PackageVersion Include="NLog" Version="6.1.4" />
|
<PackageVersion Include="NLog" Version="6.1.4" />
|
||||||
<PackageVersion Include="sqlite-net-e" Version="1.11.285" />
|
<PackageVersion Include="sqlite-net-e" Version="1.11.285" />
|
||||||
<PackageVersion Include="Repobot.SQLite.Unofficial" Version="3.53.3" />
|
<PackageVersion Include="Repobot.SQLite.Unofficial" Version="3.53.3.10" />
|
||||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||||
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
||||||
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
|
||||||
@@ -36,4 +36,4 @@
|
|||||||
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.22" />
|
<PackageVersion Include="ZXing.Net.Bindings.SkiaSharp" Version="0.16.22" />
|
||||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.4" />
|
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="3.119.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -2,8 +2,6 @@ namespace ServiceLib;
|
|||||||
|
|
||||||
public class Global
|
public class Global
|
||||||
{
|
{
|
||||||
#region const
|
|
||||||
|
|
||||||
public const string AppName = "v2rayN";
|
public const string AppName = "v2rayN";
|
||||||
public const string GithubUrl = "https://github.com";
|
public const string GithubUrl = "https://github.com";
|
||||||
public const string GithubApiUrl = "https://api.github.com/repos";
|
public const string GithubApiUrl = "https://api.github.com/repos";
|
||||||
@@ -106,9 +104,7 @@ public class Global
|
|||||||
public const string SingboxFakeDNSTag = "fake_dns";
|
public const string SingboxFakeDNSTag = "fake_dns";
|
||||||
|
|
||||||
public const int Hysteria2DefaultHopInt = 30;
|
public const int Hysteria2DefaultHopInt = 30;
|
||||||
|
|
||||||
public const string PolicyGroupExcludeKeywords = @"剩余|过期|到期|重置|[Rr]emaining|[Ee]xpir|[Rr]eset";
|
public const string PolicyGroupExcludeKeywords = @"剩余|过期|到期|重置|[Rr]emaining|[Ee]xpir|[Rr]eset";
|
||||||
|
|
||||||
public const string PolicyGroupDefaultAllFilter = $"^(?!.*(?:{PolicyGroupExcludeKeywords})).*$";
|
public const string PolicyGroupDefaultAllFilter = $"^(?!.*(?:{PolicyGroupExcludeKeywords})).*$";
|
||||||
|
|
||||||
public static readonly List<string> PolicyGroupDefaultFilterList =
|
public static readonly List<string> PolicyGroupDefaultFilterList =
|
||||||
@@ -557,7 +553,6 @@ public class Global
|
|||||||
"http",
|
"http",
|
||||||
"tls",
|
"tls",
|
||||||
"quic",
|
"quic",
|
||||||
"fakedns",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public static readonly List<int> TunMtus =
|
public static readonly List<int> TunMtus =
|
||||||
@@ -737,6 +732,12 @@ public class Global
|
|||||||
"reply",
|
"reply",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public static readonly List<string> FakeIPRanges =
|
||||||
|
[
|
||||||
|
"198.18.0.0/15",
|
||||||
|
"11.0.0.0/8",
|
||||||
|
];
|
||||||
|
|
||||||
public static readonly List<string> RootCertProviders =
|
public static readonly List<string> RootCertProviders =
|
||||||
[
|
[
|
||||||
"system",
|
"system",
|
||||||
@@ -744,5 +745,27 @@ public class Global
|
|||||||
MozillaRootProvider,
|
MozillaRootProvider,
|
||||||
];
|
];
|
||||||
|
|
||||||
#endregion const
|
public static readonly IReadOnlyList<string> TunIpv4Address =
|
||||||
|
[
|
||||||
|
"172.18.0.1/30",
|
||||||
|
"172.31.0.1/30",
|
||||||
|
"172.20.0.1/30",
|
||||||
|
"172.16.0.1/30",
|
||||||
|
"192.168.100.1/30",
|
||||||
|
"10.10.14.1/30",
|
||||||
|
"10.1.0.1/30",
|
||||||
|
"10.0.0.1/30",
|
||||||
|
];
|
||||||
|
|
||||||
|
public static readonly IReadOnlyList<string> TunIpv6Address =
|
||||||
|
[
|
||||||
|
"fc00::172:18:0:1/128",
|
||||||
|
"fc00::172:31:0:1/128",
|
||||||
|
"fc00::172:20:0:1/128",
|
||||||
|
"fc00::172:16:0:1/128",
|
||||||
|
"fc00::192:168:100:1/128",
|
||||||
|
"fc00::10:10:14:1/128",
|
||||||
|
"fc00::10:1:0:1/128",
|
||||||
|
"fc00::10:0:0:1/128",
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ global using ServiceLib.Handler.Fmt;
|
|||||||
global using ServiceLib.Handler.SysProxy;
|
global using ServiceLib.Handler.SysProxy;
|
||||||
global using ServiceLib.Helper;
|
global using ServiceLib.Helper;
|
||||||
global using ServiceLib.Manager;
|
global using ServiceLib.Manager;
|
||||||
global using ServiceLib.Models.CoreConfigs;
|
|
||||||
global using ServiceLib.Models.Configs;
|
global using ServiceLib.Models.Configs;
|
||||||
|
global using ServiceLib.Models.CoreConfigs;
|
||||||
global using ServiceLib.Models.Dto;
|
global using ServiceLib.Models.Dto;
|
||||||
global using ServiceLib.Models.Entities;
|
global using ServiceLib.Models.Entities;
|
||||||
global using ServiceLib.Resx;
|
global using ServiceLib.Resx;
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ public static class ConfigHandler
|
|||||||
config.ConstItem ??= new ConstItem();
|
config.ConstItem ??= new ConstItem();
|
||||||
|
|
||||||
config.SimpleDNSItem ??= InitBuiltinSimpleDNS();
|
config.SimpleDNSItem ??= InitBuiltinSimpleDNS();
|
||||||
|
config.SimpleDNSItem.FakeIPRange ??= Global.FakeIPRanges.FirstOrDefault();
|
||||||
config.SimpleDNSItem.GlobalFakeIp ??= true;
|
config.SimpleDNSItem.GlobalFakeIp ??= true;
|
||||||
config.SimpleDNSItem.BootstrapDNS ??= Global.DomainPureIPDNSAddress.FirstOrDefault();
|
config.SimpleDNSItem.BootstrapDNS ??= Global.DomainPureIPDNSAddress.FirstOrDefault();
|
||||||
config.SimpleDNSItem.ServeStale ??= false;
|
config.SimpleDNSItem.ServeStale ??= false;
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ public static class SysProxyHandler
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
|
|
||||||
if (port <= 0)
|
if (port <= 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -24,17 +23,18 @@ public static class SysProxyHandler
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ESysProxyType.ForcedChange when Utils.IsWindows():
|
case ESysProxyType.ForcedChange when Utils.IsWindows():
|
||||||
{
|
var (strProxy, strExceptions) = GetWindowsProxyString(config, port);
|
||||||
GetWindowsProxyString(config, port, out var strProxy, out var strExceptions);
|
ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);
|
||||||
ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ESysProxyType.ForcedChange when Utils.IsLinux():
|
case ESysProxyType.ForcedChange when Utils.IsLinux():
|
||||||
|
var exceptions = SanitizeExceptions(config);
|
||||||
await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
|
await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESysProxyType.ForcedChange when Utils.IsMacOS():
|
case ESysProxyType.ForcedChange when Utils.IsMacOS():
|
||||||
await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions);
|
var exceptions2 = SanitizeExceptions(config);
|
||||||
|
await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ESysProxyType.ForcedClear when Utils.IsWindows():
|
case ESysProxyType.ForcedClear when Utils.IsWindows():
|
||||||
@@ -66,15 +66,31 @@ public static class SysProxyHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)
|
private static string SanitizeExceptions(Config config)
|
||||||
{
|
{
|
||||||
strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
|
var exceptions = config.SystemProxyItem.SystemProxyExceptions;
|
||||||
|
if (exceptions.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = exceptions
|
||||||
|
.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(item => item.Replace(" ", string.Empty))
|
||||||
|
.Where(item => item.Length > 0);
|
||||||
|
|
||||||
|
return string.Join(',', items);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (string strProxy, string strExceptions) GetWindowsProxyString(Config config, int port)
|
||||||
|
{
|
||||||
|
var strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(" ", "");
|
||||||
if (config.SystemProxyItem.NotProxyLocalAddress)
|
if (config.SystemProxyItem.NotProxyLocalAddress)
|
||||||
{
|
{
|
||||||
strExceptions = $"<local>;{strExceptions}";
|
strExceptions = $"<local>;{strExceptions}";
|
||||||
}
|
}
|
||||||
|
|
||||||
strProxy = string.Empty;
|
var strProxy = string.Empty;
|
||||||
if (config.SystemProxyItem.SystemProxyAdvancedProtocol.IsNullOrEmpty())
|
if (config.SystemProxyItem.SystemProxyAdvancedProtocol.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
strProxy = $"{Global.Loopback}:{port}";
|
strProxy = $"{Global.Loopback}:{port}";
|
||||||
@@ -86,6 +102,8 @@ public static class SysProxyHandler
|
|||||||
.Replace("{http_port}", port.ToString())
|
.Replace("{http_port}", port.ToString())
|
||||||
.Replace("{socks_port}", port.ToString());
|
.Replace("{socks_port}", port.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (strProxy, strExceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
|
|||||||
@@ -149,6 +149,8 @@ public class TunModeItem
|
|||||||
public string IcmpRouting { get; set; }
|
public string IcmpRouting { get; set; }
|
||||||
public bool EnableLegacyProtect { get; set; }
|
public bool EnableLegacyProtect { get; set; }
|
||||||
public List<string>? RouteExcludeAddress { get; set; }
|
public List<string>? RouteExcludeAddress { get; set; }
|
||||||
|
public string Ipv4Address { get; set; }
|
||||||
|
public string Ipv6Address { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -255,6 +257,7 @@ public class Fragment4RayItem
|
|||||||
|
|
||||||
// For migration from old version, remove those properties in the future
|
// For migration from old version, remove those properties in the future
|
||||||
public string? Length { get; set; }
|
public string? Length { get; set; }
|
||||||
|
|
||||||
public string? Interval { get; set; }
|
public string? Interval { get; set; }
|
||||||
// migration end
|
// migration end
|
||||||
}
|
}
|
||||||
@@ -274,6 +277,7 @@ public class SimpleDNSItem
|
|||||||
public bool? AddCommonHosts { get; set; }
|
public bool? AddCommonHosts { get; set; }
|
||||||
public bool? FakeIP { get; set; }
|
public bool? FakeIP { get; set; }
|
||||||
public bool? GlobalFakeIp { get; set; }
|
public bool? GlobalFakeIp { get; set; }
|
||||||
|
public string? FakeIPRange { get; set; }
|
||||||
public bool? BlockBindingQuery { get; set; }
|
public bool? BlockBindingQuery { get; set; }
|
||||||
public string? DirectDNS { get; set; }
|
public string? DirectDNS { get; set; }
|
||||||
public string? RemoteDNS { get; set; }
|
public string? RemoteDNS { get; set; }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ public class V2rayConfig
|
|||||||
{
|
{
|
||||||
public Log4Ray log { get; set; }
|
public Log4Ray log { get; set; }
|
||||||
public object dns { get; set; }
|
public object dns { get; set; }
|
||||||
|
public FakeDns4Ray? fakedns { 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; }
|
||||||
@@ -43,6 +44,12 @@ public class Log4Ray
|
|||||||
public string? loglevel { get; set; }
|
public string? loglevel { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class FakeDns4Ray
|
||||||
|
{
|
||||||
|
public string? ipPool { get; set; }
|
||||||
|
public long? poolSize { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class Inbounds4Ray
|
public class Inbounds4Ray
|
||||||
{
|
{
|
||||||
public string tag { get; set; }
|
public string tag { get; set; }
|
||||||
@@ -553,6 +560,7 @@ public class Sockopt4Ray
|
|||||||
|
|
||||||
[JsonPropertyName("interface")]
|
[JsonPropertyName("interface")]
|
||||||
public string? Interface { get; set; }
|
public string? Interface { get; set; }
|
||||||
|
|
||||||
public HappyEyeballs4Ray? happyEyeballs { get; set; }
|
public HappyEyeballs4Ray? happyEyeballs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
20
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
20
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
@@ -3106,7 +3106,7 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Applies globally by default, with built-in FakeIP filtering (sing-box only). 的本地化字符串。
|
/// 查找类似 Applies globally by default, and built-in FakeIP filtering is only built into sing-box. 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbFakeIPTips {
|
public static string TbFakeIPTips {
|
||||||
get {
|
get {
|
||||||
@@ -3348,6 +3348,24 @@ namespace ServiceLib.Resx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Ipv4 Address 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbIpv4Address {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbIpv4Address", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找类似 Ipv6 Address 的本地化字符串。
|
||||||
|
/// </summary>
|
||||||
|
public static string TbIpv6Address {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("TbIpv6Address", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Most Stable 的本地化字符串。
|
/// 查找类似 Most Stable 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1495,7 +1495,7 @@
|
|||||||
<value>Select Profile</value>
|
<value>Select Profile</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>
|
<value>Applies globally by default, and built-in FakeIP filtering is only built into sing-box.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>Please Add At Least One Configuration</value>
|
<value>Please Add At Least One Configuration</value>
|
||||||
|
|||||||
@@ -1492,7 +1492,7 @@
|
|||||||
<value>Choisir une config.</value>
|
<value>Choisir une config.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>Actif globalement par défaut, avec filtre FakeIP intégré ; ne fonctionne que dans sing-box</value>
|
<value>Applies globally by default, and built-in FakeIP filtering is only built into sing-box.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>Veuillez ajouter au moins une configuration</value>
|
<value>Veuillez ajouter au moins une configuration</value>
|
||||||
|
|||||||
@@ -1495,7 +1495,7 @@
|
|||||||
<value>Select Profile</value>
|
<value>Select Profile</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>
|
<value>Applies globally by default, and built-in FakeIP filtering is only built into sing-box.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>Please Add At Least One Configuration</value>
|
<value>Please Add At Least One Configuration</value>
|
||||||
|
|||||||
@@ -1495,7 +1495,7 @@
|
|||||||
<value>Pilih profil</value>
|
<value>Pilih profil</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>Berlaku secara global secara default, dengan filter FakeIP bawaan (hanya sing-box).</value>
|
<value>Applies globally by default, and built-in FakeIP filtering is only built into sing-box.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>Silakan tambahkan setidaknya satu konfigurasi.</value>
|
<value>Silakan tambahkan setidaknya satu konfigurasi.</value>
|
||||||
|
|||||||
@@ -1501,7 +1501,7 @@
|
|||||||
<value>Select Profile</value>
|
<value>Select Profile</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>
|
<value>Applies globally by default, and built-in FakeIP filtering is only built into sing-box.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>Please Add At Least One Configuration</value>
|
<value>Please Add At Least One Configuration</value>
|
||||||
@@ -1842,4 +1842,10 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
|||||||
<data name="TbEnableHappyEyeballsTip" xml:space="preserve">
|
<data name="TbEnableHappyEyeballsTip" xml:space="preserve">
|
||||||
<value>Requires the UseIP Strategy. When enabled, it attempts IPv4 and IPv6 connections simultaneously and automatically selects the faster available path.</value>
|
<value>Requires the UseIP Strategy. When enabled, it attempts IPv4 and IPv6 connections simultaneously and automatically selects the faster available path.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbIpv6Address" xml:space="preserve">
|
||||||
|
<value>Ipv6 Address</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbIpv4Address" xml:space="preserve">
|
||||||
|
<value>Ipv4 Address</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1501,7 +1501,7 @@
|
|||||||
<value>Выбрать профиль</value>
|
<value>Выбрать профиль</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>По умолчанию применяется глобально, со встроенной фильтрацией FakeIP (только sing-box).</value>
|
<value>Applies globally by default, and built-in FakeIP filtering is only built into sing-box.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>Добавьте хотя бы одну конфигурацию</value>
|
<value>Добавьте хотя бы одну конфигурацию</value>
|
||||||
|
|||||||
@@ -1498,7 +1498,7 @@
|
|||||||
<value>选择配置</value>
|
<value>选择配置</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>默认全局生效,内置 FakeIP 过滤,仅在 sing-box 中生效</value>
|
<value>默认全局生效,仅在 sing-box 中内置 FakeIP 过滤。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>请至少添加一个配置</value>
|
<value>请至少添加一个配置</value>
|
||||||
@@ -1839,4 +1839,10 @@
|
|||||||
<data name="TbEnableHappyEyeballsTip" xml:space="preserve">
|
<data name="TbEnableHappyEyeballsTip" xml:space="preserve">
|
||||||
<value>需配合 UseIP 策略使用。启用后将同时尝试 IPv4 和 IPv6 连接,并自动选择更快可用的路径。</value>
|
<value>需配合 UseIP 策略使用。启用后将同时尝试 IPv4 和 IPv6 连接,并自动选择更快可用的路径。</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TbIpv6Address" xml:space="preserve">
|
||||||
|
<value>Ipv6 地址</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbIpv4Address" xml:space="preserve">
|
||||||
|
<value>Ipv4 地址</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1498,7 +1498,7 @@
|
|||||||
<value>選擇節點</value>
|
<value>選擇節點</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbFakeIPTips" xml:space="preserve">
|
<data name="TbFakeIPTips" xml:space="preserve">
|
||||||
<value>默認全域生效,內置 FakeIP 過濾,僅在 sing-box 中生效</value>
|
<value>默認全局生效,僅在 sing-box 中內置 FakeIP 過濾。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
<data name="PleaseAddAtLeastOneServer" xml:space="preserve">
|
||||||
<value>請至少添加一個節點</value>
|
<value>請至少添加一個節點</value>
|
||||||
@@ -1827,4 +1827,22 @@
|
|||||||
<data name="TbRootCertificateProviderTip" xml:space="preserve">
|
<data name="TbRootCertificateProviderTip" xml:space="preserve">
|
||||||
<value>僅適用於 v2rayN GUI 的下載與網路請求,不影響核心的憑證驗證</value>
|
<value>僅適用於 v2rayN GUI 的下載與網路請求,不影響核心的憑證驗證</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
<data name="TbProxyDialResolveStrategy" xml:space="preserve">
|
||||||
|
<value>連線代理解析策略</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbProxyDialResolveStrategyTip" xml:space="preserve">
|
||||||
|
<value>不建議啟用,特殊情況可能造成連線循環</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbEnableHappyEyeballs" xml:space="preserve">
|
||||||
|
<value>啟用 Happy Eyeballs</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbEnableHappyEyeballsTip" xml:space="preserve">
|
||||||
|
<value>需搭配 UseIP 策略,啟用後會同時嘗試 IPv4 與 IPv6 連線,並自動選擇速度較快的路徑</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbIpv6Address" xml:space="preserve">
|
||||||
|
<value>Ipv6 位址</value>
|
||||||
|
</data>
|
||||||
|
<data name="TbIpv4Address" xml:space="preserve">
|
||||||
|
<value>Ipv4 位址</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
||||||
@@ -1,27 +1,28 @@
|
|||||||
{
|
{
|
||||||
"tag": "tun",
|
"tag": "tun",
|
||||||
"protocol": "tun",
|
"protocol": "tun",
|
||||||
"settings": {
|
"settings": {
|
||||||
"name": "xray_tun",
|
"name": "xray_tun",
|
||||||
"MTU": 9000,
|
"MTU": 9000,
|
||||||
"gateway": [
|
"gateway": [
|
||||||
"172.18.0.1/30",
|
"172.18.0.1/30",
|
||||||
"fdfe:dcba:9876::1/126"
|
"fdfe:dcba:9876::1/126"
|
||||||
],
|
],
|
||||||
"dns": [
|
"dns": [
|
||||||
"172.18.0.1"
|
"1.1.1.1",
|
||||||
],
|
"8.8.8.8"
|
||||||
"autoSystemRoutingTable": [
|
],
|
||||||
"0.0.0.0/0",
|
"autoSystemRoutingTable": [
|
||||||
"::/0"
|
"0.0.0.0/0",
|
||||||
],
|
"::/0"
|
||||||
"autoOutboundsInterface": "auto"
|
],
|
||||||
},
|
"autoOutboundsInterface": "auto"
|
||||||
"sniffing": {
|
},
|
||||||
"enabled": true,
|
"sniffing": {
|
||||||
"destOverride": [
|
"enabled": true,
|
||||||
"http",
|
"destOverride": [
|
||||||
"tls"
|
"http",
|
||||||
]
|
"tls"
|
||||||
}
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -137,12 +137,12 @@ public partial class CoreConfigSingboxService
|
|||||||
// fake ip
|
// fake ip
|
||||||
if (simpleDnsItem.FakeIP == true)
|
if (simpleDnsItem.FakeIP == true)
|
||||||
{
|
{
|
||||||
|
var fakeipRange = simpleDnsItem.FakeIPRange.IsNullOrEmpty() ? Global.FakeIPRanges.First() : simpleDnsItem.FakeIPRange;
|
||||||
var fakeip = new Server4Sbox
|
var fakeip = new Server4Sbox
|
||||||
{
|
{
|
||||||
tag = Global.SingboxFakeDNSTag,
|
tag = Global.SingboxFakeDNSTag,
|
||||||
type = "fakeip",
|
type = "fakeip",
|
||||||
inet4_range = "198.18.0.0/15",
|
inet4_range = fakeipRange,
|
||||||
inet6_range = "fc00::/18",
|
|
||||||
};
|
};
|
||||||
_coreConfig.dns.servers.Add(fakeip);
|
_coreConfig.dns.servers.Add(fakeip);
|
||||||
}
|
}
|
||||||
@@ -266,7 +266,7 @@ public partial class CoreConfigSingboxService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == true)
|
if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp != false)
|
||||||
{
|
{
|
||||||
var fakeipFilterRule = JsonUtils.Deserialize<Rule4Sbox>(EmbedUtils.GetEmbedText(Global.SingboxFakeIPFilterFileName));
|
var fakeipFilterRule = JsonUtils.Deserialize<Rule4Sbox>(EmbedUtils.GetEmbedText(Global.SingboxFakeIPFilterFileName));
|
||||||
fakeipFilterRule.invert = true;
|
fakeipFilterRule.invert = true;
|
||||||
|
|||||||
@@ -67,9 +67,13 @@ public partial class CoreConfigSingboxService
|
|||||||
tunInbound.auto_route = _config.TunModeItem.AutoRoute;
|
tunInbound.auto_route = _config.TunModeItem.AutoRoute;
|
||||||
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
tunInbound.strict_route = _config.TunModeItem.StrictRoute;
|
||||||
tunInbound.stack = _config.TunModeItem.Stack;
|
tunInbound.stack = _config.TunModeItem.Stack;
|
||||||
if (_config.TunModeItem.EnableIPv6Address == false)
|
|
||||||
|
var address = _config.TunModeItem.Ipv4Address.NullIfEmpty() ?? Global.TunIpv4Address.First();
|
||||||
|
tunInbound.address = [address];
|
||||||
|
if (_config.TunModeItem.EnableIPv6Address == true)
|
||||||
{
|
{
|
||||||
tunInbound.address = ["172.18.0.1/30"];
|
var address6 = _config.TunModeItem.Ipv6Address.NullIfEmpty() ?? Global.TunIpv6Address.First();
|
||||||
|
tunInbound.address.Add(address6);
|
||||||
}
|
}
|
||||||
tunInbound.route_exclude_address = _config.TunModeItem.RouteExcludeAddress;
|
tunInbound.route_exclude_address = _config.TunModeItem.RouteExcludeAddress;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public partial class CoreConfigV2rayService
|
|||||||
_coreConfig.routing.rules.Add(new RulesItem4Ray
|
_coreConfig.routing.rules.Add(new RulesItem4Ray
|
||||||
{
|
{
|
||||||
type = "field",
|
type = "field",
|
||||||
inboundTag = new List<string> { Global.DnsTag },
|
inboundTag = [Global.DnsTag],
|
||||||
outboundTag = Global.ProxyTag,
|
outboundTag = Global.ProxyTag,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
@@ -120,6 +120,33 @@ public partial class CoreConfigV2rayService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GenFakeDns()
|
||||||
|
{
|
||||||
|
var fakeipRange = _config.SimpleDNSItem.FakeIPRange.IsNullOrEmpty() ? Global.FakeIPRanges.First() : _config.SimpleDNSItem.FakeIPRange;
|
||||||
|
var poolSize = 65535L;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fakeipNetwork = IPNetwork2.Parse(fakeipRange);
|
||||||
|
var totalIPs = fakeipNetwork.Total;
|
||||||
|
// see https://github.com/XTLS/Xray-core/blob/6e3322d219140a025285ded1114fe17a5edb74d8/app/dns/fakedns/fake.go#L88
|
||||||
|
// if math.Log2(float64(lruSize)) >= float64(rooms) { return errors.New("LRU size is bigger than subnet size").AtError() }
|
||||||
|
totalIPs -= 1;
|
||||||
|
if (totalIPs > 0)
|
||||||
|
{
|
||||||
|
poolSize = (totalIPs >= long.MaxValue) ? long.MaxValue : (long)totalIPs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
_coreConfig.fakedns = new()
|
||||||
|
{
|
||||||
|
ipPool = fakeipRange,
|
||||||
|
poolSize = poolSize,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void FillDnsServers(Dns4Ray dnsItem)
|
private void FillDnsServers(Dns4Ray dnsItem)
|
||||||
{
|
{
|
||||||
var simpleDNSItem = context.SimpleDnsItem;
|
var simpleDNSItem = context.SimpleDnsItem;
|
||||||
@@ -246,6 +273,23 @@ public partial class CoreConfigV2rayService
|
|||||||
|
|
||||||
var directDnsTagIndex = 1;
|
var directDnsTagIndex = 1;
|
||||||
|
|
||||||
|
if (simpleDNSItem.FakeIP == true)
|
||||||
|
{
|
||||||
|
var fakeIPMatchDomain = new HashSet<string>(proxyDomainList);
|
||||||
|
fakeIPMatchDomain.UnionWith(proxyGeositeList);
|
||||||
|
if (simpleDNSItem.GlobalFakeIp != false)
|
||||||
|
{
|
||||||
|
fakeIPMatchDomain.UnionWith(directDomainList);
|
||||||
|
fakeIPMatchDomain.UnionWith(directGeositeList);
|
||||||
|
fakeIPMatchDomain.UnionWith(expectedDomainList);
|
||||||
|
}
|
||||||
|
if (fakeIPMatchDomain.Count > 0)
|
||||||
|
{
|
||||||
|
GenFakeDns();
|
||||||
|
AddDnsServers(["fakedns"], fakeIPMatchDomain.ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
AddDnsServers(remoteDNSAddress, proxyDomainList);
|
||||||
AddDnsServers(directDNSAddress, directDomainList, true);
|
AddDnsServers(directDNSAddress, directDomainList, true);
|
||||||
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
AddDnsServers(remoteDNSAddress, proxyGeositeList);
|
||||||
|
|||||||
@@ -63,11 +63,16 @@ public partial class CoreConfigV2rayService
|
|||||||
new Inbounds4Ray();
|
new Inbounds4Ray();
|
||||||
tunInbound.settings.name = context.IsMacOS ? $"utun{new Random().Next(99)}" : "xray_tun";
|
tunInbound.settings.name = context.IsMacOS ? $"utun{new Random().Next(99)}" : "xray_tun";
|
||||||
tunInbound.settings.MTU = _config.TunModeItem.Mtu;
|
tunInbound.settings.MTU = _config.TunModeItem.Mtu;
|
||||||
if (!_config.TunModeItem.EnableIPv6Address)
|
|
||||||
|
var address = _config.TunModeItem.Ipv4Address.NullIfEmpty() ?? Global.TunIpv4Address.First();
|
||||||
|
tunInbound.settings.gateway = [address];
|
||||||
|
if (_config.TunModeItem.EnableIPv6Address == true)
|
||||||
{
|
{
|
||||||
tunInbound.settings.gateway = ["172.18.0.1/30"];
|
var address6 = _config.TunModeItem.Ipv6Address.NullIfEmpty() ?? Global.TunIpv6Address.First();
|
||||||
tunInbound.settings.autoSystemRoutingTable = ["0.0.0.0/0"];
|
tunInbound.settings.gateway.Add(address6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tunInbound.settings.autoSystemRoutingTable = ["0.0.0.0/0"];
|
||||||
var bindInterface = _config.CoreBasicItem.BindInterface?.TrimEx();
|
var bindInterface = _config.CoreBasicItem.BindInterface?.TrimEx();
|
||||||
if (!bindInterface.IsNullOrEmpty())
|
if (!bindInterface.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
@@ -152,6 +157,16 @@ public partial class CoreConfigV2rayService
|
|||||||
inbound.sniffing.destOverride = inItem.DestOverride;
|
inbound.sniffing.destOverride = inItem.DestOverride;
|
||||||
inbound.sniffing.routeOnly = inItem.RouteOnly;
|
inbound.sniffing.routeOnly = inItem.RouteOnly;
|
||||||
|
|
||||||
|
if (_config.SimpleDNSItem.FakeIP == true)
|
||||||
|
{
|
||||||
|
// Ensure destOverride contains "fakedns" if FakeIP is enabled
|
||||||
|
inbound.sniffing.destOverride ??= [];
|
||||||
|
if (!inbound.sniffing.destOverride.Contains("fakedns"))
|
||||||
|
{
|
||||||
|
inbound.sniffing.destOverride.Add("fakedns");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return inbound;
|
return inbound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ namespace ServiceLib.ViewModels;
|
|||||||
public class AddServer2ViewModel : MyReactiveObject, ICloseable
|
public class AddServer2ViewModel : MyReactiveObject, ICloseable
|
||||||
{
|
{
|
||||||
public event EventHandler? RequestClose;
|
public event EventHandler? RequestClose;
|
||||||
|
|
||||||
public Interaction<Unit, string?> BrowseConfigFileInteraction { get; } = new();
|
public Interaction<Unit, string?> BrowseConfigFileInteraction { get; } = new();
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable
|
|||||||
[Reactive] public bool UseSystemHosts { get; set; }
|
[Reactive] public bool UseSystemHosts { get; set; }
|
||||||
[Reactive] public bool AddCommonHosts { get; set; }
|
[Reactive] public bool AddCommonHosts { get; set; }
|
||||||
[Reactive] public bool FakeIP { get; set; }
|
[Reactive] public bool FakeIP { get; set; }
|
||||||
|
[Reactive] public string FakeIPRange { get; set; }
|
||||||
[Reactive] public bool BlockBindingQuery { get; set; }
|
[Reactive] public bool BlockBindingQuery { get; set; }
|
||||||
[Reactive] public string DirectDNS { get; set; }
|
[Reactive] public string DirectDNS { get; set; }
|
||||||
[Reactive] public string RemoteDNS { get; set; }
|
[Reactive] public string RemoteDNS { get; set; }
|
||||||
@@ -72,6 +73,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable
|
|||||||
UseSystemHosts = item.UseSystemHosts ?? false;
|
UseSystemHosts = item.UseSystemHosts ?? false;
|
||||||
AddCommonHosts = item.AddCommonHosts ?? false;
|
AddCommonHosts = item.AddCommonHosts ?? false;
|
||||||
FakeIP = item.FakeIP ?? false;
|
FakeIP = item.FakeIP ?? false;
|
||||||
|
FakeIPRange = item.FakeIPRange ?? string.Empty;
|
||||||
BlockBindingQuery = item.BlockBindingQuery ?? false;
|
BlockBindingQuery = item.BlockBindingQuery ?? false;
|
||||||
DirectDNS = item.DirectDNS ?? string.Empty;
|
DirectDNS = item.DirectDNS ?? string.Empty;
|
||||||
RemoteDNS = item.RemoteDNS ?? string.Empty;
|
RemoteDNS = item.RemoteDNS ?? string.Empty;
|
||||||
@@ -105,6 +107,7 @@ public class DNSSettingViewModel : MyReactiveObject, ICloseable
|
|||||||
_config.SimpleDNSItem.UseSystemHosts = UseSystemHosts;
|
_config.SimpleDNSItem.UseSystemHosts = UseSystemHosts;
|
||||||
_config.SimpleDNSItem.AddCommonHosts = AddCommonHosts;
|
_config.SimpleDNSItem.AddCommonHosts = AddCommonHosts;
|
||||||
_config.SimpleDNSItem.FakeIP = FakeIP;
|
_config.SimpleDNSItem.FakeIP = FakeIP;
|
||||||
|
_config.SimpleDNSItem.FakeIPRange = FakeIPRange;
|
||||||
_config.SimpleDNSItem.BlockBindingQuery = BlockBindingQuery;
|
_config.SimpleDNSItem.BlockBindingQuery = BlockBindingQuery;
|
||||||
_config.SimpleDNSItem.DirectDNS = DirectDNS;
|
_config.SimpleDNSItem.DirectDNS = DirectDNS;
|
||||||
_config.SimpleDNSItem.RemoteDNS = RemoteDNS;
|
_config.SimpleDNSItem.RemoteDNS = RemoteDNS;
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ public class OptionSettingViewModel : MyReactiveObject, ICloseable
|
|||||||
[Reactive] public string TunIcmpRouting { get; set; }
|
[Reactive] public string TunIcmpRouting { get; set; }
|
||||||
[Reactive] public bool TunEnableLegacyProtect { get; set; }
|
[Reactive] public bool TunEnableLegacyProtect { get; set; }
|
||||||
[Reactive] public string TunRouteExcludeAddress { get; set; }
|
[Reactive] public string TunRouteExcludeAddress { get; set; }
|
||||||
|
[Reactive] public string TunIpv4Address { get; set; }
|
||||||
|
[Reactive] public string TunIpv6Address { get; set; }
|
||||||
|
|
||||||
#endregion Tun mode
|
#endregion Tun mode
|
||||||
|
|
||||||
@@ -214,6 +216,8 @@ public class OptionSettingViewModel : MyReactiveObject, ICloseable
|
|||||||
TunIcmpRouting = _config.TunModeItem.IcmpRouting;
|
TunIcmpRouting = _config.TunModeItem.IcmpRouting;
|
||||||
TunEnableLegacyProtect = _config.TunModeItem.EnableLegacyProtect;
|
TunEnableLegacyProtect = _config.TunModeItem.EnableLegacyProtect;
|
||||||
TunRouteExcludeAddress = Utils.List2String(_config.TunModeItem.RouteExcludeAddress, true);
|
TunRouteExcludeAddress = Utils.List2String(_config.TunModeItem.RouteExcludeAddress, true);
|
||||||
|
TunIpv4Address = _config.TunModeItem.Ipv4Address;
|
||||||
|
TunIpv6Address = _config.TunModeItem.Ipv6Address;
|
||||||
|
|
||||||
#endregion Tun mode
|
#endregion Tun mode
|
||||||
|
|
||||||
@@ -378,6 +382,8 @@ public class OptionSettingViewModel : MyReactiveObject, ICloseable
|
|||||||
_config.TunModeItem.IcmpRouting = TunIcmpRouting;
|
_config.TunModeItem.IcmpRouting = TunIcmpRouting;
|
||||||
_config.TunModeItem.EnableLegacyProtect = TunEnableLegacyProtect;
|
_config.TunModeItem.EnableLegacyProtect = TunEnableLegacyProtect;
|
||||||
_config.TunModeItem.RouteExcludeAddress = Utils.String2List(TunRouteExcludeAddress);
|
_config.TunModeItem.RouteExcludeAddress = Utils.String2List(TunRouteExcludeAddress);
|
||||||
|
_config.TunModeItem.Ipv4Address = TunIpv4Address;
|
||||||
|
_config.TunModeItem.Ipv6Address = TunIpv6Address;
|
||||||
|
|
||||||
//coreType
|
//coreType
|
||||||
await SaveCoreType();
|
await SaveCoreType();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ namespace ServiceLib.ViewModels;
|
|||||||
public class ProfilesSelectViewModel : MyReactiveObject, ICloseable
|
public class ProfilesSelectViewModel : MyReactiveObject, ICloseable
|
||||||
{
|
{
|
||||||
public event EventHandler? RequestClose;
|
public event EventHandler? RequestClose;
|
||||||
|
|
||||||
public Interaction<Unit, Unit> ProfilesFocusInteraction { get; } = new();
|
public Interaction<Unit, Unit> ProfilesFocusInteraction { get; } = new();
|
||||||
|
|
||||||
#region private prop
|
#region private prop
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ namespace ServiceLib.ViewModels;
|
|||||||
public class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
public class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
||||||
{
|
{
|
||||||
public event EventHandler? RequestClose;
|
public event EventHandler? RequestClose;
|
||||||
|
|
||||||
public Interaction<string, bool> ShowYesNoInteraction { get; } = new();
|
public Interaction<string, bool> ShowYesNoInteraction { get; } = new();
|
||||||
public Interaction<string, Unit> SetClipboardDataInteraction { get; } = new();
|
public Interaction<string, Unit> SetClipboardDataInteraction { get; } = new();
|
||||||
public Interaction<Unit, string?> ReadTextFromClipboardInteraction { get; } = new();
|
public Interaction<Unit, string?> ReadTextFromClipboardInteraction { get; } = new();
|
||||||
|
|||||||
@@ -22,6 +22,14 @@
|
|||||||
<StyleInclude Source="Assets/GlobalStyles.axaml" />
|
<StyleInclude Source="Assets/GlobalStyles.axaml" />
|
||||||
<StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" />
|
<StyleInclude Source="avares://Semi.Avalonia.DataGrid/Index.axaml" />
|
||||||
<dialogHost:DialogHostStyles />
|
<dialogHost:DialogHostStyles />
|
||||||
|
|
||||||
|
<Style Selector="dialogHost|DialogHost">
|
||||||
|
<Setter Property="OverlayBackground" Value="{DynamicResource SemiColorOverlayBackground}" />
|
||||||
|
<Setter Property="Background" Value="{DynamicResource SemiColorFill0}" />
|
||||||
|
|
||||||
|
<Setter Property="dialogHost:DialogHostStyle.BoxShadow" Value="{DynamicResource SemiShadowElevated}" />
|
||||||
|
<Setter Property="dialogHost:DialogHostStyle.CornerRadius" Value="6" />
|
||||||
|
</Style>
|
||||||
</Application.Styles>
|
</Application.Styles>
|
||||||
|
|
||||||
<TrayIcon.Icons>
|
<TrayIcon.Icons>
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
this.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
||||||
|
.WhereNotNull()
|
||||||
|
.Subscribe(InitializeData)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.SelectedValue).DisposeWith(disposables);
|
||||||
@@ -43,11 +48,6 @@ public partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>
|
|||||||
this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).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.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
|
||||||
.WhereNotNull()
|
|
||||||
.Subscribe(InitializeData)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Context menu actions that require custom logic (Add, SelectAll)
|
// Context menu actions that require custom logic (Add, SelectAll)
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
this.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
||||||
|
.WhereNotNull()
|
||||||
|
.Subscribe(InitializeData)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
var configTypeBindings = new SerialDisposable().DisposeWith(disposables);
|
var configTypeBindings = new SerialDisposable().DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);
|
||||||
@@ -188,11 +193,6 @@ public partial class AddServerWindow : WindowBase<AddServerViewModel>
|
|||||||
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).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.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
|
||||||
.WhereNotNull()
|
|
||||||
.Subscribe(InitializeData)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -286,13 +286,24 @@
|
|||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbFakeIP}" />
|
Text="{x:Static resx:ResUI.TbFakeIP}" />
|
||||||
<ToggleSwitch
|
<Grid
|
||||||
x:Name="togFakeIP"
|
|
||||||
Grid.Row="3"
|
Grid.Row="3"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Margin="{StaticResource Margin4}"
|
ColumnDefinitions="Auto,*">
|
||||||
HorizontalAlignment="Left"
|
<ToggleSwitch
|
||||||
VerticalAlignment="Center" />
|
x:Name="togFakeIP"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbFakeIPRange"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsEditable="True" />
|
||||||
|
</Grid>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="3"
|
Grid.Row="3"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
|||||||
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
|
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
|
||||||
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
|
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
|
||||||
cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress;
|
cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress;
|
||||||
|
cmbFakeIPRange.ItemsSource = Global.FakeIPRanges;
|
||||||
cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;
|
cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;
|
||||||
|
|
||||||
cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy;
|
cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy;
|
||||||
@@ -32,6 +33,7 @@ public partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>
|
|||||||
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.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.FakeIPRange, v => v.cmbFakeIPRange.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -18,10 +18,7 @@
|
|||||||
ShowInTaskbar="True"
|
ShowInTaskbar="True"
|
||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<dialogHost:DialogHost
|
<dialogHost:DialogHost CloseOnClickAway="True" DisableOpeningAnimation="True">
|
||||||
Background="Gray"
|
|
||||||
CloseOnClickAway="True"
|
|
||||||
DisableOpeningAnimation="True">
|
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<DockPanel Margin="{StaticResource Margin8}" DockPanel.Dock="Top">
|
<DockPanel Margin="{StaticResource Margin8}" DockPanel.Dock="Top">
|
||||||
<ContentControl x:Name="conTheme" DockPanel.Dock="Right" />
|
<ContentControl x:Name="conTheme" DockPanel.Dock="Right" />
|
||||||
|
|||||||
@@ -961,7 +961,7 @@
|
|||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
ColumnDefinitions="Auto,Auto,Auto"
|
ColumnDefinitions="Auto,Auto,Auto"
|
||||||
DockPanel.Dock="Top"
|
DockPanel.Dock="Top"
|
||||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
@@ -1087,6 +1087,34 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbRouteExcludeAddressTip}"
|
Text="{x:Static resx:ResUI.TbRouteExcludeAddressTip}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="10"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{x:Static resx:ResUI.TbIpv4Address}" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbIpv4Address"
|
||||||
|
Grid.Row="10"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="200"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="11"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{x:Static resx:ResUI.TbIpv6Address}" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbIpv6Address"
|
||||||
|
Grid.Row="11"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="200"
|
||||||
|
Margin="{StaticResource Margin4}"
|
||||||
|
HorizontalAlignment="Left" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
|||||||
cmbMtu.ItemsSource = Global.TunMtus;
|
cmbMtu.ItemsSource = Global.TunMtus;
|
||||||
cmbStack.ItemsSource = Global.TunStacks;
|
cmbStack.ItemsSource = Global.TunStacks;
|
||||||
cmbIcmpRoutingPolicy.ItemsSource = Global.TunIcmpRoutingPolicies;
|
cmbIcmpRoutingPolicy.ItemsSource = Global.TunIcmpRoutingPolicies;
|
||||||
|
cmbIpv4Address.ItemsSource = Global.TunIpv4Address;
|
||||||
|
cmbIpv6Address.ItemsSource = Global.TunIpv6Address;
|
||||||
cmbFragmentPackets.ItemsSource = Global.FragmentPacketsOptions;
|
cmbFragmentPackets.ItemsSource = Global.FragmentPacketsOptions;
|
||||||
|
|
||||||
cmbCoreType1.ItemsSource = Global.CoreTypes;
|
cmbCoreType1.ItemsSource = Global.CoreTypes;
|
||||||
@@ -129,6 +131,8 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
|||||||
this.Bind(ViewModel, vm => vm.TunIcmpRouting, v => v.cmbIcmpRoutingPolicy.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunIcmpRouting, v => v.cmbIcmpRoutingPolicy.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableLegacyProtect, v => v.togEnableLegacyProtect.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableLegacyProtect, v => v.togEnableLegacyProtect.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunRouteExcludeAddress, v => v.txtRouteExcludeAddress.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunRouteExcludeAddress, v => v.txtRouteExcludeAddress.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.TunIpv4Address, v => v.cmbIpv4Address.SelectedValue).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.TunIpv6Address, v => v.cmbIpv6Address.SelectedValue).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
this.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
||||||
|
.WhereNotNull()
|
||||||
|
.Subscribe(InitializeData)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
||||||
@@ -35,11 +40,6 @@ public partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsVie
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SelectProfileCmd, v => v.btnSelectProfile).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SelectProfileCmd, v => v.btnSelectProfile).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.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
|
||||||
.WhereNotNull()
|
|
||||||
.Subscribe(InitializeData)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
WindowStartupLocation="CenterScreen"
|
WindowStartupLocation="CenterScreen"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<dialogHost:DialogHost
|
<dialogHost:DialogHost
|
||||||
Background="Gray"
|
|
||||||
CloseOnClickAway="True"
|
CloseOnClickAway="True"
|
||||||
DisableOpeningAnimation="True"
|
DisableOpeningAnimation="True"
|
||||||
Identifier="dialogHostSub">
|
Identifier="dialogHostSub">
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ public partial class AddGroupServerWindow
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
this.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
||||||
|
.WhereNotNull()
|
||||||
|
.Subscribe(InitializeData)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.Text).DisposeWith(disposables);
|
||||||
@@ -45,11 +50,6 @@ public partial class AddGroupServerWindow
|
|||||||
this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).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.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
|
||||||
.WhereNotNull()
|
|
||||||
.Subscribe(InitializeData)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ public partial class AddServerWindow
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
this.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
||||||
|
.WhereNotNull()
|
||||||
|
.Subscribe(InitializeData)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
var configTypeBindings = new SerialDisposable().DisposeWith(disposables);
|
var configTypeBindings = new SerialDisposable().DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);
|
||||||
@@ -186,11 +191,6 @@ public partial class AddServerWindow
|
|||||||
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).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.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
|
||||||
.WhereNotNull()
|
|
||||||
.Subscribe(InitializeData)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
||||||
|
|||||||
@@ -331,12 +331,25 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbFakeIP}" />
|
Text="{x:Static resx:ResUI.TbFakeIP}" />
|
||||||
<ToggleButton
|
<Grid Grid.Row="3" Grid.Column="1">
|
||||||
x:Name="togFakeIP"
|
<Grid.ColumnDefinitions>
|
||||||
Grid.Row="3"
|
<ColumnDefinition Width="Auto" />
|
||||||
Grid.Column="1"
|
<ColumnDefinition Width="*" />
|
||||||
Margin="{StaticResource Margin8}"
|
</Grid.ColumnDefinitions>
|
||||||
HorizontalAlignment="Left" />
|
|
||||||
|
<ToggleButton
|
||||||
|
x:Name="togFakeIP"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
HorizontalAlignment="Left" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbFakeIPRange"
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
IsEditable="True"
|
||||||
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
</Grid>
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="3"
|
Grid.Row="3"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ public partial class DNSSettingWindow
|
|||||||
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
|
cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;
|
||||||
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
|
cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;
|
||||||
cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress;
|
cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress;
|
||||||
|
cmbFakeIPRange.ItemsSource = Global.FakeIPRanges;
|
||||||
cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;
|
cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;
|
||||||
|
|
||||||
cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy;
|
cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy;
|
||||||
@@ -28,6 +29,7 @@ public partial class DNSSettingWindow
|
|||||||
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.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.FakeIPRange, v => v.cmbFakeIPRange.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -1198,6 +1198,8 @@
|
|||||||
<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.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" />
|
<ColumnDefinition Width="Auto" />
|
||||||
@@ -1346,6 +1348,39 @@
|
|||||||
Style="{StaticResource ToolbarTextBlock}"
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
Text="{x:Static resx:ResUI.TbRouteExcludeAddressTip}"
|
Text="{x:Static resx:ResUI.TbRouteExcludeAddressTip}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="10"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.TbIpv4Address}" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbIpv4Address"
|
||||||
|
Grid.Row="10"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="200"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Row="11"
|
||||||
|
Grid.Column="0"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Style="{StaticResource ToolbarTextBlock}"
|
||||||
|
Text="{x:Static resx:ResUI.TbIpv6Address}" />
|
||||||
|
<ComboBox
|
||||||
|
x:Name="cmbIpv6Address"
|
||||||
|
Grid.Row="11"
|
||||||
|
Grid.Column="1"
|
||||||
|
Width="200"
|
||||||
|
Margin="{StaticResource Margin8}"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Style="{StaticResource DefComboBox}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ public partial class OptionSettingWindow
|
|||||||
cmbMtu.ItemsSource = Global.TunMtus;
|
cmbMtu.ItemsSource = Global.TunMtus;
|
||||||
cmbStack.ItemsSource = Global.TunStacks;
|
cmbStack.ItemsSource = Global.TunStacks;
|
||||||
cmbIcmpRoutingPolicy.ItemsSource = Global.TunIcmpRoutingPolicies;
|
cmbIcmpRoutingPolicy.ItemsSource = Global.TunIcmpRoutingPolicies;
|
||||||
|
cmbIpv4Address.ItemsSource = Global.TunIpv4Address;
|
||||||
|
cmbIpv6Address.ItemsSource = Global.TunIpv6Address;
|
||||||
cmbFragmentPackets.ItemsSource = Global.FragmentPacketsOptions;
|
cmbFragmentPackets.ItemsSource = Global.FragmentPacketsOptions;
|
||||||
|
|
||||||
cmbCoreType1.ItemsSource = Global.CoreTypes;
|
cmbCoreType1.ItemsSource = Global.CoreTypes;
|
||||||
@@ -86,14 +88,6 @@ public partial class OptionSettingWindow
|
|||||||
this.Bind(ViewModel, vm => vm.FragmentDelays, v => v.txtFragmentDelays.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.FragmentDelays, v => v.txtFragmentDelays.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.FragmentMaxSplit, v => v.txtFragmentMaxSplit.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.FragmentMaxSplit, v => v.txtFragmentMaxSplit.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
//this.Bind(ViewModel, vm => vm.Kcpmtu, v => v.txtKcpmtu.Text).DisposeWith(disposables);
|
|
||||||
//this.Bind(ViewModel, vm => vm.Kcptti, v => v.txtKcptti.Text).DisposeWith(disposables);
|
|
||||||
//this.Bind(ViewModel, vm => vm.KcpuplinkCapacity, v => v.txtKcpuplinkCapacity.Text).DisposeWith(disposables);
|
|
||||||
//this.Bind(ViewModel, vm => vm.KcpdownlinkCapacity, v => v.txtKcpdownlinkCapacity.Text).DisposeWith(disposables);
|
|
||||||
//this.Bind(ViewModel, vm => vm.KcpreadBufferSize, v => v.txtKcpreadBufferSize.Text).DisposeWith(disposables);
|
|
||||||
//this.Bind(ViewModel, vm => vm.KcpwriteBufferSize, v => v.txtKcpwriteBufferSize.Text).DisposeWith(disposables);
|
|
||||||
//this.Bind(ViewModel, vm => vm.Kcpcongestion, v => v.togKcpcongestion.IsChecked).DisposeWith(disposables);
|
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DisplayRealTimeSpeed, v => v.togDisplayRealTimeSpeed.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.DisplayRealTimeSpeed, v => v.togDisplayRealTimeSpeed.IsChecked).DisposeWith(disposables);
|
||||||
@@ -132,6 +126,8 @@ public partial class OptionSettingWindow
|
|||||||
this.Bind(ViewModel, vm => vm.TunIcmpRouting, v => v.cmbIcmpRoutingPolicy.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunIcmpRouting, v => v.cmbIcmpRoutingPolicy.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableLegacyProtect, v => v.togEnableLegacyProtect.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableLegacyProtect, v => v.togEnableLegacyProtect.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunRouteExcludeAddress, v => v.txtRouteExcludeAddress.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunRouteExcludeAddress, v => v.txtRouteExcludeAddress.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.TunIpv4Address, v => v.cmbIpv4Address.Text).DisposeWith(disposables);
|
||||||
|
this.Bind(ViewModel, vm => vm.TunIpv6Address, v => v.cmbIpv6Address.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.Text).DisposeWith(disposables);
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ public partial class RoutingRuleDetailsWindow
|
|||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
|
this.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
||||||
|
.WhereNotNull()
|
||||||
|
.Subscribe(InitializeData)
|
||||||
|
.DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);
|
||||||
@@ -31,11 +36,6 @@ public partial class RoutingRuleDetailsWindow
|
|||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.SelectProfileCmd, v => v.btnSelectProfile).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.SelectProfileCmd, v => v.btnSelectProfile).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.WhenAnyValue(v => v.ViewModel.SelectedSource)
|
|
||||||
.WhereNotNull()
|
|
||||||
.Subscribe(InitializeData)
|
|
||||||
.DisposeWith(disposables);
|
|
||||||
});
|
});
|
||||||
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user