mirror of
https://github.com/2dust/v2rayN.git
synced 2026-05-30 17:54:08 +00:00
Compare commits
No commits in common. "master" and "7.22.1" have entirely different histories.
63 changed files with 296 additions and 982 deletions
|
|
@ -100,6 +100,7 @@ csharp_style_prefer_tuple_swap = true:warning
|
||||||
csharp_style_prefer_utf8_string_literals = true:warning
|
csharp_style_prefer_utf8_string_literals = true:warning
|
||||||
csharp_style_throw_expression = true:warning
|
csharp_style_throw_expression = true:warning
|
||||||
csharp_style_unused_value_assignment_preference = discard_variable:warning
|
csharp_style_unused_value_assignment_preference = discard_variable:warning
|
||||||
|
csharp_style_unused_value_expression_statement_preference = discard_variable:warning
|
||||||
csharp_using_directive_placement = outside_namespace:warning
|
csharp_using_directive_placement = outside_namespace:warning
|
||||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning
|
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning
|
||||||
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning
|
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning
|
||||||
|
|
|
||||||
6
.github/workflows/build-linux.yml
vendored
6
.github/workflows/build-linux.yml
vendored
|
|
@ -335,9 +335,9 @@ jobs:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RELEASE_TAG: ${{ case(inputs.release_tag != '', inputs.release_tag, github.ref_name) }}
|
RELEASE_TAG: ${{ case(inputs.release_tag != '', inputs.release_tag, github.ref_name) }}
|
||||||
QCOW2_URL: https://github.com/xujiegb/debian-loong64-qcow2/releases/download/13.5/debian13-loong64.qcow2
|
QCOW2_URL: https://github.com/xujiegb/debian-loong64-qcow2/releases/download/13.4/debian13-loong64.qcow2
|
||||||
EFI_CODE_URL: https://github.com/xujiegb/debian-loong64-qcow2/releases/download/13.5/edk2-loongarch64-code.fd
|
EFI_CODE_URL: https://github.com/xujiegb/debian-loong64-qcow2/releases/download/13.4/edk2-loongarch64-code.fd
|
||||||
EFI_VARS_URL: https://github.com/xujiegb/debian-loong64-qcow2/releases/download/13.5/edk2-loongarch64-vars.fd
|
EFI_VARS_URL: https://github.com/xujiegb/debian-loong64-qcow2/releases/download/13.4/edk2-loongarch64-vars.fd
|
||||||
QCOW2_IMAGE: debian13-loong64.qcow2
|
QCOW2_IMAGE: debian13-loong64.qcow2
|
||||||
EFI_CODE: edk2-loongarch64-code.fd
|
EFI_CODE: edk2-loongarch64-code.fd
|
||||||
EFI_VARS: edk2-loongarch64-vars.fd
|
EFI_VARS: edk2-loongarch64-vars.fd
|
||||||
|
|
|
||||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -52,7 +52,7 @@ jobs:
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v5.3.0
|
uses: actions/setup-dotnet@v5.2.0
|
||||||
with:
|
with:
|
||||||
dotnet-version: '10.0.1xx'
|
dotnet-version: '10.0.1xx'
|
||||||
|
|
||||||
|
|
|
||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
|
@ -20,7 +20,7 @@ jobs:
|
||||||
fetch-depth: '0'
|
fetch-depth: '0'
|
||||||
|
|
||||||
- name: Setup .NET
|
- name: Setup .NET
|
||||||
uses: actions/setup-dotnet@v5.3.0
|
uses: actions/setup-dotnet@v5.2.0
|
||||||
with:
|
with:
|
||||||
dotnet-version: '8.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,7 @@ cat >"$PackagePath/v2rayN.app/Contents/Info.plist" <<-EOF
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>en</string>
|
<string>English</string>
|
||||||
<key>CFBundleLocalizations</key>
|
|
||||||
<array>
|
|
||||||
<string>zh-Hans</string>
|
|
||||||
<string>zh-Hant</string>
|
|
||||||
<string>en</string>
|
|
||||||
<string>fa</string>
|
|
||||||
<string>fr</string>
|
|
||||||
<string>ru</string>
|
|
||||||
<string>hu</string>
|
|
||||||
</array>
|
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>v2rayN</string>
|
<string>v2rayN</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<Project>
|
<Project>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>7.22.4</Version>
|
<Version>7.22.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" />
|
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="11.4.1" />
|
||||||
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.3.13" />
|
||||||
<PackageVersion Include="Avalonia.Desktop" Version="11.3.16" />
|
<PackageVersion Include="Avalonia.Desktop" Version="11.3.15" />
|
||||||
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.16" />
|
<PackageVersion Include="Avalonia.Diagnostics" Version="11.3.15" />
|
||||||
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
<PackageVersion Include="AwesomeAssertions" Version="9.4.0" />
|
||||||
<PackageVersion Include="DialogHost.Avalonia" Version="0.11.0" />
|
<PackageVersion Include="DialogHost.Avalonia" Version="0.11.0" />
|
||||||
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.12" />
|
<PackageVersion Include="ReactiveUI.Avalonia" Version="11.4.12" />
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7.3" />
|
<PackageVersion Include="Semi.Avalonia.DataGrid" Version="11.3.7.3" />
|
||||||
<PackageVersion Include="NLog" Version="6.1.3" />
|
<PackageVersion Include="NLog" Version="6.1.3" />
|
||||||
<PackageVersion Include="sqlite-net-e" Version="1.11.0" />
|
<PackageVersion Include="sqlite-net-e" Version="1.11.0" />
|
||||||
<PackageVersion Include="Repobot.SQLite.Unofficial" Version="3.53.1.7" />
|
<PackageVersion Include="Repobot.SQLite.Unofficial" Version="3.53.1.4" />
|
||||||
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
<PackageVersion Include="TaskScheduler" Version="2.12.2" />
|
||||||
<PackageVersion Include="Tmds.DBus.Protocol" Version="0.21.3" />
|
<PackageVersion Include="Tmds.DBus.Protocol" Version="0.21.3" />
|
||||||
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
<PackageVersion Include="WebDav.Client" Version="2.9.0" />
|
||||||
|
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
namespace ServiceLib.Common;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for country code utilities
|
|
||||||
/// </summary>
|
|
||||||
public static class CountryExtension
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Country code to emoji flag mapping for common countries
|
|
||||||
/// </summary>
|
|
||||||
private static readonly Dictionary<string, string> CountryEmojiMap = new(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
// Asia
|
|
||||||
{ "CN", "🇨🇳" }, // China
|
|
||||||
{ "HK", "🇭🇰" }, // Hong Kong
|
|
||||||
{ "TW", "🇹🇼" }, // Taiwan
|
|
||||||
{ "JP", "🇯🇵" }, // Japan
|
|
||||||
{ "SG", "🇸🇬" }, // Singapore
|
|
||||||
{ "KR", "🇰🇷" }, // South Korea
|
|
||||||
{ "TH", "🇹🇭" }, // Thailand
|
|
||||||
{ "VN", "🇻🇳" }, // Vietnam
|
|
||||||
{ "ID", "🇮🇩" }, // Indonesia
|
|
||||||
{ "PH", "🇵🇭" }, // Philippines
|
|
||||||
{ "MY", "🇲🇾" }, // Malaysia
|
|
||||||
{ "IN", "🇮🇳" }, // India
|
|
||||||
{ "PK", "🇵🇰" }, // Pakistan
|
|
||||||
{ "BD", "🇧🇩" }, // Bangladesh
|
|
||||||
{ "LK", "🇱🇰" }, // Sri Lanka
|
|
||||||
{ "KH", "🇰🇭" }, // Cambodia
|
|
||||||
{ "LA", "🇱🇦" }, // Laos
|
|
||||||
{ "MM", "🇲🇲" }, // Myanmar
|
|
||||||
|
|
||||||
// Americas
|
|
||||||
{ "US", "🇺🇸" }, // United States
|
|
||||||
{ "CA", "🇨🇦" }, // Canada
|
|
||||||
{ "MX", "🇲🇽" }, // Mexico
|
|
||||||
{ "BR", "🇧🇷" }, // Brazil
|
|
||||||
{ "AR", "🇦🇷" }, // Argentina
|
|
||||||
{ "CL", "🇨🇱" }, // Chile
|
|
||||||
{ "CO", "🇨🇴" }, // Colombia
|
|
||||||
|
|
||||||
// Europe
|
|
||||||
{ "GB", "🇬🇧" }, // United Kingdom
|
|
||||||
{ "DE", "🇩🇪" }, // Germany
|
|
||||||
{ "FR", "🇫🇷" }, // France
|
|
||||||
{ "IT", "🇮🇹" }, // Italy
|
|
||||||
{ "ES", "🇪🇸" }, // Spain
|
|
||||||
{ "RU", "🇷🇺" }, // Russia
|
|
||||||
{ "NL", "🇳🇱" }, // Netherlands
|
|
||||||
{ "CH", "🇨🇭" }, // Switzerland
|
|
||||||
{ "SE", "🇸🇪" }, // Sweden
|
|
||||||
{ "NO", "🇳🇴" }, // Norway
|
|
||||||
{ "DK", "🇩🇰" }, // Denmark
|
|
||||||
{ "FI", "🇫🇮" }, // Finland
|
|
||||||
{ "PL", "🇵🇱" }, // Poland
|
|
||||||
{ "CZ", "🇨🇿" }, // Czech Republic
|
|
||||||
{ "AT", "🇦🇹" }, // Austria
|
|
||||||
{ "GR", "🇬🇷" }, // Greece
|
|
||||||
{ "PT", "🇵🇹" }, // Portugal
|
|
||||||
{ "TR", "🇹🇷" }, // Turkey
|
|
||||||
{ "UA", "🇺🇦" }, // Ukraine
|
|
||||||
{ "RO", "🇷🇴" }, // Romania
|
|
||||||
|
|
||||||
// Middle East & Central Asia
|
|
||||||
{ "AE", "🇦🇪" }, // United Arab Emirates
|
|
||||||
{ "SA", "🇸🇦" }, // Saudi Arabia
|
|
||||||
{ "IL", "🇮🇱" }, // Israel
|
|
||||||
{ "KZ", "🇰🇿" }, // Kazakhstan
|
|
||||||
|
|
||||||
// Oceania
|
|
||||||
{ "AU", "🇦🇺" }, // Australia
|
|
||||||
{ "NZ", "🇳🇿" }, // New Zealand
|
|
||||||
|
|
||||||
// Africa
|
|
||||||
{ "ZA", "🇿🇦" }, // South Africa
|
|
||||||
{ "EG", "🇪🇬" }, // Egypt
|
|
||||||
};
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts country code to flag emoji using predefined mapping
|
|
||||||
/// Example: "US" -> "🇺🇸", "CN" -> "🇨🇳"
|
|
||||||
/// </summary>
|
|
||||||
public static string? CountryToEmoji(this string? countryCode)
|
|
||||||
{
|
|
||||||
if (countryCode.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CountryEmojiMap.TryGetValue(countryCode, out var emoji) ? emoji : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,7 +12,6 @@ public enum EServerColName
|
||||||
SubRemarks,
|
SubRemarks,
|
||||||
DelayVal,
|
DelayVal,
|
||||||
SpeedVal,
|
SpeedVal,
|
||||||
IpInfo,
|
|
||||||
|
|
||||||
TodayDown,
|
TodayDown,
|
||||||
TodayUp,
|
TodayUp,
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ public static class AppEvents
|
||||||
public static readonly EventChannel<Unit> AddServerViaScanRequested = new();
|
public static readonly EventChannel<Unit> AddServerViaScanRequested = new();
|
||||||
public static readonly EventChannel<Unit> AddServerViaClipboardRequested = new();
|
public static readonly EventChannel<Unit> AddServerViaClipboardRequested = new();
|
||||||
public static readonly EventChannel<bool> SubscriptionsUpdateRequested = new();
|
public static readonly EventChannel<bool> SubscriptionsUpdateRequested = new();
|
||||||
public static readonly EventChannel<bool> HasUpdateNotified = new();
|
|
||||||
|
|
||||||
public static readonly EventChannel<Unit> ProfilesRefreshRequested = new();
|
public static readonly EventChannel<Unit> ProfilesRefreshRequested = new();
|
||||||
public static readonly EventChannel<Unit> SubscriptionsRefreshRequested = new();
|
public static readonly EventChannel<Unit> SubscriptionsRefreshRequested = new();
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ public class Global
|
||||||
public const string DnsOutboundTag = "dns";
|
public const string DnsOutboundTag = "dns";
|
||||||
public const string DnsTag = "dns-module";
|
public const string DnsTag = "dns-module";
|
||||||
public const string DirectDnsTag = "direct-dns";
|
public const string DirectDnsTag = "direct-dns";
|
||||||
public const string BalancerTagSuffix = "-balancer";
|
public const string BalancerTagSuffix = "-round";
|
||||||
public const string StreamSecurity = "tls";
|
public const string StreamSecurity = "tls";
|
||||||
public const string StreamSecurityReality = "reality";
|
public const string StreamSecurityReality = "reality";
|
||||||
public const string Loopback = "127.0.0.1";
|
public const string Loopback = "127.0.0.1";
|
||||||
|
|
@ -149,9 +149,6 @@ public class Global
|
||||||
public static readonly List<string> SpeedTestUrls =
|
public static readonly List<string> SpeedTestUrls =
|
||||||
[
|
[
|
||||||
@"https://cachefly.cachefly.net/50mb.test",
|
@"https://cachefly.cachefly.net/50mb.test",
|
||||||
@"https://cachefly.cachefly.net/100mb.test",
|
|
||||||
@"https://cachefly.cachefly.net/1mb.test",
|
|
||||||
@"https://cachefly.cachefly.net/10mb.test",
|
|
||||||
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
@"https://speed.cloudflare.com/__down?bytes=10000000",
|
||||||
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
@"https://speed.cloudflare.com/__down?bytes=50000000",
|
||||||
@"https://speed.cloudflare.com/__down?bytes=99999999",
|
@"https://speed.cloudflare.com/__down?bytes=99999999",
|
||||||
|
|
@ -160,8 +157,6 @@ public class Global
|
||||||
public static readonly List<string> SpeedPingTestUrls =
|
public static readonly List<string> SpeedPingTestUrls =
|
||||||
[
|
[
|
||||||
@"https://www.google.com/generate_204",
|
@"https://www.google.com/generate_204",
|
||||||
@"https://www.youtube.com/generate_204",
|
|
||||||
@"https://www.googlevideo.com/generate_204",
|
|
||||||
@"https://www.gstatic.com/generate_204",
|
@"https://www.gstatic.com/generate_204",
|
||||||
@"https://www.apple.com/library/test/success.html",
|
@"https://www.apple.com/library/test/success.html",
|
||||||
@"http://www.msftconnecttest.com/connecttest.txt"
|
@"http://www.msftconnecttest.com/connecttest.txt"
|
||||||
|
|
@ -212,10 +207,6 @@ public class Global
|
||||||
|
|
||||||
public const string NaiveQuicProtocolShare = "naive+quic://";
|
public const string NaiveQuicProtocolShare = "naive+quic://";
|
||||||
|
|
||||||
public const string SOCKS5Protocol = "socks5://";
|
|
||||||
|
|
||||||
public const string SOCKS4Protocol = "socks4://";
|
|
||||||
|
|
||||||
public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
|
public static readonly Dictionary<EConfigType, string> ProtocolShares = new()
|
||||||
{
|
{
|
||||||
{ EConfigType.VMess, "vmess://" },
|
{ EConfigType.VMess, "vmess://" },
|
||||||
|
|
@ -514,7 +505,6 @@ public class Global
|
||||||
|
|
||||||
public static readonly List<string> InboundTags =
|
public static readonly List<string> InboundTags =
|
||||||
[
|
[
|
||||||
"tun",
|
|
||||||
"socks",
|
"socks",
|
||||||
"socks2",
|
"socks2",
|
||||||
"socks3"
|
"socks3"
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,7 @@ public static class AutoStartupHandler
|
||||||
task.Settings.RunOnlyIfIdle = false;
|
task.Settings.RunOnlyIfIdle = false;
|
||||||
task.Settings.IdleSettings.StopOnIdleEnd = false;
|
task.Settings.IdleSettings.StopOnIdleEnd = false;
|
||||||
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
|
task.Settings.ExecutionTimeLimit = TimeSpan.Zero;
|
||||||
task.Settings.Priority = ProcessPriorityClass.Normal;
|
task.Triggers.Add(new Microsoft.Win32.TaskScheduler.LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(30) });
|
||||||
task.Triggers.Add(new Microsoft.Win32.TaskScheduler.LogonTrigger { UserId = logonUser });
|
|
||||||
task.Principal.RunLevel = Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest;
|
task.Principal.RunLevel = Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest;
|
||||||
task.Actions.Add(new Microsoft.Win32.TaskScheduler.ExecAction(fileName.AppendQuotes(), null, Path.GetDirectoryName(fileName)));
|
task.Actions.Add(new Microsoft.Win32.TaskScheduler.ExecAction(fileName.AppendQuotes(), null, Path.GetDirectoryName(fileName)));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -923,7 +923,6 @@ public static class ConfigHandler
|
||||||
Delay = t33?.Delay ?? 0,
|
Delay = t33?.Delay ?? 0,
|
||||||
Speed = t33?.Speed ?? 0,
|
Speed = t33?.Speed ?? 0,
|
||||||
Sort = t33?.Sort ?? 0,
|
Sort = t33?.Sort ?? 0,
|
||||||
IpInfo = t33?.IpInfo ?? string.Empty,
|
|
||||||
TodayDown = (t22?.TodayDown ?? 0).ToString("D16"),
|
TodayDown = (t22?.TodayDown ?? 0).ToString("D16"),
|
||||||
TodayUp = (t22?.TodayUp ?? 0).ToString("D16"),
|
TodayUp = (t22?.TodayUp ?? 0).ToString("D16"),
|
||||||
TotalDown = (t22?.TotalDown ?? 0).ToString("D16"),
|
TotalDown = (t22?.TotalDown ?? 0).ToString("D16"),
|
||||||
|
|
@ -944,7 +943,6 @@ public static class ConfigHandler
|
||||||
EServerColName.StreamSecurity => lstProfile.OrderBy(t => t.StreamSecurity).ToList(),
|
EServerColName.StreamSecurity => lstProfile.OrderBy(t => t.StreamSecurity).ToList(),
|
||||||
EServerColName.DelayVal => lstProfile.OrderBy(t => t.Delay).ToList(),
|
EServerColName.DelayVal => lstProfile.OrderBy(t => t.Delay).ToList(),
|
||||||
EServerColName.SpeedVal => lstProfile.OrderBy(t => t.Speed).ToList(),
|
EServerColName.SpeedVal => lstProfile.OrderBy(t => t.Speed).ToList(),
|
||||||
EServerColName.IpInfo => lstProfile.OrderBy(t => t.IpInfo).ToList(),
|
|
||||||
EServerColName.SubRemarks => lstProfile.OrderBy(t => t.Subid).ToList(),
|
EServerColName.SubRemarks => lstProfile.OrderBy(t => t.Subid).ToList(),
|
||||||
EServerColName.TodayDown => lstProfile.OrderBy(t => t.TodayDown).ToList(),
|
EServerColName.TodayDown => lstProfile.OrderBy(t => t.TodayDown).ToList(),
|
||||||
EServerColName.TodayUp => lstProfile.OrderBy(t => t.TodayUp).ToList(),
|
EServerColName.TodayUp => lstProfile.OrderBy(t => t.TodayUp).ToList(),
|
||||||
|
|
@ -965,7 +963,6 @@ public static class ConfigHandler
|
||||||
EServerColName.StreamSecurity => lstProfile.OrderByDescending(t => t.StreamSecurity).ToList(),
|
EServerColName.StreamSecurity => lstProfile.OrderByDescending(t => t.StreamSecurity).ToList(),
|
||||||
EServerColName.DelayVal => lstProfile.OrderByDescending(t => t.Delay).ToList(),
|
EServerColName.DelayVal => lstProfile.OrderByDescending(t => t.Delay).ToList(),
|
||||||
EServerColName.SpeedVal => lstProfile.OrderByDescending(t => t.Speed).ToList(),
|
EServerColName.SpeedVal => lstProfile.OrderByDescending(t => t.Speed).ToList(),
|
||||||
EServerColName.IpInfo => lstProfile.OrderByDescending(t => t.IpInfo).ToList(),
|
|
||||||
EServerColName.SubRemarks => lstProfile.OrderByDescending(t => t.Subid).ToList(),
|
EServerColName.SubRemarks => lstProfile.OrderByDescending(t => t.Subid).ToList(),
|
||||||
EServerColName.TodayDown => lstProfile.OrderByDescending(t => t.TodayDown).ToList(),
|
EServerColName.TodayDown => lstProfile.OrderByDescending(t => t.TodayDown).ToList(),
|
||||||
EServerColName.TodayUp => lstProfile.OrderByDescending(t => t.TodayUp).ToList(),
|
EServerColName.TodayUp => lstProfile.OrderByDescending(t => t.TodayUp).ToList(),
|
||||||
|
|
|
||||||
|
|
@ -4,41 +4,53 @@ public static class ConnectionHandler
|
||||||
{
|
{
|
||||||
private static readonly string _tag = "ConnectionHandler";
|
private static readonly string _tag = "ConnectionHandler";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Runs ping and IP checks and returns a formatted result string.
|
|
||||||
/// </summary>
|
|
||||||
public static async Task<string> RunAvailabilityCheck()
|
public static async Task<string> RunAvailabilityCheck()
|
||||||
{
|
{
|
||||||
var time = await GetRealPingTimeInfo();
|
var time = await GetRealPingTimeInfo();
|
||||||
var ip = time > 0 ? await GetIPInfo() : Global.None;
|
var ip = time > 0 ? await GetIPInfo() ?? Global.None : Global.None;
|
||||||
|
|
||||||
return string.Format(ResUI.TestMeOutput, time, ip);
|
return string.Format(ResUI.TestMeOutput, time, ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets IP information using the default local proxy.
|
|
||||||
/// </summary>
|
|
||||||
private static async Task<string?> GetIPInfo()
|
private static async Task<string?> GetIPInfo()
|
||||||
{
|
{
|
||||||
var webProxy = await GetWebProxy();
|
var url = AppManager.Instance.Config.SpeedTestItem.IPAPIUrl;
|
||||||
|
if (url.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var ipInfo = await GetIPInfo(webProxy);
|
var downloadHandle = new DownloadService();
|
||||||
return ipInfo?.ToString() ?? Global.None;
|
var result = await downloadHandle.TryDownloadString(url, true, "");
|
||||||
|
if (result == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
|
||||||
|
if (ipInfo == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ip = ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query;
|
||||||
|
var country = ipInfo.country_code ?? ipInfo.country ?? ipInfo.countryCode ?? ipInfo.location?.country_code;
|
||||||
|
|
||||||
|
return $"({country ?? "unknown"}) {ip}";
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures real ping time using configured test URL.
|
|
||||||
/// </summary>
|
|
||||||
private static async Task<int> GetRealPingTimeInfo()
|
private static async Task<int> GetRealPingTimeInfo()
|
||||||
{
|
{
|
||||||
var responseTime = -1;
|
var responseTime = -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var webProxy = await GetWebProxy();
|
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
||||||
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{port}");
|
||||||
|
var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
||||||
|
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
responseTime = await GetRealPingTime(webProxy, 10);
|
responseTime = await GetRealPingTime(url, webProxy, 10);
|
||||||
if (responseTime > 0)
|
if (responseTime > 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
|
@ -54,21 +66,8 @@ public static class ConnectionHandler
|
||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public static async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)
|
||||||
/// Creates local SOCKS proxy instance.
|
|
||||||
/// </summary>
|
|
||||||
private static async Task<WebProxy?> GetWebProxy()
|
|
||||||
{
|
{
|
||||||
var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);
|
|
||||||
return new WebProxy($"socks5://{Global.Loopback}:{port}");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Measures response time by sending HTTP requests through proxy.
|
|
||||||
/// </summary>
|
|
||||||
public static async Task<int> GetRealPingTime(IWebProxy? webProxy, int downloadTimeout)
|
|
||||||
{
|
|
||||||
var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;
|
|
||||||
var responseTime = -1;
|
var responseTime = -1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -96,41 +95,4 @@ public static class ConnectionHandler
|
||||||
}
|
}
|
||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets IP and country information through specified proxy.
|
|
||||||
/// </summary>
|
|
||||||
public static async Task<IpInfoResult?> GetIPInfo(IWebProxy? webProxy)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var url = AppManager.Instance.Config.SpeedTestItem.IPAPIUrl;
|
|
||||||
if (url.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var downloadHandle = new DownloadService();
|
|
||||||
var result = await downloadHandle.TryDownloadString(url, webProxy, "");
|
|
||||||
if (result == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);
|
|
||||||
if (ipInfo == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ip = ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query;
|
|
||||||
var country = ipInfo.country_code ?? ipInfo.country ?? ipInfo.countryCode ?? ipInfo.location?.country_code ?? "unknown";
|
|
||||||
|
|
||||||
return new IpInfoResult(country, ip);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,7 @@ public class FmtHandler
|
||||||
{
|
{
|
||||||
return ShadowsocksFmt.Resolve(str, out msg);
|
return ShadowsocksFmt.Resolve(str, out msg);
|
||||||
}
|
}
|
||||||
else if (str.StartsWith(Global.ProtocolShares[EConfigType.SOCKS])
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.SOCKS]))
|
||||||
|| str.StartsWith(Global.SOCKS5Protocol)
|
|
||||||
|| str.StartsWith(Global.SOCKS4Protocol))
|
|
||||||
{
|
{
|
||||||
return SocksFmt.Resolve(str, out msg);
|
return SocksFmt.Resolve(str, out msg);
|
||||||
}
|
}
|
||||||
|
|
@ -67,8 +65,7 @@ public class FmtHandler
|
||||||
{
|
{
|
||||||
return VLESSFmt.Resolve(str, out msg);
|
return VLESSFmt.Resolve(str, out msg);
|
||||||
}
|
}
|
||||||
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Hysteria2])
|
else if (str.StartsWith(Global.ProtocolShares[EConfigType.Hysteria2]) || str.StartsWith(Global.Hysteria2ProtocolShare))
|
||||||
|| str.StartsWith(Global.Hysteria2ProtocolShare))
|
|
||||||
{
|
{
|
||||||
return Hysteria2Fmt.Resolve(str, out msg);
|
return Hysteria2Fmt.Resolve(str, out msg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -99,17 +99,12 @@ public class SocksFmt : BaseFmt
|
||||||
};
|
};
|
||||||
// parse base64 UserInfo
|
// parse base64 UserInfo
|
||||||
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);
|
||||||
if (rawUserInfo.IsNotEmpty())
|
var userInfo = Utils.Base64Decode(rawUserInfo);
|
||||||
|
var userInfoParts = userInfo.Split([':'], 2);
|
||||||
|
if (userInfoParts.Length == 2)
|
||||||
{
|
{
|
||||||
var userInfoParts = rawUserInfo.Contains(':')
|
item.Username = userInfoParts.First();
|
||||||
? rawUserInfo.Split(":", 2)
|
item.Password = userInfoParts[1];
|
||||||
: Utils.Base64Decode(rawUserInfo).Split(":", 2);
|
|
||||||
|
|
||||||
if (userInfoParts.Length == 2)
|
|
||||||
{
|
|
||||||
item.Username = userInfoParts.First();
|
|
||||||
item.Password = userInfoParts.Last();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
|
||||||
|
|
@ -48,13 +48,6 @@ public sealed class AppManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<ECoreType, string> LastCheckUpdateResults { get; set; } = new();
|
|
||||||
|
|
||||||
public void SetLastCheckUpdateResult(ECoreType coreType, string result)
|
|
||||||
{
|
|
||||||
LastCheckUpdateResults[coreType] = result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion Property
|
#endregion Property
|
||||||
|
|
||||||
#region App
|
#region App
|
||||||
|
|
|
||||||
|
|
@ -50,50 +50,6 @@ public sealed class CoreInfoManager
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ECoreType> GetCheckUpdateCoreTypes()
|
|
||||||
{
|
|
||||||
var lst = new List<ECoreType>();
|
|
||||||
|
|
||||||
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
|
||||||
{
|
|
||||||
if (IsCheckUpdateSupported(ECoreType.v2rayN))
|
|
||||||
{
|
|
||||||
lst.Add(ECoreType.v2rayN);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Utils.IsWindows() && Environment.OSVersion.Version.Major < 10))
|
|
||||||
{
|
|
||||||
lst.Add(ECoreType.Xray);
|
|
||||||
lst.Add(ECoreType.mihomo);
|
|
||||||
lst.Add(ECoreType.sing_box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return lst;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsCheckUpdateSupported(ECoreType type)
|
|
||||||
{
|
|
||||||
return type switch
|
|
||||||
{
|
|
||||||
ECoreType.v2rayN => !Utils.IsPackagedInstall(),
|
|
||||||
ECoreType.Xray => true,
|
|
||||||
ECoreType.mihomo => true,
|
|
||||||
ECoreType.sing_box => true,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool GetCheckPreRelease(ECoreType type, bool preRelease)
|
|
||||||
{
|
|
||||||
return type switch
|
|
||||||
{
|
|
||||||
ECoreType.v2rayN => preRelease,
|
|
||||||
ECoreType.Xray => preRelease,
|
|
||||||
_ => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitCoreInfo()
|
private void InitCoreInfo()
|
||||||
{
|
{
|
||||||
var urlN = GetCoreUrl(ECoreType.v2rayN);
|
var urlN = GetCoreUrl(ECoreType.v2rayN);
|
||||||
|
|
|
||||||
|
|
@ -150,14 +150,6 @@ public class ProfileExManager
|
||||||
IndexIdEnqueue(indexId);
|
IndexIdEnqueue(indexId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTestIpInfo(string indexId, string ipInfo)
|
|
||||||
{
|
|
||||||
var profileEx = GetProfileExItem(indexId);
|
|
||||||
|
|
||||||
profileEx.IpInfo = ipInfo;
|
|
||||||
IndexIdEnqueue(indexId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetSort(string indexId, int sort)
|
public void SetSort(string indexId, int sort)
|
||||||
{
|
{
|
||||||
var profileEx = GetProfileExItem(indexId);
|
var profileEx = GetProfileExItem(indexId);
|
||||||
|
|
|
||||||
|
|
@ -70,18 +70,6 @@ public class TaskManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Execute once 24 hour
|
|
||||||
if (numOfExecuted % 1440 == 1)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await UpdateTaskRunCheckUpdate();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logging.SaveLog("ScheduledTasks - UpdateTaskRunCheckUpdate", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
numOfExecuted++;
|
numOfExecuted++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -129,23 +117,4 @@ public class TaskManager
|
||||||
}).UpdateGeoFileAll();
|
}).UpdateGeoFileAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateTaskRunCheckUpdate()
|
|
||||||
{
|
|
||||||
Logging.SaveLog("Execute check update");
|
|
||||||
|
|
||||||
var updateService = new UpdateService(_config, async (success, msg) => await Task.CompletedTask);
|
|
||||||
|
|
||||||
var msgs = await updateService.CheckHasUpdateOnlyAll(_config.CheckUpdateItem.CheckPreReleaseUpdate);
|
|
||||||
foreach (var msg in msgs)
|
|
||||||
{
|
|
||||||
await _updateFunc?.Invoke(false, msg);
|
|
||||||
}
|
|
||||||
NoticeManager.Instance.Enqueue(string.Join("\n", msgs));
|
|
||||||
|
|
||||||
if (msgs.Count > 0)
|
|
||||||
{
|
|
||||||
AppEvents.HasUpdateNotified.Publish(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -159,8 +159,6 @@ public class SpeedTestItem
|
||||||
public int MixedConcurrencyCount { get; set; }
|
public int MixedConcurrencyCount { get; set; }
|
||||||
public string IPAPIUrl { get; set; }
|
public string IPAPIUrl { get; set; }
|
||||||
public string UdpTestTarget { get; set; }
|
public string UdpTestTarget { get; set; }
|
||||||
public int? SpeedTestPageSize { get; set; }
|
|
||||||
public int? SpeedTestDelayInterval { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,6 @@ public class BalancersItem4Ray
|
||||||
public List<string>? selector { get; set; }
|
public List<string>? selector { get; set; }
|
||||||
public BalancersStrategy4Ray? strategy { get; set; }
|
public BalancersStrategy4Ray? strategy { get; set; }
|
||||||
public string? tag { get; set; }
|
public string? tag { get; set; }
|
||||||
public string? fallbackTag { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BalancersStrategy4Ray
|
public class BalancersStrategy4Ray
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,8 @@ namespace ServiceLib.Models.Dto;
|
||||||
public class CheckUpdateModel : ReactiveObject
|
public class CheckUpdateModel : ReactiveObject
|
||||||
{
|
{
|
||||||
public bool? IsSelected { get; set; }
|
public bool? IsSelected { get; set; }
|
||||||
public ECoreType? CoreType { get; set; }
|
public string? CoreType { get; set; }
|
||||||
[Reactive] public string? Remarks { get; set; }
|
[Reactive] public string? Remarks { get; set; }
|
||||||
public string? FileName { get; set; }
|
public string? FileName { get; set; }
|
||||||
public bool? IsFinished { get; set; }
|
public bool? IsFinished { get; set; }
|
||||||
public bool IsGeoFile { get; set; }
|
|
||||||
public string CoreTypeForStorage => IsGeoFile ? "GeoFiles" : (CoreType?.ToString() ?? "");
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,3 @@ public class LocationInfo
|
||||||
{
|
{
|
||||||
public string? country_code { get; set; }
|
public string? country_code { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct IpInfoResult(string Country, string? Ip)
|
|
||||||
{
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
var emoji = Country.CountryToEmoji();
|
|
||||||
return $"{emoji}({Country}) {Ip}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,6 @@ public class ProfileItemModel : ReactiveObject
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public string SpeedVal { get; set; }
|
public string SpeedVal { get; set; }
|
||||||
|
|
||||||
[Reactive]
|
|
||||||
public string IpInfo { get; set; }
|
|
||||||
|
|
||||||
[Reactive]
|
[Reactive]
|
||||||
public string TodayUp { get; set; }
|
public string TodayUp { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,4 @@ public class SpeedTestResult
|
||||||
public string? Delay { get; set; }
|
public string? Delay { get; set; }
|
||||||
|
|
||||||
public string? Speed { get; set; }
|
public string? Speed { get; set; }
|
||||||
|
|
||||||
public string? IpInfo { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,5 +10,4 @@ public class ProfileExItem
|
||||||
public decimal Speed { get; set; }
|
public decimal Speed { get; set; }
|
||||||
public int Sort { get; set; }
|
public int Sort { get; set; }
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
public string? IpInfo { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
49
v2rayN/ServiceLib/Resx/ResUI.Designer.cs
generated
|
|
@ -564,15 +564,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 IP Info 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string LvTestIpInfo {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("LvTestIpInfo", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Speed (MB/s) 的本地化字符串。
|
/// 查找类似 Speed (MB/s) 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -879,15 +870,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Only Check 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuCheckOnly {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuCheckOnly", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Check Update 的本地化字符串。
|
/// 查找类似 Check Update 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1320,15 +1302,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 New Update 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string menuNewUpdate {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("menuNewUpdate", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Open the storage location 的本地化字符串。
|
/// 查找类似 Open the storage location 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -1914,15 +1887,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 {0} has a new version available: {1} 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string MsgCheckUpdateHasNewVersion {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("MsgCheckUpdateHasNewVersion", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Core '{0}' does not support network type '{1}' 的本地化字符串。
|
/// 查找类似 Core '{0}' does not support network type '{1}' 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -2076,15 +2040,6 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 查找类似 Not Support 的本地化字符串。
|
|
||||||
/// </summary>
|
|
||||||
public static string MsgNotSupport {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("MsgNotSupport", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Not support protocol '{0}' 的本地化字符串。
|
/// 查找类似 Not support protocol '{0}' 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -3529,7 +3484,7 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 tun: TUN inbound, socks: local port, socks2: second local port, socks3: LAN port 的本地化字符串。
|
/// 查找类似 socks: local port, socks2: second local port, socks3: LAN port 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbRoutingInboundTagTips {
|
public static string TbRoutingInboundTagTips {
|
||||||
get {
|
get {
|
||||||
|
|
@ -3970,7 +3925,7 @@ namespace ServiceLib.Resx {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查找类似 Check for pre-release 的本地化字符串。
|
/// 查找类似 Check for pre-release updates 的本地化字符串。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string TbSettingsEnableCheckPreReleaseUpdate {
|
public static string TbSettingsEnableCheckPreReleaseUpdate {
|
||||||
get {
|
get {
|
||||||
|
|
|
||||||
|
|
@ -1731,19 +1731,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} has a new version available: {1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>Only Check</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>Not Support</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP Info</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>New Update</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1728,19 +1728,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} has a new version available: {1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>Only Check</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>Not Support</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP Info</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>New Update</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1731,19 +1731,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} has a new version available: {1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>Only Check</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>Not Support</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP Info</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>New Update</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -691,7 +691,7 @@
|
||||||
<value>Automatically adjust column width after subscription update</value>
|
<value>Automatically adjust column width after subscription update</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
||||||
<value>Check for pre-release</value>
|
<value>Check for pre-release updates</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsException" xml:space="preserve">
|
<data name="TbSettingsException" xml:space="preserve">
|
||||||
<value>Exception</value>
|
<value>Exception</value>
|
||||||
|
|
@ -1336,7 +1336,7 @@
|
||||||
<value>Enable second mixed port</value>
|
<value>Enable second mixed port</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
<value>tun: TUN inbound, socks: local port, socks2: second local port, socks3: LAN port</value>
|
<value>socks: local port, socks2: second local port, socks3: LAN port</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTheme" xml:space="preserve">
|
<data name="TbSettingsTheme" xml:space="preserve">
|
||||||
<value>Theme</value>
|
<value>Theme</value>
|
||||||
|
|
@ -1731,19 +1731,4 @@ The "Get Certificate" action may fail if a self-signed certificate is used or if
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
<value>Export v2rayN Internal Share Link to Clipboard</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} has a new version available: {1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>Only Check</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>Not Support</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP Info</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>New Update</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1731,19 +1731,4 @@
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>Экспорт внутренней ссылки v2rayN в буфер обмена</value>
|
<value>Экспорт внутренней ссылки v2rayN в буфер обмена</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} has a new version available: {1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>Only Check</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>Not Support</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP Info</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>New Update</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -691,7 +691,7 @@
|
||||||
<value>自动调整配置列宽在更新订阅后</value>
|
<value>自动调整配置列宽在更新订阅后</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
||||||
<value>检查 Pre-Release</value>
|
<value>检查 Pre-Release 更新 (请谨慎启用)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsException" xml:space="preserve">
|
<data name="TbSettingsException" xml:space="preserve">
|
||||||
<value>例外</value>
|
<value>例外</value>
|
||||||
|
|
@ -1333,7 +1333,7 @@
|
||||||
<value>开启第二个本地监听端口</value>
|
<value>开启第二个本地监听端口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
<data name="TbRoutingInboundTagTips" xml:space="preserve">
|
||||||
<value>Tun:TUN 入站,Socks:本地端口,Socks2:第二个本地端口,Socks3:局域网端口</value>
|
<value>Socks:本地端口,Socks2:第二个本地端口,Socks3:局域网端口</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsTheme" xml:space="preserve">
|
<data name="TbSettingsTheme" xml:space="preserve">
|
||||||
<value>主题</value>
|
<value>主题</value>
|
||||||
|
|
@ -1728,19 +1728,4 @@
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>导出 v2rayN 内部分享链接至剪贴板 (多选)</value>
|
<value>导出 v2rayN 内部分享链接至剪贴板 (多选)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} 有新版本可用:{1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>仅检查</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>不支持</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP 信息</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>有更新</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -691,7 +691,7 @@
|
||||||
<value>在更新訂閱後自動調整列寬</value>
|
<value>在更新訂閱後自動調整列寬</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
<data name="TbSettingsEnableCheckPreReleaseUpdate" xml:space="preserve">
|
||||||
<value>檢查 Pre-Release</value>
|
<value>檢查 Pre-Release 更新 (請謹慎啟用)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="TbSettingsException" xml:space="preserve">
|
<data name="TbSettingsException" xml:space="preserve">
|
||||||
<value>例外</value>
|
<value>例外</value>
|
||||||
|
|
@ -1728,19 +1728,4 @@
|
||||||
<data name="menuExport2InnerUri" xml:space="preserve">
|
<data name="menuExport2InnerUri" xml:space="preserve">
|
||||||
<value>匯出 v2rayN 內部分享連結至剪貼簿(多選)</value>
|
<value>匯出 v2rayN 內部分享連結至剪貼簿(多選)</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgCheckUpdateHasNewVersion" xml:space="preserve">
|
|
||||||
<value>{0} 有新版本可用:{1}</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuCheckOnly" xml:space="preserve">
|
|
||||||
<value>僅檢查</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgNotSupport" xml:space="preserve">
|
|
||||||
<value>不支援</value>
|
|
||||||
</data>
|
|
||||||
<data name="LvTestIpInfo" xml:space="preserve">
|
|
||||||
<value>IP 資訊</value>
|
|
||||||
</data>
|
|
||||||
<data name="menuNewUpdate" xml:space="preserve">
|
|
||||||
<value>有更新</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"type": "tun",
|
"type": "tun",
|
||||||
"tag": "tun",
|
"tag": "tun-in",
|
||||||
"interface_name": "singbox_tun",
|
"interface_name": "singbox_tun",
|
||||||
"address": [
|
"address": [
|
||||||
"172.18.0.1/30",
|
"172.18.0.1/30",
|
||||||
|
|
|
||||||
|
|
@ -87,14 +87,8 @@ public partial class CoreConfigSingboxService
|
||||||
});
|
});
|
||||||
_coreConfig.route.rules.Add(new()
|
_coreConfig.route.rules.Add(new()
|
||||||
{
|
{
|
||||||
type = "logical",
|
protocol = ["dns"],
|
||||||
mode = "or",
|
action = "hijack-dns"
|
||||||
action = "hijack-dns",
|
|
||||||
rules =
|
|
||||||
[
|
|
||||||
new() { port = [53] },
|
|
||||||
new() { protocol = ["dns"] },
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -102,7 +96,7 @@ public partial class CoreConfigSingboxService
|
||||||
_coreConfig.route.rules.Add(new()
|
_coreConfig.route.rules.Add(new()
|
||||||
{
|
{
|
||||||
port = [53],
|
port = [53],
|
||||||
action = "hijack-dns",
|
action = "hijack-dns"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,6 @@ public partial class CoreConfigV2rayService
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tag = balancerTag,
|
tag = balancerTag,
|
||||||
fallbackTag = multipleLoad == EMultipleLoad.Fallback ? Global.DirectTag : null,
|
|
||||||
};
|
};
|
||||||
_coreConfig.routing.balancers ??= new();
|
_coreConfig.routing.balancers ??= new();
|
||||||
_coreConfig.routing.balancers.Add(balancer);
|
_coreConfig.routing.balancers.Add(balancer);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ public partial class CoreConfigV2rayService
|
||||||
});
|
});
|
||||||
_coreConfig.routing.rules.Add(new()
|
_coreConfig.routing.rules.Add(new()
|
||||||
{
|
{
|
||||||
inboundTag = ["tun"],
|
|
||||||
port = "53",
|
port = "53",
|
||||||
outboundTag = Global.DnsOutboundTag,
|
outboundTag = Global.DnsOutboundTag,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ using System.Net.Http.Headers;
|
||||||
namespace ServiceLib.Services;
|
namespace ServiceLib.Services;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Download
|
///Download
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DownloadService
|
public class DownloadService
|
||||||
{
|
{
|
||||||
|
|
@ -13,10 +13,7 @@ public class DownloadService
|
||||||
|
|
||||||
private static readonly string _tag = "DownloadService";
|
private static readonly string _tag = "DownloadService";
|
||||||
|
|
||||||
/// <summary>
|
public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Func<bool, string, Task> updateFunc)
|
||||||
/// Downloads data with the specified proxy and reports progress messages.
|
|
||||||
/// </summary>
|
|
||||||
public async Task<int> DownloadDataAsync(string url, IWebProxy webProxy, int downloadTimeout, Func<bool, string, Task> updateFunc)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -39,9 +36,6 @@ public class DownloadService
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Downloads a file and reports progress through events.
|
|
||||||
/// </summary>
|
|
||||||
public async Task DownloadFileAsync(string url, string fileName, bool blProxy, int downloadTimeout)
|
public async Task DownloadFileAsync(string url, string fileName, bool blProxy, int downloadTimeout)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
@ -70,9 +64,6 @@ public class DownloadService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets redirect target URL without following redirects automatically.
|
|
||||||
/// </summary>
|
|
||||||
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
|
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
|
||||||
{
|
{
|
||||||
var webRequestHandler = new SocketsHttpHandler
|
var webRequestHandler = new SocketsHttpHandler
|
||||||
|
|
@ -95,23 +86,11 @@ public class DownloadService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to download string content using proxy switch setting.
|
|
||||||
/// </summary>
|
|
||||||
public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)
|
public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)
|
||||||
{
|
|
||||||
var webProxy = await GetWebProxy(blProxy);
|
|
||||||
return await TryDownloadString(url, webProxy, userAgent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Tries to download string content with a specified proxy.
|
|
||||||
/// </summary>
|
|
||||||
public async Task<string?> TryDownloadString(string url, IWebProxy? webProxy, string userAgent)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result1 = await DownloadStringAsync(url, webProxy, userAgent, 15);
|
var result1 = await DownloadStringAsync(url, blProxy, userAgent, 15);
|
||||||
if (result1.IsNotEmpty())
|
if (result1.IsNotEmpty())
|
||||||
{
|
{
|
||||||
return result1;
|
return result1;
|
||||||
|
|
@ -129,7 +108,7 @@ public class DownloadService
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, 15);
|
var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent, 15);
|
||||||
if (result2.IsNotEmpty())
|
if (result2.IsNotEmpty())
|
||||||
{
|
{
|
||||||
return result2;
|
return result2;
|
||||||
|
|
@ -149,12 +128,14 @@ public class DownloadService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Downloads string content via HttpClient.
|
/// DownloadString
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<string?> DownloadStringAsync(string url, IWebProxy? webProxy, string userAgent, int timeout)
|
/// <param name="url"></param>
|
||||||
|
private async Task<string?> DownloadStringAsync(string url, bool blProxy, string userAgent, int timeout)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var webProxy = await GetWebProxy(blProxy);
|
||||||
var client = new HttpClient(new SocketsHttpHandler()
|
var client = new HttpClient(new SocketsHttpHandler()
|
||||||
{
|
{
|
||||||
Proxy = webProxy,
|
Proxy = webProxy,
|
||||||
|
|
@ -191,12 +172,15 @@ public class DownloadService
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Downloads string content via DownloaderHelper.
|
/// DownloadString
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private async Task<string?> DownloadStringViaDownloader(string url, IWebProxy? webProxy, string userAgent, int timeout)
|
/// <param name="url"></param>
|
||||||
|
private async Task<string?> DownloadStringViaDownloader(string url, bool blProxy, string userAgent, int timeout)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var webProxy = await GetWebProxy(blProxy);
|
||||||
|
|
||||||
if (userAgent.IsNullOrEmpty())
|
if (userAgent.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
userAgent = Utils.GetVersion(false);
|
userAgent = Utils.GetVersion(false);
|
||||||
|
|
@ -216,9 +200,6 @@ public class DownloadService
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates local SOCKS proxy when proxy switch is enabled.
|
|
||||||
/// </summary>
|
|
||||||
private async Task<WebProxy?> GetWebProxy(bool blProxy)
|
private async Task<WebProxy?> GetWebProxy(bool blProxy)
|
||||||
{
|
{
|
||||||
if (!blProxy)
|
if (!blProxy)
|
||||||
|
|
@ -234,9 +215,6 @@ public class DownloadService
|
||||||
return new WebProxy($"socks5://{Global.Loopback}:{port}");
|
return new WebProxy($"socks5://{Global.Loopback}:{port}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks whether the specified TCP endpoint is reachable.
|
|
||||||
/// </summary>
|
|
||||||
private async Task<bool> SocketCheck(string ip, int port)
|
private async Task<bool> SocketCheck(string ip, int port)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
private readonly Config? _config = config;
|
private readonly Config? _config = config;
|
||||||
private readonly Func<SpeedTestResult, Task>? _updateFunc = updateFunc;
|
private readonly Func<SpeedTestResult, Task>? _updateFunc = updateFunc;
|
||||||
private static readonly ConcurrentBag<string> _lstExitLoop = new();
|
private static readonly ConcurrentBag<string> _lstExitLoop = new();
|
||||||
private readonly int _speedTestPageSize = config.SpeedTestItem.SpeedTestPageSize ?? Global.SpeedTestPageSize;
|
|
||||||
private readonly TimeSpan _delayInterval = TimeSpan.FromSeconds(config.SpeedTestItem.SpeedTestDelayInterval ?? 1);
|
|
||||||
|
|
||||||
public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)
|
||||||
{
|
{
|
||||||
|
|
@ -137,39 +135,32 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
|
|
||||||
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
private async Task RunTcpingAsync(List<ServerTestItem> selecteds)
|
||||||
{
|
{
|
||||||
var pageSize = Math.Min(selecteds.Count, _speedTestPageSize);
|
List<Task> tasks = [];
|
||||||
var lstBatch = GetTestBatchItem(selecteds, pageSize);
|
foreach (var it in selecteds)
|
||||||
|
|
||||||
foreach (var lst in lstBatch)
|
|
||||||
{
|
{
|
||||||
List<Task> tasks = [];
|
tasks.Add(Task.Run(async () =>
|
||||||
foreach (var it in lst)
|
|
||||||
{
|
{
|
||||||
tasks.Add(Task.Run(async () =>
|
try
|
||||||
{
|
{
|
||||||
try
|
var responseTime = await GetTcpingTime(it.Address, it.Port);
|
||||||
{
|
|
||||||
var responseTime = await GetTcpingTime(it.Address, it.Port);
|
|
||||||
|
|
||||||
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
|
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||||
await UpdateFunc(it.IndexId, responseTime.ToString());
|
await UpdateFunc(it.IndexId, responseTime.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logging.SaveLog(_tag, ex);
|
Logging.SaveLog(_tag, ex);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
await Task.WhenAll(tasks);
|
|
||||||
await Task.Delay(_delayInterval);
|
|
||||||
}
|
}
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)
|
private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)
|
||||||
{
|
{
|
||||||
if (pageSize <= 0)
|
if (pageSize <= 0)
|
||||||
{
|
{
|
||||||
pageSize = Math.Min(lstSelected.Count, _speedTestPageSize);
|
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
|
||||||
}
|
}
|
||||||
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
||||||
|
|
||||||
|
|
@ -181,7 +172,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
{
|
{
|
||||||
lstFailed.AddRange(lst);
|
lstFailed.AddRange(lst);
|
||||||
}
|
}
|
||||||
await Task.Delay(_delayInterval);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Retest the failed part
|
//Retest the failed part
|
||||||
|
|
@ -258,7 +249,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
{
|
{
|
||||||
if (pageSize <= 0)
|
if (pageSize <= 0)
|
||||||
{
|
{
|
||||||
pageSize = Math.Min(lstSelected.Count, _speedTestPageSize);
|
pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;
|
||||||
}
|
}
|
||||||
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
var lstTest = GetTestBatchItem(lstSelected, pageSize);
|
||||||
|
|
||||||
|
|
@ -270,7 +261,7 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
{
|
{
|
||||||
lstFailed.AddRange(lst);
|
lstFailed.AddRange(lst);
|
||||||
}
|
}
|
||||||
await Task.Delay(_delayInterval);
|
await Task.Delay(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Retest the failed part
|
//Retest the failed part
|
||||||
|
|
@ -401,23 +392,10 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
private async Task<int> DoRealPing(ServerTestItem it)
|
private async Task<int> DoRealPing(ServerTestItem it)
|
||||||
{
|
{
|
||||||
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}");
|
||||||
var responseTime = await ConnectionHandler.GetRealPingTime(webProxy, 10);
|
var responseTime = await ConnectionHandler.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);
|
||||||
|
|
||||||
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
|
ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);
|
||||||
await UpdateFunc(it.IndexId, responseTime.ToString());
|
await UpdateFunc(it.IndexId, responseTime.ToString());
|
||||||
|
|
||||||
if (responseTime > 0)
|
|
||||||
{
|
|
||||||
var ipInfo = await ConnectionHandler.GetIPInfo(webProxy);
|
|
||||||
var ipStr = ipInfo?.ToString() ?? Global.None;
|
|
||||||
ProfileExManager.Instance.SetTestIpInfo(it.IndexId, ipStr);
|
|
||||||
await UpdateIpInfoFunc(it.IndexId, ipStr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await UpdateIpInfoFunc(it.IndexId, ResUI.SpeedtestingSkip);
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseTime;
|
return responseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -513,9 +491,4 @@ public class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateF
|
||||||
ProfileExManager.Instance.SetTestMessage(indexId, speed);
|
ProfileExManager.Instance.SetTestMessage(indexId, speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateIpInfoFunc(string indexId, string ip)
|
|
||||||
{
|
|
||||||
await _updateFunc?.Invoke(new() { IndexId = indexId, IpInfo = ip });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,43 +100,6 @@ public class UpdateService(Config config, Func<bool, string, Task> updateFunc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UpdateResult> CheckHasUpdateOnly(ECoreType type, bool preRelease)
|
|
||||||
{
|
|
||||||
if (!CoreInfoManager.Instance.IsCheckUpdateSupported(type))
|
|
||||||
{
|
|
||||||
return new UpdateResult(false, ResUI.MsgNotSupport);
|
|
||||||
}
|
|
||||||
|
|
||||||
var downloadHandle = new DownloadService();
|
|
||||||
var checkPreRelease = CoreInfoManager.Instance.GetCheckPreRelease(type, preRelease);
|
|
||||||
return await CheckUpdateAsync(downloadHandle, type, checkPreRelease);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<List<string>> CheckHasUpdateOnlyAll(bool preRelease)
|
|
||||||
{
|
|
||||||
var msgs = new List<string>();
|
|
||||||
foreach (var type in CoreInfoManager.Instance.GetCheckUpdateCoreTypes())
|
|
||||||
{
|
|
||||||
if (!(_config.CheckUpdateItem.SelectedCoreTypes?.Contains(type.ToString()) ?? true))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = await CheckHasUpdateOnly(type, preRelease);
|
|
||||||
if (result.Success && result.Version != null)
|
|
||||||
{
|
|
||||||
var msg = string.Format(ResUI.MsgCheckUpdateHasNewVersion, type, result.Version);
|
|
||||||
msgs.Add(msg);
|
|
||||||
AppManager.Instance.SetLastCheckUpdateResult(type, msg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AppManager.Instance.SetLastCheckUpdateResult(type, result.Msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return msgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task UpdateGeoFileAll()
|
public async Task UpdateGeoFileAll()
|
||||||
{
|
{
|
||||||
await UpdateGeoFiles();
|
await UpdateGeoFiles();
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@ namespace ServiceLib.ViewModels;
|
||||||
public class CheckUpdateViewModel : MyReactiveObject
|
public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
private const string _geo = "GeoFiles";
|
private const string _geo = "GeoFiles";
|
||||||
private readonly ECoreType _v2rayN = ECoreType.v2rayN;
|
private readonly string _v2rayN = ECoreType.v2rayN.ToString();
|
||||||
private List<CheckUpdateModel> _lstUpdated = [];
|
private List<CheckUpdateModel> _lstUpdated = [];
|
||||||
private static readonly string _tag = "CheckUpdateViewModel";
|
private static readonly string _tag = "CheckUpdateViewModel";
|
||||||
|
|
||||||
public IObservableCollection<CheckUpdateModel> CheckUpdateModels { get; } = new ObservableCollectionExtended<CheckUpdateModel>();
|
public IObservableCollection<CheckUpdateModel> CheckUpdateModels { get; } = new ObservableCollectionExtended<CheckUpdateModel>();
|
||||||
public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }
|
public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }
|
||||||
public ReactiveCommand<Unit, Unit> CheckOnlyCmd { get; }
|
|
||||||
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
[Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }
|
||||||
|
|
||||||
public CheckUpdateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
public CheckUpdateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
|
||||||
|
|
@ -24,19 +23,12 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
_ = UpdateView(_v2rayN, ex.Message);
|
_ = UpdateView(_v2rayN, ex.Message);
|
||||||
});
|
});
|
||||||
|
|
||||||
CheckOnlyCmd = ReactiveCommand.CreateFromTask(CheckOnly);
|
|
||||||
CheckOnlyCmd.ThrownExceptions.Subscribe(ex =>
|
|
||||||
{
|
|
||||||
Logging.SaveLog(_tag, ex);
|
|
||||||
_ = UpdateView(_v2rayN, ex.Message);
|
|
||||||
});
|
|
||||||
|
|
||||||
EnableCheckPreReleaseUpdate = _config.CheckUpdateItem.CheckPreReleaseUpdate;
|
EnableCheckPreReleaseUpdate = _config.CheckUpdateItem.CheckPreReleaseUpdate;
|
||||||
|
|
||||||
this.WhenAnyValue(
|
this.WhenAnyValue(
|
||||||
x => x.EnableCheckPreReleaseUpdate,
|
x => x.EnableCheckPreReleaseUpdate,
|
||||||
y => y == true)
|
y => y == true)
|
||||||
.Subscribe(c => _ = OnCheckPreReleaseUpdateChanged());
|
.Subscribe(c => _config.CheckUpdateItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate);
|
||||||
|
|
||||||
RefreshCheckUpdateItems();
|
RefreshCheckUpdateItems();
|
||||||
}
|
}
|
||||||
|
|
@ -45,15 +37,21 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
CheckUpdateModels.Clear();
|
CheckUpdateModels.Clear();
|
||||||
|
|
||||||
foreach (var type in CoreInfoManager.Instance.GetCheckUpdateCoreTypes())
|
if (RuntimeInformation.ProcessArchitecture != Architecture.X86)
|
||||||
{
|
{
|
||||||
CheckUpdateModels.Add(GetCheckUpdateModel(type));
|
CheckUpdateModels.Add(GetCheckUpdateModel(_v2rayN));
|
||||||
|
//Not Windows and under Win10
|
||||||
|
if (!(Utils.IsWindows() && Environment.OSVersion.Version.Major < 10))
|
||||||
|
{
|
||||||
|
CheckUpdateModels.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));
|
||||||
|
CheckUpdateModels.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));
|
||||||
|
CheckUpdateModels.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
CheckUpdateModels.Add(GetCheckUpdateModel(_geo));
|
||||||
CheckUpdateModels.Add(GetGeoFileCheckUpdateModel());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CheckUpdateModel GetCheckUpdateModel(ECoreType coreType)
|
private CheckUpdateModel GetCheckUpdateModel(string coreType)
|
||||||
{
|
{
|
||||||
if (coreType == _v2rayN && Utils.IsPackagedInstall())
|
if (coreType == _v2rayN && Utils.IsPackagedInstall())
|
||||||
{
|
{
|
||||||
|
|
@ -61,112 +59,34 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
IsSelected = false,
|
IsSelected = false,
|
||||||
CoreType = coreType,
|
CoreType = coreType,
|
||||||
IsGeoFile = false,
|
Remarks = ResUI.menuCheckUpdate + " (Not Support)",
|
||||||
Remarks = ResUI.menuCheckUpdate + $" ({ResUI.MsgNotSupport})",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
AppManager.Instance.LastCheckUpdateResults.TryGetValue(coreType, out var lastResult);
|
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType.ToString()) ?? true,
|
IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType) ?? true,
|
||||||
CoreType = coreType,
|
CoreType = coreType,
|
||||||
IsGeoFile = false,
|
|
||||||
Remarks = lastResult ?? ResUI.menuCheckUpdate,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private CheckUpdateModel GetGeoFileCheckUpdateModel()
|
|
||||||
{
|
|
||||||
return new()
|
|
||||||
{
|
|
||||||
IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(_geo) ?? true,
|
|
||||||
CoreType = null,
|
|
||||||
IsGeoFile = true,
|
|
||||||
Remarks = ResUI.menuCheckUpdate,
|
Remarks = ResUI.menuCheckUpdate,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task OnCheckPreReleaseUpdateChanged()
|
|
||||||
{
|
|
||||||
if (_config.CheckUpdateItem.CheckPreReleaseUpdate == EnableCheckPreReleaseUpdate)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_config.CheckUpdateItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate;
|
|
||||||
await SaveSelectedCoreTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveSelectedCoreTypes()
|
private async Task SaveSelectedCoreTypes()
|
||||||
{
|
{
|
||||||
_config.CheckUpdateItem.SelectedCoreTypes =
|
_config.CheckUpdateItem.SelectedCoreTypes = CheckUpdateModels.Where(t => t.IsSelected == true).Select(t => t.CoreType ?? "").ToList();
|
||||||
CheckUpdateModels.Where(t => t.IsSelected == true)
|
|
||||||
.Select(t => t.CoreTypeForStorage)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
await ConfigHandler.SaveConfig(_config);
|
await ConfigHandler.SaveConfig(_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CheckOnly()
|
|
||||||
{
|
|
||||||
await Task.Run(CheckOnlyTask);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CheckUpdate()
|
private async Task CheckUpdate()
|
||||||
{
|
{
|
||||||
await Task.Run(CheckUpdateTask);
|
await Task.Run(CheckUpdateTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CheckOnlyTask()
|
|
||||||
{
|
|
||||||
await SaveSelectedCoreTypes();
|
|
||||||
|
|
||||||
for (var k = CheckUpdateModels.Count - 1; k >= 0; k--)
|
|
||||||
{
|
|
||||||
var item = CheckUpdateModels[k];
|
|
||||||
if (item.IsSelected != true)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
await UpdateView(item.CoreType, "...");
|
|
||||||
|
|
||||||
if (item.IsGeoFile || item.CoreType == null)
|
|
||||||
{
|
|
||||||
await UpdateView(item.CoreType, ResUI.menuCheckOnly + $" ({ResUI.MsgNotSupport})");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.CoreType == null)
|
|
||||||
{
|
|
||||||
await UpdateView(item.CoreType, ResUI.MsgNotSupport);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var updateService = new UpdateService(_config, async (success, msg) => await Task.CompletedTask);
|
|
||||||
var result = await updateService.CheckHasUpdateOnly(item.CoreType.Value, EnableCheckPreReleaseUpdate);
|
|
||||||
if (result.Success && result.Version != null)
|
|
||||||
{
|
|
||||||
await UpdateView(item.CoreType, string.Format(ResUI.MsgCheckUpdateHasNewVersion, item.CoreType, result.Version));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await UpdateView(item.CoreType, result.Msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task CheckUpdateTask()
|
private async Task CheckUpdateTask()
|
||||||
{
|
{
|
||||||
_lstUpdated.Clear();
|
_lstUpdated.Clear();
|
||||||
_lstUpdated = CheckUpdateModels
|
_lstUpdated = CheckUpdateModels.Where(x => x.IsSelected == true)
|
||||||
.Where(x => x.IsSelected == true)
|
.Select(x => new CheckUpdateModel() { CoreType = x.CoreType }).ToList();
|
||||||
.Select(x => new CheckUpdateModel()
|
|
||||||
{
|
|
||||||
CoreType = x.CoreType,
|
|
||||||
IsGeoFile = x.IsGeoFile
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
await SaveSelectedCoreTypes();
|
await SaveSelectedCoreTypes();
|
||||||
|
|
||||||
for (var k = CheckUpdateModels.Count - 1; k >= 0; k--)
|
for (var k = CheckUpdateModels.Count - 1; k >= 0; k--)
|
||||||
|
|
@ -178,8 +98,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
}
|
}
|
||||||
|
|
||||||
await UpdateView(item.CoreType, "...");
|
await UpdateView(item.CoreType, "...");
|
||||||
|
if (item.CoreType == _geo)
|
||||||
if (item.IsGeoFile)
|
|
||||||
{
|
{
|
||||||
await CheckUpdateGeo();
|
await CheckUpdateGeo();
|
||||||
}
|
}
|
||||||
|
|
@ -187,16 +106,16 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
if (Utils.IsPackagedInstall())
|
if (Utils.IsPackagedInstall())
|
||||||
{
|
{
|
||||||
await UpdateView(_v2rayN, ResUI.MsgNotSupport);
|
await UpdateView(_v2rayN, "Not Support");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
await CheckUpdateN(EnableCheckPreReleaseUpdate);
|
await CheckUpdateN(EnableCheckPreReleaseUpdate);
|
||||||
}
|
}
|
||||||
else if (item.CoreType == ECoreType.Xray)
|
else if (item.CoreType == ECoreType.Xray.ToString())
|
||||||
{
|
{
|
||||||
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);
|
||||||
}
|
}
|
||||||
else if (item.CoreType.HasValue)
|
else
|
||||||
{
|
{
|
||||||
await CheckUpdateCore(item, false);
|
await CheckUpdateCore(item, false);
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +124,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
await UpdateFinished();
|
await UpdateFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatedPlusPlus(ECoreType? coreType, string fileName)
|
private void UpdatedPlusPlus(string coreType, string fileName)
|
||||||
{
|
{
|
||||||
var item = _lstUpdated.FirstOrDefault(x => x.CoreType == coreType);
|
var item = _lstUpdated.FirstOrDefault(x => x.CoreType == coreType);
|
||||||
if (item == null)
|
if (item == null)
|
||||||
|
|
@ -223,14 +142,14 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
async Task _updateUI(bool success, string msg)
|
async Task _updateUI(bool success, string msg)
|
||||||
{
|
{
|
||||||
await UpdateView(null, msg);
|
await UpdateView(_geo, msg);
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
UpdatedPlusPlus(null, "");
|
UpdatedPlusPlus(_geo, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await new UpdateService(_config, _updateUI).UpdateGeoFileAll()
|
await new UpdateService(_config, _updateUI).UpdateGeoFileAll()
|
||||||
.ContinueWith(t => UpdatedPlusPlus(null, ""));
|
.ContinueWith(t => UpdatedPlusPlus(_geo, ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CheckUpdateN(bool preRelease)
|
private async Task CheckUpdateN(bool preRelease)
|
||||||
|
|
@ -256,15 +175,13 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
await UpdateView(model.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
|
await UpdateView(model.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);
|
||||||
|
|
||||||
UpdatedPlusPlus(model.CoreType, msg);
|
UpdatedPlusPlus(model.CoreType, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var type = (ECoreType)Enum.Parse(typeof(ECoreType), model.CoreType);
|
||||||
if (model.CoreType.HasValue)
|
await new UpdateService(_config, _updateUI).CheckUpdateCore(type, preRelease)
|
||||||
{
|
.ContinueWith(t => UpdatedPlusPlus(model.CoreType, ""));
|
||||||
await new UpdateService(_config, _updateUI).CheckUpdateCore(model.CoreType.Value, preRelease)
|
|
||||||
.ContinueWith(t => UpdatedPlusPlus(model.CoreType, ""));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateFinished()
|
private async Task UpdateFinished()
|
||||||
|
|
@ -340,7 +257,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
foreach (var item in _lstUpdated)
|
foreach (var item in _lstUpdated)
|
||||||
{
|
{
|
||||||
if (item.FileName.IsNullOrEmpty() || item.IsGeoFile)
|
if (item.FileName.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -350,9 +267,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
var toPath = Utils.GetBinPath("", item.CoreType);
|
||||||
var coreTypeStr = item.CoreType?.ToString() ?? "";
|
|
||||||
var toPath = Utils.GetBinPath("", coreTypeStr);
|
|
||||||
|
|
||||||
if (fileName.Contains(".tar.gz"))
|
if (fileName.Contains(".tar.gz"))
|
||||||
{
|
{
|
||||||
|
|
@ -369,7 +284,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
}
|
}
|
||||||
else if (fileName.Contains(".gz"))
|
else if (fileName.Contains(".gz"))
|
||||||
{
|
{
|
||||||
FileUtils.DecompressFile(fileName, toPath, coreTypeStr);
|
FileUtils.DecompressFile(fileName, toPath, item.CoreType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -381,7 +296,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
var filesList = new DirectoryInfo(toPath).GetFiles().Select(u => u.FullName).ToList();
|
var filesList = new DirectoryInfo(toPath).GetFiles().Select(u => u.FullName).ToList();
|
||||||
foreach (var file in filesList)
|
foreach (var file in filesList)
|
||||||
{
|
{
|
||||||
await Utils.SetLinuxChmod(Path.Combine(toPath, coreTypeStr.ToLower()));
|
await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType.ToLower()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -394,12 +309,11 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateView(ECoreType? coreType, string msg)
|
private async Task UpdateView(string coreType, string msg)
|
||||||
{
|
{
|
||||||
var item = new CheckUpdateModel()
|
var item = new CheckUpdateModel()
|
||||||
{
|
{
|
||||||
CoreType = coreType,
|
CoreType = coreType,
|
||||||
IsGeoFile = coreType == null,
|
|
||||||
Remarks = msg,
|
Remarks = msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -413,7 +327,7 @@ public class CheckUpdateViewModel : MyReactiveObject
|
||||||
|
|
||||||
public async Task UpdateViewResult(CheckUpdateModel model)
|
public async Task UpdateViewResult(CheckUpdateModel model)
|
||||||
{
|
{
|
||||||
var found = CheckUpdateModels.FirstOrDefault(t => t.CoreType == model.CoreType && t.IsGeoFile == model.IsGeoFile);
|
var found = CheckUpdateModels.FirstOrDefault(t => t.CoreType == model.CoreType);
|
||||||
if (found == null)
|
if (found == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -65,8 +65,6 @@ public class MainWindowViewModel : MyReactiveObject
|
||||||
|
|
||||||
[Reactive] public bool BlIsWindows { get; set; }
|
[Reactive] public bool BlIsWindows { get; set; }
|
||||||
|
|
||||||
[Reactive] public bool BlNewUpdate { get; set; }
|
|
||||||
|
|
||||||
#endregion Menu
|
#endregion Menu
|
||||||
|
|
||||||
#region Init
|
#region Init
|
||||||
|
|
@ -253,11 +251,6 @@ public class MainWindowViewModel : MyReactiveObject
|
||||||
.ObserveOn(RxSchedulers.MainThreadScheduler)
|
.ObserveOn(RxSchedulers.MainThreadScheduler)
|
||||||
.Subscribe(async blProxy => await UpdateSubscriptionProcess("", blProxy));
|
.Subscribe(async blProxy => await UpdateSubscriptionProcess("", blProxy));
|
||||||
|
|
||||||
AppEvents.HasUpdateNotified
|
|
||||||
.AsObservable()
|
|
||||||
.ObserveOn(RxSchedulers.MainThreadScheduler)
|
|
||||||
.Subscribe(async bl => BlNewUpdate = bl);
|
|
||||||
|
|
||||||
#endregion AppEvents
|
#endregion AppEvents
|
||||||
|
|
||||||
_ = Init();
|
_ = Init();
|
||||||
|
|
@ -304,22 +297,10 @@ public class MainWindowViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
var indexIdOld = _config.IndexId;
|
var indexIdOld = _config.IndexId;
|
||||||
await RefreshServers();
|
await RefreshServers();
|
||||||
|
if (indexIdOld != _config.IndexId)
|
||||||
// If indexId changed or subIndexId is empty, directly reload.
|
|
||||||
if (indexIdOld != _config.IndexId || _config.SubIndexId.IsNullOrEmpty())
|
|
||||||
{
|
{
|
||||||
await Reload();
|
await Reload();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// The activity config belongs to the current group.
|
|
||||||
var profile = await AppManager.Instance.GetProfileItem(_config.IndexId);
|
|
||||||
if (profile != null && profile.Subid == _config.SubIndexId)
|
|
||||||
{
|
|
||||||
await Reload();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_config.UiItem.EnableAutoAdjustMainLvColWidth)
|
if (_config.UiItem.EnableAutoAdjustMainLvColWidth)
|
||||||
{
|
{
|
||||||
AppEvents.AdjustMainLvColWidthRequested.Publish();
|
AppEvents.AdjustMainLvColWidthRequested.Publish();
|
||||||
|
|
|
||||||
|
|
@ -4,29 +4,29 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
#region Core
|
#region Core
|
||||||
|
|
||||||
[Reactive] public int LocalPort { get; set; }
|
[Reactive] public int localPort { get; set; }
|
||||||
[Reactive] public bool SecondLocalPortEnabled { get; set; }
|
[Reactive] public bool SecondLocalPortEnabled { get; set; }
|
||||||
[Reactive] public bool UdpEnabled { get; set; }
|
[Reactive] public bool udpEnabled { get; set; }
|
||||||
[Reactive] public bool SniffingEnabled { get; set; }
|
[Reactive] public bool sniffingEnabled { get; set; }
|
||||||
public IList<string> DestOverride { get; set; }
|
public IList<string> destOverride { get; set; }
|
||||||
[Reactive] public bool RouteOnly { get; set; }
|
[Reactive] public bool routeOnly { get; set; }
|
||||||
[Reactive] public bool AllowLANConn { get; set; }
|
[Reactive] public bool allowLANConn { get; set; }
|
||||||
[Reactive] public bool NewPort4LAN { get; set; }
|
[Reactive] public bool newPort4LAN { get; set; }
|
||||||
[Reactive] public string User { get; set; }
|
[Reactive] public string user { get; set; }
|
||||||
[Reactive] public string Pass { get; set; }
|
[Reactive] public string pass { get; set; }
|
||||||
[Reactive] public bool MuxEnabled { get; set; }
|
[Reactive] public bool muxEnabled { get; set; }
|
||||||
[Reactive] public bool LogEnabled { get; set; }
|
[Reactive] public bool logEnabled { get; set; }
|
||||||
[Reactive] public string Loglevel { get; set; }
|
[Reactive] public string loglevel { get; set; }
|
||||||
[Reactive] public bool DefAllowInsecure { get; set; }
|
[Reactive] public bool defAllowInsecure { get; set; }
|
||||||
[Reactive] public string DefFingerprint { get; set; }
|
[Reactive] public string defFingerprint { get; set; }
|
||||||
[Reactive] public string DefUserAgent { get; set; }
|
[Reactive] public string defUserAgent { get; set; }
|
||||||
[Reactive] public string SendThrough { get; set; }
|
[Reactive] public string sendThrough { get; set; }
|
||||||
[Reactive] public string BindInterface { get; set; }
|
[Reactive] public string bindInterface { get; set; }
|
||||||
[Reactive] public string Mux4SboxProtocol { get; set; }
|
[Reactive] public string mux4SboxProtocol { get; set; }
|
||||||
[Reactive] public bool EnableCacheFile4Sbox { get; set; }
|
[Reactive] public bool enableCacheFile4Sbox { get; set; }
|
||||||
[Reactive] public int? HyUpMbps { get; set; }
|
[Reactive] public int? hyUpMbps { get; set; }
|
||||||
[Reactive] public int? HyDownMbps { get; set; }
|
[Reactive] public int? hyDownMbps { get; set; }
|
||||||
[Reactive] public bool EnableFragment { get; set; }
|
[Reactive] public bool enableFragment { get; set; }
|
||||||
|
|
||||||
#endregion Core
|
#endregion Core
|
||||||
|
|
||||||
|
|
@ -83,9 +83,9 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
|
|
||||||
#region System proxy
|
#region System proxy
|
||||||
|
|
||||||
[Reactive] public bool NotProxyLocalAddress { get; set; }
|
[Reactive] public bool notProxyLocalAddress { get; set; }
|
||||||
[Reactive] public string SystemProxyAdvancedProtocol { get; set; }
|
[Reactive] public string systemProxyAdvancedProtocol { get; set; }
|
||||||
[Reactive] public string SystemProxyExceptions { get; set; }
|
[Reactive] public string systemProxyExceptions { get; set; }
|
||||||
[Reactive] public string CustomSystemProxyPacPath { get; set; }
|
[Reactive] public string CustomSystemProxyPacPath { get; set; }
|
||||||
[Reactive] public string CustomSystemProxyScriptPath { get; set; }
|
[Reactive] public string CustomSystemProxyScriptPath { get; set; }
|
||||||
|
|
||||||
|
|
@ -142,28 +142,28 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
#region Core
|
#region Core
|
||||||
|
|
||||||
var inbound = _config.Inbound.First();
|
var inbound = _config.Inbound.First();
|
||||||
LocalPort = inbound.LocalPort;
|
localPort = inbound.LocalPort;
|
||||||
SecondLocalPortEnabled = inbound.SecondLocalPortEnabled;
|
SecondLocalPortEnabled = inbound.SecondLocalPortEnabled;
|
||||||
UdpEnabled = inbound.UdpEnabled;
|
udpEnabled = inbound.UdpEnabled;
|
||||||
SniffingEnabled = inbound.SniffingEnabled;
|
sniffingEnabled = inbound.SniffingEnabled;
|
||||||
RouteOnly = inbound.RouteOnly;
|
routeOnly = inbound.RouteOnly;
|
||||||
AllowLANConn = inbound.AllowLANConn;
|
allowLANConn = inbound.AllowLANConn;
|
||||||
NewPort4LAN = inbound.NewPort4LAN;
|
newPort4LAN = inbound.NewPort4LAN;
|
||||||
User = inbound.User;
|
user = inbound.User;
|
||||||
Pass = inbound.Pass;
|
pass = inbound.Pass;
|
||||||
MuxEnabled = _config.CoreBasicItem.MuxEnabled;
|
muxEnabled = _config.CoreBasicItem.MuxEnabled;
|
||||||
LogEnabled = _config.CoreBasicItem.LogEnabled;
|
logEnabled = _config.CoreBasicItem.LogEnabled;
|
||||||
Loglevel = _config.CoreBasicItem.Loglevel;
|
loglevel = _config.CoreBasicItem.Loglevel;
|
||||||
DefAllowInsecure = _config.CoreBasicItem.DefAllowInsecure;
|
defAllowInsecure = _config.CoreBasicItem.DefAllowInsecure;
|
||||||
DefFingerprint = _config.CoreBasicItem.DefFingerprint;
|
defFingerprint = _config.CoreBasicItem.DefFingerprint;
|
||||||
DefUserAgent = _config.CoreBasicItem.DefUserAgent;
|
defUserAgent = _config.CoreBasicItem.DefUserAgent;
|
||||||
SendThrough = _config.CoreBasicItem.SendThrough ?? string.Empty;
|
sendThrough = _config.CoreBasicItem.SendThrough ?? string.Empty;
|
||||||
BindInterface = _config.CoreBasicItem.BindInterface ?? string.Empty;
|
bindInterface = _config.CoreBasicItem.BindInterface ?? string.Empty;
|
||||||
Mux4SboxProtocol = _config.Mux4SboxItem.Protocol;
|
mux4SboxProtocol = _config.Mux4SboxItem.Protocol;
|
||||||
EnableCacheFile4Sbox = _config.CoreBasicItem.EnableCacheFile4Sbox;
|
enableCacheFile4Sbox = _config.CoreBasicItem.EnableCacheFile4Sbox;
|
||||||
HyUpMbps = _config.HysteriaItem.UpMbps;
|
hyUpMbps = _config.HysteriaItem.UpMbps;
|
||||||
HyDownMbps = _config.HysteriaItem.DownMbps;
|
hyDownMbps = _config.HysteriaItem.DownMbps;
|
||||||
EnableFragment = _config.CoreBasicItem.EnableFragment;
|
enableFragment = _config.CoreBasicItem.EnableFragment;
|
||||||
|
|
||||||
#endregion Core
|
#endregion Core
|
||||||
|
|
||||||
|
|
@ -211,9 +211,9 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
|
|
||||||
#region System proxy
|
#region System proxy
|
||||||
|
|
||||||
NotProxyLocalAddress = _config.SystemProxyItem.NotProxyLocalAddress;
|
notProxyLocalAddress = _config.SystemProxyItem.NotProxyLocalAddress;
|
||||||
SystemProxyAdvancedProtocol = _config.SystemProxyItem.SystemProxyAdvancedProtocol;
|
systemProxyAdvancedProtocol = _config.SystemProxyItem.SystemProxyAdvancedProtocol;
|
||||||
SystemProxyExceptions = _config.SystemProxyItem.SystemProxyExceptions;
|
systemProxyExceptions = _config.SystemProxyItem.SystemProxyExceptions;
|
||||||
CustomSystemProxyPacPath = _config.SystemProxyItem.CustomSystemProxyPacPath;
|
CustomSystemProxyPacPath = _config.SystemProxyItem.CustomSystemProxyPacPath;
|
||||||
CustomSystemProxyScriptPath = _config.SystemProxyItem.CustomSystemProxyScriptPath;
|
CustomSystemProxyScriptPath = _config.SystemProxyItem.CustomSystemProxyScriptPath;
|
||||||
|
|
||||||
|
|
@ -297,13 +297,13 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
|
|
||||||
private async Task SaveSettingAsync()
|
private async Task SaveSettingAsync()
|
||||||
{
|
{
|
||||||
if (LocalPort.ToString().IsNullOrEmpty() || !Utils.IsNumeric(LocalPort.ToString())
|
if (localPort.ToString().IsNullOrEmpty() || !Utils.IsNumeric(localPort.ToString())
|
||||||
|| LocalPort <= 0 || LocalPort >= Global.MaxPort)
|
|| localPort <= 0 || localPort >= Global.MaxPort)
|
||||||
{
|
{
|
||||||
NoticeManager.Instance.Enqueue(ResUI.FillLocalListeningPort);
|
NoticeManager.Instance.Enqueue(ResUI.FillLocalListeningPort);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var sendThroughValue = SendThrough.TrimEx();
|
var sendThroughValue = sendThrough.TrimEx();
|
||||||
if (sendThroughValue.IsNotEmpty() && !Utils.IsIpv4(sendThroughValue))
|
if (sendThroughValue.IsNotEmpty() && !Utils.IsIpv4(sendThroughValue))
|
||||||
{
|
{
|
||||||
NoticeManager.Instance.Enqueue(ResUI.FillCorrectSendThroughIPv4);
|
NoticeManager.Instance.Enqueue(ResUI.FillCorrectSendThroughIPv4);
|
||||||
|
|
@ -328,33 +328,33 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
//}
|
//}
|
||||||
|
|
||||||
//Core
|
//Core
|
||||||
_config.Inbound.First().LocalPort = LocalPort;
|
_config.Inbound.First().LocalPort = localPort;
|
||||||
_config.Inbound.First().SecondLocalPortEnabled = SecondLocalPortEnabled;
|
_config.Inbound.First().SecondLocalPortEnabled = SecondLocalPortEnabled;
|
||||||
_config.Inbound.First().UdpEnabled = UdpEnabled;
|
_config.Inbound.First().UdpEnabled = udpEnabled;
|
||||||
_config.Inbound.First().SniffingEnabled = SniffingEnabled;
|
_config.Inbound.First().SniffingEnabled = sniffingEnabled;
|
||||||
_config.Inbound.First().DestOverride = DestOverride?.ToList();
|
_config.Inbound.First().DestOverride = destOverride?.ToList();
|
||||||
_config.Inbound.First().RouteOnly = RouteOnly;
|
_config.Inbound.First().RouteOnly = routeOnly;
|
||||||
_config.Inbound.First().AllowLANConn = AllowLANConn;
|
_config.Inbound.First().AllowLANConn = allowLANConn;
|
||||||
_config.Inbound.First().NewPort4LAN = NewPort4LAN;
|
_config.Inbound.First().NewPort4LAN = newPort4LAN;
|
||||||
_config.Inbound.First().User = User;
|
_config.Inbound.First().User = user;
|
||||||
_config.Inbound.First().Pass = Pass;
|
_config.Inbound.First().Pass = pass;
|
||||||
if (_config.Inbound.Count > 1)
|
if (_config.Inbound.Count > 1)
|
||||||
{
|
{
|
||||||
_config.Inbound.RemoveAt(1);
|
_config.Inbound.RemoveAt(1);
|
||||||
}
|
}
|
||||||
_config.CoreBasicItem.LogEnabled = LogEnabled;
|
_config.CoreBasicItem.LogEnabled = logEnabled;
|
||||||
_config.CoreBasicItem.Loglevel = Loglevel;
|
_config.CoreBasicItem.Loglevel = loglevel;
|
||||||
_config.CoreBasicItem.MuxEnabled = MuxEnabled;
|
_config.CoreBasicItem.MuxEnabled = muxEnabled;
|
||||||
_config.CoreBasicItem.DefAllowInsecure = DefAllowInsecure;
|
_config.CoreBasicItem.DefAllowInsecure = defAllowInsecure;
|
||||||
_config.CoreBasicItem.DefFingerprint = DefFingerprint;
|
_config.CoreBasicItem.DefFingerprint = defFingerprint;
|
||||||
_config.CoreBasicItem.DefUserAgent = DefUserAgent;
|
_config.CoreBasicItem.DefUserAgent = defUserAgent;
|
||||||
_config.CoreBasicItem.SendThrough = SendThrough.TrimEx();
|
_config.CoreBasicItem.SendThrough = sendThrough.TrimEx();
|
||||||
_config.CoreBasicItem.BindInterface = BindInterface.TrimEx();
|
_config.CoreBasicItem.BindInterface = bindInterface.TrimEx();
|
||||||
_config.Mux4SboxItem.Protocol = Mux4SboxProtocol;
|
_config.Mux4SboxItem.Protocol = mux4SboxProtocol;
|
||||||
_config.CoreBasicItem.EnableCacheFile4Sbox = EnableCacheFile4Sbox;
|
_config.CoreBasicItem.EnableCacheFile4Sbox = enableCacheFile4Sbox;
|
||||||
_config.HysteriaItem.UpMbps = HyUpMbps ?? 0;
|
_config.HysteriaItem.UpMbps = hyUpMbps ?? 0;
|
||||||
_config.HysteriaItem.DownMbps = HyDownMbps ?? 0;
|
_config.HysteriaItem.DownMbps = hyDownMbps ?? 0;
|
||||||
_config.CoreBasicItem.EnableFragment = EnableFragment;
|
_config.CoreBasicItem.EnableFragment = enableFragment;
|
||||||
|
|
||||||
_config.GuiItem.AutoRun = AutoRun;
|
_config.GuiItem.AutoRun = AutoRun;
|
||||||
_config.GuiItem.EnableStatistics = EnableStatistics;
|
_config.GuiItem.EnableStatistics = EnableStatistics;
|
||||||
|
|
@ -383,9 +383,9 @@ public class OptionSettingViewModel : MyReactiveObject
|
||||||
_config.SpeedTestItem.IPAPIUrl = IPAPIUrl;
|
_config.SpeedTestItem.IPAPIUrl = IPAPIUrl;
|
||||||
|
|
||||||
//systemProxy
|
//systemProxy
|
||||||
_config.SystemProxyItem.SystemProxyExceptions = SystemProxyExceptions;
|
_config.SystemProxyItem.SystemProxyExceptions = systemProxyExceptions;
|
||||||
_config.SystemProxyItem.NotProxyLocalAddress = NotProxyLocalAddress;
|
_config.SystemProxyItem.NotProxyLocalAddress = notProxyLocalAddress;
|
||||||
_config.SystemProxyItem.SystemProxyAdvancedProtocol = SystemProxyAdvancedProtocol;
|
_config.SystemProxyItem.SystemProxyAdvancedProtocol = systemProxyAdvancedProtocol;
|
||||||
_config.SystemProxyItem.CustomSystemProxyPacPath = CustomSystemProxyPacPath;
|
_config.SystemProxyItem.CustomSystemProxyPacPath = CustomSystemProxyPacPath;
|
||||||
_config.SystemProxyItem.CustomSystemProxyScriptPath = CustomSystemProxyScriptPath;
|
_config.SystemProxyItem.CustomSystemProxyScriptPath = CustomSystemProxyScriptPath;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -303,10 +303,6 @@ public class ProfilesViewModel : MyReactiveObject
|
||||||
{
|
{
|
||||||
item.SpeedVal = result.Speed ?? string.Empty;
|
item.SpeedVal = result.Speed ?? string.Empty;
|
||||||
}
|
}
|
||||||
if (result.IpInfo.IsNotEmpty())
|
|
||||||
{
|
|
||||||
item.IpInfo = result.IpInfo ?? string.Empty;
|
|
||||||
}
|
|
||||||
await Task.CompletedTask;
|
await Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,7 +437,6 @@ public class ProfilesViewModel : MyReactiveObject
|
||||||
Speed = t33?.Speed ?? 0,
|
Speed = t33?.Speed ?? 0,
|
||||||
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay}" : string.Empty,
|
DelayVal = t33?.Delay != 0 ? $"{t33?.Delay}" : string.Empty,
|
||||||
SpeedVal = t33?.Speed > 0 ? $"{t33?.Speed}" : t33?.Message ?? string.Empty,
|
SpeedVal = t33?.Speed > 0 ? $"{t33?.Speed}" : t33?.Message ?? string.Empty,
|
||||||
IpInfo = t33?.IpInfo ?? string.Empty,
|
|
||||||
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
|
TodayDown = t22 == null ? "" : Utils.HumanFy(t22.TodayDown),
|
||||||
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
|
TodayUp = t22 == null ? "" : Utils.HumanFy(t22.TodayUp),
|
||||||
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
|
TotalDown = t22 == null ? "" : Utils.HumanFy(t22.TotalDown),
|
||||||
|
|
|
||||||
|
|
@ -33,12 +33,6 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<Button
|
|
||||||
x:Name="btnCheckOnly"
|
|
||||||
Width="100"
|
|
||||||
Margin="{StaticResource Margin4}"
|
|
||||||
Content="{x:Static resx:ResUI.menuCheckOnly}" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
x:Name="btnCheckUpdate"
|
x:Name="btnCheckUpdate"
|
||||||
Width="100"
|
Width="100"
|
||||||
|
|
@ -76,7 +70,7 @@
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{Binding CoreTypeForStorage}" />
|
Text="{Binding CoreType}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ public partial class CheckUpdateView : ReactiveUserControl<CheckUpdateViewModel>
|
||||||
this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckOnlyCmd, v => v.btnCheckOnly).DisposeWith(disposables);
|
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,13 +102,6 @@
|
||||||
|
|
||||||
<MenuItem x:Name="menuClose" Header="{x:Static resx:ResUI.menuExit}" />
|
<MenuItem x:Name="menuClose" Header="{x:Static resx:ResUI.menuExit}" />
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
<Button
|
|
||||||
x:Name="btnNewUpdate"
|
|
||||||
Margin="{StaticResource MarginLr8}"
|
|
||||||
HorizontalAlignment="Left"
|
|
||||||
Content="{x:Static resx:ResUI.menuNewUpdate}"
|
|
||||||
IsVisible="False" />
|
|
||||||
</DockPanel>
|
</DockPanel>
|
||||||
|
|
||||||
<view:StatusBarView DockPanel.Dock="Bottom" />
|
<view:StatusBarView DockPanel.Dock="Bottom" />
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||||
menuSettingsSetUWP.Click += MenuSettingsSetUWP_Click;
|
menuSettingsSetUWP.Click += MenuSettingsSetUWP_Click;
|
||||||
menuPromotion.Click += MenuPromotion_Click;
|
menuPromotion.Click += MenuPromotion_Click;
|
||||||
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||||
btnNewUpdate.Click += MenuCheckUpdate_Click;
|
|
||||||
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
||||||
menuClose.Click += MenuClose_Click;
|
menuClose.Click += MenuClose_Click;
|
||||||
|
|
||||||
|
|
@ -103,7 +102,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||||
|
|
||||||
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlNewUpdate, v => v.btnNewUpdate.IsVisible).DisposeWith(disposables);
|
|
||||||
|
|
||||||
switch (_config.UiItem.MainGirdOrientation)
|
switch (_config.UiItem.MainGirdOrientation)
|
||||||
{
|
{
|
||||||
|
|
@ -369,8 +367,6 @@ public partial class MainWindow : WindowBase<MainWindowViewModel>
|
||||||
{
|
{
|
||||||
_checkUpdateView ??= new CheckUpdateView();
|
_checkUpdateView ??= new CheckUpdateView();
|
||||||
DialogHost.Show(_checkUpdateView);
|
DialogHost.Show(_checkUpdateView);
|
||||||
|
|
||||||
AppEvents.HasUpdateNotified.Publish(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MenuBackupAndRestore_Click(object? sender, RoutedEventArgs e)
|
private void MenuBackupAndRestore_Click(object? sender, RoutedEventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -876,8 +876,7 @@
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Width="200"
|
Width="200"
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left" />
|
||||||
IsEditable="True" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="6"
|
Grid.Row="6"
|
||||||
|
|
|
||||||
|
|
@ -60,30 +60,30 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.Bind(ViewModel, vm => vm.LocalPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.UdpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.udpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.sniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.RouteOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.routeOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AllowLANConn, v => v.togAllowLANConn.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.allowLANConn, v => v.togAllowLANConn.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.NewPort4LAN, v => v.togNewPort4LAN.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.togNewPort4LAN.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.NewPort4LAN, v => v.txtuser.IsEnabled).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtuser.IsEnabled).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.NewPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.User, v => v.txtuser.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.user, v => v.txtuser.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Pass, v => v.txtpass.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.pass, v => v.txtpass.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.MuxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.muxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.LogEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Loglevel, v => v.cmbloglevel.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DefAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.defAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DefFingerprint, v => v.cmbdefFingerprint.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.defFingerprint, v => v.cmbdefFingerprint.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DefUserAgent, v => v.cmbdefUserAgent.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.defUserAgent, v => v.cmbdefUserAgent.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.BindInterface, v => v.txtbindInterface.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.bindInterface, v => v.txtbindInterface.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SendThrough, v => v.txtsendThrough.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.sendThrough, v => v.txtsendThrough.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Mux4SboxProtocol, v => v.cmbmux4SboxProtocol.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.mux4SboxProtocol, v => v.cmbmux4SboxProtocol.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableCacheFile4Sbox, v => v.togenableCacheFile4Sbox.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.enableCacheFile4Sbox, v => v.togenableCacheFile4Sbox.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.HyUpMbps, v => v.txtUpMbps.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.hyUpMbps, v => v.txtUpMbps.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.HyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.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);
|
||||||
|
|
@ -104,21 +104,21 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||||
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
|
||||||
this.Bind<OptionSettingViewModel, OptionSettingWindow, int, int>(ViewModel,
|
this.Bind<OptionSettingViewModel, OptionSettingWindow, int, int>(ViewModel,
|
||||||
vm => vm.MainGirdOrientation, view => view.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
|
vm => vm.MainGirdOrientation, view => view.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.NotProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SystemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SystemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CustomSystemProxyPacPath, v => v.txtCustomSystemProxyPacPath.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CustomSystemProxyPacPath, v => v.txtCustomSystemProxyPacPath.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CustomSystemProxyScriptPath, v => v.txtCustomSystemProxyScriptPath.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CustomSystemProxyScriptPath, v => v.txtCustomSystemProxyScriptPath.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.SelectedValue).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);
|
||||||
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);
|
||||||
|
|
@ -161,18 +161,29 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||||
|
|
||||||
private async Task<List<string>> GetFonts()
|
private async Task<List<string>> GetFonts()
|
||||||
{
|
{
|
||||||
await Task.CompletedTask;
|
|
||||||
|
|
||||||
var lstFonts = new List<string>();
|
var lstFonts = new List<string>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var lst = Avalonia.Media.FontManager.Current.SystemFonts
|
if (Utils.IsWindows())
|
||||||
.Select(t => t.Name)
|
{
|
||||||
.Where(t => t.IsNotEmpty())
|
return lstFonts;
|
||||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
}
|
||||||
.OrderBy(t => t)
|
else if (Utils.IsNonWindows())
|
||||||
.ToList();
|
{
|
||||||
return lst;
|
var result = await Utils.GetLinuxFontFamily("zh");
|
||||||
|
if (result.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return lstFonts;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lst = result.Split(Environment.NewLine)
|
||||||
|
.Where(t => t.IsNotEmpty())
|
||||||
|
.ToList()
|
||||||
|
.Select(t => t.Split(",").FirstOrDefault() ?? "")
|
||||||
|
.OrderBy(t => t)
|
||||||
|
.ToList();
|
||||||
|
return lst;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -185,7 +196,7 @@ public partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>
|
||||||
{
|
{
|
||||||
if (ViewModel != null)
|
if (ViewModel != null)
|
||||||
{
|
{
|
||||||
ViewModel.DestOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();
|
ViewModel.destOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -277,12 +277,6 @@
|
||||||
Header="{x:Static resx:ResUI.LvTestSpeed}"
|
Header="{x:Static resx:ResUI.LvTestSpeed}"
|
||||||
Tag="SpeedVal" />
|
Tag="SpeedVal" />
|
||||||
|
|
||||||
<DataGridTextColumn
|
|
||||||
Width="100"
|
|
||||||
Binding="{Binding IpInfo}"
|
|
||||||
Header="{x:Static resx:ResUI.LvTestIpInfo}"
|
|
||||||
Tag="IpInfo" />
|
|
||||||
|
|
||||||
<DataGridTextColumn
|
<DataGridTextColumn
|
||||||
Width="100"
|
Width="100"
|
||||||
Binding="{Binding TodayUp}"
|
Binding="{Binding TodayUp}"
|
||||||
|
|
|
||||||
|
|
@ -425,14 +425,10 @@ public partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>
|
||||||
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);
|
item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);
|
||||||
item2.DisplayIndex = displayIndex++;
|
item2.DisplayIndex = displayIndex++;
|
||||||
}
|
}
|
||||||
if (item.Name.StartsWith("to", StringComparison.CurrentCultureIgnoreCase))
|
if (item.Name.ToLower().StartsWith("to"))
|
||||||
{
|
{
|
||||||
item2.IsVisible = _config.GuiItem.EnableStatistics;
|
item2.IsVisible = _config.GuiItem.EnableStatistics;
|
||||||
}
|
}
|
||||||
if (item.Name.Equals("IpInfo", StringComparison.CurrentCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
item2.IsVisible = _config.SpeedTestItem.IPAPIUrl.IsNotEmpty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
<Grid
|
<Grid
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
ColumnDefinitions="Auto,Auto,*"
|
ColumnDefinitions="Auto,Auto,Auto"
|
||||||
DockPanel.Dock="Top"
|
DockPanel.Dock="Top"
|
||||||
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto">
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|
@ -66,8 +66,7 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbRuleTypeTips}"
|
Text="{x:Static resx:ResUI.TbRuleTypeTips}" />
|
||||||
TextWrapping="Wrap" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
|
|
@ -94,10 +93,7 @@
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Click="BtnSelectProfile_Click"
|
Click="BtnSelectProfile_Click"
|
||||||
Content="{x:Static resx:ResUI.TbSelectProfile}" />
|
Content="{x:Static resx:ResUI.TbSelectProfile}" />
|
||||||
<TextBlock
|
<TextBlock VerticalAlignment="Center" Text="{x:Static resx:ResUI.TbRuleOutboundTagTip}" />
|
||||||
VerticalAlignment="Center"
|
|
||||||
Text="{x:Static resx:ResUI.TbRuleOutboundTagTip}"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|
@ -119,8 +115,7 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbRuleMatchingTips}"
|
Text="{x:Static resx:ResUI.TbRuleMatchingTips}" />
|
||||||
TextWrapping="Wrap" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="4"
|
Grid.Row="4"
|
||||||
|
|
@ -140,8 +135,7 @@
|
||||||
Grid.Row="4"
|
Grid.Row="4"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center">
|
||||||
TextWrapping="Wrap">
|
|
||||||
<HyperlinkButton Classes="WithIcon" Click="linkRuleobjectDoc_Click">
|
<HyperlinkButton Classes="WithIcon" Click="linkRuleobjectDoc_Click">
|
||||||
<TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" />
|
<TextBlock Text="{x:Static resx:ResUI.TbRuleobjectDoc}" />
|
||||||
</HyperlinkButton>
|
</HyperlinkButton>
|
||||||
|
|
@ -166,8 +160,7 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbRoutingInboundTagTips}"
|
Text="{x:Static resx:ResUI.TbRoutingInboundTagTips}" />
|
||||||
TextWrapping="Wrap" />
|
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="6"
|
Grid.Row="6"
|
||||||
|
|
@ -188,8 +181,7 @@
|
||||||
Margin="{StaticResource Margin4}"
|
Margin="{StaticResource Margin4}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Text="{x:Static resx:ResUI.TbRoutingTips}"
|
Text="{x:Static resx:ResUI.TbRoutingTips}" />
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,6 @@
|
||||||
Margin="{StaticResource Margin8}"
|
Margin="{StaticResource Margin8}"
|
||||||
HorizontalAlignment="Left" />
|
HorizontalAlignment="Left" />
|
||||||
|
|
||||||
<Button
|
|
||||||
x:Name="btnCheckOnly"
|
|
||||||
Width="100"
|
|
||||||
Margin="{StaticResource Margin8}"
|
|
||||||
Content="{x:Static resx:ResUI.menuCheckOnly}"
|
|
||||||
Style="{StaticResource DefButton}" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
x:Name="btnCheckUpdate"
|
x:Name="btnCheckUpdate"
|
||||||
Width="100"
|
Width="100"
|
||||||
|
|
@ -84,7 +77,7 @@
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
Style="{StaticResource ListItemTitle}"
|
Style="{StaticResource ListItemTitle}"
|
||||||
Text="{Binding CoreTypeForStorage}" />
|
Text="{Binding CoreType}" />
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
Style="{StaticResource ListItemSubTitle}"
|
Style="{StaticResource ListItemSubTitle}"
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ public partial class CheckUpdateView
|
||||||
this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckOnlyCmd, v => v.btnCheckOnly).DisposeWith(disposables);
|
|
||||||
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -313,13 +313,6 @@
|
||||||
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
|
||||||
<ContentControl x:Name="pbTheme" />
|
<ContentControl x:Name="pbTheme" />
|
||||||
</materialDesign:PopupBox>
|
</materialDesign:PopupBox>
|
||||||
|
|
||||||
<Button
|
|
||||||
x:Name="btnNewUpdate"
|
|
||||||
Margin="{StaticResource MarginLeftRight8}"
|
|
||||||
Content="{x:Static resx:ResUI.menuNewUpdate}"
|
|
||||||
Style="{StaticResource DefButton}"
|
|
||||||
Visibility="Hidden" />
|
|
||||||
</ToolBar>
|
</ToolBar>
|
||||||
</ToolBarTray>
|
</ToolBarTray>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,6 @@ public partial class MainWindow
|
||||||
menuPromotion.Click += MenuPromotion_Click;
|
menuPromotion.Click += MenuPromotion_Click;
|
||||||
menuClose.Click += MenuClose_Click;
|
menuClose.Click += MenuClose_Click;
|
||||||
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
menuCheckUpdate.Click += MenuCheckUpdate_Click;
|
||||||
btnNewUpdate.Click += MenuCheckUpdate_Click;
|
|
||||||
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
menuBackupAndRestore.Click += MenuBackupAndRestore_Click;
|
||||||
|
|
||||||
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
ViewModel = new MainWindowViewModel(UpdateViewHandler);
|
||||||
|
|
@ -103,8 +102,6 @@ public partial class MainWindow
|
||||||
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
|
||||||
|
|
||||||
this.OneWayBind(ViewModel, vm => vm.BlNewUpdate, v => v.btnNewUpdate.Visibility).DisposeWith(disposables);
|
|
||||||
|
|
||||||
switch (_config.UiItem.MainGirdOrientation)
|
switch (_config.UiItem.MainGirdOrientation)
|
||||||
{
|
{
|
||||||
case EGirdOrientation.Horizontal:
|
case EGirdOrientation.Horizontal:
|
||||||
|
|
@ -366,8 +363,6 @@ public partial class MainWindow
|
||||||
{
|
{
|
||||||
_checkUpdateView ??= new CheckUpdateView();
|
_checkUpdateView ??= new CheckUpdateView();
|
||||||
DialogHost.Show(_checkUpdateView, "RootDialog");
|
DialogHost.Show(_checkUpdateView, "RootDialog");
|
||||||
|
|
||||||
AppEvents.HasUpdateNotified.Publish(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MenuBackupAndRestore_Click(object sender, RoutedEventArgs e)
|
private void MenuBackupAndRestore_Click(object sender, RoutedEventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -1141,7 +1141,6 @@
|
||||||
Width="200"
|
Width="200"
|
||||||
Margin="{StaticResource Margin8}"
|
Margin="{StaticResource Margin8}"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
IsEditable="True"
|
|
||||||
Style="{StaticResource DefComboBox}" />
|
Style="{StaticResource DefComboBox}" />
|
||||||
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
|
|
|
||||||
|
|
@ -57,30 +57,30 @@ public partial class OptionSettingWindow
|
||||||
|
|
||||||
this.WhenActivated(disposables =>
|
this.WhenActivated(disposables =>
|
||||||
{
|
{
|
||||||
this.Bind(ViewModel, vm => vm.LocalPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.UdpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.udpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.sniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.RouteOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.routeOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.AllowLANConn, v => v.togAllowLANConn.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.allowLANConn, v => v.togAllowLANConn.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.NewPort4LAN, v => v.togNewPort4LAN.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.togNewPort4LAN.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.NewPort4LAN, v => v.txtuser.IsEnabled).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtuser.IsEnabled).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.NewPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.User, v => v.txtuser.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.user, v => v.txtuser.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Pass, v => v.txtpass.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.pass, v => v.txtpass.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.MuxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.muxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.LogEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Loglevel, v => v.cmbloglevel.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DefAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.defAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DefFingerprint, v => v.cmbdefFingerprint.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.defFingerprint, v => v.cmbdefFingerprint.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.DefUserAgent, v => v.cmbdefUserAgent.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.defUserAgent, v => v.cmbdefUserAgent.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SendThrough, v => v.txtsendThrough.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.sendThrough, v => v.txtsendThrough.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.BindInterface, v => v.txtbindInterface.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.bindInterface, v => v.txtbindInterface.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.Mux4SboxProtocol, v => v.cmbmux4SboxProtocol.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.mux4SboxProtocol, v => v.cmbmux4SboxProtocol.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableCacheFile4Sbox, v => v.togenableCacheFile4Sbox.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.enableCacheFile4Sbox, v => v.togenableCacheFile4Sbox.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.HyUpMbps, v => v.txtUpMbps.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.hyUpMbps, v => v.txtUpMbps.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.HyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.EnableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);
|
||||||
|
|
||||||
//this.Bind(ViewModel, vm => vm.Kcpmtu, v => v.txtKcpmtu.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.Kcptti, v => v.txtKcptti.Text).DisposeWith(disposables);
|
||||||
|
|
@ -114,9 +114,9 @@ public partial class OptionSettingWindow
|
||||||
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.NotProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SystemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.SystemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);
|
||||||
this.Bind(ViewModel, vm => vm.CustomSystemProxyPacPath, v => v.txtCustomSystemProxyPacPath.Text).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.CustomSystemProxyPacPath, v => v.txtCustomSystemProxyPacPath.Text).DisposeWith(disposables);
|
||||||
|
|
||||||
this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);
|
this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);
|
||||||
|
|
@ -217,7 +217,7 @@ public partial class OptionSettingWindow
|
||||||
{
|
{
|
||||||
if (ViewModel != null)
|
if (ViewModel != null)
|
||||||
{
|
{
|
||||||
ViewModel.DestOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();
|
ViewModel.destOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -345,14 +345,6 @@
|
||||||
Binding="{Binding TodayUp}"
|
Binding="{Binding TodayUp}"
|
||||||
ExName="TodayUp"
|
ExName="TodayUp"
|
||||||
Header="{x:Static resx:ResUI.LvTodayUploadDataAmount}" />
|
Header="{x:Static resx:ResUI.LvTodayUploadDataAmount}" />
|
||||||
|
|
||||||
<base:MyDGTextColumn
|
|
||||||
x:Name="colIpInfo"
|
|
||||||
Width="100"
|
|
||||||
Binding="{Binding IpInfo}"
|
|
||||||
ExName="IpInfo"
|
|
||||||
Header="{x:Static resx:ResUI.LvTestIpInfo}" />
|
|
||||||
|
|
||||||
<base:MyDGTextColumn
|
<base:MyDGTextColumn
|
||||||
x:Name="colTodayDown"
|
x:Name="colTodayDown"
|
||||||
Width="100"
|
Width="100"
|
||||||
|
|
|
||||||
|
|
@ -378,14 +378,10 @@ public partial class ProfilesView
|
||||||
item2.Width = item.Width;
|
item2.Width = item.Width;
|
||||||
item2.DisplayIndex = displayIndex++;
|
item2.DisplayIndex = displayIndex++;
|
||||||
}
|
}
|
||||||
if (item.Name.StartsWith("to", StringComparison.CurrentCultureIgnoreCase))
|
if (item.Name.ToLower().StartsWith("to"))
|
||||||
{
|
{
|
||||||
item2.Visibility = _config.GuiItem.EnableStatistics ? Visibility.Visible : Visibility.Hidden;
|
item2.Visibility = _config.GuiItem.EnableStatistics ? Visibility.Visible : Visibility.Hidden;
|
||||||
}
|
}
|
||||||
if (item.Name.Equals("IpInfo", StringComparison.CurrentCultureIgnoreCase))
|
|
||||||
{
|
|
||||||
item2.Visibility = _config.SpeedTestItem.IPAPIUrl.IsNotEmpty() ? Visibility.Visible : Visibility.Hidden;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue