Compare commits

..
39 Commits
Author SHA1 Message Date
Aigio Liu ef627692ef v2.8.3 rev.1
fix SettingsHost.Load
2022-08-15 12:32:18 +08:00
Aigio Liu 6f28ce0993 Get_Nullable remove throw 2022-08-15 12:17:07 +08:00
RMBGAME 2dbb13db87 #1888 #1897 2022-08-15 12:12:20 +08:00
Aigio Liu 40d3c0e669 Build Android versionCode="20220814" 2022-08-14 21:58:22 +08:00
RMBGAME 6be424dc5f ReverseProxyHttpClientHandler in Server 2022-08-14 16:57:49 +08:00
Aigio Liu 6babd615cd Use ReverseProxyHttpClientHandler in Server 2022-08-14 16:41:10 +08:00
Aigio Liu d1f266465b v2.8.3 rev.0 2022-08-14 16:01:31 +08:00
RMBGAME fccd8da9f6 添加asynclock尝试修复 asf启动时接收令牌输入卡死问题 2022-08-14 15:30:48 +08:00
Aigio Liu df2f84ff99 Remove ReverseProxyHttpClient userAgent 2022-08-14 15:06:28 +08:00
Aigio Liu d0bfbdbc77 Update ASF v5.2.8.4 2022-08-14 14:27:41 +08:00
RMBGAME 51e19bae95 Update Package 2022-08-14 04:54:54 +08:00
RMBGAME 5673bf2150 config bak 2022-08-14 04:49:57 +08:00
RMBGAME f5c66a353e PNA Support 2022-08-12 19:33:18 +08:00
RMBGAME 09dd6fe47e Misc 2022-08-11 18:43:28 +08:00
Aigio Liu 96471ccf27 #1875 explorer.exe full path 2022-08-11 14:26:22 +08:00
Aigio Liu 7b3f40da3b Update .NET Runtime 6.0.8/SDK 6.0.400 & VS 17.3 | Bump v2.8.3 2022-08-10 10:32:13 +08:00
Aigio Liu e369c6aa10 非简中默认隐藏加速与脚本仅在 Windows 上生效 2022-08-10 00:46:53 +08:00
Aigio Liu 5b4fcc2b8b revoke DBreeze 2022-08-10 00:36:57 +08:00
Aigio Liu 33c6f0d5f9 fix 2022-08-10 00:08:49 +08:00
RMBGAME 6abdb6dc11 Misc 2022-08-10 00:09:27 +08:00
RMBGAME a981d31ec4 修复可能导致内存泄漏的问题 2022-08-07 00:34:15 +08:00
Aigio Liu 8a0dd49e39 改进 查找脚本注入位置 2022-08-06 10:07:46 +08:00
Aigio Liu dc005a1a47 fix Release 2022-08-04 22:09:00 +08:00
Aigio Liu 5d69679073 fix Preferences 2022-08-04 19:20:08 +08:00
Aigio Liu 1030e15d8e 改进 InitTabItems,减少启动时间 2022-08-04 18:19:57 +08:00
Aigio Liu 48083a90d2 Use DBreeze Impl Preferences/SettingsHost
fix StringExtensions.Trim
2022-08-04 14:11:29 +08:00
Aigio Liu aab89668a9 fix nuget.config unix path 2022-08-03 18:50:17 +08:00
Aigio Liu a4a6f0e61d add nupkg 2022-08-03 18:19:19 +08:00
Aigio Liu a103ec141b fix Android Microsoft.Extensions.Primitives 6.X 2022-08-03 17:52:25 +08:00
ff m c23dc29e1c Mac证书安装 同步等待 2022-08-02 19:25:23 +08:00
Aigio Liu ddda4c0273 fix appcenter crashes 2022-08-02 19:17:56 +08:00
ff m cd1c1b91d7 CookieHttpClient.CookieContainer.Add Cookie
UserAgent.ParseAdd(context.Request.Headers.UserAgent)
2022-07-31 14:15:01 +08:00
Aigio Liu ce09385a52 Add CookieHttpClient(HttpLocalRequestMiddleware) 2022-07-31 13:09:20 +08:00
RMBGAME 8d6e83a42b Misc 2022-07-29 15:45:36 +08:00
RMBGAME b0a72ab23a 调整代理模式顺序 2022-07-29 15:44:38 +08:00
Aigio Liu b5f8910e2e fix SettingsHost.Load catch 2022-07-29 15:40:59 +08:00
Aigio Liu 881ff3fba9 Misc 2022-07-29 08:45:23 +08:00
Aigio Liu 8878d183a7 fix #1781 2022-07-29 07:57:20 +08:00
Aigio Liu 46f95574d1 fix Bridge & Release Windows Desktop Bridge v2.8.2 2022-07-28 13:37:48 +08:00
105 changed files with 2862 additions and 1617 deletions
+32 -28
View File
@@ -5,18 +5,18 @@
<PackageVersion Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.8" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcoreapp3.1'))">
<!-- Microsoft.Extensions.* & AspNetCore & EntityFrameworkCore(NETCOREAPP31) -->
@@ -80,6 +80,7 @@
<!--<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />-->
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.1" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="6.0.0" />
<PackageVersion Include="Microsoft.Net.Http.Headers" Version="2.2.255.255" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<!--<PackageVersion Include="CommunityToolkit.Mvvm" Version="7.1.2" />-->
<PackageVersion Include="System.Text.Encoding.CodePages" Version="6.0.0" />
@@ -113,7 +114,7 @@
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageVersion Include="nunit.xamarin" Version="3.6.1" />
<PackageVersion Include="PCLStorage" Version="1.0.2" />
<PackageVersion Include="Moq" Version="4.18.1" />
<PackageVersion Include="Moq" Version="4.18.2" />
<!-- NLog -->
<PackageVersion Include="NLog" Version="5.0.1" />
@@ -132,11 +133,11 @@
<PackageVersion Include="ReactiveUI.Maui" Version="18.3.1" />
<!-- SkiaSharp & HarfBuzzSharp -->
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/HarfBuzzSharp.props -->
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.1-preview.91" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.1-preview.91" />
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.1-preview.104" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.1-preview.104" />
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/SkiaSharp.props -->
<PackageVersion Include="SkiaSharp" Version="2.88.1-preview.91" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1-preview.91" />
<PackageVersion Include="SkiaSharp" Version="2.88.1-preview.104" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1-preview.104" />
<!-- AutoMapper -->
<PackageVersion Include="AutoMapper" Version="11.0.1" />
@@ -192,7 +193,7 @@
<PackageVersion Include="NPOI" Version="2.5.6" />
<!-- Github API -->
<PackageVersion Include="Octokit" Version="1.0.0" />
<PackageVersion Include="Octokit" Version="2.0.0" />
<!-- ORM -->
<PackageVersion Include="sqlite-net-pcl" Version="1.8.116" />
@@ -250,7 +251,7 @@
<!--<PackageVersion Include="CefNet.Avalonia" Version="93.1.21240.857" />-->
<!--<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.5.1" />-->
<!--<PackageVersion Include="FluentAvaloniaUI" Version="1.4.1" />-->
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-beta.330" />
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-beta.350" />
<PackageVersion Include="JumpLists.Win32.Avalonia" Version="1.0.0" />
<PackageVersion Include="Avalonia.Native" Version="0.10.17" />
<PackageVersion Include="Avalonia.Win32" Version="0.10.17" />
@@ -260,7 +261,7 @@
<!--Avalonia End-->
<!-- Xamarin.Android -->
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.2" />
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.3" />
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.40.5" />
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="116.1.2.5" />
<PackageVersion Include="Plugin.CurrentActivity" Version="2.1.0.4" />
@@ -274,29 +275,29 @@
<!-- V2Ray -->
<PackageVersion Include="XAB.AndroidLibV2rayLite" Version="1.0.0.1" />
<!--<PackageVersion Include="Karamunting.KotlinX.Coroutines.Core" Version="1.4.2" />-->
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.2.1" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.2.1" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.4" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.4" />
<PackageVersion Include="Xamarin.Android.ReactiveX.RxJava3.RxJava" Version="3.1.5.1" />
<!-- Xamarin.AndroidX -->
<PackageVersion Include="Xamarin.AndroidX.Migration" Version="1.0.10" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.4.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Emoji.AppCompat" Version="1.1.0.9" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.4.1.2" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.5.1" />
<PackageVersion Include="Xamarin.AndroidX.RecyclerView" Version="1.2.1.7" />
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.6.1.1" />
<PackageVersion Include="Xamarin.AndroidX.SwipeRefreshLayout" Version="1.1.0.9" />
<PackageVersion Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.4.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.4.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.4.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.5.1" />
<PackageVersion Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.16" />
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.4.0.4" />
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Biometric" Version="1.1.0.10" />
<PackageVersion Include="Xamarin.AndroidX.ExifInterface" Version="1.3.3.6" />
<PackageVersion Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.15" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.4.1.2" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.1.0-beta02" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.1.0-beta02" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.1.0" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.1.0" />
<PackageVersion Include="Xamarin.AndroidX.Camera.View" Version="1.1.0-beta02" />
<!--<PackageVersion Include="Xamarin.AndroidX.Window" Version="1.0.0.9" />-->
<PackageVersion Include="Xamarin.AndroidX.WebKit" Version="1.4.0.8" />
@@ -322,5 +323,8 @@
<!-- ArchiSteamFarm -->
<PackageVersion Include="ArchiSteamFarm.Library" Version="5.2.6.3-preview.220608" />
<!-- DBreeze(key value store embedded) -->
<PackageVersion Include="DBreeze" Version="1.107.0" />
</ItemGroup>
</Project>
+5
View File
@@ -0,0 +1,5 @@
<configuration>
<packageSources>
<add key="LocalNuGetPackages" value="./references/NuGetPackages" />
</packageSources>
</configuration>
+2 -66
View File
@@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Root", "_Root", "{66839CD8
download-guide.md = download-guide.md
global.json = global.json
packaging\Info.plist = packaging\Info.plist
NuGet.Config = NuGet.Config
packaging\package.net472.ps1 = packaging\package.net472.ps1
README.en.md = README.en.md
README.md = README.md
@@ -173,8 +174,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gameloop.Vdf", "references\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.Shadowsocks", "src\ST.Client.Android.Shadowsocks\ST.Client.Android.Shadowsocks.csproj", "{920EF29F-406F-43A9-B002-29DD6B0B4FBF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.App.Modern", "src\ST.Client.Android.App.Modern\ST.Client.Android.App.Modern.csproj", "{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ResSecrets", "ResSecrets", "{17667B53-1A09-45A6-855A-0F07F9AE044F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.ResSecrets", "src\ST.Client.Android.ResSecrets\ST.Client.Android.ResSecrets.csproj", "{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}"
@@ -189,8 +188,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Windows.ResSecret
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Avalonia.Desktop\Avalonia.Desktop.csproj", "{FA9F0E89-E410-400A-86F3-C603E51E62A8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Avalonia.App.MsixPackage", "src\ST.Client.Desktop.Avalonia.App.Bridge2\ST.Client.Avalonia.App.MsixPackage.csproj", "{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FDELauncher", "src\FDELauncher\FDELauncher.csproj", "{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Http.Headers", "src\Microsoft.Net.Http.Headers\Microsoft.Net.Http.Headers.csproj", "{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0}"
@@ -1937,36 +1934,6 @@ Global
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x64.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x86.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x86.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM64.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhone.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x64.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x64.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x86.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x86.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.Deploy.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM64.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM64.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhone.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhone.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x64.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x64.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x86.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x86.Build.0 = Release|Any CPU
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -2135,36 +2102,6 @@ Global
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x64.Build.0 = Release|Any CPU
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x86.ActiveCfg = Release|Any CPU
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x86.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|Any CPU.ActiveCfg = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|Any CPU.Build.0 = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM.Build.0 = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM64.ActiveCfg = Debug|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM64.Build.0 = Debug|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhone.Build.0 = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.ActiveCfg = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.Build.0 = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.Deploy.0 = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x86.ActiveCfg = Debug|x86
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x86.Build.0 = Debug|x86
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|Any CPU.ActiveCfg = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|Any CPU.Build.0 = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM.ActiveCfg = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM64.ActiveCfg = Release|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM64.Build.0 = Release|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhone.ActiveCfg = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhone.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.ActiveCfg = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.Build.0 = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.Deploy.0 = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x86.ActiveCfg = Release|x86
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x86.Build.0 = Release|x86
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -2733,7 +2670,6 @@ Global
{48417EE3-BACB-4E04-B48D-B3781862AD81} = {8E38AAF2-8C7D-4B0D-AB25-AB37EECB4029}
{41434AB5-48C3-47D4-8721-D118D87F472B} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{07C9AC06-5D84-41AB-A3C9-5C5B1A27F526} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{5C440EC2-9251-4DB5-A14E-68FF37814F12} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{1891DD14-628D-4921-8A1E-279320312E95} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
{3381B512-7CCB-4211-87B0-273260531BFC} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
{CCB0CAEB-FEFC-4424-B6F4-53D3BB70154D} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
@@ -2746,7 +2682,7 @@ Global
{8C996C50-B29F-4CB6-90A7-77C9CD3B0B70} = {910D6A0F-42AB-4B65-B532-852E864EC006}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
RESX_NeutralResourcesLanguage = zh-Hans
SolutionGuid = {9313F2B4-10DA-43AA-A481-CAA7571C740C}
RESX_NeutralResourcesLanguage = zh-Hans
EndGlobalSection
EndGlobal
+2 -2
View File
@@ -7,9 +7,9 @@
<key>CFBundleIdentifier</key>
<string>net.steampp.app</string>
<key>CFBundleShortVersionString</key>
<string>2.8.2</string>
<string>2.8.3</string>
<key>CFBundleVersion</key>
<string>2.8.2.0</string>
<string>2.8.3.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
<key>CFBundleDevelopmentRegion</key>
Binary file not shown.
+33 -30
View File
@@ -3,25 +3,28 @@
2. 因经济状况原因,现已停止短信服务节约开销,后续会推出邮箱注册登录,对于仅使用手机号登录的用户请绑定第三方快速登录,否则注销后将无法再次登录,需要等待至邮箱服务推出后支持会暂时在开放短信服务提供换绑邮箱。
3. 自动更新目前仅 Windows 端可用,且由于下载渠道限速可能导致无法更新成功,推荐在官网链接的网盘或群文件中下载压缩包解压覆盖更新(应用商店版由商店更新不受此影响)
4. 在 Android 上因系统限制,目前的加速功能无法正常使用,所以此功能已放弃继续开发,如仍想使用需要自行导入证书到系统目录,使用 adb 工具或 Magisk 之类的软件操作,未来会使用不需要证书的加速功能替换此功能
5. fde 版本需要安装 [ASP.NET Core 运行时 6.0.7 (x64) 与 .NET Core 运行时 6.0.7 (x64)](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)
5. fde 版本需要安装 [ASP.NET Core 运行时 6.0.8 (x64) 与 .NET Core 运行时 6.0.8 (x64)](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)
6. Windows x86 与 x64 版本令牌本机加密互不兼容,使用两者版本时注意令牌加密后的文件不能共用。
7. 由于新版本加速功能重构,调整了部分加速项目,这会影响旧版本程序使用加速功能
8. 为了能继续维持开发,从此版本开始将会添加程序内广告,赞助用户可以在设置中关闭所有广告
### 版本亮点
1. 修复与改进一些已知问题
1. .NET 运行时升级至 6.0.8,使用 fde 版本需要升级运行时
2. ASF 升级至 V5.2.8.4
### 修复问题
1. 修复 Windows FDE 版在 Windows 8.1/10 上错误识别成 Windows 8
2. 修复 网络加速 DNS 设置无效
3. 修复 网络加速 PAC 代理模式不能正常工作
4. 修复 Windows 7 上的一些兼容性问题导致加速失效
5. 改进 Windows Desktop Bridge 版本中不再弹出防火墙规则授权弹窗
6. 修复 Windows Desktop Bridge 版本开机自启静默失效
7. 改进 DNS 驱动拦截模式停止后不再占用 sys 文件
8. 改进 通知 UI 列表项中仅显示两行文字
9. 修复 第三方快速登录失败
10. 改进 关闭代理时仅根据当前代理模式进行清理
1. 修复 2.8.0 ~ 2.8.2 中 AppData/Config.mpo 文件大小为 0 时导致的程序无法正常启动
2. 修复 Windows 上版本更新在 2.8.0 ~ 2.8.2 中非 FDE 版本识别为 FDE 版
3. 改进 调整代理模式顺序,Hosts 模式置顶
4. 修复 划词翻译等一些 JS 脚本
5. 改进 macOS 上的证书安装
6. 尝试修复 网络加速中能导致内存泄露的问题
7. 改进 非简中默认隐藏加速与脚本仅在 Windows 上生效
8. 改进 减少 Android 上的启动时间
9. 修复 退出程序时可能引发的闪退
10. 修复 macOS/Linux 上设置页面打不开的问题
11. 修复 网络加速中网页上出现 Because https://... actually points to WattToolkit itself...
12. 尝试修复 ASF 控制台中输入时卡死
<!--
@@ -58,7 +61,7 @@
[![WebSite steampp.net](https://img.shields.io/badge/WebSite-steampp.net-brightgreen.svg?style=flat-square&color=61dafb)](https://steampp.net)
[![Steam++ v2.8.2](https://img.shields.io/badge/Steam++-v2.8.2-brightgreen.svg?style=flat-square&color=512bd4)]()
[![Steam++ v2.8.3](https://img.shields.io/badge/Steam++-v2.8.3-brightgreen.svg?style=flat-square&color=512bd4)]()
##### [不知道该下载哪个文件?](./download-guide.md)
@@ -67,28 +70,28 @@
### 文件校验
| File | Checksum (SHA256) |
| ---- | ---- |
| Steam++_win_x64_v2.8.2.7z | SHA256 |
| Steam++_win_x64_fde_v2.8.2.7z | SHA256 |
| Steam++_win_x64_v2.8.3.7z | SHA256 |
| Steam++_win_x64_fde_v2.8.3.7z | SHA256 |
| | |
| Steam++_win_x64_v2.8.2.exe | SHA256 |
| Steam++_win_x64_fde_v2.8.2.exe | SHA256 |
| Steam++_win_x64_v2.8.3.exe | SHA256 |
| Steam++_win_x64_fde_v2.8.3.exe | SHA256 |
| | |
| Steam++_win_x86_v2.8.2.7z | SHA256 |
| Steam++_win_x86_fde_v2.8.2.7z | SHA256 |
| Steam++_win_x86_v2.8.3.7z | SHA256 |
| Steam++_win_x86_fde_v2.8.3.7z | SHA256 |
| | |
| Steam++_win_x86_v2.8.2.exe | SHA256 |
| Steam++_win_x86_fde_v2.8.2.exe | SHA256 |
| Steam++_win_x86_v2.8.3.exe | SHA256 |
| Steam++_win_x86_fde_v2.8.3.exe | SHA256 |
| | |
| Steam++_linux_x64_v2.8.2.7z | SHA256 |
| Steam++_linux_arm64_v2.8.2.7z | SHA256 |
| Steam++_linux_x64_v2.8.3.7z | SHA256 |
| Steam++_linux_arm64_v2.8.3.7z | SHA256 |
| | |
| Steam++_linux_x64_v2.8.2.deb | SHA256 |
| Steam++_linux_arm64_v2.8.2.deb | SHA256 |
| Steam++_linux_x64_v2.8.3.deb | SHA256 |
| Steam++_linux_arm64_v2.8.3.deb | SHA256 |
| | |
| Steam++_linux_x64_v2.8.2.rpm | SHA256 |
| Steam++_linux_arm64_v2.8.2.rpm | SHA256 |
| Steam++_linux_x64_v2.8.3.rpm | SHA256 |
| Steam++_linux_arm64_v2.8.3.rpm | SHA256 |
| | |
| Steam++_macos_x64_v2.8.2.dmg | SHA256 |
| Steam++_macos_arm64_v2.8.2.dmg | SHA256 |
| Steam++_macos_x64_v2.8.3.dmg | SHA256 |
| Steam++_macos_arm64_v2.8.3.dmg | SHA256 |
| | |
| Steam++_android_v2.8.2.apk | SHA256 |
| Steam++_android_v2.8.3.apk | SHA256 |
@@ -0,0 +1,219 @@
// https://github.com/AvaloniaUI/Avalonia/blob/0.10.17/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.Threading;
namespace Avalonia.Controls.ApplicationLifetimes
{
sealed class ClassicDesktopStyleApplicationLifetime2 : IClassicDesktopStyleApplicationLifetime, IDisposable
{
private int _exitCode;
private CancellationTokenSource? _cts;
private bool _isShuttingDown;
private HashSet<Window> _windows = new();
private static ClassicDesktopStyleApplicationLifetime2? _activeLifetime;
static ClassicDesktopStyleApplicationLifetime2()
{
Window.WindowOpenedEvent.AddClassHandler(typeof(Window), OnWindowOpened);
Window.WindowClosedEvent.AddClassHandler(typeof(Window), WindowClosedEvent);
}
private static void WindowClosedEvent(object sender, RoutedEventArgs e)
{
_activeLifetime?._windows.Remove((Window)sender);
_activeLifetime?.HandleWindowClosed((Window)sender);
}
private static void OnWindowOpened(object sender, RoutedEventArgs e)
{
_activeLifetime?._windows.Add((Window)sender);
}
public ClassicDesktopStyleApplicationLifetime2()
{
if (_activeLifetime != null)
throw new InvalidOperationException(
"Can not have multiple active ClassicDesktopStyleApplicationLifetime instances and the previously created one was not disposed");
_activeLifetime = this;
}
/// <inheritdoc/>
public event EventHandler<ControlledApplicationLifetimeStartupEventArgs>? Startup;
/// <inheritdoc/>
public event EventHandler<ShutdownRequestedEventArgs>? ShutdownRequested;
/// <inheritdoc/>
public event EventHandler<ControlledApplicationLifetimeExitEventArgs>? Exit;
/// <summary>
/// Gets the arguments passed to the AppBuilder Start method.
/// </summary>
public string[]? Args { get; set; }
/// <inheritdoc/>
public ShutdownMode ShutdownMode { get; set; }
/// <inheritdoc/>
public Window? MainWindow { get; set; }
public IReadOnlyList<Window> Windows => _windows.ToList();
private void HandleWindowClosed(Window window)
{
if (window == null)
return;
if (_isShuttingDown)
return;
if (ShutdownMode == ShutdownMode.OnLastWindowClose && _windows.Count == 0)
TryShutdown();
else if (ShutdownMode == ShutdownMode.OnMainWindowClose && ReferenceEquals(window, MainWindow))
TryShutdown();
}
public void Shutdown(int exitCode = 0)
{
DoShutdown(new ShutdownRequestedEventArgs(), true, exitCode);
}
public bool TryShutdown(int exitCode = 0)
{
return DoShutdown(new ShutdownRequestedEventArgs(), false, exitCode);
}
public int Start(string[] args)
{
Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args));
var options = AvaloniaLocator.Current.GetService<ClassicDesktopStyleApplicationLifetimeOptions>();
if (options != null && options.ProcessUrlActivationCommandLine && args.Length > 0)
{
if (Application.Current is IApplicationPlatformEvents events)
{
events.RaiseUrlsOpened(args);
}
}
var lifetimeEvents = AvaloniaLocator.Current.GetService<IPlatformLifetimeEventsImpl>();
if (lifetimeEvents != null)
lifetimeEvents.ShutdownRequested += OnShutdownRequested;
_cts = new CancellationTokenSource();
// Note due to a bug in the JIT we wrap this in a method, otherwise MainWindow
// gets stuffed into a local var and can not be GCed until after the program stops.
// this method never exits until program end.
ShowMainWindow();
Dispatcher.UIThread.MainLoop(_cts.Token);
Environment.ExitCode = _exitCode;
return _exitCode;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void ShowMainWindow()
{
MainWindow?.Show();
}
public void Dispose()
{
if (_activeLifetime == this)
_activeLifetime = null;
}
private bool DoShutdown(ShutdownRequestedEventArgs e, bool force = false, int exitCode = 0)
{
if (!force)
{
ShutdownRequested?.Invoke(this, e);
if (e.Cancel)
return false;
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/3780037517u/overview
// ClassicDesktopStyleApplicationLifetime.DoShutdown (ShutdownRequestedEventArgs e, Boolean force, Int32 exitCode) /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs, line 147
// System.InvalidOperationException: Application is already shutting down.
// v2.8.2 | 73 users | 76 reports
// Exception Stack:
// System.InvalidOperationException: Application is already shutting down.
// at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.DoShutdown(ShutdownRequestedEventArgs e, Boolean force, Int32 exitCode) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 147
// at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.OnShutdownRequested(Object sender, ShutdownRequestedEventArgs e) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 186
// at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam) in /_/src/Windows/Avalonia.Win32/Win32Platform.cs:line 283
if (_isShuttingDown)
// throw new InvalidOperationException("Application is already shutting down.");
return true;
}
_exitCode = exitCode;
_isShuttingDown = true;
try
{
// When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel
// shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their
// owners.
foreach (var w in Windows)
{
if (w.Owner is null)
{
w.Close();
}
}
if (!force && Windows.Count > 0)
{
e.Cancel = true;
return false;
}
var args = new ControlledApplicationLifetimeExitEventArgs(exitCode);
Exit?.Invoke(this, args);
_exitCode = args.ApplicationExitCode;
}
finally
{
_cts?.Cancel();
_cts = null;
_isShuttingDown = false;
}
return true;
}
private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e);
}
}
namespace Avalonia
{
public static class ClassicDesktopStyleApplicationLifetimeExtensions
{
public static int StartWithClassicDesktopLifetime2<T>(
this T builder, string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
where T : AppBuilderBase<T>, new()
{
var lifetime = new ClassicDesktopStyleApplicationLifetime2()
{
Args = args,
ShutdownMode = shutdownMode,
};
builder.SetupWithLifetime(lifetime);
return lifetime.Start(args);
}
}
}
@@ -11,11 +11,22 @@ namespace System.Application;
/// </summary>
public static class MainThread2
{
static IMainThreadPlatformService? mInterface;
static IMainThreadPlatformService Interface
{
get
{
if (mInterface == null) mInterface = IMainThreadPlatformService.Instance;
return mInterface;
}
}
/// <summary>
/// 获取当前是否为主线程。
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsMainThread() => IMainThreadPlatformService.Instance.PlatformIsMainThread;
public static bool IsMainThread() => Interface.PlatformIsMainThread;
/// <summary>
/// 调用应用程序主线程上的操作。
@@ -33,7 +44,7 @@ public static class MainThread2
{
try
{
IMainThreadPlatformService.Instance.PlatformBeginInvokeOnMainThread(action, priority);
Interface.PlatformBeginInvokeOnMainThread(action, priority);
}
catch (InvalidOperationException)
{
@@ -1,6 +1,7 @@
using SQLite;
using System.Application.Entities;
using System.Application.Repositories;
using System.Application.Settings;
using System.Diagnostics;
using System.Globalization;
using SQLiteNotNull = SQLite.NotNullAttribute;
@@ -8,8 +9,13 @@ using SQLiteTable = SQLite.TableAttribute;
namespace System.Application.Services.Implementation;
internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatformService
#if DBREEZE
partial class PreferencesPlatformServiceImplV2
#else
sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatformService
#endif
{
#if !DBREEZE
readonly SQLiteConnection conn;
public PreferencesPlatformServiceImpl()
@@ -17,9 +23,9 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
conn = Repository.GetDbConnectionSync<Entity>();
}
static string GetId(string key) => $"{key}_K";
internal static string GetId(string key) => $"{key}_K";
static string GetId(string key, string? sharedName)
internal static string GetId(string key, string? sharedName)
{
if (sharedName == null) return GetId(key);
return $"{key}_{sharedName}_S";
@@ -75,12 +81,14 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
});
}
}
#endif
const string TableName = "1984415E";
const string ColumnName_Id = "0F5E4BAA";
const string ColumnName_Value = "4FC331D7";
const string ColumnName_SharedName = "F6A739AA";
#if !DBREEZE
const string Sql_Delete_Where_SharedName_Equals =
$"DELETE FROM \"{TableName}\" WHERE \"{ColumnName_SharedName}\" = ?";
@@ -101,12 +109,12 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
//const string Sql_Select_Value_Where_Key_Equals_And_SharedName_Equals =
// $"SELECT \"{ColumnName_Value}\" FROM \"{TableName}\" WHERE \"{ColumnName_Id}\" = ? AND \"{ColumnName_SharedName}\" = ?";
#endif
[SQLiteTable(TableName)]
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public sealed class Entity : IEntity<string>
{
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
[Column(ColumnName_Id)]
[PrimaryKey]
[SQLiteNotNull]
@@ -115,7 +123,6 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
[Column(ColumnName_Value)]
[SQLiteNotNull]
public string Value { get; set; } = string.Empty;
#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
[Column(ColumnName_SharedName)]
[SQLiteNotNull]
@@ -124,3 +131,121 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
string DebuggerDisplay() => SharedName == string.Empty ? $"{Id}, {Value}" : $"{Id}, {Value}, {SharedName}";
}
}
#if DBREEZE
public sealed partial class PreferencesPlatformServiceImplV2 : IPreferencesGenericPlatformService
{
static string GetTableName(string? sharedName) => $"Preferences.{sharedName}";
public void PlatformSet<T>(string key, T? value, string? sharedName) where T : notnull, IConvertible
{
if (value == null)
{
PlatformRemove(key, sharedName);
}
else
{
using var t = SettingsProviderV3.Provider.GetTransaction();
t.Insert(GetTableName(sharedName), key, value.ToString(CultureInfo.InvariantCulture));
t.Commit();
}
}
public void PlatformClear(string? sharedName)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
t.RemoveAllKeys(GetTableName(sharedName), true);
t.Commit();
}
public bool PlatformContainsKey(string key, string? sharedName)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
var row = t.Select<string, string>(GetTableName(sharedName), key);
if (row == null) return false;
return row.Exists;
}
public T? PlatformGet<T>(string key, T? defaultValue, string? sharedName) where T : notnull, IConvertible
{
using var t = SettingsProviderV3.Provider.GetTransaction();
var row = t.Select<string, string>(GetTableName(sharedName), key);
if (row == null || !row.Exists) return defaultValue;
var value = ConvertibleHelper.Convert<T>(row.Value);
return value;
}
public void PlatformRemove(string key, string? sharedName)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
t.RemoveKey(GetTableName(sharedName), key);
t.Commit();
}
/// <summary>
/// 将数据从
/// <para>使用 SQLiteConnection 的 PreferencesPlatformServiceImpl</para>
/// <para>迁移到</para>
/// <para>使用 DBreeze 的 PreferencesPlatformServiceImplV2</para>
/// </summary>
public static void Migrate()
{
var dbPath = Repository.DataBaseDirectory;
bool isOK = false;
bool exists = false;
try
{
var dbFilePath = Path.Combine(dbPath, "application2.dbf");
try
{
exists = File.Exists(dbFilePath);
}
catch
{
}
if (!exists) return;
var conn = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);
var items = conn.Table<Entity>().ToArray();
if (items.Any())
{
var itemGroups = items.GroupBy(x => x.SharedName).ToArray();
foreach (var itemGroup in itemGroups)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
foreach (var item in itemGroup)
{
if (item.Value != null)
{
string key;
if (string.IsNullOrEmpty(item.SharedName)) key = item.Id.TrimEnd("_K");
else key = item.Id.TrimEnd($"_{item.SharedName}_S");
var tableName = GetTableName(item.SharedName);
t.Insert(tableName, key, item.Value.ToString(CultureInfo.InvariantCulture));
}
}
t.Commit();
}
}
conn.Close();
conn.Dispose();
isOK = true;
}
catch
{
}
finally
{
if (isOK)
{
var files = Directory.GetFiles(dbPath, "application2*");
foreach (var item in files)
{
IOPath.FileTryDelete(item);
}
}
}
}
}
#endif
@@ -62,7 +62,11 @@ public static class ServiceCollectionExtensions
/// <returns></returns>
public static IServiceCollection AddRepositoryPreferences(this IServiceCollection services)
{
#if DBREEZE
services.AddSingleton<IPreferencesPlatformService, PreferencesPlatformServiceImplV2>();
#else
services.AddSingleton<IPreferencesPlatformService, PreferencesPlatformServiceImpl>();
#endif
return services;
}
}
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.Diagnostics.CodeAnalysis;
namespace System.Application.Settings;
@@ -82,7 +83,7 @@ public sealed class FileSettingsProvider : ISerializationProvider
{
stream.Position = 0;
}
var source = Serializable.DMP<IDictionary<string, object?>>(stream);
var source = stream.Length == 0 ? null : Serializable.DMP<IDictionary<string, object?>>(stream);
//var source = XamlServices.Load(stream) as IDictionary<string, object>;
_settings = source == null
? new SortedDictionary<string, object?>()
@@ -107,4 +108,5 @@ public sealed class FileSettingsProvider : ISerializationProvider
add { }
remove { }
}
}
}
#endif
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.Diagnostics.CodeAnalysis;
namespace System.Application.Settings;
@@ -22,4 +23,5 @@ public interface ISerializationProvider
bool RemoveValue(string key);
string ToJsonString();
}
}
#endif
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.ComponentModel;
using System.Diagnostics;
@@ -194,4 +195,5 @@ public class SerializableProperty<T> : INotifyPropertyChanged
}
#endregion
}
}
#endif
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.Runtime.CompilerServices;
namespace System.Application.Settings;
@@ -43,23 +44,96 @@ public static class SettingsHost
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), "Config Save", ex);
Log.Error(nameof(SettingsHost), ex, "Config Save");
throw;
}
}
/// <summary>
/// 尝试备份配置
/// </summary>
/// <param name="bakLocalFilePath"></param>
static void TryBackup(string bakLocalFilePath)
{
try
{
var localFilePath = SettingsHostBase.LocalFilePath;
if (File.Exists(localFilePath))
{
File.Copy(localFilePath, bakLocalFilePath, true);
}
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryBackUp");
}
}
/// <summary>
/// 尝试还原备份配置,返回是否有备份文件
/// </summary>
/// <param name="bakLocalFilePath"></param>
/// <returns></returns>
static bool TryRestoreBackup(string bakLocalFilePath)
{
try
{
var exists = File.Exists(bakLocalFilePath);
if (exists)
{
var localFilePath = SettingsHostBase.LocalFilePath;
File.Copy(bakLocalFilePath, localFilePath, true);
}
return exists;
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryRestoreBackup");
}
return false;
}
/// <summary>
/// 尝试删除配置
/// </summary>
static void TryDelete()
{
try
{
var localFilePath = SettingsHostBase.LocalFilePath;
if (File.Exists(localFilePath))
{
File.Delete(localFilePath);
}
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryDelete");
}
}
public static void Load()
{
var isLoad = false;
var bakLocalFilePath = $"{SettingsHostBase.LocalFilePath}.bak";
try
{
SettingsHostBase.Local.Load();
isLoad = true;
TryBackup(bakLocalFilePath);
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), "Config Load", ex);
if (!TryRestoreBackup(bakLocalFilePath))
{
// 还原备份文件失败,删除当前配置
TryDelete();
}
File.Delete(SettingsHostBase.LocalFilePath);
SettingsHostBase.Local.Load();
Log.Error(nameof(SettingsHost), ex, $"Config Load, isLoad: {isLoad}");
if (!isLoad) SettingsHostBase.Local.Load();
}
}
}
@@ -85,5 +159,6 @@ public abstract class SettingsHost2<TSettings> : SettingsHostBase where TSetting
static string GetKey(string propertyName) => $"{CategoryName}.{propertyName}";
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave, [CallerMemberName] string propertyName = "") => GetProperty(GetKey, Local, defaultValue, autoSave, propertyName);
}
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave = true, [CallerMemberName] string propertyName = "") => GetProperty(GetKey, Local, defaultValue, autoSave, propertyName);
}
#endif
@@ -0,0 +1,168 @@
#if DBREEZE
using DBreeze;
using System.ComponentModel;
using System.Diagnostics;
using static System.Application.Settings.ISerializableProperty;
namespace System.Application.Settings;
public interface ISerializableProperty : INotifyPropertyChanged
{
public const string tableName = "SerializableProperty";
}
[DebuggerDisplay("Value={Value}, Key={Key}, Default={Default}")]
public sealed class SerializableProperty<T> : ISerializableProperty, INotifyPropertyChanged
{
T? _value;
bool _cached;
DBreezeEngine? _Provider;
public string Key { get; }
public DBreezeEngine Provider { get => _Provider ?? throw new ArgumentNullException(nameof(_Provider)); set => _Provider = value; }
public T? Default { get; }
public T? Value
{
get
{
if (!_cached)
{
{
using var t = Provider.GetTransaction();
var row = t.Select<string, byte[]>(tableName, Key);
if (row?.Value == null)
{
_value = Default;
}
else
{
try
{
_value = Serializable.DMP<T>(row.Value);
}
catch
{
_value = Default;
}
}
}
_cached = true;
}
return _value;
}
set
{
var comparer = EqualityComparer<T?>.Default;
if (_cached && comparer.Equals(_value, value)) return;
var old = _value;
_value = value;
_cached = true;
SetValue(comparer, old, value);
}
}
void SetValue(EqualityComparer<T?> comparer, T? oldValue, T? newValue)
{
{
using var t = Provider.GetTransaction();
if (comparer.Equals(newValue, Default))
t.RemoveKey(tableName, Key);
else
t.Insert(tableName, Key, Serializable.SMP(newValue));
t.Commit();
}
OnValueChanged(oldValue, newValue);
}
public override string ToString() => Value?.ToString() ?? string.Empty;
public void RaiseValueChanged()
{
var comparer = EqualityComparer<T?>.Default;
SetValue(comparer, _value, _value);
}
public SerializableProperty(string key, DBreezeEngine provider) : this(key, provider, default)
{
}
public SerializableProperty(string key, DBreezeEngine provider, T? defaultValue)
{
Key = key;
Provider = provider;
Default = defaultValue;
}
public IDisposable Subscribe(Action<T?> listener, bool notifyOnInitialValue = true)
{
if (notifyOnInitialValue)
listener(Value);
return new ValueChangedEventListener(this, listener);
}
public void Reset()
{
var comparer = EqualityComparer<T?>.Default;
SetValue(comparer, _value, Default);
}
sealed class ValueChangedEventListener : IDisposable
{
private readonly Action<T?> _listener;
private readonly SerializableProperty<T> _source;
public ValueChangedEventListener(SerializableProperty<T> property, Action<T?> listener)
{
_listener = listener;
_source = property;
_source.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object? sender, ValueChangedEventArgs<T?> args)
{
_listener(args.NewValue);
}
public void Dispose()
{
_source.ValueChanged -= HandleValueChanged;
}
}
public static implicit operator T?(SerializableProperty<T> property) => property.Value;
#region events
public event EventHandler<ValueChangedEventArgs<T?>>? ValueChanged;
void OnValueChanged(T? oldValue, T? newValue) => ValueChanged?.Invoke(this, new ValueChangedEventArgs<T?>(oldValue, newValue));
readonly Dictionary<PropertyChangedEventHandler, EventHandler<ValueChangedEventArgs<T>>> _handlers = new();
event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged
{
add
{
if (value == null) return;
ValueChanged += _handlers[value] = (sender, args) => value(sender, new PropertyChangedEventArgs(nameof(Value)));
}
remove
{
if (value == null) return;
if (_handlers.TryGetValue(value, out var handler))
{
ValueChanged -= handler;
_handlers.Remove(value);
}
}
}
#endregion
}
#endif
@@ -0,0 +1,28 @@
#if DBREEZE
using System.Runtime.CompilerServices;
namespace System.Application.Settings;
public static class SettingsHost
{
public static void Load() => SettingsProviderV3.Load();
[Obsolete]
public static void Save()
{
}
}
public abstract class SettingsHost2<TSettings> where TSettings : SettingsHost2<TSettings>, new()
{
static readonly string CategoryName = typeof(TSettings).Name;
static string GetKey(string propertyName) => $"{CategoryName}.{propertyName}";
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, [CallerMemberName] string propertyName = "") => new(GetKey(propertyName), SettingsProviderV3.Provider, defaultValue);
[Obsolete("autoSave N/A")]
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave, [CallerMemberName] string propertyName = "") => new(GetKey(propertyName), SettingsProviderV3.Provider, defaultValue);
}
#endif
@@ -0,0 +1,90 @@
#if DBREEZE
using DBreeze;
using DBreeze.Utils;
namespace System.Application.Settings;
public static class SettingsProviderV3
{
static DBreezeEngine? _Provider;
static readonly object lock_load = new();
public static DBreezeEngine Provider
{
get
{
if (_Provider == null) Load();
return _Provider ?? throw new ArgumentNullException(nameof(_Provider));
}
set => _Provider = value;
}
public static void Load()
{
lock (lock_load)
{
if (_Provider == null)
{
_Provider = new(Path.Combine(IOPath.AppDataDirectory, "Config"));
//Setting up NetJSON serializer (from NuGet) to be used by DBreeze
CustomSerializator.ByteArraySerializator = value => Serializable.SMP(value == null ? typeof(object) : value.GetType(), value!);
CustomSerializator.ByteArrayDeSerializator = (buffer, type) => Serializable.DMP(type, buffer);
}
}
}
/// <summary>
/// 将数据从
/// <para>使用 <see cref="IDictionary{TKey, TValue}"/> + <see cref="MessagePack"/> 单文件 的 FileSettingsProvider</para>
/// <para>迁移到</para>
/// <para>使用 DBreeze 的 SettingsProviderV3</para>
/// </summary>
public static void Migrate()
{
var filePath = Path.Combine(IOPath.AppDataDirectory, "Config" + FileEx.MPO);
bool exists = false;
try
{
exists = File.Exists(filePath);
}
catch
{
}
if (exists)
{
try
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
if (stream.Position > 0)
{
stream.Position = 0;
}
var source = stream.Length == 0 ? null : Serializable.DMP<IDictionary<string, object?>>(stream);
if (source.Any_Nullable())
{
if (_Provider == null) Load();
using var t = Provider.GetTransaction();
foreach (var item in source)
{
if (item.Value == null) continue;
var valueType = item.Value.GetType();
var value = Serializable.SMP(valueType, item.Value);
t.Insert(ISerializableProperty.tableName, item.Key, value);
}
t.Commit();
}
}
catch
{
}
finally
{
IOPath.FileTryDelete(filePath);
}
}
}
}
#endif
@@ -1,6 +1,6 @@
namespace System.Application.Settings;
public sealed class ValueChangedEventArgs<T> : EventArgs where T : notnull
public sealed class ValueChangedEventArgs<T> : EventArgs
{
public T? OldValue { get; }
+1
View File
@@ -20,6 +20,7 @@
<PackageReference Include="gfoidl.Base64" />
<PackageReference Include="MessagePack" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="DBreeze" Condition=" $(DefineConstants.Contains('DBREEZE')) " />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
+2 -8
View File
@@ -77,10 +77,7 @@ public static partial class DI
/// <inheritdoc cref="Get{T}"/>
public static T? Get_Nullable<T>() where T : notnull
{
if (value == null)
{
throw GetDIGetFailException(typeof(T));
}
if (value == null) return default;
return value.GetService<T>();
}
@@ -97,10 +94,7 @@ public static partial class DI
/// <inheritdoc cref="Get_Nullable{T}"/>
public static object? Get_Nullable(Type serviceType)
{
if (value == null)
{
throw GetDIGetFailException(serviceType);
}
if (value == null) return default;
return value.GetService(serviceType);
}
@@ -3,11 +3,11 @@ namespace System;
public static partial class StringExtensions
{
public static string TrimStart(this string s, string trimString)
public static string TrimStart(this string s, string value)
{
if (trimString.StartsWith(trimString))
if (s.StartsWith(value))
{
return s[trimString.Length..];
return s[value.Length..];
}
else
{
@@ -15,11 +15,11 @@ public static partial class StringExtensions
}
}
public static string TrimEnd(this string s, string trimString)
public static string TrimEnd(this string s, string value)
{
if (trimString.EndsWith(trimString))
if (s.EndsWith(value))
{
return s[..^trimString.Length];
return s[..^value.Length];
}
else
{
@@ -27,11 +27,11 @@ public static partial class StringExtensions
}
}
public static string TrimStart(this string s, string trimString, StringComparison comparisonType)
public static string TrimStart(this string s, string value, StringComparison comparisonType)
{
if (trimString.StartsWith(trimString, comparisonType))
if (s.StartsWith(value, comparisonType))
{
return s[trimString.Length..];
return s[value.Length..];
}
else
{
@@ -39,11 +39,11 @@ public static partial class StringExtensions
}
}
public static string TrimEnd(this string s, string trimString, StringComparison comparisonType)
public static string TrimEnd(this string s, string value, StringComparison comparisonType)
{
if (trimString.EndsWith(trimString, comparisonType))
if (s.EndsWith(value, comparisonType))
{
return s[..^trimString.Length];
return s[..^value.Length];
}
else
{
+4
View File
@@ -291,6 +291,10 @@ public static class IOPath
{
paths[i] = item;
}
else
{
DirCreateByNotExists(paths[i]);
}
}
InitFileSystem(GetAppDataDirectory, GetCacheDirectory);
+1 -1
View File
@@ -15,7 +15,7 @@ public static class Log
static ILoggerFactory? factory;
public static ILoggerFactory Factory => factory ??= DI.Get_Nullable<ILoggerFactory>() ?? LoggerFactory?.Invoke() ?? throw new ArgumentNullException(nameof(LoggerFactory));
public static ILoggerFactory Factory => factory ??= (DI.IsConfigured ? DI.Get<ILoggerFactory>() : null) ?? LoggerFactory?.Invoke() ?? throw new ArgumentNullException(nameof(LoggerFactory));
public static ILogger CreateLogger(string tag) => Factory.CreateLogger(tag);
@@ -58,7 +58,7 @@ partial class GeneralHttpClientFactory
/// <summary>
/// https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpNoProxy.cs
/// </summary>
sealed class HttpNoProxy : IWebProxy
public sealed class HttpNoProxy : IWebProxy
{
public static readonly HttpNoProxy Instance = new();
@@ -12,7 +12,7 @@ namespace System.Properties
/// <item> macOS:\packaging\build-osx-app.sh &lt;CFBundleVersion&gt; &lt;CFBundleShortVersionString&gt; </item>
/// </list>
/// </summary>
public const string Version = "2.8.2";
public const string Version = "2.8.3";
//public const string InfoVersion = Version + "-beta";
}
@@ -0,0 +1,84 @@
using System.Net.Security;
using System.Net.Sockets;
namespace System.Net.Http;
public sealed class ReverseProxyHttpClientHandler : DelegatingHandler
{
readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
public ReverseProxyHttpClientHandler()
{
InnerHandler = new SocketsHttpHandler()
{
Proxy = GeneralHttpClientFactory.HttpNoProxy.Instance,
UseProxy = false,
UseCookies = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
ConnectCallback = ConnectCallback,
};
}
/// <summary>
/// 连接回调
/// </summary>
/// <param name="context"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
async ValueTask<Stream> ConnectCallback(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
{
var innerExceptions = new List<Exception>();
var ipEndPoints = (await Dns.GetHostAddressesAsync("steamcommunity.rmbgame.net", cancellationToken)).Select(s => new IPEndPoint(s, context.DnsEndPoint.Port));
foreach (var ipEndPoint in ipEndPoints)
{
try
{
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, cancellationToken);
return await ConnectAsync(context, ipEndPoint, linkedTokenSource.Token);
}
catch (OperationCanceledException)
{
cancellationToken.ThrowIfCancellationRequested();
innerExceptions.Add(new TimeoutException(
$"HTTP connection to {ipEndPoint.Address} timed out."));
}
catch (Exception ex)
{
innerExceptions.Add(ex);
}
}
throw new AggregateException("Could not find any IP that can be successfully connected.", innerExceptions);
}
/// <summary>
/// 建立连接
/// </summary>
/// <param name="context"></param>
/// <param name="ipEndPoint"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
static async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext context, IPEndPoint ipEndPoint, CancellationToken cancellationToken)
{
var socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(ipEndPoint, cancellationToken);
var stream = new NetworkStream(socket, ownsSocket: true);
if (context.DnsEndPoint.Port != 443)
{
return stream;
}
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
{
TargetHost = string.Empty,
RemoteCertificateValidationCallback = (_, _, _, _) => true,
}, cancellationToken);
return sslStream;
}
}
+12 -5
View File
@@ -17,8 +17,10 @@ internal static class Program
{
const string ExecutiveName = "Steam++";
static BundleArch matchArch;
static readonly SemanticVersion runtimeVersion = new(6, 0, 7);
static readonly SemanticVersion sdkVersion = new(6, 0, 107);
static readonly SemanticVersion runtimeVersion = new(6, 0, 8);
static readonly SemanticVersion sdkVersion1 = new(6, 0, 108);
static readonly SemanticVersion sdkVersion3 = new(6, 0, 303);
static readonly SemanticVersion sdkVersion4 = new(6, 0, 400);
/// <summary>
/// 应用程序的主入口点。
@@ -56,7 +58,7 @@ internal static class Program
if (RuntimeInformation2.OSArchitecture != Architecture.Arm64) throw new PlatformNotSupportedException();
break;
}
if (IsRuntimeInstalled(matchArch, runtimeVersion, sdkVersion))
if (IsRuntimeInstalled(matchArch, runtimeVersion, sdkVersion1, sdkVersion3, sdkVersion4))
{
Run();
}
@@ -193,7 +195,7 @@ internal static class Program
/// 是否已安装运行时或 SDK
/// </summary>
/// <returns></returns>
static bool IsRuntimeInstalled(BundleArch matchArch, SemanticVersion runtimeVersion, SemanticVersion sdkVersion)
static bool IsRuntimeInstalled(BundleArch matchArch, SemanticVersion runtimeVersion, SemanticVersion sdkVersion1, SemanticVersion sdkVersion3, SemanticVersion sdkVersion4)
{
// ArchiSteamFarm 依赖 ASP.NET Core
// ASP.NET Core 运行时安装程序除 Hosting Bundle 不包含 .NET 运行时 缺少文件 C:\Program Files\dotnet\host\fxr\{version}\hostfxr.dll
@@ -202,7 +204,12 @@ internal static class Program
// https://github.com/dotnet/runtime/blob/v6.0.5/src/native/corehost/apphost/apphost.windows.cpp#L106-L113
var installed = RegistryQuery.GetAllInstalledBundles().Where(m => m.Arch.HasFlags(matchArch)).ToArray();
var query_sdk = installed.Where(m => m.Version.Type == BundleType.Sdk && m.Version.SemVer >= sdkVersion);
var query_sdk = installed.Where(m => m.Version.Type == BundleType.Sdk &&
(
(m.Version.SemVer >= sdkVersion1 && m.Version.SemVer < new SemanticVersion(sdkVersion1.Major, sdkVersion1.Minor, 199)) ||
(m.Version.SemVer >= sdkVersion3 && m.Version.SemVer < new SemanticVersion(sdkVersion3.Major, sdkVersion3.Minor, 399)) ||
(m.Version.SemVer >= sdkVersion4 && m.Version.SemVer < new SemanticVersion(sdkVersion4.Major, sdkVersion4.Minor, 499))
));
if (query_sdk.Any()) return true;
var query_runtime = installed.Where(m => (m.Version.Type == BundleType.Runtime || m.Version.Type == BundleType.WindowsDesktopRuntime) && m.Version.SemVer >= runtimeVersion);
@@ -1,15 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>$(MSBuildProjectDirectory)\..\..\avalonia.snk</AssemblyOriginatorKeyFile>
<Version>2.2.255.255</Version>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\AssemblyInfo.Version.Max.cs">
<LinkBase>Properties</LinkBase>
</Compile>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Primitives" />
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220725" android:versionName="2.8.2" package="net.steampp.app" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220803" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
@@ -19,7 +19,8 @@
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
<AndroidLinkMode>None</AndroidLinkMode>
<AndroidLinkMode>Full</AndroidLinkMode>
<AndroidLinkTool>r8</AndroidLinkTool>
<PublishTrimmed>false</PublishTrimmed>
<AndroidFragmentType>AndroidX.Fragment.App.Fragment</AndroidFragmentType>
</PropertyGroup>
@@ -187,7 +188,7 @@
<PackageReference Include="Xamarin.Build.Download" />
<!--<PackageReference Include="Xamarin.AndroidX.Window" />-->
</ItemGroup>
<ItemGroup>
<AndroidAsset Include="..\..\references\Android Assets\cncity.txt" Link="Assets\cncity.txt" />
</ItemGroup>
@@ -553,6 +554,9 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_toolbar_tablayout_viewpager2.xml">
<Link>Resources\layout\activity_toolbar_tablayout_viewpager2.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_toolbar_webview.xml">
<Link>Resources\layout\activity_toolbar_webview.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_about.xml">
<Link>Resources\layout\fragment_about.xml</Link>
</AndroidResource>
@@ -149,6 +149,7 @@
<PackageReference Include="Xamarin.Google.MLKit.BarcodeScanning" />
<PackageReference Include="Xamarin.Build.Download" />
<!--<PackageReference Include="Xamarin.AndroidX.Window" />-->
<PackageReference Include="Microsoft.Net.Http.Headers" />
</ItemGroup>
<!--<ItemGroup Condition="'$(Configuration)'=='Debug'">
@@ -25,7 +25,7 @@ namespace System.Application.UI
VisualStudioAppCenterSDK.Init();
}
void IApplication.IProgramHost.ConfigureServices(DILevel level) => ConfigureServices(this, level);
void IApplication.IProgramHost.ConfigureServices(DILevel level, bool isTrace) => ConfigureServices(this, level, isTrace: isTrace);
void IApplication.IProgramHost.OnStartup() => OnStartup(this);
+1 -5
View File
@@ -102,7 +102,7 @@ namespace System.Application.UI
var level = DILevel.Min;
if (IsMainProcess) level = DILevel.MainProcess;
IApplication.IProgramHost host = this;
host.ConfigureServices(level);
host.ConfigureServices(level, isTrace);
if (isTrace) StartWatchTrace.Record("Startup");
if (IsMainProcess)
@@ -125,8 +125,6 @@ namespace System.Application.UI
if (IsMainProcess)
{
var vmService = IViewModelManager.Instance;
#if __XAMARIN_FORMS__
Forms.Init(this, null);
FormsMaterial.Init(this, null);
@@ -136,8 +134,6 @@ namespace System.Application.UI
_Current = new(RealTheme);
if (isTrace) StartWatchTrace.Record("XFApp");
#endif
vmService.MainWindow!.Initialize();
if (isTrace) StartWatchTrace.Record("MainVM.Init");
}
StartupTrack = StartWatchTrace.ToString();
+41 -27
View File
@@ -23,7 +23,7 @@ public abstract class CommandLineHost : IDisposable
protected abstract IApplication.IDesktopProgramHost Host { get; }
protected abstract void ConfigureServices(DILevel level);
protected abstract void ConfigureServices(DILevel level, bool isTrace = false);
#if StartWatchTrace
protected abstract void StartWatchTraceRecord(string? mark = null, bool dispose = false);
@@ -136,15 +136,22 @@ public abstract class CommandLineHost : IDisposable
void ProxyMessageReceived()
{
var value = Enum.TryParse<EOnOff>(args[1], out var value_) ? value_ : default;
MainThread2.BeginInvokeOnMainThread(() =>
try
{
ProxyService.Current.ProxyStatus = value switch
MainThread2.BeginInvokeOnMainThread(() =>
{
EOnOff.On => true,
EOnOff.Off => false,
_ => !ProxyService.Current.ProxyStatus,
};
});
ProxyService.Current.ProxyStatus = value switch
{
EOnOff.On => true,
EOnOff.Off => false,
_ => !ProxyService.Current.ProxyStatus,
};
});
}
catch
{
}
}
break;
}
@@ -152,8 +159,15 @@ public abstract class CommandLineHost : IDisposable
break;
}
}
var app = await WaitForApplicationAsync();
MainThread2.BeginInvokeOnMainThread(app.RestoreMainWindow);
try
{
var app = await WaitForApplicationAsync();
MainThread2.BeginInvokeOnMainThread(app.RestoreMainWindow);
}
catch
{
}
};
}
//#if StartWatchTrace
@@ -297,27 +311,27 @@ public abstract class CommandLineHost : IDisposable
// -clt show -config -cert
var show = new Command("show", "显示信息");
show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
//show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
show.AddOption(new Option<bool>("-cert", "显示当前根证书信息"));
show.Handler = CommandHandler.Create((bool config, bool cert) =>
show.Handler = CommandHandler.Create((/*bool config,*/ bool cert) =>
{
if (OperatingSystem.IsWindows()) if (!AttachConsole()) AllocConsole();
if (config)
{
Console.WriteLine("Config: ");
try
{
SettingsHost.Load();
var configValue = SettingsHostBase.Local.ToJsonString();
Console.WriteLine(configValue);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine();
}
//if (config)
//{
// Console.WriteLine("Config: ");
// try
// {
// SettingsHost.Load();
// var configValue = SettingsHostBase.Local.ToJsonString();
// Console.WriteLine(configValue);
// }
// catch (Exception e)
// {
// Console.WriteLine(e.ToString());
// }
// Console.WriteLine();
//}
if (cert)
{
@@ -11,7 +11,7 @@
<Identity
Name="4651ED44255E.47979655102CE"
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
Version="2.8.1.0" />
Version="2.8.3.0" />
<Properties>
<DisplayName>Watt Toolkit</DisplayName>
+40 -7
View File
@@ -1,14 +1,22 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Runtime.Versioning;
using System.Application.Settings;
using System.Application.CommandLine;
using System.Application.UI.Resx;
using NLog;
using Avalonia;
using Avalonia.ReactiveUI;
using Avalonia.Controls;
#if WINDOWS || WINDOWS_DESKTOP_BRIDGE
using WPFMessageBox = System.Windows.MessageBox;
using WPFMessageBoxButton = System.Windows.MessageBoxButton;
using WPFMessageBoxImage = System.Windows.MessageBoxImage;
#endif
#if MAC
[assembly: SupportedOSPlatform("macOS")]
#elif LINUX
@@ -39,17 +47,42 @@ namespace System.Application.UI
// fix The request was aborted: Could not create SSL/TLS secure channel
TrySetSecurityProtocol();
var host = ProgramHost.Instance;
host.IsMainProcess = args.Length == 0;
host.IsCLTProcess = !host.IsMainProcess && args.FirstOrDefault() == "-clt";
#if WINDOWS_DESKTOP_BRIDGE
if (!DesktopBridgeHelper.Init()) return 0;
InitWithUWP(ref args);
#elif WINDOWS
//#if NET7_0_OR_GREATER
// if (/*Environment.Version >= new Version(7, 0) && */!OperatingSystem2.IsWindows10AtLeast())
// {
// // [TBD] .NET 7 中考虑弃用对 Windows 7/2008 R2/8.1/2012 R2 的支持
// WPFMessageBox.Show("TBD", AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
// return 0;
// }
//#endif
if (OperatingSystem2.IsWindows10AtLeast() &&
!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 14393))
{
// Win10 最低需要 1607,低于此版本则弹窗错误中止运行
// appcenter.ms 上有 10240,10586 的 crash 报告
WPFMessageBox.Show(AppResources.Error_Lower_Than_Windows10_1607, AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
return 0;
}
if (AppContext.BaseDirectory.StartsWith(Path.GetTempPath(), StringComparison.OrdinalIgnoreCase))
{
// 检测当前目录 Temp\Rar$ 这类目录,可能是在压缩包中直接启动程序导致的,还有一堆 文件找不到/加载失败的异常
// System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\USER\AppData\Local\Temp\Rar$EXa15528.13350\Cache\switchproxy.reg'.
// System.IO.FileLoadException ...
// System.IO.FileNotFoundException: Could not load file or assembly ...
WPFMessageBox.Show(AppResources.Error_BaseDir_StartsWith_Temp, AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
return 0;
}
#elif MAC
InitWithMAC(args);
#endif
var host = ProgramHost.Instance;
host.IsMainProcess = args.Length == 0;
host.IsCLTProcess = !host.IsMainProcess && args.FirstOrDefault() == "-clt";
OnCreateAppExecuting();
// InitCefNetApp(args);
@@ -87,7 +120,7 @@ namespace System.Application.UI
{
ServicePointManager.SecurityProtocol = type;
}
catch (NotSupportedException)
catch
{
}
@@ -205,7 +238,7 @@ namespace System.Application.UI
static void StartAvaloniaApp(string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
{
var builder = BuildAvaloniaApp();
builder.StartWithClassicDesktopLifetime(args, shutdownMode);
builder.StartWithClassicDesktopLifetime2(args, shutdownMode);
}
}
}
@@ -37,7 +37,7 @@ static partial class
public EOnOff ProxyStatus { get; set; }
void IApplication.IProgramHost.ConfigureServices(DILevel level) => ConfigureServices(level);
void IApplication.IProgramHost.ConfigureServices(DILevel level, bool isTrace) => ConfigureServices(level, isTrace);
public void InitVisualStudioAppCenterSDK()
{
@@ -55,6 +55,14 @@ static partial class
IApplication IApplication.IProgramHost.Application => App.Instance;
void IApplication.IDesktopProgramHost.OnCreateAppExecuted(Action<IViewModelManager>? handlerViewModelManager, bool isTrace) => Program.OnCreateAppExecuted(this, handlerViewModelManager, isTrace);
DeploymentMode IApplication.IDesktopProgramHost.DeploymentMode => DeploymentMode.
#if FRAMEWORK_DEPENDENT || !PUBLISH
FDE
#else
SCD
#endif
;
}
partial class ProgramHost : CommandLineHost
@@ -63,7 +71,7 @@ static partial class
public Action<DILevel>? ConfigureServicesDelegate { get; set; }
protected override void ConfigureServices(DILevel level)
protected override void ConfigureServices(DILevel level, bool isTrace = false)
{
if (ConfigureServicesDelegate != null)
{
@@ -71,7 +79,7 @@ static partial class
}
else
{
Program.ConfigureServices(this, level);
Program.ConfigureServices(this, level, isTrace: isTrace);
}
}
@@ -482,7 +482,15 @@ namespace System.Application.UI
#endif
//AppHelper.TryShutdown();
INotificationService.ILifeCycle.Instance?.OnShutdown();
try
{
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/952960442u/overview
INotificationService.ILifeCycle.Instance?.OnShutdown();
}
catch (ObjectDisposedException)
{
}
}
internal void NotifyIcon_Click(object? sender, EventArgs e)
@@ -667,12 +675,6 @@ namespace System.Application.UI
object IApplication.CurrentPlatformUIHost => MainWindow!;
DeploymentMode IApplication.DeploymentMode => DeploymentMode.
#if FRAMEWORK_DEPENDENT || !PUBLISH
FDE
#else
SCD
#endif
;
DeploymentMode IApplication.DeploymentMode => ProgramHost.DeploymentMode;
}
}
@@ -253,7 +253,7 @@ namespace System.Application.UI
//#endif
// }
static NativeMenuItem? exitMenuItem;
static Dictionary<TabItemViewModel, NativeMenuItem>? tabItems;
static Dictionary<TabItemViewModel.TabItemId, NativeMenuItem>? tabItems;
static IDisposable? InitMenuItems(NativeMenu menu)
{
@@ -262,19 +262,15 @@ namespace System.Application.UI
#else
MainWindowViewModel main = new();
#endif
var query = from x in main.AllTabItems
let tabItem = x is TabItemViewModel item ? item : null
where tabItem != null
select tabItem;
tabItems = new();
foreach (var item in query)
foreach (var item in main.AllTabIdItems)
{
var menuItem = new NativeMenuItem
{
Header = item.Name,
Header = TabItemViewModel.GetName(item),
Command = ReactiveCommand.Create(() =>
{
OnMenuClick(item.Id);
OnMenuClick(item);
}),
};
tabItems.Add(item, menuItem);
@@ -299,7 +295,7 @@ namespace System.Application.UI
}
foreach (var item in tabItems)
{
item.Value.Header = item.Key.Name;
item.Value.Header = TabItemViewModel.GetName(item.Key);
}
});
#else
@@ -160,7 +160,7 @@ namespace System.Application.UI.Views.Pages
chart.Series = new ISeries[] { readSeries, writeSeries };
});
}
catch (Exception)
catch
{
}
finally
@@ -89,6 +89,27 @@ namespace System.Application.Services.Implementation
ValueTask IPlatformService.RunShellAsync(string script, bool admin) => RunShellAsync(script, admin);
async ValueTask<bool?> IPlatformService.TrustRootCertificate(string filePath)
{
var script = $"security add-trusted-cert -d -r trustRoot -k /Users/{Environment.UserName}/Library/Keychains/login.keychain-db \\\"{filePath}\\\"";
TextBoxWindowViewModel vm = new()
{
Title = AppResources.MacTrustRootCertificateTips,
InputType = TextBoxWindowViewModel.TextBoxInputType.ReadOnlyText,
Description = AppResources.MacTrustRootCertificateTips,
};
var scriptContent = $"osascript -e 'tell app \"Terminal\" to do script \"sudo -S {script}\"'";
var msg = UnixHelper.RunShell(scriptContent.ToString());
if (await TextBoxWindowViewModel.ShowDialogAsync(vm) == null)
return null;
if (!string.IsNullOrWhiteSpace(msg))
{
Toast.Show(msg);
return false;
}
return true;
}
/// <summary>
/// 尝试删除证书
/// </summary>
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationCore/SR.cs
#if !NETFRAMEWORK && WINDOWS
namespace MS.Internal.PresentationCore;
internal static class SR
{
public static string Get(string name) => name switch
{
SRID.CantShowMBServiceWithOwner => "Cannot show MessageBox Service with Owner.",
_ => "",
};
}
#endif
@@ -0,0 +1,13 @@
#if !NETFRAMEWORK && WINDOWS
namespace MS.Internal.PresentationCore;
static class SRID
{
/// <summary>
/// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Resources/Strings.resx#L510
/// </summary>
public const string CantShowMBServiceWithOwner = "CantShowMBServiceWithOwner";
}
#endif
@@ -0,0 +1,57 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs
#if !NETFRAMEWORK && WINDOWS
namespace MS.Win32;
internal static class ExternDll
{
//public const string Activeds = "activeds.dll";
//public const string Advapi32 = "advapi32.dll";
//public const string Comctl32 = "comctl32.dll";
//public const string Comdlg32 = "comdlg32.dll";
//public const string DwmAPI = "dwmapi.dll";
//public const string Gdi32 = "gdi32.dll";
//public const string Gdiplus = "gdiplus.dll";
//public const string Hhctrl = "hhctrl.ocx";
//public const string Imm32 = "imm32.dll";
//public const string Kernel32 = "kernel32.dll";
//public const string Loadperf = "Loadperf.dll";
//public const string Mqrt = "mqrt.dll";
//public const string Mscoree = "mscoree.dll";
//public const string MsDrm = "msdrm.dll";
//public const string Mshwgst = "mshwgst.dll";
//public const string Msi = "msi.dll";
//public const string NaturalLanguage6 = "naturallanguage6.dll";
//public const string Ntdll = "ntdll.dll";
//public const string Ole32 = "ole32.dll";
//public const string Oleacc = "oleacc.dll";
//public const string Oleaut32 = "oleaut32.dll";
//public const string Olepro32 = "olepro32.dll";
//public const string Penimc = "PenIMC_cor3.dll";
//public const string PresentationCore = "PresentationCore.dll";
//public const string PresentationFramework = "PresentationFramework.dll";
//public const string PresentationHostDll = "PresentationHost_cor3.dll";
//public const string PresentationNativeDll = "PresentationNative_cor3.dll";
//public const string Psapi = "psapi.dll";
//public const string Shcore = "shcore.dll";
//public const string Shell32 = "shell32.dll";
//public const string Shfolder = "shfolder.dll";
//public const string Urlmon = "urlmon.dll";
public const string User32 = "user32.dll";
//public const string Uxtheme = "uxtheme.dll";
//public const string Version = "version.dll";
//public const string Vsassert = "vsassert.dll";
//public const string WindowsBase = "windowsbase.dll";
//public const string Wininet = "wininet.dll";
//public const string Winmm = "winmm.dll";
//public const string Winspool = "winspool.drv";
//public const string Wldp = "wldp.dll";
//public const string WpfGfx = "WpfGfx_cor3.dll";
//public const string WtsApi32 = "wtsapi32.dll";
}
#endif
@@ -0,0 +1,22 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs
#if !NETFRAMEWORK && WINDOWS
using System;
using System.Runtime.InteropServices;
namespace MS.Win32;
internal static class UnsafeNativeMethods
{
[DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetActiveWindow();
[DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
public static extern int MessageBox(HandleRef hWnd, string text, string caption, int type);
}
#endif
@@ -0,0 +1,248 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/MessageBox.cs
#if !NETFRAMEWORK && WINDOWS
using MS.Win32;
using System.ComponentModel;
using System.Runtime.InteropServices;
using SR_ = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
namespace System.Windows;
public static class MessageBox
{
const int IDOK = 1;
const int IDCANCEL = 2;
const int IDYES = 6;
const int IDNO = 7;
const int DEFAULT_BUTTON1 = 0x00000000;
const int DEFAULT_BUTTON2 = 0x00000100;
const int DEFAULT_BUTTON3 = 0x00000200;
static MessageBoxResult Win32ToMessageBoxResult(int value) => value switch
{
IDOK => MessageBoxResult.OK,
IDCANCEL => MessageBoxResult.Cancel,
IDYES => MessageBoxResult.Yes,
IDNO => MessageBoxResult.No,
_ => MessageBoxResult.No,
};
public static MessageBoxResult Show(
string messageBoxText,
string caption,
MessageBoxButton button,
MessageBoxImage icon,
MessageBoxResult defaultResult,
MessageBoxOptions options) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, defaultResult, options);
public static MessageBoxResult Show(
string messageBoxText,
string caption,
MessageBoxButton button,
MessageBoxImage icon,
MessageBoxResult defaultResult) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, defaultResult, 0);
public static MessageBoxResult Show(
string messageBoxText,
string caption,
MessageBoxButton button,
MessageBoxImage icon) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, 0, 0);
public static MessageBoxResult Show(
string messageBoxText,
string caption,
MessageBoxButton button) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, MessageBoxImage.None, 0, 0);
public static MessageBoxResult Show(string messageBoxText, string caption) => ShowCore(IntPtr.Zero, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, 0, 0);
public static MessageBoxResult Show(string messageBoxText) => ShowCore(IntPtr.Zero, messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, 0, 0);
static int DefaultResultToButtonNumber(MessageBoxResult result, MessageBoxButton button)
{
if (result == 0) return DEFAULT_BUTTON1;
switch (button)
{
case MessageBoxButton.OK:
return DEFAULT_BUTTON1;
case MessageBoxButton.OKCancel:
if (result == MessageBoxResult.Cancel) return DEFAULT_BUTTON2;
return DEFAULT_BUTTON1;
case MessageBoxButton.YesNo:
if (result == MessageBoxResult.No) return DEFAULT_BUTTON2;
return DEFAULT_BUTTON1;
case MessageBoxButton.YesNoCancel:
if (result == MessageBoxResult.No) return DEFAULT_BUTTON2;
if (result == MessageBoxResult.Cancel) return DEFAULT_BUTTON3;
return DEFAULT_BUTTON1;
default:
return DEFAULT_BUTTON1;
}
}
internal static MessageBoxResult ShowCore(
IntPtr owner,
string messageBoxText,
string caption,
MessageBoxButton button,
MessageBoxImage icon,
MessageBoxResult defaultResult,
MessageBoxOptions options)
{
if (!IsValidMessageBoxButton(button))
{
throw new InvalidEnumArgumentException("button", (int)button, typeof(MessageBoxButton));
}
if (!IsValidMessageBoxImage(icon))
{
throw new InvalidEnumArgumentException("icon", (int)icon, typeof(MessageBoxImage));
}
if (!IsValidMessageBoxResult(defaultResult))
{
throw new InvalidEnumArgumentException("defaultResult", (int)defaultResult, typeof(MessageBoxResult));
}
if (!IsValidMessageBoxOptions(options))
{
throw new InvalidEnumArgumentException("options", (int)options, typeof(MessageBoxOptions));
}
// UserInteractive??
//
/*if (!SystemInformation.UserInteractive && (options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) == 0) {
throw new InvalidOperationException("UNDONE: SR.GetString(SR.CantShowModalOnNonInteractive)");
}*/
if ((options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) != 0)
{
if (owner != IntPtr.Zero)
{
throw new ArgumentException(SR_.Get(SRID.CantShowMBServiceWithOwner));
}
}
else
{
if (owner == IntPtr.Zero)
{
owner = UnsafeNativeMethods.GetActiveWindow();
}
}
int style = (int)button | (int)icon | (int)DefaultResultToButtonNumber(defaultResult, button) | (int)options;
// modal dialog notification?
//
//Application.BeginModalMessageLoop();
//MessageBoxResult result = Win32ToMessageBoxResult(SafeNativeMethods.MessageBox(new HandleRef(owner, handle), messageBoxText, caption, style));
MessageBoxResult result = Win32ToMessageBoxResult(UnsafeNativeMethods.MessageBox(new HandleRef(null, owner), messageBoxText, caption, style));
// modal dialog notification?
//
//Application.EndModalMessageLoop();
return result;
}
static bool IsValidMessageBoxButton(MessageBoxButton value) => value == MessageBoxButton.OK
|| value == MessageBoxButton.OKCancel
|| value == MessageBoxButton.YesNo
|| value == MessageBoxButton.YesNoCancel;
static bool IsValidMessageBoxImage(MessageBoxImage value) => value == MessageBoxImage.Asterisk
|| value == MessageBoxImage.Error
|| value == MessageBoxImage.Exclamation
|| value == MessageBoxImage.Hand
|| value == MessageBoxImage.Information
|| value == MessageBoxImage.None
|| value == MessageBoxImage.Question
|| value == MessageBoxImage.Stop
|| value == MessageBoxImage.Warning;
static bool IsValidMessageBoxResult(MessageBoxResult value) => value == MessageBoxResult.Cancel
|| value == MessageBoxResult.No
|| value == MessageBoxResult.None
|| value == MessageBoxResult.OK
|| value == MessageBoxResult.Yes;
static bool IsValidMessageBoxOptions(MessageBoxOptions value)
{
int mask = ~((int)MessageBoxOptions.ServiceNotification |
(int)MessageBoxOptions.DefaultDesktopOnly |
(int)MessageBoxOptions.RightAlign |
(int)MessageBoxOptions.RtlReading);
if (((int)value & mask) == 0)
return true;
return false;
}
}
public enum MessageBoxResult
{
None = 0,
OK = 1,
Cancel = 2,
Yes = 6,
No = 7,
// NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxResult()
}
[Flags]
public enum MessageBoxOptions
{
None = 0x00000000,
ServiceNotification = 0x00200000,
DefaultDesktopOnly = 0x00020000,
RightAlign = 0x00080000,
RtlReading = 0x00100000,
}
public enum MessageBoxImage
{
None = 0,
Hand = 0x00000010,
Question = 0x00000020,
Exclamation = 0x00000030,
Asterisk = 0x00000040,
Stop = Hand,
Error = Hand,
Warning = Exclamation,
Information = Asterisk,
// NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxIcon()
}
public enum MessageBoxButton
{
OK = 0x00000000,
OKCancel = 0x00000001,
YesNoCancel = 0x00000003,
YesNo = 0x00000004,
// NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxButton()
}
#endif
@@ -75,10 +75,6 @@ namespace System.Application.Services.Implementation
}
}
const string explorer = "explorer.exe";
static string Explorer => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), explorer);
public void OpenFolderByDirectoryPath(DirectoryInfo info)
{
Process.Start(new ProcessStartInfo
@@ -186,16 +182,21 @@ namespace System.Application.Services.Implementation
// return Process.Start(runas_exe, arguments_);
//}
const string explorer_exe = "explorer.exe";
static readonly Lazy<string> _explorer_exe = new(() => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "explorer.exe"));
/// <summary>
/// %windir%\explorer.exe
/// </summary>
static string Explorer => _explorer_exe.Value;
static Process? StartAsInvokerByExplorer(string fileName, string? arguments = null)
{
if (string.IsNullOrEmpty(arguments))
return Process.Start(explorer_exe, $"\"{fileName}\"");
return Process.Start(Explorer, $"\"{fileName}\"");
var cacheCmdFile = Path.Combine(IOPath.CacheDirectory, "StartAsInvokerByExplorer" + FileEx.CMD);
if (File.Exists(cacheCmdFile)) File.Delete(cacheCmdFile);
File.WriteAllText(cacheCmdFile, $"@echo {Constants.HARDCODED_APP_NAME} StartAsInvokerByExplorer{Environment.NewLine}start \"\" \"{fileName}\" {arguments}{Environment.NewLine}exit 0");
return Process.Start(explorer_exe, $"\"{cacheCmdFile}\"");
return Process.Start(Explorer, $"\"{cacheCmdFile}\"");
}
public Process? StartAsInvoker(string fileName, string? arguments = null)
@@ -279,15 +280,23 @@ namespace System.Application.Services.Implementation
/// <returns></returns>
public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
{
var proxyEnable = $"\"ProxyEnable\"=dword:{(state ? "00000001" : "00000000")}";
var hasIpAndProt = ip != null && port >= 0;
var proxyServer = hasIpAndProt ? $"\"proxyServer\"=\"{ip}:{port}\"" : "";
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings]{Environment.NewLine}{proxyEnable}{Environment.NewLine}{(state ? $"{ProxyOverride}{Environment.NewLine}" : "")}{proxyServer}";
var path = Path.Combine(IOPath.CacheDirectory, "switchproxy.reg");
File.WriteAllText(path, reg, Text.Encoding.UTF8);
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
p?.WaitForExit();
return true;
try
{
var proxyEnable = $"\"ProxyEnable\"=dword:{(state ? "00000001" : "00000000")}";
var hasIpAndProt = ip != null && port >= 0;
var proxyServer = hasIpAndProt ? $"\"proxyServer\"=\"{ip}:{port}\"" : "";
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings]{Environment.NewLine}{proxyEnable}{Environment.NewLine}{(state ? $"{ProxyOverride}{Environment.NewLine}" : "")}{proxyServer}";
var path = Path.Combine(IOPath.CacheDirectory, "switchproxy.reg");
File.WriteAllText(path, reg, Text.Encoding.UTF8);
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
p?.WaitForExit();
return true;
}
catch (Exception ex)
{
Toast.LogAndShowT(ex, TAG);
return false;
}
}
/// <summary>
@@ -298,13 +307,21 @@ namespace System.Application.Services.Implementation
/// <returns></returns>
public bool SetAsSystemPACProxy(bool state, string? url = null)
{
var regAutoConfigUrl = state ? $"\"AutoConfigURL\"=\"{url}\"" : "\"AutoConfigURL\"=\"\"";
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings]{Environment.NewLine}{regAutoConfigUrl}";
var path = Path.Combine(IOPath.CacheDirectory, "switchpacproxy.reg");
File.WriteAllText(path, reg, Text.Encoding.UTF8);
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
p?.WaitForExit();
return true;
try
{
var regAutoConfigUrl = state ? $"\"AutoConfigURL\"=\"{url}\"" : "\"AutoConfigURL\"=\"\"";
var reg = $"Windows Registry Editor Version 5.00{Environment.NewLine}[HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings]{Environment.NewLine}{regAutoConfigUrl}";
var path = Path.Combine(IOPath.CacheDirectory, "switchpacproxy.reg");
File.WriteAllText(path, reg, Text.Encoding.UTF8);
var p = Process2.Start("regedit", $"/s \"{path}\"", true);
p?.WaitForExit();
return true;
}
catch (Exception ex)
{
Toast.LogAndShowT(ex, TAG);
return false;
}
}
public IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByGdiPlus()
@@ -71,6 +71,7 @@
<ProjectReference Include="..\Common.CoreLib\Common.CoreLib.csproj" />
<ProjectReference Include="..\ST.Client.CommandLine\ST.Client.CommandLine.csproj" />
<ProjectReference Include="..\ST.Client.Maui\ST.Client.Maui.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy.Yarp\ST.Client.ReverseProxy.Yarp.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
+1 -1
View File
@@ -86,7 +86,7 @@ public partial class AppShell : Shell, IViewFor<MainWindowViewModel>
void InitTabItems(MainWindowViewModel mainWindow, IEnumerable<TabItemId>? topTabs = null)
{
var tabItems = mainWindow.AllTabItems.Where(x => x.Id != TabItemId.GameList);
var tabItems = mainWindow.TabItems.Where(x => x.Id != TabItemId.GameList);
if (topTabs.Any_Nullable())
{
tabItems = tabItems.Where(x => topTabs.Contains(x.Id)).Concat(tabItems.Where(x => !topTabs.Contains(x.Id)));
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220725" android:versionName="2.8.2" package="net.steampp.app" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220814" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
@@ -145,7 +145,7 @@
<Import Condition=" Exists('$(MSBuildProjectDirectory)\..\..\Xamarin.Android.KeyStore.props') " Project="..\..\Xamarin.Android.KeyStore.props" />
<ProjectExtensions>
<VisualStudio>
<UserProperties XamarinHotReloadWrongLinkerErrorInfoBarSTClientMobileDroidAppHideInfoBar="True" XamarinHotReloadDebuggerTimeoutExceptionSTClientAndroidAppHideInfoBar="True" />
<UserProperties XamarinHotReloadDebuggerTimeoutExceptionSTClientAndroidAppHideInfoBar="True" XamarinHotReloadWrongLinkerErrorInfoBarSTClientMobileDroidAppHideInfoBar="True" />
</VisualStudio>
</ProjectExtensions>
</Project>
@@ -75,6 +75,9 @@ public static partial class ServiceCollectionExtensions
internal static IServiceCollection AddReverseProxyServer(this IServiceCollection services)
{
// https://github.com/dotnetcore/FastGithub/blob/2.1.4/FastGithub.HttpServer/ServiceCollectionExtensions.cs#L15
CookieHttpClient.AddHttpClient(services);
return services
.AddMemoryCache()
.AddHttpForwarder()
@@ -0,0 +1,33 @@
using Microsoft.Extensions.DependencyInjection;
using System.Net;
namespace System.Application.Services.Implementation;
sealed class CookieHttpClient
{
public static readonly CookieContainer CookieContainer = new();
public const string HttpClientName = "CookieHttpClient";
readonly IHttpClientFactory httpClientFactory;
public CookieHttpClient(IHttpClientFactory httpClientFactory)
{
this.httpClientFactory = httpClientFactory;
}
public HttpClient HttpClient => httpClientFactory.CreateClient(HttpClientName);
public static void AddHttpClient(IServiceCollection services)
{
services.AddSingleton<CookieHttpClient>();
services.AddHttpClient(HttpClientName, (s, c) =>
{
c.Timeout = GeneralHttpClientFactory.DefaultTimeout;
}).ConfigurePrimaryHttpMessageHandler(() => GeneralHttpClientFactory.CreateSocketsHttpHandler(new()
{
UseCookies = true,
CookieContainer = CookieContainer,
}));
}
}
@@ -11,11 +11,11 @@ namespace System.Application.Services.Implementation.Http;
/// </summary>
public class ReverseProxyHttpClient : HttpMessageInvoker
{
/// <summary>
/// 插入的 UserAgent 标记
/// </summary>
static readonly ProductInfoHeaderValue userAgent
= new(new ProductHeaderValue(Constants.HARDCODED_APP_NAME_NEW, ThisAssembly.Version));
///// <summary>
///// 插入的 UserAgent 标记
///// </summary>
//static readonly ProductInfoHeaderValue userAgent
// = new(new ProductHeaderValue(Constants.HARDCODED_APP_NAME_NEW + "_" + DateTimeOffset.UtcNow.Ticks, ThisAssembly.Version));
public ReverseProxyHttpClient(IDomainConfig domainConfig, IDomainResolver domainResolver)
: this(new ReverseProxyHttpClientHandler(domainConfig, domainResolver), disposeHandler: true)
@@ -36,14 +36,14 @@ public class ReverseProxyHttpClient : HttpMessageInvoker
/// <exception cref="Exception"></exception>
public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.Headers.UserAgent.Contains(userAgent))
{
const string message =
$"Because {{0}} actually points to {Constants.HARDCODED_APP_NAME_NEW} itself, " +
$"{Constants.HARDCODED_APP_NAME_NEW} has interrupted this forwarding";
throw new ApplicationException(string.Format(message, request.RequestUri));
}
request.Headers.UserAgent.Add(userAgent);
//if (request.Headers.UserAgent.Contains(userAgent))
//{
// const string message =
// $"Because {{0}} actually points to {Constants.HARDCODED_APP_NAME_NEW} itself, " +
// $"{Constants.HARDCODED_APP_NAME_NEW} has interrupted this forwarding";
// throw new ApplicationException(string.Format(message, request.RequestUri));
//}
//request.Headers.UserAgent.Add(userAgent);
var response = await base.SendAsync(request, cancellationToken);
response.Headers.Server.TryParseAdd(Constants.HARDCODED_APP_NAME_NEW);
return response;
@@ -62,7 +62,7 @@ sealed class ReverseProxyHttpClientHandler : DelegatingHandler
/// <returns></returns>
SocketsHttpHandler CreateSocketsHttpHandler() => GeneralHttpClientFactory.CreateSocketsHttpHandler(new()
{
Proxy = null,
Proxy = GeneralHttpClientFactory.HttpNoProxy.Instance,
UseProxy = false,
UseCookies = false,
AllowAutoRedirect = false,
@@ -3,6 +3,7 @@ using System.Application.Models;
using Microsoft.AspNetCore.Http;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Http.Extensions;
using System.Net;
namespace System.Application.Services.Implementation.HttpServer.Middleware;
@@ -12,10 +13,16 @@ namespace System.Application.Services.Implementation.HttpServer.Middleware;
sealed class HttpLocalRequestMiddleware
{
readonly IReverseProxyConfig reverseProxyConfig;
readonly CookieHttpClient cookieHttpClient;
public HttpLocalRequestMiddleware(IReverseProxyConfig reverseProxyConfig)
HttpClient HttpClient => cookieHttpClient.HttpClient;
public HttpLocalRequestMiddleware(
IReverseProxyConfig reverseProxyConfig,
CookieHttpClient cookieHttpClient)
{
this.reverseProxyConfig = reverseProxyConfig;
this.cookieHttpClient = cookieHttpClient;
}
/// <summary>
@@ -26,9 +33,15 @@ sealed class HttpLocalRequestMiddleware
/// <returns></returns>
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (HttpMethods.IsOptions(context.Request.Method) && context.Request.Headers.ContainsKey("Access-Control-Request-Private-Network"))
{
// https://wicg.github.io/private-network-access/
context.Response.Headers["Access-Control-Allow-Private-Network"] = "true";
}
if (context.Request.Host.Host.Equals(IReverseProxyService.LocalDomain, StringComparison.OrdinalIgnoreCase))
{
if (context.Request.Method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase))
if (HttpMethods.IsOptions(context.Request.Method))
{
context.Response.Headers.AccessControlAllowOrigin = context.Request.Headers.Origin.Count == 0 ? "*" : context.Request.Headers.Origin;
context.Response.Headers.AccessControlAllowHeaders = "*";
@@ -66,6 +79,7 @@ sealed class HttpLocalRequestMiddleware
return;
}
}
await next(context);
}
@@ -74,81 +88,98 @@ sealed class HttpLocalRequestMiddleware
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
static async Task HandleHttpRequestAsync(HttpContext context)
async Task HandleHttpRequestAsync(HttpContext context)
{
if (string.IsNullOrEmpty(context.Request.QueryString.Value))
return;
var url = Web.HttpUtility.UrlDecode(context.Request.QueryString.Value.Replace("?request=", ""));
string? cookie = context.Request.Headers["cookie-steamTool"];
if (string.IsNullOrEmpty(cookie))
cookie = context.Request.Headers["Cookie"];
string? referer = context.Request.Headers["Referer-steamTool"];
context.Response.Headers.AccessControlAllowOrigin = context.Request.Headers.Origin.Count == 0 ? "*" : context.Request.Headers.Origin;
context.Response.Headers.AccessControlAllowHeaders = "*";
context.Response.Headers.AccessControlAllowMethods = "*";
context.Response.Headers.AccessControlAllowCredentials = "true";
//if (cookie != null)
// context.Response.Cookies.Append(cookie);
if (context.Request.ContentType != null)
context.Response.Headers.ContentType = context.Request.ContentType;
if (context.Request.Method == HttpMethods.Get)
try
{
var body = await IHttpService.Instance.GetAsync<string>(url, cookie: cookie);
if (string.IsNullOrEmpty(body))
if (string.IsNullOrEmpty(context.Request.QueryString.Value))
return;
var url = Web.HttpUtility.UrlDecode(context.Request.QueryString.Value.Replace("?request=", ""));
string? cookie = context.Request.Headers["cookie-steamTool"];
if (string.IsNullOrEmpty(cookie))
cookie = context.Request.Headers["Cookie"];
string? referer = context.Request.Headers["Referer-steamTool"];
context.Response.Headers.AccessControlAllowOrigin = context.Request.Headers.Origin.Count == 0 ? "*" : context.Request.Headers.Origin;
context.Response.Headers.AccessControlAllowHeaders = "*";
context.Response.Headers.AccessControlAllowMethods = "*";
context.Response.Headers.AccessControlAllowCredentials = "true";
//if (cookie != null)
// context.Response.Cookies.Append(cookie);
if (context.Request.ContentType != null)
context.Response.Headers.ContentType = context.Request.ContentType;
async Task SendAsync()
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
}
await context.Response.WriteAsync(body);
}
else if (context.Request.Method == HttpMethods.Post)
{
try
{
if (context.Request.ContentLength > 0)
var method = context.Request.Method;
var hasContent = method != HttpMethods.Get && context.Request.ContentLength > 0;
var req = new HttpRequestMessage
{
var conext = await IHttpService.Instance.SendAsync<string>(url, () =>
RequestUri = new Uri(url),
Method = new(method),
Content = hasContent ? new StreamContent(context.Request.Body) : null,
};
req.Headers.UserAgent.ParseAdd(context.Request.Headers.UserAgent);
if (cookie != null)
{
CookieHttpClient.CookieContainer.Add(new Cookie
{
var req = new HttpRequestMessage
{
RequestUri = new Uri(url),
Method = HttpMethod.Post,
Content = new StreamContent(context.Request.Body),
};
if (cookie != null)
{
req.Headers.Add("Cookie", cookie);
}
if (referer != null)
req.Headers.Referrer = new Uri(referer);
req.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType);
req.Content.Headers.ContentLength = context.Request.ContentLength;
return req;
}, null/*, false*/, default);
if (string.IsNullOrEmpty(conext))
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
return;
}
await context.Response.WriteAsync(conext);
CommentUri = req.RequestUri,
Domain = req.RequestUri.Host,
Value = cookie
});
// req.Headers.Add("Cookie", cookie);
}
if (referer != null) req.Headers.Referrer = new Uri(referer);
if (hasContent)
{
req.Content!.Headers.ContentType = MediaTypeHeaderValue.Parse(context.Request.ContentType);
req.Content.Headers.ContentLength = context.Request.ContentLength;
}
var rsp = await HttpClient.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted).ConfigureAwait(false);
if (rsp.IsSuccessStatusCode && rsp.Content != null)
{
context.Response.StatusCode = StatusCodes.Status200OK;
using var body = await rsp.Content.ReadAsStreamAsync(context.RequestAborted);
await body.CopyToAsync(context.Response.BodyWriter.AsStream(), context.RequestAborted);
}
else
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
return;
}
}
catch (Exception error)
if (context.Request.Method == HttpMethods.Get)
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
await context.Response.WriteAsync(error.Message);
await SendAsync();
return;
}
else if (context.Request.Method == HttpMethods.Post)
{
if (context.Request.ContentLength > 0)
{
await SendAsync();
return;
}
}
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
}
catch (Exception error)
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
await context.Response.WriteAsync(error.Message, context.RequestAborted);
}
}
static async Task HandleStatusCodeAsync(HttpContext context, int statusCode)
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(string.Empty, context.RequestAborted);
}
/// <summary>
@@ -156,9 +187,6 @@ sealed class HttpLocalRequestMiddleware
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
static async Task Handle404NotFoundAsync(HttpContext context)
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
await context.Response.WriteAsync(string.Empty);
}
static Task Handle404NotFoundAsync(HttpContext context)
=> HandleStatusCodeAsync(context, StatusCodes.Status404NotFound);
}
@@ -1,5 +1,6 @@
// https://github.com/dotnetcore/FastGithub/blob/2.1.4/FastGithub.HttpServer/HttpReverseProxyMiddleware.cs
using DynamicData.Kernel;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Logging;
@@ -60,17 +61,27 @@ sealed class HttpReverseProxyMiddleware
if (TryGetDomainConfig(url, out var domainConfig) == false)
{
await next(context);
if (isScriptInject)
await HandleScriptInject(context, scriptConfigs, memoryStream!, originalBody!);
return;
}
if (domainConfig == defaultDomainConfig)
{
//部分运营商将奇怪的域名解析到127.0.0.1 再此排除这些不支持的代理域名
var ip = await IDnsAnalysisService.Instance.AnalysisDomainIpAsync(url, IDnsAnalysisService.DNS_Alis).FirstOrDefaultAsync();
if (ip == null || IPAddress.IsLoopback(ip))
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
await context.Response.WriteAsync($"域名 {context.Request.Host.Host} 可能已经被 DNS 污染,如果域名为本机域名,请解析为非回环 IP。");
return;
}
}
if (domainConfig.Items.Any_Nullable())
domainConfig = RecursionMatchDomainConfig(url, domainConfig);
if (domainConfig.Response == null)
{
if (IReverseProxyService.Instance.EnableHttpProxyToHttps && context.Request.Scheme == Uri.UriSchemeHttp)
if (reverseProxyConfig.Service.EnableHttpProxyToHttps && context.Request.Scheme == Uri.UriSchemeHttp)
{
context.Response.Redirect(Uri.UriSchemeHttps + "://" + context.Request.Host.Host + context.Request.RawUrl());
return;
@@ -126,7 +137,7 @@ sealed class HttpReverseProxyMiddleware
{
domainConfig = null;
if (!IReverseProxyService.Instance.OnlyEnableProxyScript && reverseProxyConfig.TryGetDomainConfig(uri, out domainConfig) == true)
if (!reverseProxyConfig.Service.OnlyEnableProxyScript && reverseProxyConfig.TryGetDomainConfig(uri, out domainConfig) == true)
{
return true;
}
@@ -135,9 +146,8 @@ sealed class HttpReverseProxyMiddleware
// 未配置的域名,但仍然被解析到本机 IP 的域名
if (IsDomain(host))
{
if (IReverseProxyService.Instance.ProxyMode != ProxyMode.System)
logger.LogWarning(
$"域名 {host} 可能已经被 DNS 污染,如果域名为本机域名,请解析为非回环 IP。");
logger.LogWarning(
$"域名 {host} 可能已经被 DNS 污染,如果域名为本机域名,请解析为非回环 IP。");
domainConfig = defaultDomainConfig;
return true;
}
@@ -487,18 +497,24 @@ sealed class HttpReverseProxyMiddleware
match_mark_start_index++;
if (match_mark_start_index >= mark_start.Length)
{
const int matchCharCount = 4;
var index_name_start = i + mark_start.Length;
var name = encoding.GetString(buffer.Span[index_name_start..index_name_end]);
if (name.Equals("body", StringComparison.OrdinalIgnoreCase) ||
name.Equals("head", StringComparison.OrdinalIgnoreCase))
//if (encoding.GetMaxCharCount(index_name_end - index_name_start) >= matchCharCount)
//{
var bytes = buffer.Span[index_name_start..index_name_end];
var charCount = encoding.GetCharCount(bytes);
if (charCount == matchCharCount)
{
insertPosition = index_name_start - mark_start.Length;
return true;
}
else
{
goto reset;
var name = encoding.GetString(bytes);
if (name.Equals("body", StringComparison.OrdinalIgnoreCase) ||
name.Equals("head", StringComparison.OrdinalIgnoreCase))
{
insertPosition = index_name_start - mark_start.Length;
return true;
}
}
//}
goto reset;
}
}
}
@@ -78,13 +78,13 @@ public interface ICertificateManager
/// <summary>
/// 由平台实现的信任根证书引导,有 Root 权限将尝试执行信任,否则则 UI 引导,跳转网页或弹窗
/// </summary>
void PlatformTrustRootCertificateGuide();
ValueTask PlatformTrustRootCertificateGuide();
/// <summary>
/// 安装根证书,如果没有证书将生成一个新的
/// </summary>
/// <returns>返回根证书是否受信任</returns>
bool SetupRootCertificate();
ValueTask<bool> SetupRootCertificate();
/// <summary>
/// 删除根证书,如果没有证书将返回 <see langword="true"/>
@@ -117,7 +117,7 @@ public interface IReverseProxyService : IDisposable
/// <returns></returns>
bool PortInUse(int port);
Task<bool> StartProxy();
ValueTask<bool> StartProxy();
Task StopProxy();
@@ -87,7 +87,7 @@ abstract partial class CertificateManagerImpl
}
}
void TrustRootCertificate()
async ValueTask TrustRootCertificate()
{
try
{
@@ -102,17 +102,17 @@ abstract partial class CertificateManagerImpl
catch { }
#endif
PlatformTrustRootCertificateGuide();
await PlatformTrustRootCertificateGuide();
}
/// <inheritdoc cref="ICertificateManager.PlatformTrustRootCertificateGuide"/>
public void PlatformTrustRootCertificateGuide()
public async ValueTask PlatformTrustRootCertificateGuide()
{
try
{
if (OperatingSystem2.IsMacOS())
{
TrustRootCertificateMacOS();
await TrustRootCertificateMacOS();
}
else if (OperatingSystem2.IsLinux() && !OperatingSystem2.IsAndroid())
{
@@ -130,11 +130,14 @@ abstract partial class CertificateManagerImpl
}
[SupportedOSPlatform("macOS")]
void TrustRootCertificateMacOS()
async ValueTask TrustRootCertificateMacOS()
{
var filePath = GetCerFilePathGeneratedWhenNoFileExists();
if (filePath == null) return;
platformService.RunShell($"security add-trusted-cert -d -r trustRoot -k /Users/{Environment.UserName}/Library/Keychains/login.keychain-db \\\"{filePath}\\\"", true);
var state = await platformService.TrustRootCertificate(filePath);
//await platformService.RunShellAsync($"security add-trusted-cert -d -r trustRoot -k /Users/{Environment.UserName}/Library/Keychains/login.keychain-db \\\"{filePath}\\\"", true);
if (state != null && !IsRootCertificateInstalled)
await TrustRootCertificateMacOS();
}
[SupportedOSPlatform("Linux")]
@@ -152,12 +155,12 @@ abstract partial class CertificateManagerImpl
}
/// <inheritdoc cref="ICertificateManager.SetupRootCertificate"/>
public bool SetupRootCertificate()
public async ValueTask<bool> SetupRootCertificate()
{
if (!GenerateCertificate()) return false;
if (!IsRootCertificateInstalled)
{
TrustRootCertificate();
await TrustRootCertificate();
return IsRootCertificateInstalled;
}
return true;
@@ -153,14 +153,15 @@ abstract class ReverseProxyServiceImpl
public abstract EReverseProxyEngine ReverseProxyEngine { get; }
public async Task<bool> StartProxy()
public async ValueTask<bool> StartProxy()
{
if (!CertificateManager.IsRootCertificateInstalled)
{
//CertificateManager.DeleteRootCertificate();
var isOk = CertificateManager.SetupRootCertificate();
var isOk = await CertificateManager.SetupRootCertificate();
if (!isOk)
{
Log.Error("StartProxy", "证书安装失败,或未信任。");
return false;
}
}
+9 -1
View File
@@ -7,6 +7,10 @@
<AssemblyName>System.Application.SteamTools.Client</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" $(TargetFramework.Contains('-android')) ">
<DefineConstants>EXCLUDE_ASF;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
@@ -42,8 +46,11 @@
<PackageReference Include="JustArchiNET.Madness" />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition=" !$(TargetFramework.Contains('-android')) ">
<ProjectReference Include="..\..\references\ArchiSteamFarm\ArchiSteamFarm.Library\ArchiSteamFarm.Library.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common.PinyinLib\Common.PinyinLib.csproj" />
<ProjectReference Include="..\Repositories.sqlite-net-pcl\Repositories.sqlite-net-pcl.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy\ST.Client.ReverseProxy.csproj" />
@@ -84,4 +91,5 @@
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
</ItemGroup>
</Project>
@@ -1,3 +1,4 @@
#if !EXCLUDE_ASF
using ArchiSteamFarm;
using ArchiSteamFarm.Steam;
using ArchiSteamFarm.Storage;
@@ -79,4 +80,5 @@ namespace System.Application.Services
}
}
}
}
}
#endif
@@ -1,3 +1,4 @@
#if !EXCLUDE_ASF
using ArchiSteamFarm;
using System.Application.Settings;
using System.Collections.Generic;
@@ -30,3 +31,4 @@ partial interface IArchiSteamFarmService : IArchiSteamFarmHelperService
}
}
}
#endif
@@ -12,6 +12,11 @@ namespace System.Application.Services
return true;
}
async ValueTask<bool?> TrustRootCertificate(string filePath)
{
return true;
}
/// <summary>
/// 删除证书
/// </summary>
@@ -31,6 +31,8 @@ namespace System.Application.Services
/// <inheritdoc cref="RunShell(string, bool)"/>
ValueTask RunShellAsync(string script, bool admin = false) => default;
ValueTask<bool?> RunShellReturnAsync(string script, bool admin = false) => default;
/// <summary>
/// 使用文本阅读器打开文件
/// </summary>
@@ -300,8 +300,6 @@ namespace System.Application.Services.Implementation
isDownloading = true;
OnReport();
var newVersionInfo = NewVersionInfo;
if (newVersionInfo.HasValue())
@@ -325,6 +323,8 @@ namespace System.Application.Services.Implementation
newVersionInfo.AllFiles.Any_Nullable() &&
newVersionInfo.AllFiles.All(x => x.HasValue())) // 增量更新 v2
{
OnReport();
if (Path.DirectorySeparatorChar != '\\') // 路径分隔符在客户端系统上与服务端纪录的值不同时,替换分隔符
{
void CorrectionDirectorySeparatorChar(IEnumerable<AppVersionDTO.IncrementalUpdateDownload> items)
@@ -475,6 +475,8 @@ namespace System.Application.Services.Implementation
}
if (download.HasValue()) // 压缩包格式是否正确
{
OnReport();
var packFileName = GetPackName(newVersionInfo, isDirOrFile: true);
var packFilePath = Path.Combine(GetPackCacheDirPath(!isSupportedResume), packFileName);
if (File.Exists(packFilePath)) // 存在压缩包文件
@@ -1,3 +1,4 @@
#if !EXCLUDE_ASF
using System.Security;
using System.Threading.Tasks;
using System.Application.UI.ViewModels;
@@ -67,4 +68,5 @@ namespace System.Application.Services
/// <returns></returns>
Task SetEncryptionKeyAsync();
}
}
}
#endif
@@ -1,3 +1,4 @@
#if !EXCLUDE_ASF
using ArchiSteamFarm;
using ArchiSteamFarm.Core;
using ArchiSteamFarm.Library;
@@ -7,6 +8,7 @@ using ArchiSteamFarm.Steam;
using ArchiSteamFarm.Steam.Storage;
using ArchiSteamFarm.Storage;
using Microsoft.Extensions.Configuration;
using Nito.AsyncEx;
using NLog;
using ReactiveUI;
using System.Application.UI;
@@ -36,6 +38,8 @@ namespace System.Application.Services.Implementation
public TaskCompletionSource<string>? ReadLineTask { get; set; }
private readonly AsyncLock @lock = new AsyncLock();
bool _IsReadPasswordLine;
public bool IsReadPasswordLine
@@ -68,17 +72,20 @@ namespace System.Application.Services.Implementation
ArchiSteamFarm.NLog.Logging.GetUserInputFunc = async (bool isPassword) =>
{
ReadLineTask = new(TaskCreationOptions.AttachedToParent);
IsReadPasswordLine = isPassword;
using (await @lock.LockAsync())
{
ReadLineTask = new(TaskCreationOptions.AttachedToParent);
IsReadPasswordLine = isPassword;
#if NET6_0_OR_GREATER
var result = await ReadLineTask.Task.WaitAsync(TimeSpan.FromSeconds(60));
var result = await ReadLineTask.Task.WaitAsync(TimeSpan.FromSeconds(60));
#else
var result = await ReadLineTask.Task;
var result = await ReadLineTask.Task;
#endif
if (IsReadPasswordLine)
IsReadPasswordLine = false;
ReadLineTask = null;
return result;
if (IsReadPasswordLine)
IsReadPasswordLine = false;
ReadLineTask = null;
return result;
}
};
await ReadEncryptionKeyAsync();
@@ -281,3 +288,4 @@ namespace System.Application.Services.Implementation
//}
}
}
#endif
@@ -1,5 +1,6 @@
using ReactiveUI;
using System.Application.Mvvm;
using System.Application.UI;
using System.Application.UI.ViewModels;
using System.Collections.Generic;
using System.Linq;
+8 -8
View File
@@ -147,7 +147,7 @@ namespace System.Application.Services
{
proxyip = IPAddress.Loopback;
}
if (!IPlatformService.Instance.SetAsSystemProxy(true, proxyip, reverseProxyService.ProxyPort))
if (!platformService.SetAsSystemProxy(true, proxyip, reverseProxyService.ProxyPort))
{
Toast.Show("系统代理开启失败");
return;
@@ -160,7 +160,7 @@ namespace System.Application.Services
{
proxyip = IPAddress.Loopback;
}
if (!IPlatformService.Instance.SetAsSystemPACProxy(true, $"http://{proxyip}:{reverseProxyService.ProxyPort}/pac"))
if (!platformService.SetAsSystemPACProxy(true, $"http://{proxyip}:{reverseProxyService.ProxyPort}/pac"))
{
Toast.Show("PAC代理开启失败");
return;
@@ -258,11 +258,11 @@ namespace System.Application.Services
}
else if (reverseProxyService.ProxyMode == ProxyMode.System)
{
IPlatformService.Instance.SetAsSystemProxy(false);
platformService.SetAsSystemProxy(false);
}
else if (reverseProxyService.ProxyMode == ProxyMode.PAC)
{
IPlatformService.Instance.SetAsSystemPACProxy(false);
platformService.SetAsSystemPACProxy(false);
}
}
});
@@ -806,8 +806,8 @@ namespace System.Application.Services
if (OperatingSystem2.IsWindows())
{
await reverseProxyService.StopProxy();
IPlatformService.Instance.SetAsSystemProxy(false);
IPlatformService.Instance.SetAsSystemPACProxy(false);
platformService.SetAsSystemProxy(false);
platformService.SetAsSystemPACProxy(false);
Process.Start("cmd.exe", "netsh winsock reset");
}
@@ -830,11 +830,11 @@ namespace System.Application.Services
}
else if (reverseProxyService.ProxyMode == ProxyMode.System)
{
IPlatformService.Instance.SetAsSystemProxy(false);
platformService.SetAsSystemProxy(false);
}
else if (reverseProxyService.ProxyMode == ProxyMode.PAC)
{
IPlatformService.Instance.SetAsSystemPACProxy(false);
platformService.SetAsSystemPACProxy(false);
}
}
reverseProxyService.Dispose();
+6 -16
View File
@@ -1,19 +1,9 @@
using System.Collections.Generic;
using System.Application.UI;
using System.Runtime.Versioning;
using System.Application.Services;
#if !EXCLUDE_ASF
namespace System.Application.Settings
namespace System.Application.Settings;
partial class ASFSettings
{
partial class ASFSettings
{
//static readonly SerializableProperty<string>? _ConsoleFontName = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: IFontManager.KEY_Default, autoSave: true) : null;
///// <summary>
///// 字体
///// </summary>
//[SupportedOSPlatform("Windows7.0")]
//[SupportedOSPlatform("macOS")]
//[SupportedOSPlatform("Linux")]
//public static SerializableProperty<string> ConsoleFontName => _ConsoleFontName ?? throw new PlatformNotSupportedException();
}
}
#endif
+51 -55
View File
@@ -1,69 +1,65 @@
using System.Application.Services;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
#if !EXCLUDE_ASF
namespace System.Application.Settings
namespace System.Application.Settings;
public sealed partial class ASFSettings : SettingsHost2<ASFSettings>
{
public sealed partial class ASFSettings : SettingsHost2<ASFSettings>
{
/// <summary>
/// ASF路径
/// </summary>
public static SerializableProperty<string> ArchiSteamFarmExePath { get; }
= GetProperty(defaultValue: string.Empty, autoSave: true);
/// <summary>
/// ASF路径
/// </summary>
public static SerializableProperty<string> ArchiSteamFarmExePath { get; }
= GetProperty(defaultValue: string.Empty);
/// <summary>
/// 程序启动时自动运行ASF
/// </summary>
public static SerializableProperty<bool> AutoRunArchiSteamFarm { get; }
= GetProperty(defaultValue: false, autoSave: true);
/// <summary>
/// 程序启动时自动运行ASF
/// </summary>
public static SerializableProperty<bool> AutoRunArchiSteamFarm { get; }
= GetProperty(defaultValue: false);
#region ConsoleMaxLine
#region ConsoleMaxLine
/// <summary>
/// 控制台默认最大行数
/// </summary>
public const int DefaultConsoleMaxLine = 200;
/// <summary>
/// 控制台默认最大行数
/// </summary>
public const int DefaultConsoleMaxLine = 200;
/// <summary>
/// 控制台默认最大行数范围最小值
/// </summary>
public const int MinRangeConsoleMaxLine = DefaultConsoleMaxLine;
/// <summary>
/// 控制台默认最大行数范围最小值
/// </summary>
public const int MinRangeConsoleMaxLine = DefaultConsoleMaxLine;
/// <summary>
/// 控制台默认最大行数范围最大值
/// </summary>
public const int MaxRangeConsoleMaxLine = 5000;
/// <summary>
/// 控制台默认最大行数范围最大值
/// </summary>
public const int MaxRangeConsoleMaxLine = 5000;
public static SerializableProperty<int> ConsoleMaxLine { get; }
= GetProperty(defaultValue: DefaultConsoleMaxLine, autoSave: true);
public static SerializableProperty<int> ConsoleMaxLine { get; }
= GetProperty(defaultValue: DefaultConsoleMaxLine);
#endregion
#endregion
public const int DefaultConsoleFontSize = 14;
public const int MinRangeConsoleFontSize = 8;
public const int MaxRangeConsoleFontSize = 24;
public const int DefaultConsoleFontSize = 14;
public const int MinRangeConsoleFontSize = 8;
public const int MaxRangeConsoleFontSize = 24;
/// <summary>
/// 控制台字体大小,默认值 14,Android 上单位为 sp
/// </summary>
public static SerializableProperty<int> ConsoleFontSize { get; }
= GetProperty(defaultValue: DefaultConsoleFontSize, autoSave: true);
/// <summary>
/// 控制台字体大小,默认值 14,Android 上单位为 sp
/// </summary>
public static SerializableProperty<int> ConsoleFontSize { get; }
= GetProperty(defaultValue: DefaultConsoleFontSize);
public const int DefaultIPCPortIdValue = 6242;
public const int DefaultIPCPortIdValue = 6242;
/// <summary>
/// IPC 端口号,默认值为 <see cref="DefaultIPCPortIdValue"/>
/// </summary>
public static SerializableProperty<int> IPCPortId { get; }
= GetProperty(defaultValue: DefaultIPCPortIdValue, autoSave: true);
/// <summary>
/// IPC 端口号,默认值为 <see cref="DefaultIPCPortIdValue"/>
/// </summary>
public static SerializableProperty<int> IPCPortId { get; }
= GetProperty(defaultValue: DefaultIPCPortIdValue);
/// <summary>
/// IPC 端口号被占用时是否随机一个未使用的端口号,默认值 <see langword="true"/>
/// </summary>
public static SerializableProperty<bool> IPCPortOccupiedRandom { get; }
= GetProperty(defaultValue: true, autoSave: true);
}
}
/// <summary>
/// IPC 端口号被占用时是否随机一个未使用的端口号,默认值 <see langword="true"/>
/// </summary>
public static SerializableProperty<bool> IPCPortOccupiedRandom { get; }
= GetProperty(defaultValue: true);
}
#endif
@@ -1,225 +1,221 @@
using System.Application.UI;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Versioning;
using System.Application.Models;
namespace System.Application.Settings
namespace System.Application.Settings;
partial class GameLibrarySettings
{
partial class GameLibrarySettings
{
static readonly SerializableProperty<bool> _GameIsInstalledFilter = GetProperty(defaultValue: false, autoSave: true);
static readonly SerializableProperty<bool> _GameIsInstalledFilter = GetProperty(defaultValue: false);
/// <summary>
/// 已安装游戏筛选
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> GameIsInstalledFilter => _GameIsInstalledFilter;
/// <summary>
/// 已安装游戏筛选
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> GameIsInstalledFilter => _GameIsInstalledFilter;
static readonly SerializableProperty<bool> _GameIsCloudArchiveFilter = GetProperty(defaultValue: false, autoSave: true);
static readonly SerializableProperty<bool> _GameIsCloudArchiveFilter = GetProperty(defaultValue: false);
/// <summary>
/// 支持云存档游戏筛选状态
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> GameIsCloudArchiveFilter => _GameIsCloudArchiveFilter;
/// <summary>
/// 支持云存档游戏筛选状态
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> GameIsCloudArchiveFilter => _GameIsCloudArchiveFilter;
static readonly SerializableProperty<List<SteamAppType>>? _GameTypeFiltres = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: new List<SteamAppType> { SteamAppType.Game, SteamAppType.Application, SteamAppType.Demo, SteamAppType.Beta }, autoSave: true) : null;
static readonly SerializableProperty<List<SteamAppType>>? _GameTypeFiltres = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: new List<SteamAppType> { SteamAppType.Game, SteamAppType.Application, SteamAppType.Demo, SteamAppType.Beta }) : null;
/// <summary>
/// 游戏类型筛选状态列表
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<List<SteamAppType>> GameTypeFiltres => _GameTypeFiltres ?? throw new PlatformNotSupportedException();
/// <summary>
/// 游戏类型筛选状态列表
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<List<SteamAppType>> GameTypeFiltres => _GameTypeFiltres ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<Dictionary<uint, string?>>? _HideGameList = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: new Dictionary<uint, string?>(), autoSave: true) : null;
static readonly SerializableProperty<Dictionary<uint, string?>>? _HideGameList = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: new Dictionary<uint, string?>()) : null;
/// <summary>
/// 隐藏的游戏列表
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<Dictionary<uint, string?>> HideGameList => _HideGameList ?? throw new PlatformNotSupportedException();
/// <summary>
/// 隐藏的游戏列表
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<Dictionary<uint, string?>> HideGameList => _HideGameList ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<Dictionary<uint, string?>?>? _AFKAppList = IApplication.IsDesktopPlatform ?
GetProperty<Dictionary<uint, string?>?>(defaultValue: null, autoSave: true) : null;
static readonly SerializableProperty<Dictionary<uint, string?>?>? _AFKAppList = IApplication.IsDesktopPlatform ?
GetProperty<Dictionary<uint, string?>?>(defaultValue: null) : null;
/// <summary>
/// 挂时长游戏列表
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<Dictionary<uint, string?>?> AFKAppList => _AFKAppList ?? throw new PlatformNotSupportedException();
/// <summary>
/// 挂时长游戏列表
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<Dictionary<uint, string?>?> AFKAppList => _AFKAppList ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsAutoAFKApps
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsAutoAFKApps
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
/// <summary>
/// 启用自动挂机
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsAutoAFKApps => _IsAutoAFKApps ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用自动挂机
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsAutoAFKApps => _IsAutoAFKApps ?? throw new PlatformNotSupportedException();
// [SupportedOSPlatform("Windows7.0")]
// [SupportedOSPlatform("macOS")]
// [SupportedOSPlatform("Linux")]
// public static readonly Lazy<ReadOnlyCollection<uint>>? DefaultIgnoreList = IApplication.IsDesktopPlatform ? new(new ReadOnlyCollection<uint>(new uint[]
// {
// 5,
// 7,
// 8,
// 90,
// 92,
// 205,
// 211,
// 215,
// 218,
// 310,
// 364,
// 459,
// 480,
// 513,
// 563,
// 564,
// 575,
// 629,
// 635,
// 640,
// 644,
// 740,
// 745,
// 753,
// 760,
// 761,
// 764,
// 765,
// 766,
// 767,
// 1007,
// 1213,
// 1255,
// 1260,
// 1273,
// 2145,
// 2403,
// 4270,
// 4940,
// 8680,
// 8710,
// 8730,
// 8770,
// 12250,
// 12750,
// 13180,
// 13260,
// 16830,
// 16864,
// 16865,
// 16871,
// 16872,
// 16879,
// 17505,
// 17515,
// 17525,
// 17535,
// 17555,
// 17575,
// 17585,
// 17705,
// 61800,
// 61810,
// 61820,
// 61830,
// 104700,
// 201700,
// 224220,
// 232610,
// 375350,
// 245550,
// 254000,
// 254020,
// 254040,
// 259280,
// 285050,
// 312710,
// 314700,
// 321040,
// 329950,
// 331710,
// 344750,
// 354850,
// 368900,
// 373110,
// 383030,
// 385200,
// 388870,
// 392050,
// 392870,
// 395980,
// 397620,
// 399580,
// 407730,
// 407740,
// 407750,
// 410590,
// 410700,
// 416270,
// 428430,
// 431270,
// 432150,
// 447880,
// 449630,
// 457930,
// 457940,
// 460660,
// 461570,
// 462370,
// 463620,
// 473580,
// 473620,
// 473630,
// 473640,
// 473650,
// 486340,
// 488200,
// 491250,
// 492240,
// 496600,
// 501690,
// 505440,
// 509840,
// 516230,
// 516700,
// 524440,
// 526790,
// 528210,
// 533710,
// 545950,
// 546450,
// 559500,
// 559940,
// 562020,
// 576080,
// 576440,
// 581620,
// 592490,
// 603770,
// 603780,
// 605470,
// 654310,
// 700580
//})) : null;
}
// [SupportedOSPlatform("Windows7.0")]
// [SupportedOSPlatform("macOS")]
// [SupportedOSPlatform("Linux")]
// public static readonly Lazy<ReadOnlyCollection<uint>>? DefaultIgnoreList = IApplication.IsDesktopPlatform ? new(new ReadOnlyCollection<uint>(new uint[]
// {
// 5,
// 7,
// 8,
// 90,
// 92,
// 205,
// 211,
// 215,
// 218,
// 310,
// 364,
// 459,
// 480,
// 513,
// 563,
// 564,
// 575,
// 629,
// 635,
// 640,
// 644,
// 740,
// 745,
// 753,
// 760,
// 761,
// 764,
// 765,
// 766,
// 767,
// 1007,
// 1213,
// 1255,
// 1260,
// 1273,
// 2145,
// 2403,
// 4270,
// 4940,
// 8680,
// 8710,
// 8730,
// 8770,
// 12250,
// 12750,
// 13180,
// 13260,
// 16830,
// 16864,
// 16865,
// 16871,
// 16872,
// 16879,
// 17505,
// 17515,
// 17525,
// 17535,
// 17555,
// 17575,
// 17585,
// 17705,
// 61800,
// 61810,
// 61820,
// 61830,
// 104700,
// 201700,
// 224220,
// 232610,
// 375350,
// 245550,
// 254000,
// 254020,
// 254040,
// 259280,
// 285050,
// 312710,
// 314700,
// 321040,
// 329950,
// 331710,
// 344750,
// 354850,
// 368900,
// 373110,
// 383030,
// 385200,
// 388870,
// 392050,
// 392870,
// 395980,
// 397620,
// 399580,
// 407730,
// 407740,
// 407750,
// 410590,
// 410700,
// 416270,
// 428430,
// 431270,
// 432150,
// 447880,
// 449630,
// 457930,
// 457940,
// 460660,
// 461570,
// 462370,
// 463620,
// 473580,
// 473620,
// 473630,
// 473640,
// 473650,
// 486340,
// 488200,
// 491250,
// 492240,
// 496600,
// 501690,
// 505440,
// 509840,
// 516230,
// 516700,
// 524440,
// 526790,
// 528210,
// 533710,
// 545950,
// 546450,
// 559500,
// 559940,
// 562020,
// 576080,
// 576440,
// 581620,
// 592490,
// 603770,
// 603780,
// 605470,
// 654310,
// 700580
//})) : null;
}
@@ -1,13 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
namespace System.Application.Settings;
namespace System.Application.Settings
public sealed partial class GameLibrarySettings : SettingsHost2<GameLibrarySettings>
{
public sealed partial class GameLibrarySettings : SettingsHost2<GameLibrarySettings>
{
}
}
@@ -1,17 +1,14 @@
using System.Collections.Generic;
using System.Text;
using System.Runtime.Versioning;
namespace System.Application.Settings
{
partial class GeneralSettings
{
static readonly SerializableProperty<bool>? _CaptureScreen = OperatingSystem2.IsAndroid() ? GetProperty(defaultValue: false, autoSave: true) : null;
namespace System.Application.Settings;
/// <summary>
/// 屏幕捕获(允许截图)
/// </summary>
[SupportedOSPlatform("Android")]
public static SerializableProperty<bool> CaptureScreen => _CaptureScreen ?? throw new PlatformNotSupportedException();
}
partial class GeneralSettings
{
static readonly SerializableProperty<bool>? _CaptureScreen = OperatingSystem2.IsAndroid() ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 屏幕捕获(允许截图)
/// </summary>
[SupportedOSPlatform("Android")]
public static SerializableProperty<bool> CaptureScreen => _CaptureScreen ?? throw new PlatformNotSupportedException();
}
@@ -1,127 +1,122 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using System.Properties;
using System.Application.Services;
using System.Application.UI;
using System.Runtime.Versioning;
namespace System.Application.Settings
namespace System.Application.Settings;
partial class GeneralSettings
{
partial class GeneralSettings
{
static readonly SerializableProperty<bool>? _WindowsStartupAutoRun = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _WindowsStartupAutoRun = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 程序是否开机自启动
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> WindowsStartupAutoRun => _WindowsStartupAutoRun ?? throw new PlatformNotSupportedException();
/// <summary>
/// 程序是否开机自启动
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> WindowsStartupAutoRun => _WindowsStartupAutoRun ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsStartupAppMinimized = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsStartupAppMinimized = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 程序启动时最小化
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsStartupAppMinimized => _IsStartupAppMinimized ?? throw new PlatformNotSupportedException();
/// <summary>
/// 程序启动时最小化
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsStartupAppMinimized => _IsStartupAppMinimized ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsEnableTrayIcon = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsEnableTrayIcon = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
/// <summary>
/// 启用托盘
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsEnableTrayIcon => _IsEnableTrayIcon ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用托盘
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsEnableTrayIcon => _IsEnableTrayIcon ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsSteamAppListLocalCache
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsSteamAppListLocalCache
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
/// <summary>
/// 启用游戏列表本地缓存
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsSteamAppListLocalCache => _IsSteamAppListLocalCache ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用游戏列表本地缓存
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsSteamAppListLocalCache => _IsSteamAppListLocalCache ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<IReadOnlyDictionary<Platform, string>>? _TextReaderProvider = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: (IReadOnlyDictionary<Platform, string>?)null, autoSave: true) : null;
static readonly SerializableProperty<IReadOnlyDictionary<Platform, string>>? _TextReaderProvider = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: (IReadOnlyDictionary<Platform, string>?)null) : null;
/// <summary>
/// 用户设置的文本阅读器提供商,根据平台值不同,值格式为 枚举字符串 或 程序路径
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<IReadOnlyDictionary<Platform, string>> TextReaderProvider => _TextReaderProvider ?? throw new PlatformNotSupportedException();
/// <summary>
/// 用户设置的文本阅读器提供商,根据平台值不同,值格式为 枚举字符串 或 程序路径
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<IReadOnlyDictionary<Platform, string>> TextReaderProvider => _TextReaderProvider ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<IHostsFileService.EncodingType>? _HostsEncodingType = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: default(IHostsFileService.EncodingType), autoSave: true) : null;
static readonly SerializableProperty<IHostsFileService.EncodingType>? _HostsEncodingType = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: default(IHostsFileService.EncodingType)) : null;
/// <summary>
/// Hosts 文件编码类型
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<IHostsFileService.EncodingType> HostsEncodingType => _HostsEncodingType ?? throw new PlatformNotSupportedException();
/// <summary>
/// Hosts 文件编码类型
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<IHostsFileService.EncodingType> HostsEncodingType => _HostsEncodingType ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _UseGPURendering = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true, autoSave: true) : null;
static readonly SerializableProperty<bool>? _UseGPURendering = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
/// <summary>
/// 使用硬件加速
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> UseGPURendering => _UseGPURendering ?? throw new PlatformNotSupportedException();
/// <summary>
/// 使用硬件加速
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> UseGPURendering => _UseGPURendering ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _UseWgl = OperatingSystem2.IsWindows() ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _UseWgl = OperatingSystem2.IsWindows() ? GetProperty(defaultValue: false) : null;
/// <summary>
/// (仅 Windows)Avalonia would try to use native Widows OpenGL when set to true. The default value is false.
/// </summary>
[SupportedOSPlatform("Windows7.0")]
public static SerializableProperty<bool> UseWgl => _UseWgl ?? throw new PlatformNotSupportedException();
/// <summary>
/// (仅 Windows)Avalonia would try to use native Widows OpenGL when set to true. The default value is false.
/// </summary>
[SupportedOSPlatform("Windows7.0")]
public static SerializableProperty<bool> UseWgl => _UseWgl ?? throw new PlatformNotSupportedException();
///// <summary>
///// 使用 Direct2D1 渲染(仅 Windows)
///// </summary>
//public static SerializableProperty<bool> UseDirect2D1 { get; }
// = GetProperty(defaultValue: false, autoSave: true);
///// <summary>
///// 使用 Direct2D1 渲染(仅 Windows)
///// </summary>
//public static SerializableProperty<bool> UseDirect2D1 { get; }
// = GetProperty(defaultValue: false, autoSave: true);
///// <summary>
///// 创建桌面快捷方式
///// </summary>
//public static SerializableProperty<bool> CreateDesktopShortcut { get; }
// = new SerializableProperty<bool>(GetKey(), Providers.Roaming, false) { AutoSave = true };
///// <summary>
///// 创建桌面快捷方式
///// </summary>
//public static SerializableProperty<bool> CreateDesktopShortcut { get; }
// = new SerializableProperty<bool>(GetKey(), Providers.Roaming, false) { AutoSave = true };
///// <summary>
///// 是否显示起始页
///// </summary>
//public static SerializableProperty<bool> IsShowStartPage { get; }
// = GetProperty(defaultValue: true, autoSave: true);
///// <summary>
///// 是否显示起始页
///// </summary>
//public static SerializableProperty<bool> IsShowStartPage { get; }
// = GetProperty(defaultValue: true, autoSave: true);
///// <summary>
///// 启用错误日志记录
///// </summary>
//public static SerializableProperty<bool> IsEnableLogRecord { get; }
// = GetProperty(defaultValue: false, autoSave: true);
///// <summary>
///// 启用错误日志记录
///// </summary>
//public static SerializableProperty<bool> IsEnableLogRecord { get; }
// = GetProperty(defaultValue: false, autoSave: true);
static readonly SerializableProperty<bool>? _UseWinHttpHandler = OperatingSystem2.IsWindows() ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _UseWinHttpHandler = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// (仅 Windows)使用基于 Windows 的 WinHTTP 接口处理消息
/// <para>https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.winhttphandler?view=dotnet-plat-ext-6.0</para>
/// <para>https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.socketshttphandler?view=net-6.0</para>
/// </summary>
[SupportedOSPlatform("Windows7.0")]
public static SerializableProperty<bool> UseWinHttpHandler => _UseWinHttpHandler ?? throw new PlatformNotSupportedException();
}
/// <summary>
/// (仅 Windows)使用基于 Windows 的 WinHTTP 接口处理消息
/// <para>https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.winhttphandler?view=dotnet-plat-ext-6.0</para>
/// <para>https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.socketshttphandler?view=net-6.0</para>
/// </summary>
[SupportedOSPlatform("Windows7.0")]
public static SerializableProperty<bool> UseWinHttpHandler => _UseWinHttpHandler ?? throw new PlatformNotSupportedException();
}
@@ -1,10 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace System.Application.Settings;
namespace System.Application.Settings
partial class GeneralSettings
{
partial class GeneralSettings
{
}
}
+12 -22
View File
@@ -1,26 +1,16 @@
using System;
using System.Application.Services;
using System.Application.UI;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Properties;
using System.Text;
using System.Threading.Tasks;
namespace System.Application.Settings;
namespace System.Application.Settings
public sealed partial class GeneralSettings : SettingsHost2<GeneralSettings>
{
public sealed partial class GeneralSettings : SettingsHost2<GeneralSettings>
{
/// <summary>
/// 自动检查更新
/// </summary>
public static SerializableProperty<bool> IsAutoCheckUpdate { get; }
= GetProperty(defaultValue: true, autoSave: true);
/// <summary>
/// 自动检查更新
/// </summary>
public static SerializableProperty<bool> IsAutoCheckUpdate { get; }
= GetProperty(defaultValue: true);
/// <summary>
/// 下载更新渠道
/// </summary>
public static SerializableProperty<UpdateChannelType> UpdateChannel { get; }
= GetProperty(defaultValue: default(UpdateChannelType), autoSave: true);
}
/// <summary>
/// 下载更新渠道
/// </summary>
public static SerializableProperty<UpdateChannelType> UpdateChannel { get; }
= GetProperty(defaultValue: default(UpdateChannelType));
}
@@ -1,15 +1,12 @@
using System.Runtime.Versioning;
namespace System.Application.Settings;
namespace System.Application.Settings
partial class ProxySettings
{
partial class ProxySettings
{
//static readonly SerializableProperty<bool>? _IsVpnMode = OperatingSystem2.IsAndroid() ? GetProperty(defaultValue: true, autoSave: true) : null;
//static readonly SerializableProperty<bool>? _IsVpnMode = OperatingSystem2.IsAndroid() ? GetProperty(defaultValue: true) : null;
///// <summary>
///// 是否启用 VPN 模式
///// </summary>
//[SupportedOSPlatform("Android")]
//public static SerializableProperty<bool> IsVpnMode => _IsVpnMode ?? throw new PlatformNotSupportedException();
}
///// <summary>
///// 是否启用 VPN 模式
///// </summary>
//[SupportedOSPlatform("Android")]
//public static SerializableProperty<bool> IsVpnMode => _IsVpnMode ?? throw new PlatformNotSupportedException();
}
@@ -1,31 +1,29 @@
using System.Collections.Generic;
using System.Application.UI;
using System.Runtime.Versioning;
namespace System.Application.Settings
namespace System.Application.Settings;
partial class ProxySettings
{
partial class ProxySettings
{
static readonly SerializableProperty<bool>? _IsProxyGOG
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsProxyGOG
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 启用 GOG 插件代理
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsProxyGOG => _IsProxyGOG ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用 GOG 插件代理
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsProxyGOG => _IsProxyGOG ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsOnlyWorkSteamBrowser
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsOnlyWorkSteamBrowser
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 是否只针对 Steam 内置浏览器启用脚本
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsOnlyWorkSteamBrowser => _IsOnlyWorkSteamBrowser ?? throw new PlatformNotSupportedException();
}
/// <summary>
/// 是否只针对 Steam 内置浏览器启用脚本
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsOnlyWorkSteamBrowser => _IsOnlyWorkSteamBrowser ?? throw new PlatformNotSupportedException();
}
+182 -184
View File
@@ -1,200 +1,198 @@
using System.Linq;
using System.Application.Columns;
using System.Application.Services;
using System.Application.UI.Resx;
using System.Collections.Generic;
using EProxyMode = System.Application.ProxyMode;
using IPAddress = System.Net.IPAddress;
namespace System.Application.Settings
namespace System.Application.Settings;
public sealed partial class ProxySettings : SettingsHost2<ProxySettings>
{
public sealed partial class ProxySettings : SettingsHost2<ProxySettings>
/// <summary>
/// 启用脚本自动检查更新
/// </summary>
public static SerializableProperty<bool> IsAutoCheckScriptUpdate { get; }
= GetProperty(defaultValue: true);
/// <summary>
/// 启用代理脚本
/// </summary>
public static SerializableProperty<bool> IsEnableScript { get; }
= GetProperty(defaultValue: false);
/// <summary>
/// 代理服务启用状态
/// </summary>
public static SerializableProperty<IReadOnlyCollection<string>> SupportProxyServicesStatus { get; }
= GetProperty(defaultValue: (IReadOnlyCollection<string>)Array.Empty<string>(), autoSave: false);
/// <summary>
/// 脚本启用状态
/// </summary>
public static SerializableProperty<IReadOnlyCollection<int>> ScriptsStatus { get; }
= GetProperty(defaultValue: (IReadOnlyCollection<int>)Array.Empty<int>());
#region 代理设置
/// <summary>
/// 程序启动时自动启动代理
/// </summary>
public static SerializableProperty<bool> ProgramStartupRunProxy { get; }
= GetProperty(defaultValue: false);
/// <summary>
/// 系统代理模式端口
/// </summary>
public static SerializableProperty<int> SystemProxyPortId { get; }
= GetProperty(defaultValue: 26501, autoSave: false);
/// <summary>
/// 系统代理模式IP
/// </summary>
public static SerializableProperty<string> SystemProxyIp { get; }
= GetProperty(defaultValue: IPAddress.Any.ToString(), autoSave: false);
/// <summary>
/// 开启加速后仅代理脚本而不加速
/// </summary>
public static SerializableProperty<bool> OnlyEnableProxyScript { get; }
= GetProperty(defaultValue: false, autoSave: false);
/// <summary>
/// 代理时使用的解析主DNS
/// </summary>
public static SerializableProperty<string?> ProxyMasterDns { get; }
= GetProperty<string?>(defaultValue: "223.5.5.5", autoSave: false);
/// <summary>
/// 启用 Http 链接转发到 Https
/// </summary>
public static SerializableProperty<bool> EnableHttpProxyToHttps { get; }
= GetProperty(defaultValue: true);
#endregion
#region 本地代理设置
/// <summary>
/// Socks5 Enable
/// </summary>
public static SerializableProperty<bool> Socks5ProxyEnable { get; }
= GetProperty(defaultValue: false, autoSave: false);
/// <summary>
/// Socks5 监听端口
/// </summary>
public static SerializableProperty<int> Socks5ProxyPortId { get; }
= GetProperty(defaultValue: DefaultSocks5ProxyPortId, autoSave: false);
public const int DefaultSocks5ProxyPortId = 8868;
#endregion
#region 二级代理设置
/// <summary>
/// TwoLevelAgent Enable
/// </summary>
public static SerializableProperty<bool> TwoLevelAgentEnable { get; }
= GetProperty(defaultValue: false, autoSave: false);
/// <summary>
/// TwoLevelAgent ProxyType
/// </summary>
public static SerializableProperty<short> TwoLevelAgentProxyType { get; }
= GetProperty(defaultValue: DefaultTwoLevelAgentProxyType, autoSave: false);
public const short DefaultTwoLevelAgentProxyType =
(short)IReverseProxyService.DefaultTwoLevelAgentProxyType;
/// <summary>
/// 二级代理 IP
/// </summary>
public static SerializableProperty<string> TwoLevelAgentIp { get; }
= GetProperty(defaultValue: IPAddress.Loopback.ToString(), autoSave: false);
/// <summary>
/// 二级代理 监听端口
/// </summary>
public static SerializableProperty<int> TwoLevelAgentPortId { get; }
= GetProperty(defaultValue: DefaultTwoLevelAgentPortId, autoSave: false);
public const int DefaultTwoLevelAgentPortId = 7890;
/// <summary>
/// TwoLevelAgent UserName
/// </summary>
public static SerializableProperty<string> TwoLevelAgentUserName { get; }
= GetProperty(defaultValue: string.Empty, autoSave: false);
/// <summary>
/// TwoLevelAgent Password
/// </summary>
public static SerializableProperty<string> TwoLevelAgentPassword { get; }
= GetProperty(defaultValue: string.Empty, autoSave: false);
#endregion
#region 代理模式设置
static EProxyMode DefaultProxyMode => ProxyModes.FirstOrDefault();
static IEnumerable<EProxyMode> GetProxyModes()
{
/// <summary>
/// 启用脚本自动检查更新
/// </summary>
public static SerializableProperty<bool> IsAutoCheckScriptUpdate { get; }
= GetProperty(defaultValue: true, autoSave: true);
/// <summary>
/// 启用代理脚本
/// </summary>
public static SerializableProperty<bool> IsEnableScript { get; }
= GetProperty(defaultValue: false, autoSave: true);
/// <summary>
/// 代理服务启用状态
/// </summary>
public static SerializableProperty<IReadOnlyCollection<string>> SupportProxyServicesStatus { get; }
= GetProperty(defaultValue: (IReadOnlyCollection<string>)Array.Empty<string>(), autoSave: false);
/// <summary>
/// 脚本启用状态
/// </summary>
public static SerializableProperty<IReadOnlyCollection<int>> ScriptsStatus { get; }
= GetProperty(defaultValue: (IReadOnlyCollection<int>)Array.Empty<int>(), autoSave: true);
#region 代理设置
/// <summary>
/// 程序启动时自动启动代理
/// </summary>
public static SerializableProperty<bool> ProgramStartupRunProxy { get; }
= GetProperty(defaultValue: false, autoSave: true);
/// <summary>
/// 系统代理模式端口
/// </summary>
public static SerializableProperty<int> SystemProxyPortId { get; }
= GetProperty(defaultValue: 26501, autoSave: false);
/// <summary>
/// 系统代理模式IP
/// </summary>
public static SerializableProperty<string> SystemProxyIp { get; }
= GetProperty(defaultValue: IPAddress.Any.ToString(), autoSave: false);
/// <summary>
/// 开启加速后仅代理脚本而不加速
/// </summary>
public static SerializableProperty<bool> OnlyEnableProxyScript { get; }
= GetProperty(defaultValue: false, autoSave: false);
/// <summary>
/// 代理时使用的解析主DNS
/// </summary>
public static SerializableProperty<string?> ProxyMasterDns { get; }
= GetProperty<string?>(defaultValue: "223.5.5.5", autoSave: false);
/// <summary>
/// 启用 Http 链接转发到 Https
/// </summary>
public static SerializableProperty<bool> EnableHttpProxyToHttps { get; }
= GetProperty(defaultValue: true, autoSave: true);
#endregion
#region 本地代理设置
/// <summary>
/// Socks5 Enable
/// </summary>
public static SerializableProperty<bool> Socks5ProxyEnable { get; }
= GetProperty(defaultValue: false, autoSave: false);
/// <summary>
/// Socks5 监听端口
/// </summary>
public static SerializableProperty<int> Socks5ProxyPortId { get; }
= GetProperty(defaultValue: DefaultSocks5ProxyPortId, autoSave: false);
public const int DefaultSocks5ProxyPortId = 8868;
#endregion
#region 二级代理设置
/// <summary>
/// TwoLevelAgent Enable
/// </summary>
public static SerializableProperty<bool> TwoLevelAgentEnable { get; }
= GetProperty(defaultValue: false, autoSave: false);
/// <summary>
/// TwoLevelAgent ProxyType
/// </summary>
public static SerializableProperty<short> TwoLevelAgentProxyType { get; }
= GetProperty(defaultValue: DefaultTwoLevelAgentProxyType, autoSave: false);
public const short DefaultTwoLevelAgentProxyType =
(short)IReverseProxyService.DefaultTwoLevelAgentProxyType;
/// <summary>
/// 二级代理 IP
/// </summary>
public static SerializableProperty<string> TwoLevelAgentIp { get; }
= GetProperty(defaultValue: IPAddress.Loopback.ToString(), autoSave: false);
/// <summary>
/// 二级代理 监听端口
/// </summary>
public static SerializableProperty<int> TwoLevelAgentPortId { get; }
= GetProperty(defaultValue: DefaultTwoLevelAgentPortId, autoSave: false);
public const int DefaultTwoLevelAgentPortId = 7890;
/// <summary>
/// TwoLevelAgent UserName
/// </summary>
public static SerializableProperty<string> TwoLevelAgentUserName { get; }
= GetProperty(defaultValue: string.Empty, autoSave: false);
/// <summary>
/// TwoLevelAgent Password
/// </summary>
public static SerializableProperty<string> TwoLevelAgentPassword { get; }
= GetProperty(defaultValue: string.Empty, autoSave: false);
#endregion
#region 代理模式设置
static EProxyMode DefaultProxyMode => ProxyModes.FirstOrDefault();
static IEnumerable<EProxyMode> GetProxyModes()
if (OperatingSystem2.IsWindows())
{
if (OperatingSystem2.IsWindows())
{
yield return EProxyMode.DNSIntercept;
yield return EProxyMode.Hosts;
yield return EProxyMode.PAC;
yield return EProxyMode.System;
}
else if (OperatingSystem2.IsAndroid())
{
yield return EProxyMode.VPN;
yield return EProxyMode.ProxyOnly;
}
else if (OperatingSystem2.IsLinux() || OperatingSystem2.IsMacOS())
{
yield return EProxyMode.Hosts;
yield return EProxyMode.System;
}
yield return EProxyMode.Hosts;
yield return EProxyMode.DNSIntercept;
yield return EProxyMode.PAC;
yield return EProxyMode.System;
}
public static IReadOnlyList<EProxyMode> ProxyModes => mProxyModes.Value;
static readonly Lazy<IReadOnlyList<EProxyMode>> mProxyModes = new(() => GetProxyModes().ToArray());
/// <summary>
/// 当前代理模式
/// </summary>
public static SerializableProperty<EProxyMode> ProxyMode { get; }
= GetProperty(defaultValue: DefaultProxyMode, autoSave: true);
/// <inheritdoc cref="ProxyMode"/>
public static EProxyMode ProxyModeValue
else if (OperatingSystem2.IsAndroid())
{
get
{
var value = ProxyMode.Value;
if (ProxyModes.Contains(value)) return value;
return DefaultProxyMode;
}
set => ProxyMode.Value = value;
yield return EProxyMode.VPN;
yield return EProxyMode.ProxyOnly;
}
public static string ToStringByProxyMode(EProxyMode mode) => mode switch
else if (OperatingSystem2.IsLinux() || OperatingSystem2.IsMacOS())
{
EProxyMode.DNSIntercept => AppResources.ProxyMode_DNSIntercept,
EProxyMode.Hosts => AppResources.ProxyMode_Hosts,
EProxyMode.System => AppResources.ProxyMode_System,
EProxyMode.VPN => AppResources.ProxyMode_VPN,
EProxyMode.ProxyOnly => AppResources.ProxyMode_ProxyOnly,
_ => string.Empty,
};
public static string ProxyModeValueString => ToStringByProxyMode(ProxyModeValue);
#endregion
yield return EProxyMode.Hosts;
yield return EProxyMode.System;
}
}
public static IReadOnlyList<EProxyMode> ProxyModes => mProxyModes.Value;
static readonly Lazy<IReadOnlyList<EProxyMode>> mProxyModes = new(() => GetProxyModes().ToArray());
/// <summary>
/// 当前代理模式
/// </summary>
public static SerializableProperty<EProxyMode> ProxyMode { get; }
= GetProperty(defaultValue: DefaultProxyMode);
/// <inheritdoc cref="ProxyMode"/>
public static EProxyMode ProxyModeValue
{
get
{
var value = ProxyMode.Value;
if (ProxyModes.Contains(value)) return value;
return DefaultProxyMode;
}
set => ProxyMode.Value = value;
}
public static string ToStringByProxyMode(EProxyMode mode) => mode switch
{
EProxyMode.DNSIntercept => AppResources.ProxyMode_DNSIntercept,
EProxyMode.Hosts => AppResources.ProxyMode_Hosts,
EProxyMode.System => AppResources.ProxyMode_System,
EProxyMode.VPN => AppResources.ProxyMode_VPN,
EProxyMode.ProxyOnly => AppResources.ProxyMode_ProxyOnly,
_ => string.Empty,
};
public static string ProxyModeValueString => ToStringByProxyMode(ProxyModeValue);
#endregion
}
+19 -20
View File
@@ -5,29 +5,28 @@ using System.Runtime.Versioning;
using System.Application.Models;
using Compat = System.Application.Settings.GameLibrarySettings;
namespace System.Application.Settings
namespace System.Application.Settings;
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public sealed class SteamAccountSettings : SettingsHost2<SteamAccountSettings>
{
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public sealed class SteamAccountSettings : SettingsHost2<SteamAccountSettings>
{
#region Compat
#region Compat
static readonly SerializableProperty<ConcurrentDictionary<long, string?>?>? _AccountRemarks = IApplication.IsDesktopPlatform ?
Compat.GetProperty<ConcurrentDictionary<long, string?>?>(defaultValue: null, autoSave: false) : null;
static readonly SerializableProperty<ConcurrentDictionary<long, string?>?>? _AccountRemarks = IApplication.IsDesktopPlatform ?
Compat.GetProperty<ConcurrentDictionary<long, string?>?>(defaultValue: null, autoSave: false) : null;
/// <summary>
/// Steam账号备注字典
/// </summary>
public static SerializableProperty<ConcurrentDictionary<long, string?>?> AccountRemarks => _AccountRemarks ?? throw new PlatformNotSupportedException();
/// <summary>
/// Steam 账号备注字典
/// </summary>
public static SerializableProperty<ConcurrentDictionary<long, string?>?> AccountRemarks => _AccountRemarks ?? throw new PlatformNotSupportedException();
// ----- AccountRemarks ClassName 之前用的 GameLibrarySettings 需要兼容已发行的版本,将错就错,之后新增的还是使用 GetProperty 而不是 Compat.GetProperty -----
// ----- AccountRemarks ClassName 之前用的 GameLibrarySettings 需要兼容已发行的版本,将错就错,之后新增的还是使用 GetProperty 而不是 Compat.GetProperty -----
/// <summary>
/// Steam家庭共享临时禁用
/// </summary>
public static SerializableProperty<IReadOnlyCollection<DisableAuthorizedDevice>> DisableAuthorizedDevice => GetProperty(defaultValue: (IReadOnlyCollection<DisableAuthorizedDevice>)Array.Empty<DisableAuthorizedDevice>(), autoSave: true);
#endregion
}
/// <summary>
/// Steam 家庭共享临时禁用
/// </summary>
public static SerializableProperty<IReadOnlyCollection<DisableAuthorizedDevice>> DisableAuthorizedDevice => GetProperty(defaultValue: (IReadOnlyCollection<DisableAuthorizedDevice>)Array.Empty<DisableAuthorizedDevice>());
#endregion
}
+91 -92
View File
@@ -2,113 +2,112 @@ using System.Application.Models;
using System.Application.UI;
using System.Runtime.Versioning;
namespace System.Application.Settings
namespace System.Application.Settings;
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public sealed class SteamSettings : SettingsHost2<SteamSettings>
{
static SteamSettings()
{
if (!IApplication.IsDesktopPlatform) return;
IsRunSteamMinimized.ValueChanged += IsRunSteamMinimized_ValueChanged;
IsRunSteamNoCheckUpdate.ValueChanged += IsRunSteamNoCheckUpdate_ValueChanged;
}
static void IsRunSteamNoCheckUpdate_ValueChanged(object? sender, ValueChangedEventArgs<bool> e)
{
if (e.NewValue)
SteamStratParameter.Value += " -noverifyfiles";
else if (SteamStratParameter.Value != null)
SteamStratParameter.Value = SteamStratParameter.Value.Replace("-noverifyfiles", "").Trim();
}
static void IsRunSteamMinimized_ValueChanged(object? sender, ValueChangedEventArgs<bool> e)
{
if (e.NewValue)
SteamStratParameter.Value += " -silent";
else if (SteamStratParameter.Value != null)
SteamStratParameter.Value = SteamStratParameter.Value.Replace("-silent", "").Trim();
}
static readonly SerializableProperty<string?>? _SteamStratParameter = IApplication.IsDesktopPlatform ?
GetProperty<string?>(defaultValue: null) : null;
/// <summary>
/// Steam 启动参数
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public sealed class SteamSettings : SettingsHost2<SteamSettings>
{
static SteamSettings()
{
if (!IApplication.IsDesktopPlatform) return;
IsRunSteamMinimized.ValueChanged += IsRunSteamMinimized_ValueChanged;
IsRunSteamNoCheckUpdate.ValueChanged += IsRunSteamNoCheckUpdate_ValueChanged;
}
public static SerializableProperty<string?> SteamStratParameter => _SteamStratParameter ?? throw new PlatformNotSupportedException();
static void IsRunSteamNoCheckUpdate_ValueChanged(object? sender, ValueChangedEventArgs<bool> e)
{
if (e.NewValue)
SteamStratParameter.Value += " -noverifyfiles";
else if (SteamStratParameter.Value != null)
SteamStratParameter.Value = SteamStratParameter.Value.Replace("-noverifyfiles", "").Trim();
}
//static readonly SerializableProperty<string>? _SteamSkin = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: string.Empty, autoSave: true) : null;
///// <summary>
///// Steam 皮肤
///// </summary>
//[SupportedOSPlatform("Windows7.0")]
//[SupportedOSPlatform("macOS")]
//[SupportedOSPlatform("Linux")]
//public static SerializableProperty<string> SteamSkin => _SteamSkin ?? throw new PlatformNotSupportedException();
static void IsRunSteamMinimized_ValueChanged(object? sender, ValueChangedEventArgs<bool> e)
{
if (e.NewValue)
SteamStratParameter.Value += " -silent";
else if (SteamStratParameter.Value != null)
SteamStratParameter.Value = SteamStratParameter.Value.Replace("-silent", "").Trim();
}
static readonly SerializableProperty<bool>? _IsAutoRunSteam = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
static readonly SerializableProperty<string?>? _SteamStratParameter = IApplication.IsDesktopPlatform ?
GetProperty<string?>(defaultValue: null, autoSave: true) : null;
/// <summary>
/// 自动运行 Steam
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsAutoRunSteam => _IsAutoRunSteam ?? throw new PlatformNotSupportedException();
/// <summary>
/// Steam启动参数
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string?> SteamStratParameter => _SteamStratParameter ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsRunSteamMinimized = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
//static readonly SerializableProperty<string>? _SteamSkin = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: string.Empty, autoSave: true) : null;
///// <summary>
///// Steam皮肤
///// </summary>
//[SupportedOSPlatform("Windows7.0")]
//[SupportedOSPlatform("macOS")]
//[SupportedOSPlatform("Linux")]
//public static SerializableProperty<string> SteamSkin => _SteamSkin ?? throw new PlatformNotSupportedException();
/// <summary>
/// Steam 启动时最小化到托盘
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsRunSteamMinimized => _IsRunSteamMinimized ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsAutoRunSteam = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsRunSteamNoCheckUpdate = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 自动运行Steam
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsAutoRunSteam => _IsAutoRunSteam ?? throw new PlatformNotSupportedException();
/// <summary>
/// Steam 启动时不检查更新
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsRunSteamNoCheckUpdate => _IsRunSteamNoCheckUpdate ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsRunSteamMinimized = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsEnableSteamLaunchNotification = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
/// <summary>
/// Steam启动时最小化到托盘
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsRunSteamMinimized => _IsRunSteamMinimized ?? throw new PlatformNotSupportedException();
/// <summary>
/// 检测到 Steam 登录时弹出消息通知
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsEnableSteamLaunchNotification => _IsEnableSteamLaunchNotification ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsRunSteamNoCheckUpdate = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
/// <summary>
/// Steam 下载完成执行任务
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<SystemEndMode>? DownloadCompleteSystemEndMode = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: SystemEndMode.Sleep) : null;
/// <summary>
/// Steam启动时不检查更新
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsRunSteamNoCheckUpdate => _IsRunSteamNoCheckUpdate ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _IsRunSteamAdministrator = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
static readonly SerializableProperty<bool>? _IsEnableSteamLaunchNotification = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true, autoSave: true) : null;
/// <summary>
/// 以管理员权限运行 Steam
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsRunSteamAdministrator => _IsRunSteamAdministrator ?? throw new PlatformNotSupportedException();
/// <summary>
/// 检测到Steam登录时弹出消息通知
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsEnableSteamLaunchNotification => _IsEnableSteamLaunchNotification ?? throw new PlatformNotSupportedException();
/// <summary>
/// Steam下载完成执行任务
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<SystemEndMode>? DownloadCompleteSystemEndMode = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: SystemEndMode.Sleep, autoSave: true) : null;
static readonly SerializableProperty<bool>? _IsRunSteamAdministrator = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
/// <summary>
/// 以管理员权限运行Steam
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> IsRunSteamAdministrator => _IsRunSteamAdministrator ?? throw new PlatformNotSupportedException();
}
}
+109 -114
View File
@@ -1,148 +1,143 @@
using System;
using System.Application.Models;
using System.Application.UI;
using System.Application.UI.ViewModels;
using System.Application.Services;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
using DynamicData;
using System.Runtime.Versioning;
namespace System.Application.Settings
namespace System.Application.Settings;
partial class UISettings
{
partial class UISettings
{
static readonly SerializableProperty<ConcurrentDictionary<string, SizePosition>?>? _WindowSizePositions = WindowViewModel.IsSupportedSizePosition ?
GetProperty<ConcurrentDictionary<string, SizePosition>?>(defaultValue: null, autoSave: false) : null;
static readonly SerializableProperty<ConcurrentDictionary<string, SizePosition>?>? _WindowSizePositions = WindowViewModel.IsSupportedSizePosition ?
GetProperty<ConcurrentDictionary<string, SizePosition>?>(defaultValue: null, autoSave: false) : null;
/// <summary>
/// 所有窗口位置记忆字典集合
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<ConcurrentDictionary<string, SizePosition>?> WindowSizePositions => _WindowSizePositions ?? throw new PlatformNotSupportedException();
/// <summary>
/// 所有窗口位置记忆字典集合
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<ConcurrentDictionary<string, SizePosition>?> WindowSizePositions => _WindowSizePositions ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<string>? _FontName = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: IFontManager.KEY_Default, autoSave: true) : null;
static readonly SerializableProperty<string>? _FontName = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: IFontManager.KEY_Default) : null;
/// <summary>
/// 字体
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string> FontName => _FontName ?? throw new PlatformNotSupportedException();
/// <summary>
/// 字体
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string> FontName => _FontName ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<double>? _AcrylicOpacity = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: .8, autoSave: true) : null;
static readonly SerializableProperty<double>? _AcrylicOpacity = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: .8) : null;
/// <summary>
/// 窗口背景透明度
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<double> AcrylicOpacity => _AcrylicOpacity ?? throw new PlatformNotSupportedException();
/// <summary>
/// 窗口背景透明度
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<double> AcrylicOpacity => _AcrylicOpacity ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<int>? _WindowBackgroundMateria = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: OperatingSystem2.IsWindows7() ? 0 : (OperatingSystem2.IsWindows11AtLeast() ? 5 : 3), autoSave: true) : null;
static readonly SerializableProperty<int>? _WindowBackgroundMateria = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: OperatingSystem2.IsWindows7() ? 0 : (OperatingSystem2.IsWindows11AtLeast() ? 5 : 3)) : null;
/// <summary>
/// 窗口背景材质
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<int> WindowBackgroundMateria => _WindowBackgroundMateria ?? throw new PlatformNotSupportedException();
/// <summary>
/// 窗口背景材质
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<int> WindowBackgroundMateria => _WindowBackgroundMateria ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<int>? _AppGridSize = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: 150, autoSave: true) : null;
static readonly SerializableProperty<int>? _AppGridSize = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: 150) : null;
/// <summary>
/// 库存游戏封面大小
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<int> AppGridSize => _AppGridSize ?? throw new PlatformNotSupportedException();
/// <summary>
/// 库存游戏封面大小
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<int> AppGridSize => _AppGridSize ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _SteamAccountRemarkReplaceName = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _SteamAccountRemarkReplaceName = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// Steam账号备注替换名称显示
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> SteamAccountRemarkReplaceName => _SteamAccountRemarkReplaceName ?? throw new PlatformNotSupportedException();
/// <summary>
/// Steam账号备注替换名称显示
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> SteamAccountRemarkReplaceName => _SteamAccountRemarkReplaceName ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _EnableFilletUI = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _EnableFilletUI = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 启用圆角界面
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> EnableFilletUI => _EnableFilletUI ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用圆角界面
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> EnableFilletUI => _EnableFilletUI ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _EnableDesktopBackground = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _EnableDesktopBackground = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 启用动态桌面背景
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> EnableDesktopBackground => _EnableDesktopBackground ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用动态桌面背景
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> EnableDesktopBackground => _EnableDesktopBackground ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _EnableCustomBackgroundImage
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _EnableCustomBackgroundImage
= IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 启用自定义背景图片
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> EnableCustomBackgroundImage => _EnableCustomBackgroundImage ?? throw new PlatformNotSupportedException();
/// <summary>
/// 启用自定义背景图片
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> EnableCustomBackgroundImage => _EnableCustomBackgroundImage ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<string>? _BackgroundImagePath = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: "avares://System.Application.SteamTools.Client.Avalonia/Application/UI/Assets/AppResources/Placeholders/0.png", autoSave: true) : null;
static readonly SerializableProperty<string>? _BackgroundImagePath = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: "avares://System.Application.SteamTools.Client.Avalonia/Application/UI/Assets/AppResources/Placeholders/0.png") : null;
/// <summary>
/// 背景图片路径
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string> BackgroundImagePath => _BackgroundImagePath ?? throw new PlatformNotSupportedException();
/// <summary>
/// 背景图片路径
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string> BackgroundImagePath => _BackgroundImagePath ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<string>? _ThemeAccent = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: "#FF0078D7", autoSave: true) : null;
static readonly SerializableProperty<string>? _ThemeAccent = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: "#FF0078D7") : null;
/// <summary>
/// 主题颜色(十六进制字符串)
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string> ThemeAccent => _ThemeAccent ?? throw new PlatformNotSupportedException();
/// <summary>
/// 主题颜色(十六进制字符串)
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<string> ThemeAccent => _ThemeAccent ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _GetUserThemeAccent = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true, autoSave: true) : null;
static readonly SerializableProperty<bool>? _GetUserThemeAccent = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: true) : null;
/// <summary>
/// 主题颜色从系统获取
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> GetUserThemeAccent => _GetUserThemeAccent ?? throw new PlatformNotSupportedException();
/// <summary>
/// 主题颜色从系统获取
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> GetUserThemeAccent => _GetUserThemeAccent ?? throw new PlatformNotSupportedException();
static readonly SerializableProperty<bool>? _MainMenuExpandedState = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false, autoSave: true) : null;
static readonly SerializableProperty<bool>? _MainMenuExpandedState = IApplication.IsDesktopPlatform ? GetProperty(defaultValue: false) : null;
/// <summary>
/// 主菜单展开状态
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> MainMenuExpandedState => _MainMenuExpandedState ?? throw new PlatformNotSupportedException();
}
/// <summary>
/// 主菜单展开状态
/// </summary>
[SupportedOSPlatform("Windows7.0")]
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Linux")]
public static SerializableProperty<bool> MainMenuExpandedState => _MainMenuExpandedState ?? throw new PlatformNotSupportedException();
}
+23 -31
View File
@@ -1,40 +1,32 @@
using DynamicData;
using System.Application.Models;
using System.Application.Services;
using System.Application.UI;
using System.Application.UI.ViewModels;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;
namespace System.Application.Settings
namespace System.Application.Settings;
public sealed partial class UISettings : SettingsHost2<UISettings>
{
public sealed partial class UISettings : SettingsHost2<UISettings>
{
/// <summary>
/// 主题
/// </summary>
public static SerializableProperty<short> Theme { get; }
= GetProperty(defaultValue: (short)0, autoSave: true);
/// <summary>
/// 主题
/// </summary>
public static SerializableProperty<short> Theme { get; }
= GetProperty(defaultValue: (short)0);
/// <summary>
/// 语言
/// </summary>
public static SerializableProperty<string> Language { get; }
= GetProperty(defaultValue: string.Empty, autoSave: true);
/// <summary>
/// 语言
/// </summary>
public static SerializableProperty<string> Language { get; }
= GetProperty(defaultValue: string.Empty);
/// <summary>
/// 不再提示的消息框数组
/// </summary>
public static SerializableProperty<HashSet<MessageBox.DontPromptType>?> DoNotShowMessageBoxs { get; }
= GetProperty<HashSet<MessageBox.DontPromptType>?>(defaultValue: null, autoSave: false);
/// <summary>
/// 不再提示的消息框数组
/// </summary>
public static SerializableProperty<HashSet<MessageBox.DontPromptType>?> DoNotShowMessageBoxs { get; }
= GetProperty<HashSet<MessageBox.DontPromptType>?>(defaultValue: null, autoSave: false);
/// <summary>
/// 是否显示广告
/// </summary>
public static SerializableProperty<bool> IsShowAdvertise { get; }
= GetProperty(defaultValue: true, autoSave: true);
}
/// <summary>
/// 是否显示广告
/// </summary>
public static SerializableProperty<bool> IsShowAdvertise { get; }
= GetProperty(defaultValue: true);
}
//static void EnableDesktopBackground_ValueChanged(object? sender, ValueChangedEventArgs<bool> e)
+3 -7
View File
@@ -165,7 +165,7 @@ namespace System.Application.UI
public const string LogDirName = "Logs";
public static void InitLogDir(string? alias = null)
public static void InitLogDir(string? alias = null, bool isTrace = false)
{
if (!string.IsNullOrEmpty(LogDirPath)) return;
@@ -183,9 +183,7 @@ namespace System.Application.UI
// LogDirName);
var logDirPath = Path.Combine(IOPath.CacheDirectory, LogDirName);
IOPath.DirCreateByNotExists(logDirPath);
#if StartWatchTrace
StartWatchTrace.Record("InitLogDir.IO");
#endif
if (isTrace) StartWatchTrace.Record("InitLogDir.IO");
var logDirPath_ = logDirPath + Path.DirectorySeparatorChar;
NInternalLogger.LogFile = logDirPath_ + "internal-nlog" + alias + ".txt";
@@ -202,9 +200,7 @@ namespace System.Application.UI
};
objConfig.AddTarget(logfile);
InitializeTarget(objConfig, logfile, defMinLevel);
#if StartWatchTrace
StartWatchTrace.Record("InitLogDir.CreateLoggingConfiguration");
#endif
if (isTrace) StartWatchTrace.Record("InitLogDir.CreateCfg");
NLogManager.Configuration = objConfig;
LogDirPathASF = ASFPathHelper.GetLogDirectory(logDirPath_);
+3 -1
View File
@@ -41,7 +41,7 @@ namespace System.Application.UI
public interface IProgramHost : IStartupArgs
{
void ConfigureServices(DILevel level);
void ConfigureServices(DILevel level, bool isTrace = false);
void OnStartup();
@@ -53,6 +53,8 @@ namespace System.Application.UI
public interface IDesktopProgramHost : IProgramHost, IDesktopStartupArgs
{
void OnCreateAppExecuted(Action<IViewModelManager>? handlerViewModelManager = null, bool isTrace = false);
DeploymentMode DeploymentMode { get; }
}
}
}
+36
View File
@@ -1976,6 +1976,33 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 错误 的本地化字符串。
/// </summary>
public static string Error {
get {
return ResourceManager.GetString("Error", resourceCulture);
}
}
/// <summary>
/// 查找类似 不能在临时文件夹中运行此程序,请将所有文件复制或解压到其他路径后再启动程序 的本地化字符串。
/// </summary>
public static string Error_BaseDir_StartsWith_Temp {
get {
return ResourceManager.GetString("Error_BaseDir_StartsWith_Temp", resourceCulture);
}
}
/// <summary>
/// 查找类似 对于 Windows 10 操作系统最低需要 version 1607(10.0.14393) 的本地化字符串。
/// </summary>
public static string Error_Lower_Than_Windows10_1607 {
get {
return ResourceManager.GetString("Error_Lower_Than_Windows10_1607", resourceCulture);
}
}
/// <summary>
/// 查找类似 可执行文件 的本地化字符串。
/// </summary>
@@ -3978,6 +4005,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 请在弹出的控制台窗口输入系统密码以安装信任证书。信任完成后点击确定按钮继续。 的本地化字符串。
/// </summary>
public static string MacTrustRootCertificateTips {
get {
return ResourceManager.GetString("MacTrustRootCertificateTips", resourceCulture);
}
}
/// <summary>
/// 查找类似 媒体 的本地化字符串。
/// </summary>
+12
View File
@@ -2389,4 +2389,16 @@ AAAAA-BBBBB-CCCC3</value>
<data name="Settings_General_UseWinHttpHandler" xml:space="preserve">
<value>使用 WinHttpHandler</value>
</data>
<data name="Error" xml:space="preserve">
<value>错误</value>
</data>
<data name="Error_BaseDir_StartsWith_Temp" xml:space="preserve">
<value>不能在临时文件夹中运行此程序,请将所有文件复制或解压到其他路径后再启动程序</value>
</data>
<data name="Error_Lower_Than_Windows10_1607" xml:space="preserve">
<value>对于 Windows 10 操作系统最低需要 version 1607(10.0.14393)</value>
</data>
<data name="MacTrustRootCertificateTips" xml:space="preserve">
<value>请在弹出的控制台窗口输入系统密码以安装信任证书。信任完成后点击确定按钮继续。</value>
</data>
</root>
@@ -1,6 +1,4 @@
using System.Application.UI.Resx;
using System.Collections.Generic;
using System.Text;
// ReSharper disable once CheckNamespace
namespace System.Application.UI.ViewModels
@@ -18,7 +16,54 @@ namespace System.Application.UI.ViewModels
GameRelated,
Settings,
About,
#if DEBUG
Debug = byte.MaxValue,
#endif
}
public static string GetName(TabItemId tabItemId) => tabItemId switch
{
TabItemId.CommunityProxy => CommunityProxyPageViewModel.DisplayName,
TabItemId.ProxyScriptManage => ProxyScriptManagePageViewModel.DisplayName,
TabItemId.SteamAccount => SteamAccountPageViewModel.DisplayName,
TabItemId.GameList => GameListPageViewModel.DisplayName,
TabItemId.LocalAuth => LocalAuthPageViewModel.DisplayName,
TabItemId.ArchiSteamFarmPlus => ArchiSteamFarmPlusPageViewModel.DisplayName,
TabItemId.GameRelated => GameRelatedPageViewModel.DisplayName,
TabItemId.Settings => SettingsPageViewModel.DisplayName,
TabItemId.About => AboutPageViewModel.DisplayName,
#if DEBUG
TabItemId.Debug => DebugPageViewModel.DisplayName,
#endif
_ => "",
};
public static Type GetType(TabItemId tabItemId) => tabItemId switch
{
TabItemId.CommunityProxy => typeof(CommunityProxyPageViewModel),
TabItemId.ProxyScriptManage => typeof(ProxyScriptManagePageViewModel),
TabItemId.SteamAccount => typeof(SteamAccountPageViewModel),
TabItemId.GameList => typeof(GameListPageViewModel),
TabItemId.LocalAuth => typeof(LocalAuthPageViewModel),
TabItemId.ArchiSteamFarmPlus => typeof(ArchiSteamFarmPlusPageViewModel),
TabItemId.GameRelated => typeof(GameRelatedPageViewModel),
TabItemId.Settings => typeof(SettingsPageViewModel),
TabItemId.About => typeof(AboutPageViewModel),
#if DEBUG
TabItemId.Debug => typeof(DebugPageViewModel),
#endif
_ => throw new ArgumentOutOfRangeException(nameof(tabItemId), tabItemId, null),
};
public static TabItemViewModel Create(TabItemId tabItemId) => tabItemId switch
{
TabItemId.Settings => SettingsPageViewModel.Instance,
TabItemId.About => AboutPageViewModel.Instance,
#if DEBUG
TabItemId.Debug => DebugPageViewModel.Instance,
#endif
_ => (TabItemViewModel)System.Activator.CreateInstance(GetType(tabItemId))!,
};
}
partial class StartPageViewModel : TabItemViewModel
@@ -152,6 +197,8 @@ namespace System.Application.UI.ViewModels
{
public const string DisplayName = "Debug";
public override TabItemId Id => TabItemId.Debug;
public override string Name
{
get => DisplayName;
@@ -36,6 +36,11 @@ namespace System.Application.UI.ViewModels
{
var typeName = GetType().Name;
IconKey = OperatingSystem2.Application.UseMaui() ? $"{typeName.ToLowerInvariant()}.png" : typeName;
R.Subscribe(() =>
{
this.RaisePropertyChanged(nameof(Name));
}).AddTo(this);
}
public virtual void Initialize()
@@ -30,7 +30,8 @@ namespace System.Application.UI.ViewModels
{
var name = GetType().Name;
if (IsSupportedSizePosition)
bool isSupportedSizePosition = IsSupportedSizePosition;
if (isSupportedSizePosition)
{
if (UISettings.WindowSizePositions.Value?.ContainsKey(name) == true)
{
@@ -6,92 +6,66 @@ namespace System.Application.UI.ViewModels
{
partial class MainWindowViewModel
{
readonly Dictionary<Type, Lazy<TabItemViewModel>> mTabItems = new();
readonly object mTabItemsLock = new();
static TabItemViewModel[]? mTabItems;
public IEnumerable<TabItemViewModel> TabItems => mTabItems.Values.Select(x => x.Value);
IReadOnlyList<TabItemViewModel>? _FooterTabItems;
public IReadOnlyList<TabItemViewModel>? FooterTabItems
public TabItemViewModel[] TabItems
{
get
{
if (_FooterTabItems == null)
lock (mTabItemsLock)
{
var items = new List<TabItemViewModel>
if (mTabItems == null) mTabItems = GetTabItems().ToArray();
return mTabItems;
}
IEnumerable<TabItemViewModel> GetTabItems()
{
foreach (var item in TabIdItems)
{
SettingsPageViewModel.Instance,
AboutPageViewModel.Instance,
};
#if !TRAY_INDEPENDENT_PROGRAM && DEBUG
if (IApplication.EnableDevtools && IApplication.IsDesktopPlatform)
{
items.Insert(0, DebugPageViewModel.Instance);
//items.Insert(1, DebugWebViewPageViewModel.Instance);
var type = TabItemViewModel.GetType(item);
yield return AllTabLazyItems[type].Value;
}
#endif
_FooterTabItems = items;
}
return _FooterTabItems;
}
}
public IEnumerable<TabItemViewModel> AllTabItems
readonly object mFooterTabItemsLock = new();
static TabItemViewModel[]? mFooterTabItems;
public TabItemViewModel[] FooterTabItems
{
get
{
if (FooterTabItems == null) return TabItems;
else return TabItems.Concat(FooterTabItems);
lock (mFooterTabItemsLock)
{
if (mFooterTabItems == null) mFooterTabItems = GetFooterTabItems().ToArray();
return mFooterTabItems;
}
IEnumerable<TabItemViewModel> GetFooterTabItems()
{
foreach (var item in FooterTabIdItems)
{
var type = TabItemViewModel.GetType(item);
yield return AllTabLazyItems[type].Value;
}
}
}
}
/// <summary>
/// 当前 <see cref="AllTabItems"/>,延时加载 <see cref="FooterTabItems"/>
/// </summary>
public IEnumerable<TabItemViewModel> CurrentAllTabItems
{
get
{
if (_FooterTabItems == null) return TabItems;
else return TabItems.Concat(_FooterTabItems);
}
}
public TabItemViewModel.TabItemId[] TabIdItems { get; }
void AddTabItem<TabItemVM>() where TabItemVM : TabItemViewModel, new()
{
Lazy<TabItemViewModel> value = new(() => new TabItemVM()
#if !TRAY_INDEPENDENT_PROGRAM
.AddTo(this)
#endif
);
mTabItems.Add(typeof(TabItemVM), value);
}
public TabItemViewModel.TabItemId[] FooterTabIdItems { get; }
//void AddTabItem<TabItemVM>(Func<TabItemVM> func) where TabItemVM : TabItemViewModel
//{
// Lazy<TabItemViewModel> value = new(func);
// mTabItems.Add(typeof(TabItemVM), value);
//}
public IReadOnlyCollection<TabItemViewModel.TabItemId> AllTabIdItems { get; }
public Dictionary<Type, Lazy<TabItemViewModel>> AllTabLazyItems { get; }
internal TabItemVM GetTabItemVM<TabItemVM>() where TabItemVM : TabItemViewModel
{
var type = typeof(TabItemVM);
if (mTabItems.ContainsKey(type))
if (AllTabLazyItems.ContainsKey(type))
{
return (TabItemVM)mTabItems[type].Value;
}
if (FooterTabItems != null)
{
foreach (var item in FooterTabItems)
{
if (item is TabItemVM itemVM)
{
return itemVM;
}
}
return (TabItemVM)AllTabLazyItems[type].Value;
}
throw new KeyNotFoundException($"type: {type} not found.");
@@ -81,71 +81,53 @@ namespace System.Application.UI.ViewModels
#region InitTabItems
//AddTabItem<StartPageViewModel>();
if (R.IsChineseSimplified || !IApplication.IsDesktopPlatform)
List<TabItemViewModel.TabItemId> tabIdItems = new();
List<TabItemViewModel.TabItemId> footerTabIdItems = new();
var showProxyScript = !OperatingSystem2.IsWindows() || R.IsChineseSimplified;
//tabIdItems.Add(TabItemViewModel.TabItemId.StartPage);
if (showProxyScript)
{
// Android 目前底部菜单实现要隐藏需要改多个地方
// 主要是初始化时不依赖 TabItems,两边逻辑暂不能同步一套代码
AddTabItem<CommunityProxyPageViewModel>();
tabIdItems.Add(TabItemViewModel.TabItemId.CommunityProxy);
}
if (IApplication.IsDesktopPlatform)
{
if (R.IsChineseSimplified)
if (showProxyScript)
{
AddTabItem<ProxyScriptManagePageViewModel>();
tabIdItems.Add(TabItemViewModel.TabItemId.ProxyScriptManage);
}
AddTabItem<SteamAccountPageViewModel>();
AddTabItem<GameListPageViewModel>();
tabIdItems.Add(TabItemViewModel.TabItemId.SteamAccount);
tabIdItems.Add(TabItemViewModel.TabItemId.GameList);
}
AddTabItem<LocalAuthPageViewModel>();
AddTabItem<ArchiSteamFarmPlusPageViewModel>();
tabIdItems.Add(TabItemViewModel.TabItemId.LocalAuth);
tabIdItems.Add(TabItemViewModel.TabItemId.ArchiSteamFarmPlus);
//tabIdItems.Add(TabItemViewModel.TabItemId.SteamIdle);
//AddTabItem<SteamIdlePageViewModel>();
#if !TRAY_INDEPENDENT_PROGRAM
if (OperatingSystem2.IsWindows())
AddTabItem<GameRelatedPageViewModel>();
tabIdItems.Add(TabItemViewModel.TabItemId.GameRelated);
#endif
//AddTabItem<AccountPageViewModel>();
//AddTabItem<OtherPlatformPageViewModel>();
//#if !TRAY_INDEPENDENT_PROGRAM && DEBUG
// if (IApplication.EnableDevtools && IApplication.IsDesktopPlatform)
// {
// AddTabItem<DebugPageViewModel>();
// //FooterTabItems.Add(new DebugPageViewModel().AddTo(this));
#if !TRAY_INDEPENDENT_PROGRAM && DEBUG
if (IApplication.EnableDevtools && IApplication.IsDesktopPlatform)
{
footerTabIdItems.Add(TabItemViewModel.TabItemId.Debug);
}
#endif
footerTabIdItems.Add(TabItemViewModel.TabItemId.Settings);
footerTabIdItems.Add(TabItemViewModel.TabItemId.About);
// //if (AppHelper.IsSystemWebViewAvailable)
// //{
// // AddTabItem<DebugWebViewPageViewModel>();
// //}
// }
//#endif
TabIdItems = tabIdItems.ToArray();
FooterTabIdItems = footerTabIdItems.ToArray();
AllTabIdItems = new HashSet<TabItemViewModel.TabItemId>(TabIdItems.Concat(FooterTabIdItems));
AllTabLazyItems = AllTabIdItems.ToDictionary(TabItemViewModel.GetType, v => new Lazy<TabItemViewModel>(() => TabItemViewModel.Create(v)));
#endregion
SelectedItem = TabItems.First();
R.Subscribe(() =>
{
foreach (var item in CurrentAllTabItems)
{
item.RaisePropertyChanged(nameof(TabItemViewModelBase.Name));
}
}).AddTo(this);
//this.WhenAnyValue(x => x.SelectedItem)
// .Subscribe(x =>
// {
// if (x != null)
// FrameContent = x;
// }).AddTo(this);
//this.WhenAnyValue(x => x.FrameContent)
// .Subscribe(x =>
// {
// if (x != SelectedItem)
// SelectedItem = null;
// }).AddTo(this);
SelectedItem = AllTabLazyItems.First().Value.Value;
}
public override void Initialize()
@@ -142,7 +142,14 @@ namespace System.Application.UI.ViewModels
{
if (IApplication.IsDesktopPlatform) // Android 上手动调用加载
{
LoadDonateRankListData(true);
try
{
LoadDonateRankListData(true);
}
catch (Exception ex)
{
Log.Error(nameof(AboutPageViewModel), ex, nameof(LoadDonateRankListData));
}
}
base.Activation();
}
@@ -192,7 +199,7 @@ namespace System.Application.UI.ViewModels
{
if (DonateList.Count <= content.Total)
{
if (content.DataSource.Any())
if (content.DataSource.Any_Nullable())
{
DonateList.AddRange(content.DataSource);
}
@@ -1,7 +1,8 @@
// ReSharper disable once CheckNamespace
#if !EXCLUDE_ASF
using System.Application.Services;
using System.Application.UI.Resx;
// ReSharper disable once CheckNamespace
namespace System.Application.UI.ViewModels
{
partial class ArchiSteamFarmPlusPageViewModel : IActionItem<ArchiSteamFarmPlusPageViewModel.ActionItem>
@@ -70,4 +71,5 @@ namespace System.Application.UI.ViewModels
_ => false,
};
}
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More