mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-28 05:56:52 +08:00
Compare commits
24
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0e757dc12 | ||
|
|
fcecb2c14c | ||
|
|
408911de4a | ||
|
|
23932298fc | ||
|
|
7c554190af | ||
|
|
2f2065e453 | ||
|
|
1480b5d4df | ||
|
|
9ae326ce9f | ||
|
|
3dd83886b8 | ||
|
|
3a1a256198 | ||
|
|
84f9ae5227 | ||
|
|
ce85b39328 | ||
|
|
6c23ac30a3 | ||
|
|
bbe9596d8d | ||
|
|
5c42a2336d | ||
|
|
afa4ad9e91 | ||
|
|
50a3c7624e | ||
|
|
b40dac00b9 | ||
|
|
35be6db96e | ||
|
|
35641d5c79 | ||
|
|
07f1a9f43b | ||
|
|
002e550149 | ||
|
|
b84fd825b3 | ||
|
|
1732c84606 |
@@ -997,6 +997,15 @@
|
||||
"Summary": "加速后自动唤起 Watt 加速器界面",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
},
|
||||
{
|
||||
"TypeName": "bool",
|
||||
"PropertyName": "ProxyBeforeDNSCheck",
|
||||
"DefaultValue": "true",
|
||||
"DefaultValueIsConst": true,
|
||||
"Summary": "加速前进行 DNS 可用性检查",
|
||||
"IsRegionOrEndregion": null,
|
||||
"IsValueType": null
|
||||
}
|
||||
],
|
||||
"Usings": ""
|
||||
|
||||
+1
-1
Submodule ref/DirectoryPackages updated: adcb50a330...8f5b07fa7e
+1
-1
Submodule ref/SteamClient updated: d276f9eefa...215ee80032
@@ -16,14 +16,14 @@ public static partial class AssemblyInfo
|
||||
/// <summary>
|
||||
/// 预览版本号,范围 1~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_preview = "9";
|
||||
const string ver_for_preview = "0";
|
||||
|
||||
/// <summary>
|
||||
/// RC 版本号,范围 0~9,只增不减
|
||||
/// </summary>
|
||||
const string ver_for_rc = "12";
|
||||
const string ver_for_rc = "14";
|
||||
|
||||
public const string FileVersion = $"{Version2}.{ver_for_rc}1{ver_for_preview}.0";
|
||||
public const string FileVersion = $"{Version2}.{ver_for_rc}2{ver_for_preview}.0";
|
||||
|
||||
//public const string InformationalVersion = Version;
|
||||
//public const string InformationalVersion = $"{Version}-preview.{ver_for_preview}";
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace Avalonia.Controls;
|
||||
public static class AvaloniaControlsInternalsWindowExtensions
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void CloseCore_(this Window window, WindowCloseReason reason, bool isProgrammatic) => window.CloseCore(reason, isProgrammatic);
|
||||
public static void CloseCore_(this Window window, WindowCloseReason reason, bool isProgrammatic, bool ignoreCancel) => window.CloseCore(reason, isProgrammatic, ignoreCancel);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void HandleResized_(this Window window, Size clientSize, WindowResizeReason reason) => window.HandleResized(clientSize, reason);
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
|
||||
{
|
||||
if (w.Owner is null)
|
||||
{
|
||||
w.CloseCore_(WindowCloseReason.ApplicationShutdown, isProgrammatic);
|
||||
w.CloseCore_(WindowCloseReason.ApplicationShutdown, isProgrammatic, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
<dict>
|
||||
<key>CFBundleName</key>
|
||||
<string>Watt Toolkit</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Watt Toolkit</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.0.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3.0.0.0</string>
|
||||
<string>3.0.1219.0</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
|
||||
@@ -175,6 +175,10 @@ partial class Program
|
||||
{
|
||||
RenderingMode = GetRenderingMode().ToArray(),
|
||||
});
|
||||
builder.With(new MacOSPlatformOptions
|
||||
{
|
||||
DisableDefaultApplicationMenuItems = true,
|
||||
});
|
||||
#elif LINUX
|
||||
builder.With(new X11PlatformOptions
|
||||
{
|
||||
|
||||
@@ -13,8 +13,16 @@ public sealed partial class App : Application
|
||||
|
||||
public App()
|
||||
{
|
||||
Name = AssemblyInfo.Trademark;
|
||||
OpenBrowserCommand = ReactiveCommand.Create<object?>(OpenBrowserCommandCore);
|
||||
CopyToClipboardCommand = ReactiveCommand.Create<object?>(CopyToClipboardCommandCore);
|
||||
#if MACOS
|
||||
var menus = new NativeMenu();
|
||||
menus.Add(new NativeMenuItem { Header = Strings.Settings, Command = ReactiveCommand.Create(() => { INavigationService.Instance.Navigate(typeof(SettingsPage)); }) });
|
||||
menus.Add(new NativeMenuItemSeparator());
|
||||
menus.Add(new NativeMenuItem { Header = Strings.Exit, Command = ReactiveCommand.Create(() => { Shutdown(); }) });
|
||||
NativeMenu.SetMenu(this, menus);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ms="https://steampp.net/settings"
|
||||
xmlns:sys="using:System"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls"
|
||||
x:CompileBindings="True">
|
||||
<Styles.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -39,6 +40,14 @@
|
||||
<Setter Property="FontFamily" Value="{Binding Source={x:Static ms:UISettings.FontName}, Path=Value, Mode=OneWay, Converter={StaticResource NameToFontFamilyConverter}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|FontIcon">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="ui|SymbolIcon">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
</Style>
|
||||
|
||||
<!--<Style Selector="TextBlock">
|
||||
<Setter Property="FontFamily" Value="{Binding Source={x:Static ms:UISettings.FontName}, Path=Value, Mode=OneWay, Converter={StaticResource NameToFontFamilyConverter}}" />
|
||||
</Style>-->
|
||||
|
||||
@@ -91,6 +91,12 @@
|
||||
CommandParameter="{Binding Data.AssemblyLocation}"
|
||||
Content="{Binding Path=Res.Plugin_OpenFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IsClickEnabled="True" />
|
||||
<ui:SettingsExpanderItem
|
||||
ActionIconSource="Open"
|
||||
Command="{Binding $parent[spp:Settings_Plugin].((spp:SettingsPageViewModel)DataContext).OpenPluginCacheDirectory_Click}"
|
||||
CommandParameter="{Binding Data.AppDataDirectory}"
|
||||
Content="{Binding Path=Res.Plugin_OpenAppDataFolder, Mode=OneWay, Source={x:Static s:ResourceService.Current}}"
|
||||
IsClickEnabled="True" />
|
||||
<ui:SettingsExpanderItem
|
||||
ActionIconSource="Open"
|
||||
Command="{Binding $parent[spp:Settings_Plugin].((spp:SettingsPageViewModel)DataContext).OpenPluginCacheDirectory_Click}"
|
||||
|
||||
+31
-16
@@ -48,26 +48,41 @@ sealed partial class YarpReverseProxyServiceImpl : ReverseProxyServiceImpl, IRev
|
||||
platformService,
|
||||
CertificateManager);
|
||||
|
||||
X509Certificate2? cer = CertificateManager.RootCertificatePackable;
|
||||
if (cer is not null && DateTime.Now <= cer.NotAfter && cer.NotAfter <= DateTime.Now.AddMonths(1))
|
||||
try
|
||||
{
|
||||
var interval = cer.NotAfter - DateTime.Now;
|
||||
|
||||
_certificateTimer = new System.Timers.Timer(interval)
|
||||
X509Certificate2? cer = CertificateManager.RootCertificatePackable;
|
||||
if (cer is not null &&
|
||||
DateTime.Now <= cer.NotAfter && cer.NotAfter <= DateTime.Now.AddMilliseconds(int.MaxValue))
|
||||
{
|
||||
AutoReset = false,
|
||||
};
|
||||
var interval = cer.NotAfter - DateTime.Now;
|
||||
|
||||
_certificateTimer.Elapsed += async (_, _) =>
|
||||
{
|
||||
ICertificateManager.Constants.CheckRootCertificate(
|
||||
platformService,
|
||||
CertificateManager);
|
||||
_certificateTimer = new System.Timers.Timer(interval)
|
||||
{
|
||||
AutoReset = false,
|
||||
};
|
||||
|
||||
await StopProxyAsync();
|
||||
await StartProxyImpl();
|
||||
};
|
||||
_certificateTimer.Start();
|
||||
_certificateTimer.Elapsed += async (_, _) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
ICertificateManager.Constants.CheckRootCertificate(
|
||||
platformService,
|
||||
CertificateManager);
|
||||
|
||||
await StopProxyAsync();
|
||||
await StartProxyImpl();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.LogAndShowT(TAG, msg: "CheckRootCertificate in Timer.Elapsed Error");
|
||||
}
|
||||
};
|
||||
_certificateTimer.Start();
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.LogAndShowT(TAG, msg: "CheckRootCertificate Error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -345,7 +345,8 @@ internal partial class NetworkTestService : INetworkTestService
|
||||
)
|
||||
{
|
||||
using UdpClient udpClient = new UdpClient(dnsServerIp, dnsServerPort);
|
||||
|
||||
udpClient.Client.SendTimeout = 3000;
|
||||
udpClient.Client.ReceiveTimeout = 3000;
|
||||
var query = new DnsQueryUdpRequest(testDomain, dnsRecordType);
|
||||
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
@@ -382,7 +383,7 @@ internal partial class NetworkTestService : INetworkTestService
|
||||
Proxy = HttpNoProxy.Instance,
|
||||
};
|
||||
using HttpClient client = new HttpClient(handler);
|
||||
|
||||
client.Timeout = TimeSpan.FromSeconds(3);
|
||||
string queryUrl = $"{dohServer}?name={testDomain}&type={dnsRecordType}";
|
||||
|
||||
Stopwatch watch = Stopwatch.StartNew();
|
||||
|
||||
@@ -307,6 +307,7 @@ public sealed partial class GameAcceleratorService
|
||||
Games.AddOrUpdate(CurrentAcceleratorGame);
|
||||
|
||||
//加速后
|
||||
TracepointHelper.TrackEvent("AcceleratorGameSuccess");
|
||||
Toast.Show(ToastIcon.Success, "加速成功");
|
||||
if (ProxySettings.AutoShowWattAcceleratorWindow.Value)
|
||||
{
|
||||
@@ -628,44 +629,45 @@ public sealed partial class GameAcceleratorService
|
||||
};
|
||||
var install = Ioc.Get<IAcceleratorService>().XY_Install(GameAcceleratorSettings.WattAcceleratorDirPath.Value!);
|
||||
|
||||
td.Opened += async (s, e) =>
|
||||
td.Opened += (s, e) =>
|
||||
{
|
||||
await foreach (var item in install)
|
||||
{
|
||||
if (item.HandleUI(out var content))
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case < 100:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"正在下载 {item.Content}%"; });
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Normal);
|
||||
break;
|
||||
case 100:
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Indeterminate);
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"下载完成,正在安装..."; });
|
||||
break;
|
||||
case (int)XunYouDownLoadCode.安装成功:
|
||||
//处理成功
|
||||
//Dispatcher.UIThread.Post(() => { td.Content = $"安装完成"; });
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
td.Hide();
|
||||
break;
|
||||
case int n when n > 101 && n < (int)XunYouDownLoadCode.启动安装程序失败:
|
||||
//处理失败
|
||||
break;
|
||||
// Code 和进度重叠 递进 1000 XunYouInstallOrStartCode.默认 XunYouInstallOrStartCode.已安装
|
||||
case 1000:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"默认"; });
|
||||
// XunYouInstallOrStartCode.默认
|
||||
break;
|
||||
case 1001:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"已安装"; });
|
||||
// XunYouInstallOrStartCode.已安装
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadCallbackAsync(td, install).Wait();
|
||||
//await foreach (var item in install)
|
||||
//{
|
||||
// if (item.HandleUI(out var content))
|
||||
// {
|
||||
// switch (content)
|
||||
// {
|
||||
// case < 100:
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"正在下载 {item.Content}%"; });
|
||||
// td.SetProgressBarState(item.Content, TaskDialogProgressState.Normal);
|
||||
// break;
|
||||
// case 100:
|
||||
// td.SetProgressBarState(item.Content, TaskDialogProgressState.Indeterminate);
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"下载完成,正在安装..."; });
|
||||
// break;
|
||||
// case (int)XunYouDownLoadCode.安装成功:
|
||||
// //处理成功
|
||||
// //Dispatcher.UIThread.Post(() => { td.Content = $"安装完成"; });
|
||||
// Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
// td.Hide();
|
||||
// break;
|
||||
// case int n when n > 101 && n < (int)XunYouDownLoadCode.启动安装程序失败:
|
||||
// //处理失败
|
||||
// break;
|
||||
// // Code 和进度重叠 递进 1000 XunYouInstallOrStartCode.默认 XunYouInstallOrStartCode.已安装
|
||||
// case 1000:
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"默认"; });
|
||||
// // XunYouInstallOrStartCode.默认
|
||||
// break;
|
||||
// case 1001:
|
||||
// Dispatcher.UIThread.Post(() => { td.Content = $"已安装"; });
|
||||
// // XunYouInstallOrStartCode.已安装
|
||||
// Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
};
|
||||
|
||||
//_ = Task.Run(() => { XunYouSDK.InstallAsync(progress, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "WattAccelerator")); });
|
||||
@@ -674,6 +676,47 @@ public sealed partial class GameAcceleratorService
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task DownloadCallbackAsync(TaskDialog td, IAsyncEnumerable<ApiRsp<int>> install)
|
||||
{
|
||||
await foreach (var item in install)
|
||||
{
|
||||
if (item.HandleUI(out var content))
|
||||
{
|
||||
switch (content)
|
||||
{
|
||||
case < 100:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"正在下载 {item.Content}%"; });
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Normal);
|
||||
break;
|
||||
case 100:
|
||||
td.SetProgressBarState(item.Content, TaskDialogProgressState.Indeterminate);
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"下载完成,正在安装..."; });
|
||||
break;
|
||||
case (int)XunYouDownLoadCode.安装成功:
|
||||
//处理成功
|
||||
//Dispatcher.UIThread.Post(() => { td.Content = $"安装完成"; });
|
||||
TracepointHelper.TrackEvent("DownloadInstallSuccess");
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
td.Hide();
|
||||
break;
|
||||
case int n when n > 101 && n < (int)XunYouDownLoadCode.启动安装程序失败:
|
||||
//处理失败
|
||||
break;
|
||||
// Code 和进度重叠 递进 1000 XunYouInstallOrStartCode.默认 XunYouInstallOrStartCode.已安装
|
||||
case 1000:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"默认"; });
|
||||
// XunYouInstallOrStartCode.默认
|
||||
break;
|
||||
case 1001:
|
||||
Dispatcher.UIThread.Post(() => { td.Content = $"已安装"; });
|
||||
// XunYouInstallOrStartCode.已安装
|
||||
Dispatcher.UIThread.Post(() => { td.Hide(TaskDialogStandardResult.OK); });
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async void UninstallAccelerator()
|
||||
{
|
||||
var xunYouIsInstall = await Ioc.Get<IAcceleratorService>().XY_IsInstall();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
using BD.WTTS.Helpers;
|
||||
using BD.WTTS.Services.Implementation;
|
||||
|
||||
namespace BD.WTTS.Services;
|
||||
|
||||
@@ -73,6 +74,18 @@ partial class ProxyService
|
||||
bool useDoh = ProxySettings.UseDoh.Value;
|
||||
string? customDohAddres = ProxySettings.CustomDohAddres2.Value;
|
||||
|
||||
if (ProxySettings.ProxyBeforeDNSCheck.Value)
|
||||
{
|
||||
if (useDoh)
|
||||
{
|
||||
customDohAddres = await GetFastestDNSAsync(ProxySettingsWindowViewModel.DohAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyDNS = await GetFastestDNSAsync(ProxySettingsWindowViewModel.ProxyDNSs.Skip(1));
|
||||
}
|
||||
}
|
||||
|
||||
Lazy<IPAddress> proxyIp_ = new(() => ReverseProxySettings.GetProxyIp(proxyIp));
|
||||
void SetProxyIp(IPAddress proxyIPAddress)
|
||||
{
|
||||
@@ -463,4 +476,69 @@ partial class ProxyService
|
||||
return proxyStatus;
|
||||
}
|
||||
}
|
||||
|
||||
async Task<(long delayMs, string dns)> GetValidDNSAsync(string dns, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var testDomain = "dnscheck-test.steampp.net";
|
||||
try
|
||||
{
|
||||
long delayMs;
|
||||
IPAddress[] address;
|
||||
if (ProxySettings.UseDoh.Value)
|
||||
{
|
||||
(delayMs, address) = await INetworkTestService.Instance.TestDNSOverHttpsAsync(testDomain, dns, cancellationToken: cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
(delayMs, address) = await INetworkTestService.Instance.TestDNSAsync(testDomain, dns, 53, cancellationToken: cancellationToken);
|
||||
}
|
||||
if (address.Length == 0)
|
||||
throw new Exception("Parsing failed. Return empty ip address.");
|
||||
|
||||
return (delayMs, dns);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(StartOrStopProxyService), ex.ToString(), "DNS检测出错");
|
||||
return (0, dns);
|
||||
}
|
||||
}
|
||||
|
||||
async Task<string?> GetFastestDNSAsync(IEnumerable<string> dnsAddresses, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||
var tasks = new List<Task<(long delayMs, string dns)>>();
|
||||
|
||||
foreach (var dns in dnsAddresses)
|
||||
{
|
||||
tasks.Add(GetValidDNSAsync(dns, cts.Token));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// 等待任意一个任务完成
|
||||
var completedTask = await Task.WhenAny(tasks);
|
||||
|
||||
// 获取任务结果
|
||||
var (delayMs, dns) = await completedTask;
|
||||
_ = cts.CancelAsync(); // 取消其他任务
|
||||
|
||||
// 如果任务成功完成(假设 delayMs > 0 表示成功)
|
||||
if (delayMs > 0)
|
||||
{
|
||||
return dns; // 返回第一个成功的 DNS 地址
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
// 任务被取消,忽略
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(StartOrStopProxyService), ex.ToString(), "DNS检测出错");
|
||||
}
|
||||
|
||||
// 如果没有有效结果,返回默认值
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -165,6 +165,11 @@ public partial interface IProxySettings
|
||||
/// </summary>
|
||||
bool AutoShowWattAcceleratorWindow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查
|
||||
/// </summary>
|
||||
bool ProxyBeforeDNSCheck { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 启用脚本自动检查更新的默认值
|
||||
/// </summary>
|
||||
@@ -290,4 +295,9 @@ public partial interface IProxySettings
|
||||
/// </summary>
|
||||
const bool DefaultAutoShowWattAcceleratorWindow = true;
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查的默认值
|
||||
/// </summary>
|
||||
const bool DefaultProxyBeforeDNSCheck = true;
|
||||
|
||||
}
|
||||
|
||||
@@ -209,6 +209,12 @@ public sealed partial class ProxySettings_ : IProxySettings, ISettings, ISetting
|
||||
[MPKey(24), MP2Key(24), JsonPropertyOrder(24)]
|
||||
public bool AutoShowWattAcceleratorWindow { get; set; } = IProxySettings.DefaultAutoShowWattAcceleratorWindow;
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查
|
||||
/// </summary>
|
||||
[MPKey(25), MP2Key(25), JsonPropertyOrder(25)]
|
||||
public bool ProxyBeforeDNSCheck { get; set; } = IProxySettings.DefaultProxyBeforeDNSCheck;
|
||||
|
||||
}
|
||||
|
||||
public static partial class ProxySettings
|
||||
@@ -383,4 +389,10 @@ public static partial class ProxySettings
|
||||
public static SettingsStructProperty<bool, ProxySettings_> AutoShowWattAcceleratorWindow { get; }
|
||||
= new(DefaultAutoShowWattAcceleratorWindow);
|
||||
|
||||
/// <summary>
|
||||
/// 加速前进行 DNS 可用性检查
|
||||
/// </summary>
|
||||
public static SettingsStructProperty<bool, ProxySettings_> ProxyBeforeDNSCheck { get; }
|
||||
= new(DefaultProxyBeforeDNSCheck);
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class AcceleratorPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.Welcome;
|
||||
public override string Name => Strings.CommunityFix;
|
||||
|
||||
[Reactive]
|
||||
public ReadOnlyCollection<ProxyDomainGroupViewModel>? EnableProxyDomainGroupVMs { get; set; }
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class GameAcceleratorPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.Welcome;
|
||||
public override string Name => Strings.GameAccelerator;
|
||||
|
||||
private readonly ReadOnlyObservableCollection<XunYouGameViewModel>? _Games;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public partial class ScriptPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.Welcome;
|
||||
public override string Name => Strings.ScriptConfig;
|
||||
|
||||
protected readonly ReadOnlyObservableCollection<ScriptDTO>? _ProxyScripts;
|
||||
|
||||
|
||||
@@ -88,6 +88,12 @@
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
|
||||
<ui:SettingsExpanderItem>
|
||||
<TextBlock Text="启动加速时检查 DNS 可用性" />
|
||||
<ui:SettingsExpanderItem.Footer>
|
||||
<ToggleSwitch Classes="LeftContent" IsChecked="{Binding Source={x:Static ms:ProxySettings.ProxyBeforeDNSCheck}, Path=Value, Mode=TwoWay}" />
|
||||
</ui:SettingsExpanderItem.Footer>
|
||||
</ui:SettingsExpanderItem>
|
||||
<!--<DockPanel>
|
||||
<Label Content="自定义根证书密码"></Label>
|
||||
<TextBox></TextBox>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ using BD.WTTS.UI.Views.Controls;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class ArchiSteamFarmPlusPageViewModel : ViewModelBase
|
||||
public sealed partial class ArchiSteamFarmPlusPageViewModel
|
||||
{
|
||||
|
||||
private readonly IArchiSteamFarmService asfService = IArchiSteamFarmService.Instance;
|
||||
|
||||
+3
-1
@@ -2,8 +2,10 @@ using ArchiSteamFarm.Steam;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class ArchiSteamFarmPlusPageViewModel
|
||||
public sealed partial class ArchiSteamFarmPlusPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => "ASF";
|
||||
|
||||
/// <summary>
|
||||
/// 选择 ASF 可执行文件路径
|
||||
/// </summary>
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ using BD.WTTS.UI.Views.Controls;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class AuthenticatorHomePageViewModel : ViewModelBase
|
||||
public sealed partial class AuthenticatorHomePageViewModel
|
||||
{
|
||||
const int MAX_SYNC_VALUE = 100;
|
||||
|
||||
|
||||
+3
-1
@@ -2,8 +2,10 @@ using KeyValuePair = BD.Common.Entities.KeyValuePair;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public partial class AuthenticatorHomePageViewModel
|
||||
public partial class AuthenticatorHomePageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.LocalAuth;
|
||||
|
||||
[Reactive]
|
||||
public bool IsLoading { get; set; }
|
||||
|
||||
|
||||
+45
-3
@@ -1,5 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System.Text.Json.Nodes;
|
||||
using AppResources = BD.WTTS.Client.Resources.Strings;
|
||||
|
||||
namespace BD.WTTS.Services.Implementation;
|
||||
@@ -82,7 +83,8 @@ public sealed class BasicPlatformSwitcher : IPlatformSwitcher
|
||||
var selector = accFile.Split("::")[2];
|
||||
if (!JTokenHelper.ReplaceVarInJsonFile(path, selector, jToken))
|
||||
{
|
||||
Toast.Show(ToastIcon.Error, AppResources.Error_ModifyJsonFileFailed);
|
||||
//Toast.Show(ToastIcon.Error, AppResources.Error_ModifyJsonFileFailed);
|
||||
Log.Error(nameof(BasicPlatformSwitcher), $"Failed to modify JSON file: {path}");
|
||||
//return false;
|
||||
}
|
||||
continue;
|
||||
@@ -179,7 +181,7 @@ public sealed class BasicPlatformSwitcher : IPlatformSwitcher
|
||||
{
|
||||
var path = uniqueIdFile.Split("::")[0];
|
||||
var selector = uniqueIdFile.Split("::")[1];
|
||||
JTokenHelper.ReplaceVarInJsonFile(path, selector, "");
|
||||
JTokenHelper.ReplaceVarInJsonFile(path, selector, string.Empty);
|
||||
}
|
||||
|
||||
if (platform.UniqueIdType != UniqueIdType.CREATE_ID_FILE) return true;
|
||||
@@ -514,7 +516,47 @@ public sealed class BasicPlatformSwitcher : IPlatformSwitcher
|
||||
if (js == null)
|
||||
continue;
|
||||
|
||||
var originalValue = js.SelectToken(selector);
|
||||
JToken? originalValue = null;
|
||||
|
||||
try
|
||||
{
|
||||
originalValue = js.SelectToken(selector);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(CurrnetUserAdd), ex, $"Failed to select token: {selector}");
|
||||
}
|
||||
|
||||
if (originalValue == null)
|
||||
{
|
||||
// 尝试以数组形式再次寻找
|
||||
try
|
||||
{
|
||||
var tokens = js.SelectTokens(selector);
|
||||
|
||||
//暂时将就写一个临时的战网处理方法解决问题
|
||||
if (platform.Platform == ThirdpartyPlatform.BattleNet)
|
||||
{
|
||||
originalValue = tokens.FirstOrDefault(x =>
|
||||
{
|
||||
var temp = x.Parent?.Parent?.Parent?.Parent?["Path"]?.Value<string>();
|
||||
var temp2 = platform.FolderPath;
|
||||
if (temp != null && temp2 != null)
|
||||
return string.Equals(
|
||||
temp.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar),
|
||||
temp2.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar),
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
originalValue ??= tokens.FirstOrDefault();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(nameof(CurrnetUserAdd), ex, $"Failed to select tokens: {selector}");
|
||||
}
|
||||
}
|
||||
|
||||
if (originalValue == null)
|
||||
continue;
|
||||
|
||||
|
||||
@@ -148,7 +148,10 @@
|
||||
"PlatformIds": [ "b", "bnet", "battlenet", "blizzard" ],
|
||||
"DefaultExePath": "%ProgramFiles(x86)%\\Battle.net\\Battle.net.exe",
|
||||
"ExesToEnd": [ "Battle.net" ],
|
||||
"ClearPaths": [ "SAME_AS_LOGIN_FILES" ],
|
||||
"ClearPaths": [
|
||||
"JSON_SELECT_FIRST,::%AppData%\\Battle.net\\Battle.net.config::$.Client.SavedAccountNames",
|
||||
"%AppData%\\Battle.net\\WattToolkit.id"
|
||||
],
|
||||
"LoginFiles": {
|
||||
"JSON_SELECT_FIRST,::%AppData%\\Battle.net\\Battle.net.config::$.Client.SavedAccountNames": "email.json",
|
||||
"JSON_SELECT_FIRST,::%AppData%\\Battle.net\\Battle.net.config::$..Services.LastLoginRegion": "LastLoginRegion",
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ public sealed partial class GameAccountPageViewModel : TabItemViewModel
|
||||
{
|
||||
static readonly Uri PlatformsPath = new("avares://BD.WTTS.Client.Plugins.GameAccount/UI/Assets/Platforms.json");
|
||||
|
||||
public override string Name => Strings.Welcome;
|
||||
public override string Name => Strings.UserFastChange;
|
||||
|
||||
[Reactive]
|
||||
public ObservableCollection<PlatformAccount>? GamePlatforms { get; set; }
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:i="using:Avalonia.Xaml.Interactivity"
|
||||
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ms="https://steampp.net/settings"
|
||||
xmlns:s="https://steampp.net/services"
|
||||
@@ -190,7 +188,15 @@
|
||||
</spp:AppItem.ActionButton>-->
|
||||
<spp:AppItem.Image>
|
||||
<Panel x:Name="ItemImage">
|
||||
<i:Interaction.Behaviors>
|
||||
<Panel.Styles>
|
||||
<Style Selector="Panel#ItemBox">
|
||||
<Setter Property="Opacity" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="Panel#ItemBox:pointerover">
|
||||
<Setter Property="Opacity" Value="0.8" />
|
||||
</Style>
|
||||
</Panel.Styles>
|
||||
<!--<i:Interaction.Behaviors>
|
||||
<ia:EventTriggerBehavior EventName="PointerEntered" SourceObject="{Binding #ItemImage}">
|
||||
<ia:ChangePropertyAction
|
||||
PropertyName="IsVisible"
|
||||
@@ -203,7 +209,7 @@
|
||||
TargetObject="{Binding #ItemBox}"
|
||||
Value="False" />
|
||||
</ia:EventTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
</i:Interaction.Behaviors>-->
|
||||
<Panel MinWidth="{Binding $parent[spp:AppItem].MinWidth}" MaxWidth="{Binding $parent[spp:AppItem].MaxWidth}">
|
||||
<spp:Image2
|
||||
Name="AppImage"
|
||||
@@ -247,11 +253,7 @@
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</Panel>
|
||||
<Panel
|
||||
x:Name="ItemBox"
|
||||
Background="{DynamicResource SolidBackgroundFillColorBaseBrush}"
|
||||
IsVisible="False"
|
||||
Opacity="0.8">
|
||||
<Panel x:Name="ItemBox" Background="{DynamicResource SolidBackgroundFillColorBaseBrush}">
|
||||
<Button
|
||||
Padding="0"
|
||||
HorizontalAlignment="Center"
|
||||
|
||||
@@ -8,7 +8,7 @@ using BD.WTTS.Helpers;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class IdleCardPageViewModel : ViewModelBase
|
||||
public sealed partial class IdleCardPageViewModel
|
||||
{
|
||||
readonly ISteamService SteamTool = ISteamService.Instance;
|
||||
readonly ISteamIdleCardService IdleCard = ISteamIdleCardService.Instance;
|
||||
|
||||
+3
-1
@@ -4,8 +4,10 @@ using BD.SteamClient.Services;
|
||||
|
||||
namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed partial class IdleCardPageViewModel
|
||||
public sealed partial class IdleCardPageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.SteamIdleCard;
|
||||
|
||||
/// <summary>
|
||||
/// 有限运行此游戏
|
||||
/// </summary>
|
||||
|
||||
+10
-1
@@ -124,7 +124,7 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 调整当前设备上共享的 Steam 账号优先级顺序,用于解决想玩账号 B 的共享却一直使用的是账号 A 的共享这种问题,拖拽操作从上到下的排序为共享库使用的优先级顺序,也可以选择暂时禁用或启用指定账号的共享。调整后保存重启 Steam 生效! 的本地化字符串。
|
||||
/// 查找类似 (因 Steam 已抛弃旧版本家庭共享 该功能已经失效!) 调整当前设备上共享的 Steam 账号优先级顺序,用于解决想玩账号 B 的共享却一直使用的是账号 A 的共享这种问题,拖拽操作从上到下的排序为共享库使用的优先级顺序,也可以选择暂时禁用或启用指定账号的共享。调整后保存重启 Steam 生效! 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string AccountChange_ShareManageAboutTips {
|
||||
get {
|
||||
@@ -5414,6 +5414,15 @@ namespace BD.WTTS.Client.Resources {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 打开插件 AppData 文件夹 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Plugin_OpenAppDataFolder {
|
||||
get {
|
||||
return ResourceManager.GetString("Plugin_OpenAppDataFolder", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 打开插件缓存文件夹 的本地化字符串。
|
||||
/// </summary>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2236,7 +2236,7 @@
|
||||
<value>修改的数据生效需要重启 Steam 是否需要重启 Steam。</value>
|
||||
</data>
|
||||
<data name="AccountChange_ShareManageAboutTips" xml:space="preserve">
|
||||
<value>调整当前设备上共享的 Steam 账号优先级顺序,用于解决想玩账号 B 的共享却一直使用的是账号 A 的共享这种问题,拖拽操作从上到下的排序为共享库使用的优先级顺序,也可以选择暂时禁用或启用指定账号的共享。调整后保存重启 Steam 生效!</value>
|
||||
<value>(因 Steam 已抛弃旧版本家庭共享 该功能已经失效!) 调整当前设备上共享的 Steam 账号优先级顺序,用于解决想玩账号 B 的共享却一直使用的是账号 A 的共享这种问题,拖拽操作从上到下的排序为共享库使用的优先级顺序,也可以选择暂时禁用或启用指定账号的共享。调整后保存重启 Steam 生效!</value>
|
||||
</data>
|
||||
<data name="CommunityFix_SubProcessFileNotExist" xml:space="preserve">
|
||||
<value>网络加速子进程文件不存在</value>
|
||||
@@ -2267,6 +2267,9 @@
|
||||
</data>
|
||||
<data name="Plugin_OpenCacheFolder" xml:space="preserve">
|
||||
<value>打开插件缓存文件夹</value>
|
||||
</data>
|
||||
<data name="Plugin_OpenAppDataFolder" xml:space="preserve">
|
||||
<value>打开插件 AppData 文件夹</value>
|
||||
</data>
|
||||
<data name="Plugin_OpenFolder" xml:space="preserve">
|
||||
<value>打开插件文件夹</value>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ namespace BD.WTTS.UI.ViewModels;
|
||||
|
||||
public sealed class PluginStorePageViewModel : TabItemViewModel
|
||||
{
|
||||
public override string Name => Strings.Welcome;
|
||||
public override string Name => Strings.Plugin_Store;
|
||||
|
||||
public override string IconKey => "avares://BD.WTTS.Client.Avalonia/UI/Assets/Icons/home.ico";
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
|
||||
<Deterministic>true</Deterministic>
|
||||
<CheckEolWorkloads>false</CheckEolWorkloads>
|
||||
<DefineConstants>REMOVE_DNS_INTERCEPT;$(DefineConstants)</DefineConstants>
|
||||
<!--<DefineConstants>REMOVE_DNS_INTERCEPT;$(DefineConstants)</DefineConstants>-->
|
||||
<CETCompat>false</CETCompat>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="..\AssemblyInfo.cs">
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('linux'))">net$(DotNet_Version)</TargetFrameworks>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">12.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('linux'))">$(TargetFrameworks)</TargetFrameworks>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">12.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('linux'))">net$(DotNet_Version)</TargetFrameworks>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">12.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net$(DotNet_Version)-windows10.0.19041</TargetFrameworks>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">12.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
|
||||
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
|
||||
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
|
||||
|
||||
Reference in New Issue
Block a user