Compare commits

..
87 Commits
Author SHA1 Message Date
Aigio Liu 8046ee7a5b v2.4.12 2021-09-06 18:34:59 +08:00
Aigio Liu a77aa692c7 v2.4.12 2021-09-06 18:21:56 +08:00
Aigio Liu e4e5c5c0fd v2.4.12 2021-09-06 18:05:42 +08:00
Aigio Liu c103867f39 fix 2021-09-06 17:42:49 +08:00
Aigio Liu 5a8544bbc3 fix 2021-09-06 17:41:18 +08:00
Aigio Liu 14589068ff v2.4.12 2021-09-06 17:13:26 +08:00
Aigio Liu 77655f590b fix Linux OpenDir 2021-09-06 16:54:45 +08:00
Aigio Liu 8c71f57633 v2.4.12 2021-09-06 16:27:34 +08:00
Aigio Liu adca1019ff sh 2021-09-06 10:30:23 +08:00
RMBGAME d0b45b5727 UI 2021-09-06 01:33:33 +08:00
Aigio Liu 93ac9272f8 Chmod 2021-09-05 23:34:32 +08:00
Aigio Liu 3a61c38282 Update release md 2021-09-05 17:20:49 +08:00
Aigio Liu 6f38aba692 sh 2021-09-05 17:20:48 +08:00
Aigio Liu 006b249073 v2.4.12 2021-09-05 16:20:57 +08:00
Aigio Liu 30b7679573 改进 SteamServiceImpl 存在的 null 异常 2021-09-05 14:12:14 +08:00
Aigio Liu 40379ae63c pubxml & sh 2021-09-05 12:43:09 +08:00
RMBGAME ffeb55142e Misc 2021-09-05 09:29:44 +08:00
Aigio Liu 1a3e38350b remove NotifyIcon 2021-09-04 19:13:51 +08:00
Aigio Liu 4fd9fb75a0 trimming-options 2021-09-04 18:24:21 +08:00
Aigio Liu d2fe34ce23 pubxml 2021-09-04 18:22:19 +08:00
Aigio Liu c2f99c9778 Linux 托盘独立进程文件实现 2021-09-04 18:10:27 +08:00
Mossimo 909da224e2 savew 2021-09-04 17:13:52 +08:00
RMBGAME b83d400373 #438 功能实现 2021-09-04 17:09:51 +08:00
Aigio Liu 8d731d9d89 fix IsDirectory 2021-09-04 15:17:30 +08:00
Aigio Liu a703a6f5d9 fix pub debug 2021-09-04 14:32:33 +08:00
Aigio Liu dae24ed970 fix pub 2021-09-04 14:01:21 +08:00
Mossimo e56003a716 save 2021-09-04 13:07:47 +08:00
Aigio Liu 4a75f261d6 fix 2021-09-04 12:56:10 +08:00
Aigio Liu d783dcde79 ImageSouce 2021-09-04 12:54:49 +08:00
Aigio Liu af61df6f20 修复 默认头像可能引发的闪退
左侧菜单图标改为 Webp 格式
2021-09-04 12:05:26 +08:00
Aigio Liu f01c5c09ef ANDROID IS_STORE_PACKAGE 2021-09-04 10:58:19 +08:00
Aigio Liu 3761a98eb1 Update ASF 2021-09-04 10:49:24 +08:00
RMBGAME d79a4ac103 Misc 2021-09-04 06:56:41 +08:00
RMBGAME 6a413b38e9 new icon 2021-09-04 06:34:17 +08:00
RMBGAME 9ef08a8d4d 加速功能UI和交互优化 2021-09-04 05:12:59 +08:00
Aigio Liu 5e10a72cb3 LocalAuthAppWidgetProvider 2021-09-03 19:28:51 +08:00
RMBGAME 79105b264c 托盘菜单支持切换账号和复制令牌 2021-09-02 20:45:45 +08:00
RMBGAME c0a26a22d9 taskbar submenu 2021-09-02 17:44:57 +08:00
Aigio Liu b29a41f9b6 MyAuthenticator Name MaxLength 2021-09-01 17:06:38 +08:00
RMBGAME 01a8a9060c Hide GameRelated Menu 2021-09-01 01:06:20 +08:00
RMBGAME e42428d065 Delete references/references directory 2021-09-01 01:01:49 +08:00
RMBGAME cbcc32f081 Fix 2021-09-01 01:00:30 +08:00
RMBGAME ca5d26dba5 Fix 2021-09-01 00:51:34 +08:00
RMBGAME ac0429f7ef TaskBar Update 2021-09-01 00:51:34 +08:00
Aigio Liu 44dd8ad39d using var qrCodeData 2021-08-31 23:54:24 +08:00
Aigio Liu d914c0fdf2 Android 添加屏幕捕获设置项,用于允许截图或录制视频 2021-08-31 20:54:19 +08:00
Aigio Liu 91156646f9 改为 Timer 实现令牌刷新倒计时 2021-08-31 04:09:08 +08:00
Aigio Liu 7890968d59 修复 Android 上暗色模式下某些区域背景为白色 2021-08-31 00:01:55 +08:00
Aigio Liu a3809691d4 fix NotifyIcon.Windows 2021-08-30 10:52:46 +08:00
RMBGAME 9ef771ae5c Fix 2021-08-30 07:31:13 +08:00
RMBGAME fad9f741dd Fix 2021-08-30 07:02:22 +08:00
RMBGAME 3231b0ad6a update 2021-08-30 06:52:29 +08:00
RMBGAME 4af50e0d76 代理设置 2021-08-30 06:52:29 +08:00
Aigio Liu c1d14ce052 area lib 2021-08-30 00:26:25 +08:00
Aigio Liu d19111bb88 fix 2021-08-30 00:12:20 +08:00
Aigio Liu 75a3844aa0 fix 2021-08-29 23:54:55 +08:00
Aigio Liu ac529aa52a fix 2021-08-29 22:25:09 +08:00
Aigio Liu dbd5512dcb fix 2021-08-29 22:09:52 +08:00
Aigio Liu 7c73a9b860 ManagePackageVersionsCentrally 2021-08-29 22:04:27 +08:00
Aigio Liu 63ae983230 remove AddNotifyIcon<TNotifyIcon> 2021-08-29 19:05:11 +08:00
Aigio Liu 7bac01cdd4 remove INotifyIconWindow 2021-08-29 18:57:29 +08:00
Aigio Liu 7478763d19 summary 2021-08-29 18:51:32 +08:00
Aigio Liu f0167a4256 new NotifyIcon Impl 2021-08-29 18:46:03 +08:00
Aigio Liu 2377f3e775 remove AppDelegateHelper 2021-08-28 23:23:36 +08:00
Mossimo c5ee5788db fix liunxproxy 2021-08-28 18:09:53 +08:00
Mossimo b92df79243 save 2021-08-28 18:09:53 +08:00
Aigio Liu 2a9c53239b fix 2021-08-28 16:38:58 +08:00
Aigio Liu 0502eda850 fix http request 302 异常 2021-08-28 16:29:32 +08:00
Aigio Liu b8bba04029 fix 2021-08-28 02:31:04 +08:00
Aigio Liu d69826c424 linux dev pubxml 2021-08-28 02:31:03 +08:00
RMBGAME da27ede448 修复某些情况下少加载了部分已安装游戏的问题
#413
2021-08-27 15:36:21 +08:00
RMBGAME dc0596ec32 修复库存游戏刷新可能导致的闪退问题
新增社区加速代理设置
2021-08-26 23:59:16 +08:00
RMBGAME 21fe383a86 Frame 2021-08-26 19:08:38 +08:00
RMBGAME 374aedc264 FontManger
Text
Misc
2021-08-26 17:22:28 +08:00
Aigio Liu 5d903d130e fix 2021-08-26 17:16:56 +08:00
Aigio Liu 7555946433 remove app.demo 2021-08-26 16:41:00 +08:00
RMBGAME 9202866596 Fix 2021-08-26 15:36:52 +08:00
RMBGAME 50abad9f96 Fix Proxy Bug 2021-08-26 15:33:31 +08:00
RMBGAME e6a0b16508 Fix Mac Proxy Error 2021-08-26 15:25:13 +08:00
Aigio Liu 69c16d5c57 fix 2021-08-26 14:35:31 +08:00
Aigio Liu ecf0e5296a add MacPlatformLoggerProvider 2021-08-26 14:32:52 +08:00
Aigio Liu ee61b9fbf6 修复 Android 上令牌倒计时引发的闪退
改进 代理服务潜在的空指针异常
改进 hosts macOS 上文件操作
2021-08-26 13:44:19 +08:00
Aigio Liu 7ecc411c84 修复 Android 切换语言可能导致的闪退
修复 Windows 10 上启动时可能出现的网络连接中断提示
2021-08-25 14:49:50 +08:00
Aigio Liu 0cf9b05950 fix Android Release appcenter-secret
tryfix ChangeLanguage InvokeOnMainThread
2021-08-25 11:06:38 +08:00
Aigio Liu 787a81f805 add settingPriority 2021-08-25 00:57:54 +08:00
Aigio Liu 60164a776b fix 2021-08-25 00:52:45 +08:00
Aigio Liu c0a3977e0b 修复 头像应当为圆形而不是方形 2021-08-25 00:09:17 +08:00
255 changed files with 5536 additions and 3814 deletions
+1
View File
@@ -5,6 +5,7 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<TrimMode>link</TrimMode>
<DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<PropertyGroup Condition=" Exists('$(MSBuildProjectDirectory)\..\..\Unicorn.pfx') ">
+153
View File
@@ -0,0 +1,153 @@
<Project>
<ItemGroup>
<PackageVersion Include="ReactiveUI" Version="16.2.1" />
<PackageVersion Include="DynamicData" Version="7.3.1" />
<PackageVersion Include="Splat" Version="13.1.1" />
<PackageVersion Include="OperatingSystem2" Version="1.2.0" />
<PackageVersion Include="Microsoft.AppCenter" Version="4.3.0" />
<PackageVersion Include="Microsoft.AppCenter.Analytics" Version="4.3.0" />
<PackageVersion Include="Microsoft.AppCenter.Crashes" Version="4.3.0" />
<PackageVersion Include="Aigio.Avalonia.AppCenter" Version="4.3.1" />
<PackageVersion Include="Aigio.Avalonia.AppCenter.Analytics" Version="4.3.1" />
<PackageVersion Include="Aigio.Avalonia.AppCenter.Crashes" Version="4.3.1" />
<PackageVersion Include="nor0x.AppCenter" Version="4.3.1-XMAC" />
<PackageVersion Include="nor0x.AppCenter.Analytics" Version="4.3.1-XMAC" />
<PackageVersion Include="nor0x.AppCenter.Crashes" Version="4.3.1-XMAC" />
<PackageVersion Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageVersion Include="Nito.Comparers" Version="6.2.0" />
<PackageVersion Include="Xamarin.Essentials" Version="1.7.0" />
<PackageVersion Include="Crc32.NET" Version="1.2.0" />
<PackageVersion Include="gfoidl.Base64" Version="1.1.1" />
<PackageVersion Include="MessagePack" Version="2.3.75" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
<PackageVersion Include="System.Text.Json" Version="5.0.2" />
<PackageVersion Include="System.Text.Encodings.Web" Version="5.0.1" />
<PackageVersion Include="Polly" Version="7.2.2" />
<PackageVersion Include="sqlite-net-pcl" Version="1.8.103-beta" />
<PackageVersion Include="NUnit" Version="3.13.2" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageVersion Include="System.Security.Cryptography.ProtectedData" Version="5.0.0" />
<PackageVersion Include="nunit.xamarin" Version="3.6.1" />
<PackageVersion Include="PCLStorage" Version="1.0.2" />
<PackageVersion Include="Xamarin.Forms" Version="5.0.0.2083" />
<PackageVersion Include="Xamarin.Forms.Visual.Material" Version="5.0.0.2083" />
<PackageVersion Include="Moq" Version="4.16.1" />
<PackageVersion Include="AutoMapper" Version="10.1.1" />
<PackageVersion Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
<PackageVersion Include="Portable.BouncyCastle" Version="1.8.10" />
<PackageVersion Include="QRCoder" Version="1.4.1" />
<PackageVersion Include="DnsClient" Version="1.5.0" />
<PackageVersion Include="Fleck" Version="1.2.0" />
<PackageVersion Include="Gameloop.Vdf" Version="0.6.1" />
<PackageVersion Include="NLog" Version="4.7.11" />
<PackageVersion Include="NLog.Extensions.Logging" Version="1.7.4" />
<PackageVersion Include="NotifyIcon.Base" Version="1.0.2" />
<PackageVersion Include="NotifyIcon.Linux" Version="1.0.2" />
<PackageVersion Include="NotifyIcon.Mac" Version="1.0.2" />
<PackageVersion Include="NotifyIcon.Windows" Version="1.0.3" />
<PackageVersion Include="GtkSharp" Version="3.24.24.34" />
<PackageVersion Include="SharpZipLib" Version="1.3.2" />
<PackageVersion Include="Squid-Box.SevenZipSharp" Version="1.5.0.366" />
<PackageVersion Include="StatefulModel.Standard" Version="0.1.0" />
<PackageVersion Include="Titanium.Web.Proxy" Version="3.1.1397" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta1.21308.1" />
<PackageVersion Include="System.Drawing.Common" Version="5.0.2" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageVersion Include="Avalonia" Version="0.10.7" />
<PackageVersion Include="Avalonia.Desktop" Version="0.10.7" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.7" />
<PackageVersion Include="Avalonia.AvaloniaEdit" Version="0.10.4" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="0.10.7" />
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="0.10.7" />
<PackageVersion Include="CefNet.Avalonia" Version="93.1.21240.857" />
<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.5.1" />
<PackageVersion Include="FluentAvaloniaUI" Version="1.1.1" />
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.7" />
<PackageVersion Include="MonoMac.NetStandard" Version="0.0.4" />
<PackageVersion Include="JumpLists.Win32.Avalonia" Version="0.0.1" />
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="1.3.3" />
<PackageVersion Include="TaskScheduler" Version="2.9.1" />
<PackageVersion Include="Microsoft.Identity.Client" Version="4.35.1" />
<PackageVersion Include="de.hdodenhof.circleimageview" Version="3.1.0" />
<PackageVersion Include="ReactiveUI.AndroidX" Version="16.2.1" />
<PackageVersion Include="Square.OkHttp3" Version="4.9.1" />
<PackageVersion Include="Square.Picasso" Version="2.71828.0" />
<PackageVersion Include="TencentOpenApiSDK.Android" Version="3.5.4.11" />
<PackageVersion Include="LeakCanaryBinding" Version="1.5.1.1" />
<PackageVersion Include="Toast.iOS" Version="1.2.0" />
<PackageVersion Include="NPOI" Version="2.5.4" />
<PackageVersion Include="Octokit" Version="0.50.0" />
<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />
<PackageVersion Include="System.Runtime.WindowsRuntime" Version="4.7.0" />
<PackageVersion Include="System.Runtime.WindowsRuntime.UI.Xaml" Version="4.7.0" />
<PackageVersion Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageVersion Include="SQLitePCLRaw.bundle_green" Version="2.0.4" />
<PackageVersion Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageVersion Include="BrotliSharpLib" Version="0.3.3" />
<PackageVersion Include="System.Buffers" Version="4.5.1" />
<PackageVersion Include="System.Memory" Version="4.5.4" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.20348.19" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="5.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.9" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.9" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.9" />
<PackageVersion Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageVersion Include="Z.EntityFramework.Plus.EFCore" Version="5.2.9" />
<PackageVersion Include="AutoMapper" Version="10.1.1" />
<PackageVersion Include="AutoMapper.Collection" Version="7.0.1" />
<PackageVersion Include="AutoMapper.Collection.EntityFrameworkCore" Version="7.0.1" />
<PackageVersion Include="AutoMapper.Extensions.ExpressionMapping" Version="4.1.1" />
<PackageVersion Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
<PackageVersion Include="HtmlAgilityPack" Version="1.11.36" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.9" />
<PackageVersion Include="Microsoft.PowerShell.5.ReferenceAssemblies" Version="1.1.0" />
<PackageVersion Include="TextCopy" Version="4.3.1" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.9" />
<PackageVersion Include="AlipaySDKNet.Standard" Version="4.6.0" />
<PackageVersion Include="AspNet.Security.OAuth.Apple" Version="5.0.11" />
<PackageVersion Include="AspNet.Security.OAuth.QQ" Version="5.0.11" />
<PackageVersion Include="AspNet.Security.OpenId.Steam" Version="5.0.0" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="5.0.9" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.9" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.9" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.1" />
</ItemGroup>
<ItemGroup Condition=" $(DefineConstants.Contains('_HAVE_XF_')) ">
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.2.0.7" />
<PackageVersion Include="Xamarin.AndroidX.Emoji.AppCompat" Version="1.1.0.2" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.3.3" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.3.5" />
<PackageVersion Include="Xamarin.AndroidX.RecyclerView" Version="1.1.0.8" />
<PackageVersion Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.9" />
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.2.1.1" />
</ItemGroup>
<ItemGroup Condition=" !$(DefineConstants.Contains('_HAVE_XF_')) ">
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.3.1.1" />
<PackageVersion Include="Xamarin.AndroidX.SwipeRefreshLayout" Version="1.1.0.3" />
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.4.0.2" />
<PackageVersion Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.0" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.3.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.3.5.1" />
<PackageVersion Include="Xamarin.AndroidX.RecyclerView" Version="1.2.1.1" />
<PackageVersion Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.10" />
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.3.1" />
<PackageVersion Include="Xamarin.AndroidX.Biometric" Version="1.1.0.4" />
<PackageVersion Include="Xamarin.AndroidX.ExifInterface" Version="1.3.3" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.3.6.1" />
<PackageVersion Include="Xamarin.AndroidX.Migration" Version="1.0.8" />
<PackageVersion Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.9" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.3.1.1" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.0.1.1" />
<PackageVersion Include="Xamarin.AndroidX.Camera.View" Version="1.0.0.5-alpha20" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.0.1.1" />
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.37.0" />
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="116.1.2" />
</ItemGroup>
</Project>
+89 -37
View File
@@ -47,39 +47,91 @@ English | [简体中文](./README.md)
<!--Prerequisites Microsoft Visual C++ 2015-2019 Redistributable [64 bit](https://aka.ms/vs/16/release/vc_redist.x64.exe) / [32 bit](https://aka.ms/vs/16/release/vc_redist.x86.exe)-->
## 🖥 Supported Operating Systems
- Desktop(Only X64 and ARM64 are supported)
- Windows 10 / Windows Server, Version 20H2
- Windows 10 / Windows Server, Version 2004
- Windows 10 / Windows Server, Version 1909
- Windows 10 / Windows Server, Version 1903
- Windows 10, Version 1809
- Windows 10, Version 1803
- Windows 10, Version 1709
- Windows 10, Version 1607
- Windows 8.1 / Windows Server 2012 R2
- Windows 7 SP1 [ESU](https://docs.microsoft.com/troubleshoot/windows-client/windows-7-eos-faq/windows-7-extended-security-updates-faq)
- Prerequisites
- KB3063858 [64 bit](https://www.microsoft.com/download/details.aspx?id=47442) / [32 bit](https://www.microsoft.com/download/details.aspx?id=47409)
- Windows Server 2019
- Windows Server 2016
- Windows Server 2012 R2
- Windows Server 2012
- macOS 10.14 Mojave Or Higher
- Linux Distribution
- Arch Linux
- Alpine Linux 3.13+
- CentOS 7+
- Debian 10+
- Deepin 20.1 / UOS 20
- Fedora 32+
- Linux Mint 18+
- openSUSE 15+
- Red Hat Enterprise Linux 7+
- SUSE Enterprise Linux (SLES) 12 SP2+
- Ubuntu 16.04, 18.04, 20.04+
- Mobile
- Android 5.0/API 21+ (Only [arm64-v8a](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#arm64-v8a) and [armeabiv-v7a](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#v7a) are supported)
- iOS 10.0+ (ARM64 only)
### Windows
OS | Version | Architectures | Lifecycle
--------------------------------------|-------------------------|-----------------|----------
[Windows Client][Windows-client] | 7 SP1(**\***), 8.1 | x64 | [Windows][Windows-lifecycle]
[Windows 10 Client][Windows-client] | Version 1607+ | x64 | [Windows][Windows-lifecycle]
[Windows Server][Windows-Server] | 2012+ | x64 | [Windows Server][Windows-Server-lifecycle]
**\*** Windows 7 SP1 is supported with KB3063858 [64 bit](https://www.microsoft.com/download/details.aspx?id=47442) installed.
[Windows-client]: https://www.microsoft.com/windows/
[Windows-lifecycle]: https://support.microsoft.com/help/13853/windows-lifecycle-fact-sheet
[win-client-docker]: https://hub.docker.com/_/microsoft-windows
[Windows-Server-lifecycle]: https://docs.microsoft.com/windows-server/get-started/windows-server-release-info
[Nano-Server]: https://docs.microsoft.com/windows-server/get-started/getting-started-with-nano-server
[Windows-Server]: https://docs.microsoft.com/windows-server/
### Linux
OS | Version | Architectures | Lifecycle
--------------------------------------|-----------------------|-------------------|----------
[Alpine Linux][Alpine] | 3.13+ | x64, Arm64, Arm32 | [Alpine][Alpine-lifecycle]
[CentOS][CentOS] | 7+ | x64 | [CentOS][CentOS-lifecycle]
[Debian][Debian] | 10+ | x64, Arm64, Arm32 | [Debian][Debian-lifecycle]
[Fedora][Fedora] | 33+ | x64 | [Fedora][Fedora-lifecycle]
[openSUSE][OpenSUSE] | 15+ | x64 | [OpenSUSE][OpenSUSE-lifecycle]
[Red Hat Enterprise Linux][RHEL] | 7+ | x64, Arm64 | [Red Hat][RHEL-lifecycle]
[SUSE Enterprise Linux (SLES)][SLES] | 12 SP2+ | x64 | [SUSE][SLES-lifecycle]
[Ubuntu][Ubuntu] | 16.04, 18.04, 20.04+ | x64, Arm64, Arm32 | [Ubuntu][Ubuntu-lifecycle]
[Deepin / UOS][Deepin] | 20+ | x64 | [Deepin][Deepin-lifecycle]
[Alpine]: https://alpinelinux.org/
[Alpine-lifecycle]: https://wiki.alpinelinux.org/wiki/Alpine_Linux:Releases
[CentOS]: https://www.centos.org/
[CentOS-lifecycle]:https://wiki.centos.org/FAQ/General
[CentOS-docker]: https://hub.docker.com/_/centos
[CentOS-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-centos8
[Debian]: https://www.debian.org/
[Debian-lifecycle]: https://wiki.debian.org/DebianReleases
[Debian-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-debian10
[Fedora]: https://getfedora.org/
[Fedora-lifecycle]: https://fedoraproject.org/wiki/End_of_life
[Fedora-docker]: https://hub.docker.com/_/fedora
[Fedora-msft-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-fedora32
[Fedora-pm]: https://fedoraproject.org/wiki/DotNet
[OpenSUSE]: https://opensuse.org/
[OpenSUSE-lifecycle]: https://en.opensuse.org/Lifetime
[OpenSUSE-docker]: https://hub.docker.com/r/opensuse/leap
[OpenSUSE-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-opensuse15
[RHEL]: https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux
[RHEL-lifecycle]: https://access.redhat.com/support/policy/updates/errata/
[RHEL-msft-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-rhel8
[RHEL-pm]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/developing_.net_applications_in_rhel_8/using-net-core-on-rhel_gsg#installing-net-core_gsg
[SLES]: https://www.suse.com/products/server/
[SLES-lifecycle]: https://www.suse.com/lifecycle/
[SLES-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-sles15
[Ubuntu]: https://ubuntu.com/
[Ubuntu-lifecycle]: https://wiki.ubuntu.com/Releases
[Ubuntu-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-ubuntu-2004
[Deepin]: https://www.deepin.org/
[Deepin-lifecycle]: https://www.deepin.org/release-notes
### macOS
OS | Version | Architectures |
------------------------------|---------------------------|-------------------|
[macOS][macOS] | 10.14+ | x64 |
[macOS]: https://support.apple.com/macos
### Android
OS | Version | Architectures |
------------------------------|-------------------------|-------------------|
[Android][Android] | 5.0(API 21)+ | [Arm32](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#v7a), [Arm64](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#arm64-v8a) |
[Android]: https://support.google.com/android
### iOS / iPadOS
OS | Version | Architectures |
------------------------------|-------------------------|-------------------|
[iOS][iOS] | 10.0+ | x64, Arm32, Arm64 |
[iOS]: https://support.apple.com/ios
## ⛔ Unsupported Operating System
- Windows 8
@@ -92,9 +144,9 @@ English | [简体中文](./README.md)
Read what we [milestones](https://github.com/SteamTools-Team/SteamTools/milestones), and feel free to ask questions.
## ⌨️ Development Environment
[Visual Studio 2019 Version 16.10 Or Higher](https://visualstudio.microsoft.com/vs/) Or [JetBrains Rider](https://www.jetbrains.com/rider/) Or ~~[Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/)~~ Or ~~[Visual Studio Code](https://code.visualstudio.com/)~~
[Visual Studio 2019 Version 16.11 Or Higher](https://visualstudio.microsoft.com/vs/) Or [JetBrains Rider](https://www.jetbrains.com/rider/) Or ~~[Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/)~~ Or ~~[Visual Studio Code](https://code.visualstudio.com/)~~
- Supported Operating Systems
- [Windows 10 version 2004 or higher: Home, Professional, Education, and Enterprise (LTSC and S are not supported)](https://docs.microsoft.com/en-us/visualstudio/releases/2019/system-requirements)
- [Windows 10 Version 2004 Or Higher: Home, Professional, Education, and Enterprise (LTSC and S are not supported)](https://docs.microsoft.com/en-us/visualstudio/releases/2019/system-requirements)
- [macOS 10.14 Mojave Or Higher](https://docs.microsoft.com/en-us/visualstudio/productinfo/vs2019-system-requirements-mac)
- Workload
- Web and Cloud
@@ -112,8 +164,8 @@ Read what we [milestones](https://github.com/SteamTools-Team/SteamTools/mileston
- [Avalonia for Visual Studio](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
- [NUnit VS Templates](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
[Android Studio 4.2+](https://developer.android.com/studio/)
[Xcode 13](https://developer.apple.com/xcode/)
[Android Studio 2020.3.1 Or Higher](https://developer.android.com/studio/)
[Xcode 13 Or Higher](https://developer.apple.com/xcode/)
## 📄 Thanks to the following Open Source Projects
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
+88 -36
View File
@@ -56,39 +56,91 @@
<!--发布配置SelfContained=true时会自动打包VC++相关程序集-->
<!--先决条件 Microsoft Visual C++ 2015-2019 Redistributable [64 位](https://aka.ms/vs/16/release/vc_redist.x64.exe) / [32 位](https://aka.ms/vs/16/release/vc_redist.x86.exe)-->
## 🖥 系统要求
- 桌面端(仅支持 X64 和 ARM64)
- Windows 10/Windows Server 版本 20H2
- Windows 10/Windows Server 版本 2004
- Windows 10/Windows Server 版本 1909
- Windows 10/Windows Server 版本 1903
- Windows 10 版本 1809
- Windows 10 版本 1803
- Windows 10 版本 1709
- Windows 10 版本 1607
- Windows 8.1
- Windows 7 SP1 [ESU](https://docs.microsoft.com/zh-cn/troubleshoot/windows-client/windows-7-eos-faq/windows-7-extended-security-updates-faq)
- 先决条件
- KB3063858 [64 位](https://www.microsoft.com/zh-cn/download/details.aspx?id=47442) / [32 位](https://www.microsoft.com/zh-cn/download/details.aspx?id=47409)
- Windows Server 2019
- Windows Server 2016
- Windows Server 2012 R2
- Windows Server 2012
- macOS 10.14 Mojave 或更高版本
- Linux 发行版
- Arch Linux
- Alpine Linux 3.13+
- CentOS 7+
- Debian 10+
- Deepin 20.1 / UOS 20
- Fedora 32+
- Linux Mint 18+
- openSUSE 15+
- Red Hat Enterprise Linux 7+
- SUSE Enterprise Linux (SLES) 12 SP2+
- Ubuntu 16.04, 18.04, 20.04+
- 移动端
- Android 5.0/API 21+ (仅支持 [arm64-v8a](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#arm64-v8a) 和 [armeabiv-v7a](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#v7a))
- iOS 10.0+ (仅支持 ARM64)
### Windows
OS | Version | Architectures | Lifecycle
--------------------------------------|-------------------------|-----------------|----------
[Windows Client][Windows-client] | 7 SP1(**\***), 8.1 | x64 | [Windows][Windows-lifecycle]
[Windows 10 Client][Windows-client] | Version 1607+ | x64 | [Windows][Windows-lifecycle]
[Windows Server][Windows-Server] | 2012+ | x64 | [Windows Server][Windows-Server-lifecycle]
**\*** Windows 7 SP1 is supported with KB3063858 [64 位](https://www.microsoft.com/zh-cn/download/details.aspx?id=47442) installed.
[Windows-client]: https://www.microsoft.com/windows/
[Windows-lifecycle]: https://support.microsoft.com/help/13853/windows-lifecycle-fact-sheet
[win-client-docker]: https://hub.docker.com/_/microsoft-windows
[Windows-Server-lifecycle]: https://docs.microsoft.com/windows-server/get-started/windows-server-release-info
[Nano-Server]: https://docs.microsoft.com/windows-server/get-started/getting-started-with-nano-server
[Windows-Server]: https://docs.microsoft.com/windows-server/
### Linux
OS | Version | Architectures | Lifecycle
--------------------------------------|-----------------------|-------------------|----------
[Alpine Linux][Alpine] | 3.13+ | x64, Arm64, Arm32 | [Alpine][Alpine-lifecycle]
[CentOS][CentOS] | 7+ | x64 | [CentOS][CentOS-lifecycle]
[Debian][Debian] | 10+ | x64, Arm64, Arm32 | [Debian][Debian-lifecycle]
[Fedora][Fedora] | 33+ | x64 | [Fedora][Fedora-lifecycle]
[openSUSE][OpenSUSE] | 15+ | x64 | [OpenSUSE][OpenSUSE-lifecycle]
[Red Hat Enterprise Linux][RHEL] | 7+ | x64, Arm64 | [Red Hat][RHEL-lifecycle]
[SUSE Enterprise Linux (SLES)][SLES] | 12 SP2+ | x64 | [SUSE][SLES-lifecycle]
[Ubuntu][Ubuntu] | 16.04, 18.04, 20.04+ | x64, Arm64, Arm32 | [Ubuntu][Ubuntu-lifecycle]
[Deepin / UOS][Deepin] | 20+ | x64 | [Deepin][Deepin-lifecycle]
[Alpine]: https://alpinelinux.org/
[Alpine-lifecycle]: https://wiki.alpinelinux.org/wiki/Alpine_Linux:Releases
[CentOS]: https://www.centos.org/
[CentOS-lifecycle]:https://wiki.centos.org/FAQ/General
[CentOS-docker]: https://hub.docker.com/_/centos
[CentOS-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-centos8
[Debian]: https://www.debian.org/
[Debian-lifecycle]: https://wiki.debian.org/DebianReleases
[Debian-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-debian10
[Fedora]: https://getfedora.org/
[Fedora-lifecycle]: https://fedoraproject.org/wiki/End_of_life
[Fedora-docker]: https://hub.docker.com/_/fedora
[Fedora-msft-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-fedora32
[Fedora-pm]: https://fedoraproject.org/wiki/DotNet
[OpenSUSE]: https://opensuse.org/
[OpenSUSE-lifecycle]: https://en.opensuse.org/Lifetime
[OpenSUSE-docker]: https://hub.docker.com/r/opensuse/leap
[OpenSUSE-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-opensuse15
[RHEL]: https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux
[RHEL-lifecycle]: https://access.redhat.com/support/policy/updates/errata/
[RHEL-msft-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-rhel8
[RHEL-pm]: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/developing_.net_applications_in_rhel_8/using-net-core-on-rhel_gsg#installing-net-core_gsg
[SLES]: https://www.suse.com/products/server/
[SLES-lifecycle]: https://www.suse.com/lifecycle/
[SLES-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-sles15
[Ubuntu]: https://ubuntu.com/
[Ubuntu-lifecycle]: https://wiki.ubuntu.com/Releases
[Ubuntu-pm]: https://docs.microsoft.com/dotnet/core/install/linux-package-manager-ubuntu-2004
[Deepin]: https://www.deepin.org/
[Deepin-lifecycle]: https://www.deepin.org/release-notes
### macOS
OS | Version | Architectures |
------------------------------|---------------------------|-------------------|
[macOS][macOS] | 10.14+ | x64 |
[macOS]: https://support.apple.com/macos
### Android
OS | Version | Architectures |
------------------------------|-------------------------|-------------------|
[Android][Android] | 5.0(API 21)+ | [Arm32](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#v7a), [Arm64](https://developer.android.google.cn/ndk/guides/abis?hl=zh_cn#arm64-v8a) |
[Android]: https://support.google.com/android
### iOS / iPadOS
OS | Version | Architectures |
------------------------------|-------------------------|-------------------|
[iOS][iOS] | 10.0+ | x64, Arm32, Arm64 |
[iOS]: https://support.apple.com/ios
## ⛔ 不受支持的操作系统
- Windows 8
@@ -101,7 +153,7 @@
查看这个 [milestones](https://github.com/SteamTools-Team/SteamTools/milestones) 来了解我们下一步的开发计划,并随时提出问题。
## ⌨️ 开发环境
[Visual Studio 2019 版本 16.10 或更高版本](https://visualstudio.microsoft.com/zh-hans/vs/) 或 [JetBrains Rider](https://www.jetbrains.com/rider/) 或 ~~[Visual Studio for Mac](https://visualstudio.microsoft.com/zh-hans/vs/mac/)~~ 或 ~~[Visual Studio Code](https://code.visualstudio.com/)~~
[Visual Studio 2019 版本 16.11 或更高版本](https://visualstudio.microsoft.com/zh-hans/vs/) 或 [JetBrains Rider](https://www.jetbrains.com/rider/) 或 ~~[Visual Studio for Mac](https://visualstudio.microsoft.com/zh-hans/vs/mac/)~~ 或 ~~[Visual Studio Code](https://code.visualstudio.com/)~~
- 系统要求
- [Windows 10 版本 2004 或更高版本:家庭版、专业版、教育版和企业版(不支持 LTSC 和 Windows 10 S,在较早的操作系统上可能不受支持)](https://docs.microsoft.com/zh-cn/visualstudio/releases/2019/system-requirements)
- [macOS 10.14 Mojave 或更高版本](https://docs.microsoft.com/zh-cn/visualstudio/productinfo/vs2019-system-requirements-mac)
@@ -121,8 +173,8 @@
- [Avalonia for Visual Studio](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
- [NUnit VS Templates](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
[Android Studio 4.2+](https://developer.android.google.cn/studio/)
[Xcode 13](https://developer.apple.com/xcode/)
[Android Studio 2020.3.1 或更高版本](https://developer.android.google.cn/studio/)
[Xcode 13 或更高版本](https://developer.apple.com/xcode/)
## 🏗️ [项目结构](./src/README.md)
+31 -30
View File
@@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Root", "_Root", "{66839CD8
.gitignore = .gitignore
packaging\build-osx-app.sh = packaging\build-osx-app.sh
Directory.Build.props = Directory.Build.props
Directory.Packages.props = Directory.Packages.props
global.json = global.json
nuget.config = nuget.config
README.en.md = README.en.md
@@ -102,8 +103,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Tools.Translate", "src\S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.Avalonia.App", "src\ST.Client.Desktop.Avalonia.App\ST.Client.Desktop.Avalonia.App.csproj", "{1CB40DC8-8FBC-4278-A19A-D872CFA353C0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.Avalonia.Demo.App", "src\ST.Client.Desktop.Avalonia.Demo.App\ST.Client.Desktop.Avalonia.Demo.App.csproj", "{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ST.Client.Mobile.Droid.App", "src\ST.Client.Mobile.Droid.App\ST.Client.Mobile.Droid.App.csproj", "{B355E372-27D2-4217-A129-D3355573681F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ST.Client.Mobile.iOS.App", "src\ST.Client.Mobile.iOS.App\ST.Client.Mobile.iOS.App.csproj", "{AFC828ED-21EE-4FD4-A40D-FEFED5EED4EA}"
@@ -126,6 +125,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Server.Resources", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FluentAvalonia", "references\FluentAvalonia\FluentAvalonia\FluentAvalonia.csproj", "{42154590-445B-41CF-AAEB-AACD1B65FA2C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ST.Client.Desktop.Linux.App.TrayIcon", "src\ST.Client.Desktop.Linux.App.TrayIcon\ST.Client.Desktop.Linux.App.TrayIcon.csproj", "{D9AF058F-D954-439B-BD72-51C47F65E7BE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1194,34 +1195,6 @@ Global
{1CB40DC8-8FBC-4278-A19A-D872CFA353C0}.Release|x64.Build.0 = Release|Any CPU
{1CB40DC8-8FBC-4278-A19A-D872CFA353C0}.Release|x86.ActiveCfg = Release|Any CPU
{1CB40DC8-8FBC-4278-A19A-D872CFA353C0}.Release|x86.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|ARM.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|ARM64.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|iPhone.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|x64.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|x64.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|x86.ActiveCfg = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Debug|x86.Build.0 = Debug|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|Any CPU.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|ARM.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|ARM.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|ARM64.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|ARM64.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|iPhone.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|iPhone.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|x64.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|x64.Build.0 = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|x86.ActiveCfg = Release|Any CPU
{7EC4BAB6-B7C0-4E87-9FB6-091ABFF10D88}.Release|x86.Build.0 = Release|Any CPU
{B355E372-27D2-4217-A129-D3355573681F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B355E372-27D2-4217-A129-D3355573681F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B355E372-27D2-4217-A129-D3355573681F}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
@@ -1548,6 +1521,34 @@ Global
{42154590-445B-41CF-AAEB-AACD1B65FA2C}.Release|x64.Build.0 = Release|Any CPU
{42154590-445B-41CF-AAEB-AACD1B65FA2C}.Release|x86.ActiveCfg = Release|Any CPU
{42154590-445B-41CF-AAEB-AACD1B65FA2C}.Release|x86.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|ARM.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|ARM.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|ARM64.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|iPhone.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|x64.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|x64.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|x86.ActiveCfg = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Debug|x86.Build.0 = Debug|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|Any CPU.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|ARM.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|ARM.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|ARM64.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|ARM64.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|iPhone.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|iPhone.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|x64.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|x64.Build.0 = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|x86.ActiveCfg = Release|Any CPU
{D9AF058F-D954-439B-BD72-51C47F65E7BE}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+2 -2
View File
@@ -33,9 +33,9 @@ emit_plist() {
<key>CFBundleIdentifier</key>
<string>net.steampp.app</string>
<key>CFBundleShortVersionString</key>
<string>2.4.11</string>
<string>2.4.12</string>
<key>CFBundleVersion</key>
<string>2.4.11.0</string>
<string>2.4.12.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.14</string>
<key>CFBundleDevelopmentRegion</key>
+149
View File
@@ -0,0 +1,149 @@
// https://github.com/aspnet/Hosting/blob/2.2.0/src/Microsoft.AspNetCore.Hosting/WebHostExtensions.cs
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.Hosting
{
public static class WebHostCompatExtensions
{
/// <summary>
/// Runs a web application and block the calling thread until host shutdown.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
public static void RunCompat(this IWebHost host)
{
host.RunCompatAsync().GetAwaiter().GetResult();
}
/// <summary>
/// Runs a web application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task RunCompatAsync(this IWebHost host, CancellationToken token = default)
{
// Wait for token shutdown if it can be canceled
if (token.CanBeCanceled)
{
await host.RunAsync(token, shutdownMessage: null);
return;
}
// If token cannot be canceled, attach Ctrl+C and SIGTERM shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
var shutdownMessage = host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages ? string.Empty : "Application is shutting down...";
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: shutdownMessage);
try
{
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
}
finally
{
done.Set();
}
}
}
private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
{
using (host)
{
await host.StartAsync(token);
var hostingEnvironment = host.Services.GetService<IHostingEnvironment>();
var options = host.Services.GetRequiredService<WebHostOptions>();
if (!options.SuppressStatusMessages)
{
Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
var serverAddresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
if (serverAddresses != null)
{
foreach (var address in serverAddresses)
{
Console.WriteLine($"Now listening on: {address}");
}
}
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
}
await host.WaitForTokenShutdownAsync(token);
}
}
private static void AttachCtrlcSigtermShutdown(CancellationTokenSource cts, ManualResetEventSlim resetEvent, string shutdownMessage)
{
void Shutdown()
{
if (!cts.IsCancellationRequested)
{
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
try
{
cts.Cancel();
}
catch (ObjectDisposedException) { }
}
// Wait on the given reset event
resetEvent.Wait();
};
AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => Shutdown();
try
{
Console.CancelKeyPress += (sender, eventArgs) =>
{
Shutdown();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
}
catch (PlatformNotSupportedException)
{
}
}
private static async Task WaitForTokenShutdownAsync(this IWebHost host, CancellationToken token)
{
var applicationLifetime = host.Services.GetService<IApplicationLifetime>();
token.Register(state =>
{
((IApplicationLifetime)state).StopApplication();
},
applicationLifetime);
var waitForStop = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
applicationLifetime.ApplicationStopping.Register(obj =>
{
var tcs = (TaskCompletionSource<object>)obj;
tcs.TrySetResult(null);
}, waitForStop);
await waitForStop.Task;
// WebHost will use its default ShutdownTimeout if none is specified.
await host.StopAsync();
}
}
}
+48 -28
View File
@@ -13,21 +13,45 @@ Steam++是完全开源的,请不要在非官方渠道下载软件,对于软
5. 新增 Desktop 上现可刷新头像
6. 新增 UI设置-主题色设置
7. 新增 UI设置-自定义背景图片设置
8. 新增 库存游戏可浏览已安装的游戏文件夹
9. 新增 创意工坊划词翻译脚本
10. 新增 通用设置-使用硬件加速设置项,也可通过命令行参数禁用硬件加速启动 -clt devtools -disable_gpu
11. 新增 账号切换内新增家庭库共享排序功能,该功能可调整当前设备的多个家庭共享账号库存的优先级顺序。
12. 新增 QQ 快速登录渠道
13. 新增 意大利语支持
14. 新增 西班牙语支持
15. 新增 通用设置内可支持访问程序的 AppData、Cache、Logs 文件夹和查看缓存及日志占用空间大小情况
16. 新增 本地令牌可以查看令牌二维码导入到移动端
17. Android/macOS/Linux 版现已开启 Beta/Alpha 测试,可从 GitHub/Gitee 上下载
### 修复问题
1. 修复 Desktop 上账号切换功能
2. 改进 Desktop 上受保护的成就不在支持勾选
3. 修复 Linux 上因字体引发的启动时闪退
4. 修复 Android 上扫码导入功能
5. 修复 Android 上 Toast 不能正常显示
6. 改进 Android 上的令牌导入方式
7. 修复 Android 上导入带密码的令牌时不显示密码输入框
8. 修复 导入带密码的令牌时密码输入文本框窗口不能正确取消
9. 修复 Desktop 上使用火狐浏览器无法进行快速登录
10. 修复 Android 8.0 以下启动时闪退
11. 修复 Desktop 上部分用户库存游戏已安装游戏无法读取
12. 尝试修复 Windows 上托盘菜单有时无法打开窗口
13. 改进 Android 上确认交易页面上的显示隐藏逻辑
1. 修复 开机自启动在 2.4.x 中不生效
2. 改进 深色和浅色模式的视觉效果
3. 改进 社区加速计时逻辑
4. 更正 导出令牌窗口标题文本错误
5. 改进 添加令牌弹窗可调整窗口大小
6. 改进 本地令牌自定义修改名称操作
7. 修复 我的面板中出现垂直滚动条
8. 改进 解锁成就风险提示弹窗可以设置不再提示
9. 修复 任务栏位于顶部时托盘菜单位置不正确
10. 修复 挂时长运行中列表移除游戏时引发的闪退
11. 改进 自动更新机制
12. 改进 开机自启动现仅对当前用户生效
13. 改进 第三方账号快速登录,现使用系统浏览器进行快速登录
14. 改进 现已编译为 ReadyToRun (R2R) 格式,这将改进应用程序的启动时间和延迟(仅 Windows 版)
15. 修复 库存游戏中部分游戏被错误屏蔽没有加载
16. 改进 部分语言的翻译文本
17. 改进 本地令牌上移下移功能顺序错乱问题
18. 修复 程序在加载库存游戏时有概率闪退的问题
19. 修复 打开托盘菜单有概率导致程序闪退的问题
20. 修复 程序启动时界面不会加载任何内容无法正常使用的问题
21. 改进 账号切换功能 UI
22. 改进 移除了 CEF 模块,缩减程序体积和运行时内存占用
23. 改进 库存游戏支持显示已安装游戏占用空间大小
24. 改进 库存游戏封面大小调节可支持滚动调节
25. 改进 hosts 文件编码在 Windows 上使用系统的活动代码页(ANSICodePage),例如 GB2312/936,其他操作系统则使用 UTF-8,还原 V1 版本行为
26. 改进 开始菜单磁贴背景由黑色更改为透明
27. 修复 账号切换修改账号备注重启后被还原
### 已知问题
- Desktop
@@ -59,10 +83,7 @@ Steam++是完全开源的,请不要在非官方渠道下载软件,对于软
软件截图
[hide]
[attachimg]1228394[/attachimg]
[attachimg]1228395[/attachimg]
[attachimg]1228396[/attachimg]
[attachimg]1228397[/attachimg]
[/hide]
## 核心功能
@@ -71,21 +92,18 @@ Steam++是完全开源的,请不要在非官方渠道下载软件,对于软
### 1. 通过本地反代理Steam的社区等网页使其能正常访问
功能使用Titanium-Web-Proxy开源项目进行本地反代,相比SteamCommunity302工具具有更快的启动速度。让用户能够连接上诸如Steam社区(个人资料页)、Discord语音聊天、Twitch直播观看、Origin下载加速、谷歌验证码、Pixiv图片等。
[attachimg]1228388[/attachimg]
### 2. 快速切换当前PC已经记住登陆的Steam账号
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。如果您的ip地址更换,会导致登陆状态失效。在Steam++2.0新版本支持了动态头像。
[attachimg]1228389[/attachimg]
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。如果您的ip地址更换,会导致登陆状态失效。
### 3. Steam游戏的成就统计管理功能
### 3. Steam游戏成就管理
能够读取任何游戏的成就信息(包括隐藏成就),并且能进行成就修改,包括成就解锁以及成就反解锁,还能够修改成就统计信息
参考SAM(SteamAchievementManager)进行二次开发,修复了成就语言有中文却依然是英文成就信息的BUG,修改了游戏列表的加载和操作易用性。
注意:滥用成就管理功能可能会导致开发者封禁!
[attachimg]1228390[/attachimg]
### 4. Steam本地两步身份验证器
@@ -94,19 +112,20 @@ Steam++是完全开源的,请不要在非官方渠道下载软件,对于软
不仅能查看手机令牌,还能进行交易报价确认,并且能一键全部确认。
功能参考WinAuth开发,功能类似的软件有WinAuth、SteamDesktopAuthenticator。
[attachimg]1228391[/attachimg]
本地令牌交易市场报价确认
[attachimg]1262615[/attachimg]
### 5. Steam内置浏览器脚本注入
通过反代加速功能将js脚本内置插入了Steam客户端内的浏览器,达到了与油猴类似的效果。目前2.0.0.6版本新增了脚本工坊,可以从我们的服务器上下载到已经兼容的脚本。我们也会不断添加新的脚本,同时也会对旧的脚本进行维护。
### 6. 更多的游戏工具功能
### 6.Steam家庭库共享排序
可以排序你的共享库存顺序,避免只能读取A的共享游戏,却想玩B的共享游戏。
### 7. 更多的游戏工具功能
支持各种老游戏无边框窗口化等等
### 6. 更新计划(画饼时间到)
我们预计会在6月份将推出本地挂卡、挂时长功能。并且同步推出iOS、安卓端App,用户可以利用手机查看多个账号的令牌,一键确认上架,并且支持手机挂卡。
### 8. 更新计划(画饼时间到)
我们预计会在6月份将推出ASF挂卡功能。并且同步推出iOS、安卓端App,用户可以利用手机查看多个账号的令牌,一键确认上架,并且支持手机挂卡。
#### 并且,以上功能全部免费。
@@ -120,9 +139,10 @@ Steam++是完全开源的,请不要在非官方渠道下载软件,对于软
## 下载
> [官网](https://steampp.net/)
> [Github](https://github.com/rmbadmin/SteamTools/releases)
> [Gitee](https://gitee.com/rmbgame/SteamTools/releases)
> 分流下载:
> [hide]
> [蓝奏云](https://cliencer.lanzous.com/b0165duja)
> [蓝奏云](https://cliencer.lanzoux.com/b0165duja)
> 提取码:1234
> [/hide]
使用过程中可能遇到windows defender误报,您可以选择添加信任。
+38 -30
View File
@@ -1,14 +1,22 @@
### 新增内容
1. 部分新增文本的其他语言翻译
1. 新增 Desktop 上网络加速代理设置
2. 新增 Android 上屏幕捕获设置项,用于允许截图或录制视频
3. 新增 Windows 托盘菜单支持切换账号与复制令牌
4. 新增 Linux/macOS 托盘菜单改进与完善
### 修复问题
1. 修复 Desktop 上因登录或注册后头像引发的无限闪退
2. 修复 Windows 上托盘菜单有时无法打开窗口
3. 改进 Desktop 上库存游戏右键菜单隐藏游戏项位置
4. 移除 Desktop 上菜单栏用户手机号显示
5. 修复 Desktop 上库存游戏中磁盘占用 UI 错位
6. 修复 Desktop 上快速登录等待中 UI 错位
7. 修复一些杂项问题,增强程序稳定性
1. 修复 Desktop 上用户头像应当为圆形而不是方形
2. 修复 Android 上切换系统语言可能引发的闪退
3. 修复 Windows 10 上启动时可能出现的网络连接中断提示
4. 修复 Android 上令牌倒计时可能引发的闪退
5. 修复 Desktop 上库存游戏刷新可能引发的闪退
6. 修复 Desktop 上可能少加载了部分已安装游戏
7. 修复 Android 上暗色模式下某些区域背景为白色
8. 改进 Android 上令牌刷新倒计时
9. 改进 本地令牌名称最大长度限制 32 个字符
10. 改进 Desktop 上网络加速 UI
11. 修复 Desktop 上默认头像可能引发的闪退
12. 改进 Desktop 上左侧菜单图标
### 已知问题
- Desktop
@@ -17,7 +25,7 @@
- 某些窗口顶部会有两个标题栏
- 自动更新不可用
- Linux
- 托盘不生效,这将影响程序不能正常退出
- 当使用 root 权限运行时托盘不生效,可通过 Exit.sh 退出程序
- 窗口弹出位置不正确
- 窗口顶部会有两个标题栏
- 自动更新不可用
@@ -25,7 +33,6 @@
- 主题切换需重启软件后生效,且跟随系统暂不可用
- Mobile
- Android
- 本地令牌倒计时存在误差不够精确,可能导致令牌值不一致
- 确认交易列表刷新后数据显示不正确
- 自动更新暂不可用
@@ -47,37 +54,38 @@
| win-arm64 | ❌ | |
| ios-arm64 | ❌ | |
<!--
- macOS
- 如果你使用 ARM 芯片的 Mac(较为**稀有**),例如 **M1**,则下载文件名中带有 **macos_arm64** 的文件
- 如果你使用 Intel、AMD 芯片的 Mac(较为**普遍**),则下载文件名中带有 **macos_x64** 的文件
-->
## 下载指南
- Windows
- 如果你使用 Intel、AMD 的 x64 芯片的 Mac(较为**普遍**),则下载文件名中带有 **win_x64** 的文件
- **[暂未支持]** ~~如果你使用 ARM64 芯片的 PC(极为**稀有**),例如 **Surface Pro X**,则下载文件名中带有 **win_arm64** 的文件~~
- macOS
- 如果你使用 Intel、AMD 的 x64 芯片的 Mac(较为**普遍**),则下载文件名中带有 **macos_x64** 的文件
- 如果你使用 ARM64 芯片的 Mac(较为**稀有**),例如 **M1**,则下载文件名中带有 **macos_x64** 的文件可通过 [Rosetta 2](https://support.apple.com/zh-cn/HT211861) 运行
- **[暂未支持]** ~~如果你使用 ARM64 芯片的 Mac(较为**稀有**),例如 **M1**,则下载文件名中带有 **macos_arm64** 的文件~~
- Linux
- 如果你使用 Intel、AMD 芯片的 PC(较为**普遍**)则下载文件名中带有 **linux_x64** 的文件
- 如果你使用 Intel、AMD 的 x64 芯片的 PC(较为**普遍**)则下载文件名中带有 **linux_x64** 的文件
- 如果你使用 ARM64 芯片的 PC(较为**稀有**)例如 **Raspberry Pi Model 3+**,则下载文件名中带有 **linux_arm64** 的文件
- 如果你使用 ARM 芯片的 PC(较为**稀有**)例如 **Raspberry Pi Model 2+**,则下载文件名中带有 **linux_arm** 的文件
- 如果你使用 ARM32 芯片的 PC(较为**稀有**)例如 **Raspberry Pi Model 2+**,则下载文件名中带有 **linux_arm** 的文件
- Android
- 如果你使用 ARM64 芯片的设备(较为**普遍**)则下载文件名中带有 **android_arm64_v8a** 的文件
- 如果你使用 ARM 芯片的设备(较为**稀有**)通常为 **14** 年下半年之前生产的设备,则下载文件名中带有 **android_armeabi_v7a** 的文件
- 如果你使用 ARM32 芯片的设备(较为**稀有**)通常为 **14** 年下半年之前生产的设备,则下载文件名中带有 **android_armeabi_v7a** 的文件
| File | Checksum (SHA256) |
| ---- | ---- |
| Steam++_win_x64_v2.4.11.7z | SHA256 |
| Steam++_win_x64_v2.4.11.exe | SHA256 |
| Steam++_win_x64_v2.4.12.7z | SHA256 |
| Steam++_win_x64_v2.4.12.exe | SHA256 |
| | |
| Steam++_linux_x64_v2.4.11.7z | SHA256 |
| Steam++_linux_arm64_v2.4.11.7z | SHA256 |
| Steam++_linux_arm_v2.4.11.7z | SHA256 |
| Steam++_linux_x64_v2.4.12.7z | SHA256 |
| Steam++_linux_arm64_v2.4.12.7z | SHA256 |
| Steam++_linux_arm_v2.4.12.7z | SHA256 |
| | |
| Steam++_macos_x64_v2.4.11.dmg | SHA256 |
| Steam++_macos_x64_v2.4.11.app.zip | SHA256 |
| Steam++_macos_x64_v2.4.11.7z | SHA256 |
| Steam++_macos_x64_v2.4.12.dmg | SHA256 |
| Steam++_macos_x64_v2.4.12.app.zip | SHA256 |
| Steam++_macos_x64_v2.4.12.7z | SHA256 |
| | |
| Steam++_android_arm64_v8a_v2.4.11.apk | SHA256 |
| Steam++_android_armeabi_v7a_v2.4.11.apk | SHA256 |
| Steam++_android_arm64_v8a_v2.4.12.apk | SHA256 |
| Steam++_android_armeabi_v7a_v2.4.12.apk | SHA256 |
<!-- ***
由于程序体积较大,推荐从 [官网 https://steampp.net](https://steampp.net) 中下载 -->
由于程序体积较大,推荐从 [官网 https://steampp.net](https://steampp.net) 中下载 -->
@@ -1,4 +1,4 @@
namespace System.Application.Entities
namespace System.Application.Entities
{
public partial interface IArea : IEntity<int>
{
@@ -24,6 +24,11 @@
/// </summary>
string? ShortName { get; set; }
protected static string ToString(IArea area) => AreaExtensions.ToString(area);
protected static string ToString(IArea area)
{
if (!string.IsNullOrWhiteSpace(area.ShortName)) return area.ShortName;
if (!string.IsNullOrWhiteSpace(area.Name)) return area.Name;
return area.Id.ToString();
}
}
}
@@ -1,4 +1,4 @@
using System.Application.Entities;
using System.Application.Entities;
namespace System.Application.Services
{
@@ -1,4 +1,4 @@
using System.Application.Entities;
using System.Application.Entities;
using System.Linq;
namespace System.Application.Services
@@ -10,7 +10,7 @@ namespace System.Application.Services
/// </summary>
/// <param name="area"></param>
/// <returns></returns>
public TArea GetSecondaryOrThis(TArea area)
TArea GetSecondaryOrThis(TArea area)
{
if (area.Level == AreaLevel.区县_县级市 && area.Up.HasValue)
{
@@ -42,7 +42,7 @@ namespace System.Application.Services
/// </summary>
/// <param name="area"></param>
/// <returns></returns>
public string GetFullName(TArea area)
string GetFullName(TArea area)
{
if (area.Up.HasValue)
{
@@ -52,7 +52,7 @@ namespace System.Application.Services
return $"{entity} {area}";
}
}
return AreaExtensions.ToString(area);
return area.ToString();
}
}
}
@@ -7,17 +7,14 @@ namespace System.Application.Services.Implementation
{
internal sealed class AreaResourceImpl<TArea> : IAreaResource<TArea>, IAreaResourceHelper<TArea> where TArea : class, IArea
{
TArea[]? areas;
public TArea[] GetAll()
static readonly Lazy<TArea[]> areas = new(() =>
{
if (areas == null)
{
var lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray);
areas = MessagePackSerializer.Deserialize<TArea[]>(SR.AMap_adcode_citycode_20210406_xlsx, lz4Options);
}
var lz4Options = MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray);
var areas = MessagePackSerializer.Deserialize<TArea[]>(SR.AMap_adcode_citycode_20210406_xlsx, lz4Options);
return areas;
}
});
public TArea[] GetAll() => areas.Value;
const int DefaultSelectionId = 110000;
@@ -1,4 +1,4 @@
using System.Application.Entities;
using System.Application.Entities;
using System.Application.Services;
// ReSharper disable once CheckNamespace
@@ -6,21 +6,14 @@ namespace System
{
public static class AreaExtensions
{
internal static string ToString(IArea area)
{
if (!string.IsNullOrWhiteSpace(area.ShortName)) return area.ShortName;
if (!string.IsNullOrWhiteSpace(area.Name)) return area.Name;
return area.Id.ToString();
}
/// <inheritdoc cref="IAreaResource{TArea}.GetSecondaryOrThis(TArea)"/>
/// <inheritdoc cref="IAreaResourceHelper{TArea}.GetSecondaryOrThis(TArea)"/>
public static TArea GetSecondaryOrThis<TArea>(this TArea area) where TArea : class, IArea
{
var s = DI.Get<IAreaResourceHelper<TArea>>();
return s.GetSecondaryOrThis(area);
}
/// <inheritdoc cref="IAreaResource{TArea}.GetFullName(TArea)"/>
/// <inheritdoc cref="IAreaResourceHelper{TArea}.GetFullName(TArea)"/>
public static string GetFullName<TArea>(this TArea area) where TArea : class, IArea
{
var s = DI.Get<IAreaResourceHelper<TArea>>();
@@ -5,6 +5,7 @@
<RootNamespace>System</RootNamespace>
<AssemblyName>System.Common.ClientLib.Droid</AssemblyName>
<AndroidUseIntermediateDesignerFile>false</AndroidUseIntermediateDesignerFile>
<DefineConstants>_HAVE_XF_;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
@@ -24,17 +25,17 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AppCenter" Version="4.3.0" />
<PackageReference Include="Microsoft.AppCenter.Analytics" Version="4.3.0" />
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="4.3.0" />
<PackageReference Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" Version="1.2.0.7" />
<PackageReference Include="Xamarin.AndroidX.Emoji.AppCompat" Version="1.1.0.2" />
<PackageReference Include="Xamarin.AndroidX.Fragment" Version="1.3.3" />
<PackageReference Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.3.5" />
<PackageReference Include="Xamarin.AndroidX.RecyclerView" Version="1.1.0.8" />
<PackageReference Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.9" />
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.2.1.1" />
<PackageReference Include="Microsoft.AppCenter" />
<PackageReference Include="Microsoft.AppCenter.Analytics" />
<PackageReference Include="Microsoft.AppCenter.Crashes" />
<PackageReference Include="Plugin.CurrentActivity" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" />
<PackageReference Include="Xamarin.AndroidX.Emoji.AppCompat" />
<PackageReference Include="Xamarin.AndroidX.Fragment" />
<PackageReference Include="Xamarin.AndroidX.Navigation.Fragment" />
<PackageReference Include="Xamarin.AndroidX.RecyclerView" />
<PackageReference Include="Xamarin.AndroidX.ViewPager2" />
<PackageReference Include="Xamarin.Google.Android.Material" />
</ItemGroup>
<ItemGroup>
@@ -6,6 +6,8 @@ namespace System.Logging
[ProviderAlias("Droid")]
public class PlatformLoggerProvider : ILoggerProvider
{
private PlatformLoggerProvider() { }
public ILogger CreateLogger(string name)
{
return new PlatformLogger(name);
+3 -1
View File
@@ -19,7 +19,9 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ReactiveUI" Version="15.1.1" />
<PackageReference Include="ReactiveUI" />
<PackageReference Include="Splat" />
<PackageReference Include="DynamicData" />
</ItemGroup>
<ItemGroup>
@@ -0,0 +1,23 @@
using System.Application;
using System.Net.Http;
using System.Threading.Tasks;
// ReSharper disable once CheckNamespace
namespace System
{
public static class HttpPlatformHelperExtensions
{
/// <summary>
/// 是否有网络链接
/// </summary>
/// <param name="helper"></param>
/// <returns></returns>
public static Task<bool> IsConnectedAsync(this IHttpPlatformHelper helper) =>
MainThread2.InvokeOnMainThreadAsync(() =>
{
#pragma warning disable CS0618 // 类型或成员已过时
return helper.IsConnected;
#pragma warning restore CS0618 // 类型或成员已过时
});
}
}
+12 -12
View File
@@ -7,18 +7,18 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
<PackageReference Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageReference Include="Nito.Comparers" Version="6.2.0" />
<PackageReference Include="OperatingSystem2" Version="1.1.0" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
<PackageReference Include="Crc32.NET" Version="1.2.0" />
<PackageReference Include="gfoidl.Base64" Version="1.1.1" />
<PackageReference Include="MessagePack" Version="2.3.75" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Text.Json" Version="5.0.2" />
<PackageReference Include="System.Text.Encodings.Web" Version="5.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
<PackageReference Include="Microsoft.Extensions.Http" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<PackageReference Include="Nito.Comparers" />
<PackageReference Include="OperatingSystem2" />
<PackageReference Include="Xamarin.Essentials" />
<PackageReference Include="Crc32.NET" />
<PackageReference Include="gfoidl.Base64" />
<PackageReference Include="MessagePack" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="System.Text.Json" />
<PackageReference Include="System.Text.Encodings.Web" />
</ItemGroup>
<ItemGroup>
-3
View File
@@ -2,9 +2,6 @@
using Microsoft.Extensions.DependencyInjection;
#endif
using System.Runtime.InteropServices;
#if !NOT_XE
using Xamarin.Essentials;
#endif
namespace System
{
+30 -45
View File
@@ -218,40 +218,28 @@ namespace System
}
/// <summary>
/// 判断路径是否为[文件夹(Dir)]
/// 判断路径是否为[文件夹(Dir)],返回 <see cref="FileInfo"/> 或 <see cref="DirectoryInfo"/>,<see langword="true"/> 为文件夹,<see langword="false"/> 为文件,路径不存在则为 <see langword="null"/>
/// </summary>
/// <param name="path"></param>
/// <param name="fileInfo"></param>
/// <param name="directoryInfo"></param>
/// <returns></returns>
public static bool IsDirectory(string path)
public static bool? IsDirectory(string path, [NotNullWhen(false)] out FileInfo? fileInfo, [NotNullWhen(true)] out DirectoryInfo? directoryInfo)
{
#if NET35
throw new PlatformNotSupportedException();
#else
var attr = File.GetAttributes(path);
return attr.HasFlag(FileAttributes.Directory);
#endif
}
/// <summary>
/// 获取[文件夹(Dir)]路径
/// <para>如果传入的参数为[文件(File)]路径,则返回当前所在[文件夹(Dir)]路径</para>
/// <para>如果传入的参数为[文件夹(Dir)]路径,则直接返回参数</para>
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static string GetDirectoryPath(string path)
{
try
fileInfo = new(path);
if (fileInfo.Exists) // 路径为文件
{
if (!IsDirectory(path))
{
return Path.GetDirectoryName(path) ?? string.Empty;
}
directoryInfo = null;
return false;
}
catch
fileInfo = null;
directoryInfo = new(path);
if (directoryInfo.Exists) // 路径为文件夹
{
return true;
}
return path;
directoryInfo = null;
return null;
}
static FileStream OpenReadCore(string filePath) => new(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
@@ -337,12 +325,7 @@ namespace System
/// </summary>
/// <param name="filePath"></param>
/// <returns>单位 字节</returns>
public static double GetFileSize(string filePath)
{
// 定义一个FileInfo对象,是指与filePath所指向的文件相关联,以获取其大小
FileInfo fileInfo = new(filePath);
return fileInfo.Length;
}
public static double GetFileSize(FileInfo fileInfo) => fileInfo.Exists ? fileInfo.Length : 0D;
/// <summary>
/// 获取指定路径的大小
@@ -351,21 +334,23 @@ namespace System
/// <returns>单位 字节</returns>
public static double GetDirectorySize(string dirPath)
{
double len = 0;
double len = 0D;
// 判断该路径是否存在(是否为文件夹)
if (!IsDirectory(dirPath))
var isDirectory = IsDirectory(dirPath, out var fileInfo, out var directoryInfo);
if (isDirectory.HasValue)
{
//查询文件的大小
len = GetFileSize(dirPath);
}
else
{
// 定义一个DirectoryInfo对象
DirectoryInfo di = new(dirPath);
// 通过GetFiles方法,获取di目录中的所有文件的大小
len += di.GetFiles().Sum(x => x.Length);
// 获取di中所有的文件夹,并存到一个新的对象数组中,以进行递归
len += di.GetDirectories().Sum(x => GetDirectorySize(x.FullName));
if (!isDirectory.Value)
{
//查询文件的大小
len = GetFileSize(fileInfo!);
}
else
{
// 通过GetFiles方法,获取di目录中的所有文件的大小
len += directoryInfo!.GetFiles().Sum(x => x.Length);
// 获取di中所有的文件夹,并存到一个新的对象数组中,以进行递归
len += directoryInfo.GetDirectories().Sum(x => GetDirectorySize(x.FullName));
}
}
return len;
}
@@ -63,5 +63,25 @@ namespace System.Net.Http
return _clientFactory.CreateClient(clientName);
}
}
static void ConfigHttpWebRequest(HttpWebRequest request)
{
request.AllowAutoRedirect = true;
request.MaximumAutomaticRedirections = 200;
}
public static HttpWebRequest Create(string requestUriString)
{
var request = WebRequest.CreateHttp(requestUriString);
ConfigHttpWebRequest(request);
return request;
}
public static HttpWebRequest Create(Uri requestUri)
{
var request = WebRequest.CreateHttp(requestUri);
ConfigHttpWebRequest(request);
return request;
}
}
}
@@ -33,6 +33,7 @@ namespace System.Net.Http
/// <summary>
/// 是否有网络链接
/// </summary>
[Obsolete("use IsConnectedAsync")]
bool IsConnected { get; }
}
}
@@ -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.4.11";
public const string Version = "2.4.12";
//public const string InfoVersion = Version + "-beta";
}
+7 -7
View File
@@ -32,12 +32,12 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.9" />
<!--<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.2" />-->
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.9" />
<PackageReference Include="NLog" Version="4.7.10" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.13.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />
<!--<PackageReference Include="Microsoft.Extensions.Logging.AzureAppServices" />-->
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" />
<PackageReference Include="NLog" />
<PackageReference Include="NLog.Web.AspNetCore" />
</ItemGroup>
</Project>
@@ -26,8 +26,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.8" />
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="5.2.5" />
<PackageReference Include="Microsoft.EntityFrameworkCore" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" />
<PackageReference Include="Z.EntityFramework.Plus.EFCore" />
</ItemGroup>
</Project>
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
@@ -24,7 +24,7 @@
</ItemGroup>
<ItemGroup>
<!--<PackageReference Include="sqlite-net-pcl" Version="1.7.335" />-->
<PackageReference Include="Polly" Version="7.2.2" />
<!--<PackageReference Include="sqlite-net-pcl" />-->
<PackageReference Include="Polly" />
</ItemGroup>
</Project>
@@ -37,8 +37,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />
<PackageReference Include="System.Runtime.WindowsRuntime" Version="4.7.0" />
<PackageReference Include="System.Runtime.WindowsRuntime.UI.Xaml" Version="4.7.0" />
<PackageReference Include="Microsoft.Windows.SDK.Contracts" />
<PackageReference Include="System.Runtime.WindowsRuntime" />
<PackageReference Include="System.Runtime.WindowsRuntime.UI.Xaml" />
</ItemGroup>
</Project>
@@ -10,7 +10,7 @@
<Identity
Name="4651ED44255E.47979655102CE"
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
Version="2.4.10.0" />
Version="2.4.11.0" />
<Properties>
<DisplayName>Steam++</DisplayName>
@@ -161,7 +161,7 @@
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.20348.19" PrivateAssets="all" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ST.Client.Desktop.Avalonia.App.Bridge.Package.RefLauncher\Launcher\Launcher.csproj" />
+2 -2
View File
@@ -22,14 +22,14 @@
<StyleInclude Source="avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Styles/ThemeDark.xaml" />
<StyleInclude Source="avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Styles/ThemeAccent.xaml" />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" />
<!--<StyleInclude Source="avares://AvaloniaEdit/AvaloniaEdit.xaml"/>-->
<sty:FluentAvaloniaTheme ControlsVersion="2"
RequestedTheme="Dark"
DefaultToUserTheme="False"
GetUserAccentColor="False"
UseSegoeUIOnWindows="False"/>
<StyleInclude Source="avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Styles/Controls.xaml" />
</Application.Styles>
+39 -59
View File
@@ -182,7 +182,7 @@ namespace System.Application.UI
//SettingsHost.Load();
var windowService = IWindowService.Instance;
windowService.Init();
DI.Get<IDesktopPlatformService>().SetSystemSessionEnding(compositeDisposable.Dispose);
DI.Get<IDesktopPlatformService>().SetSystemSessionEnding(() => Shutdown());
#if StartupTrace
StartupTrace.Restart("WindowService.Init");
#endif
@@ -209,6 +209,7 @@ namespace System.Application.UI
switch (windowService.MainWindow)
{
case AchievementWindowViewModel window:
Program.IsMinimize = false;
MainWindow = new AchievementWindow
{
DataContext = windowService.MainWindow,
@@ -220,14 +221,13 @@ namespace System.Application.UI
#if !UI_DEMO
compositeDisposable.Add(SettingsHost.Save);
compositeDisposable.Add(ProxyService.Current.Dispose);
//compositeDisposable.Add(AuthService.Current.SaveEditNameAuthenticators);
compositeDisposable.Add(SteamConnectService.Current.Dispose);
compositeDisposable.Add(ASFService.Current.StopASF);
if (GeneralSettings.IsStartupAppMinimized.Value)
{
Program.IsMinimize = true;
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = null;
//if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
// desktop.MainWindow = null;
}
#endif
#endregion
@@ -246,6 +246,12 @@ namespace System.Application.UI
public override void OnFrameworkInitializationCompleted()
{
if (Program.IsTrayProcess)
{
base.OnFrameworkInitializationCompleted();
return;
}
// 在UI预览中,ApplicationLifetime 为 null
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
@@ -257,75 +263,34 @@ namespace System.Application.UI
{
if (Startup.HasNotifyIcon)
{
#region NotifyIcon
var notifyIcon = INotifyIcon.Instance;
notifyIcon.Visible = true;
notifyIcon.ToolTipText = ThisAssembly.AssemblyTrademark;
if (OperatingSystem2.IsMacOS)
if (!OperatingSystem2.IsLinux)
{
notifyIcon.IconPath = "avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Assets/Icon_16.png";
(var notifyIcon, var menuItemDisposable) = NotifyIconHelper.Init(NotifyIconHelper.GetIconByCurrentAvaloniaLocator);
notifyIcon.Click += NotifyIcon_Click;
notifyIcon.DoubleClick += NotifyIcon_Click;
if (menuItemDisposable != null) menuItemDisposable.AddTo(this);
notifyIcon.AddTo(this);
}
else
{
notifyIcon.IconPath = "avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Assets/Icon.ico";
#if LINUX || DEBUG
NotifyIconHelper.StartPipeServer();
#endif
}
#if WINDOWS
notifyIcon.RightClick += (s, e) =>
{
if (e is MouseEventArgs args)
{
IWindowService.Instance.ShowTaskBarWindow(args.MousePosition.X, args.MousePosition.Y);
}
};
#endif
#if !WINDOWS
NotifyIconContextMenu = new ContextMenu();
mNotifyIconMenus.Add("Light", ReactiveCommand.Create(() =>
{
Theme = AppTheme.Light;
}));
mNotifyIconMenus.Add("Dark", ReactiveCommand.Create(() =>
{
Theme = AppTheme.Dark;
}));
mNotifyIconMenus.Add("Show",
ReactiveCommand.Create(RestoreMainWindow));
mNotifyIconMenus.Add("Exit",
ReactiveCommand.Create(() => Shutdown()));
NotifyIconContextMenu.Items = mNotifyIconMenus
.Select(x => new MenuItem { Header = x.Key, Command = x.Value }).ToList();
notifyIcon.ContextMenu = NotifyIconContextMenu;
#endif
notifyIcon.Click += NotifyIcon_Click;
notifyIcon.DoubleClick += NotifyIcon_Click;
compositeDisposable.Add(() =>
{
notifyIcon.IconPath = string.Empty;
});
}
#endregion
#if WINDOWS
JumpLists.Init();
#endif
}
IWindowService.Instance.MainWindow.Initialize();
desktop.MainWindow =
#if !UI_DEMO
Program.IsMinimize ? null :
#endif
MainWindow;
IWindowService.Instance.MainWindow.Initialize();
desktop.Startup += Desktop_Startup;
desktop.Exit += ApplicationLifetime_Exit;
desktop.ShutdownMode =
@@ -385,6 +350,10 @@ namespace System.Application.UI
void ApplicationLifetime_Exit(object? sender, ControlledApplicationLifetimeExitEventArgs e)
{
#if LINUX || DEBUG
NotifyIconHelper.StopPipeServer();
#endif
try
{
compositeDisposable.Dispose();
@@ -399,7 +368,7 @@ namespace System.Application.UI
AppHelper.TryShutdown();
}
void NotifyIcon_Click(object? sender, EventArgs e)
internal void NotifyIcon_Click(object? sender, EventArgs e)
{
RestoreMainWindow();
}
@@ -436,7 +405,7 @@ namespace System.Application.UI
{
Window? mainWindow = null;
if (AvaloniaApplication.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
if (Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
mainWindow = desktop.MainWindow;
if (mainWindow == null)
@@ -489,12 +458,23 @@ namespace System.Application.UI
return MainWindow;
}
public void SetDesktopBackgroundWindow()
{
if (OperatingSystem2.IsWindows)
{
var window = (App.Instance.MainWindow as MainWindow);
DI.Get<ISystemWindowApiService>().SetDesktopBackgroundToWindow(
window._backHandle, (int)App.Instance.MainWindow.Width, (int)App.Instance.MainWindow.Height);
}
}
/// <summary>
/// Exits the app by calling <c>Shutdown()</c> on the <c>IClassicDesktopStyleApplicationLifetime</c>.
/// </summary>
public static bool Shutdown(int exitCode = 0)
{
if (AvaloniaApplication.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
if (Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
MainThread2.BeginInvokeOnMainThread(() =>
{
@@ -1,11 +1,9 @@
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Threading;
using Microsoft.Extensions.DependencyInjection;
using System.Application.Services;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.Threading.Tasks;
using System.Windows;
using AvaloniaApplication = Avalonia.Application;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace System.Application.UI
@@ -20,10 +18,7 @@ namespace System.Application.UI
/// </summary>
static class CommandLineTools
{
public static int Run(string[] args,
Action<DILevel> initStartup,
Action initUIApp/*,*/
/*Action initCef*/)
public static int Run(string[] args)
{
if (args.Length == 0) args = new[] { "-h" };
@@ -36,7 +31,7 @@ namespace System.Application.UI
#if StartupTrace
StartupTrace.Restart("ProcessCheck");
#endif
initStartup(IsMainProcess ? DILevel.MainProcess : DILevel.Min);
Startup.Init(IsMainProcess ? DILevel.MainProcess : DILevel.Min);
#if StartupTrace
StartupTrace.Restart("Startup.Init");
#endif
@@ -79,16 +74,16 @@ namespace System.Application.UI
}
};
}
//#if StartupTrace
// StartupTrace.Restart("ApplicationInstance");
//#endif
// initCef();
//#if StartupTrace
// StartupTrace.Restart("InitCefNetApp");
//#endif
//#if StartupTrace
// StartupTrace.Restart("ApplicationInstance");
//#endif
// initCef();
//#if StartupTrace
// StartupTrace.Restart("InitCefNetApp");
//#endif
if (IsMainProcess)
{
initUIApp();
BuildAvaloniaAppAndStartWithClassicDesktopLifetime(args);
}
#if StartupTrace
StartupTrace.Restart("InitAvaloniaApp");
@@ -139,7 +134,7 @@ namespace System.Application.UI
// -clt c -silence
var common = new Command("c", "common");
common.AddOption(new Option<bool>("-silence", "静默启动(不弹窗口)"));
common.Handler = CommandHandler.Create((bool silence, long steamuser) =>
common.Handler = CommandHandler.Create((bool silence) =>
{
IsMinimize = silence;
MainHandlerByCLT();
@@ -153,7 +148,7 @@ namespace System.Application.UI
{
if (!string.IsNullOrEmpty(account))
{
initStartup(DILevel.Steam);
Startup.Init(DILevel.Steam);
ISteamService.Instance.TryKillSteamProcess();
ISteamService.Instance.SetCurrentUser(account);
ISteamService.Instance.StartSteam();
@@ -172,13 +167,13 @@ namespace System.Application.UI
if (id <= 0) return;
if (!silence)
{
initStartup(DILevel.GUI | DILevel.Steam | DILevel.HttpClientFactory);
Startup.Init(DILevel.GUI | DILevel.Steam | DILevel.HttpClientFactory);
IWindowService.Instance.InitUnlockAchievement(id);
initUIApp();
BuildAvaloniaAppAndStartWithClassicDesktopLifetime(args);
}
else
{
initStartup(DILevel.Steam);
Startup.Init(DILevel.Steam);
SteamConnectService.Current.Initialize(id);
TaskCompletionSource tcs = new();
await tcs.Task;
@@ -0,0 +1,424 @@
#if !TRAY_INDEPENDENT_PROGRAM
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform;
using Avalonia.Shared.PlatformSupport;
using Avalonia.Threading;
using System.Application.Mvvm;
using System.Application.Services;
using System.Application.UI.Views.Windows;
using AvaloniaApplication = Avalonia.Application;
#else
using System.Application.UI.Properties;
#endif
using ReactiveUI;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Application.UI.ViewModels;
using System.Application.UI.Resx;
#if LINUX && TRAY_INDEPENDENT_PROGRAM
using GtkApplication = Gtk.Application;
#endif
namespace System.Application.UI
{
static class NotifyIconHelper
{
#if !TRAY_INDEPENDENT_PROGRAM
static object GetIcon(IAssetLoader assets)
{
string iconPath;
if (OperatingSystem2.IsMacOS)
{
iconPath = "avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Assets/Icon_16.png";
}
else
{
iconPath = "avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Assets/Icon.ico";
}
return assets.Open(new(iconPath));
}
public static object GetIconByCurrentAvaloniaLocator()
{
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
return GetIcon(assets);
}
#endif
public static object GetIcon()
{
#if !TRAY_INDEPENDENT_PROGRAM
var assets = new AssetLoader(typeof(TaskBarWindow).Assembly);
return GetIcon(assets);
#else
return SR.Icon;
#endif
}
public static (NotifyIcon notifyIcon, IDisposable? menuItemDisposable) Init(Func<object> getIcon)
{
IDisposable? menuItemDisposable = null;
var notifyIcon = DI.Get<NotifyIcon>();
notifyIcon.Text = TaskBarWindowViewModel.TitleString;
notifyIcon.Icon = getIcon();
#if WINDOWS
notifyIcon.RightClick += (_, e) =>
{
IWindowService.Instance.ShowTaskBarWindow(e.X, e.Y);
};
#else
menuItemDisposable = InitMenuItems(notifyIcon);
#endif
return (notifyIcon, menuItemDisposable);
}
#region 仅在非 Windows 上使用平台原生托盘菜单
#if !WINDOWS || DEBUG
static string Exit => AppResources.Exit;
static void OnMenuClick(string command)
{
#if TRAY_INDEPENDENT_PROGRAM
notifyIconPipeClient?.Append(command);
#else
TaskBarWindowViewModel.OnMenuClick(command);
#endif
}
static void OnMenuClick(TabItemViewModel.TabItemId tabItemId)
{
#if TRAY_INDEPENDENT_PROGRAM
notifyIconPipeClient?.Append(tabItemId.ToString());
#else
TaskBarWindowViewModel.OnMenuClick(tabItemId);
#endif
}
static ContextMenuStrip.MenuItem? exitMenuItem;
static readonly Dictionary<TabItemViewModel, ContextMenuStrip.MenuItem> tabItems = new();
static IDisposable? InitMenuItems(NotifyIcon notifyIcon)
{
#if !TRAY_INDEPENDENT_PROGRAM
if (IWindowService.Instance.MainWindow is not MainWindowViewModel main) return null;
#else
MainWindowViewModel main = new();
#endif
var query = from x in main.TabItems.Concat(main.FooterTabItems)
let tabItem = x is TabItemViewModel item ? item : null
where tabItem != null
select tabItem;
foreach (var item in query)
{
var menuItem = new ContextMenuStrip.MenuItem
{
Text = item.Name,
Command = ReactiveCommand.Create(() =>
{
OnMenuClick(item.Id);
}),
};
tabItems.Add(item, menuItem);
notifyIcon.ContextMenuStrip.Items.Add(menuItem);
}
exitMenuItem = new ContextMenuStrip.MenuItem
{
Text = Exit,
Command = ReactiveCommand.Create(() =>
{
OnMenuClick(TaskBarWindowViewModel.CommandExit);
}),
};
notifyIcon.ContextMenuStrip.Items.Add(exitMenuItem);
#if !TRAY_INDEPENDENT_PROGRAM
return R.Current.WhenAnyValue(x => x.Res).SubscribeInMainThread(_ =>
{
if (exitMenuItem != null)
{
exitMenuItem.Text = Exit;
}
foreach (var item in tabItems)
{
item.Value.Text = item.Key.Name;
}
});
#else
return null;
#endif
}
#endif
#endregion
#region 仅在 Linux 上使用管道 IPC 调用托盘菜单项点击事件
#if LINUX || DEBUG
public abstract class PipeCore : IDisposable
{
public const string CommandNotifyIconClick = "NotifyIconClick";
protected readonly CancellationTokenSource cts = new();
bool isStarted;
/// <summary>
///
/// </summary>
public void OnStart()
{
if (isStarted) return;
isStarted = true;
Task.Run(OnStartCore);
}
protected abstract void OnStartCore();
bool disposedValue;
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
cts.Cancel();
}
// TODO: 释放未托管的资源(未托管的对象)并重写终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
}
// // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
// ~NotifyIconPipeCore()
// {
// // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
// Dispose(disposing: false);
// }
public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
#if !TRAY_INDEPENDENT_PROGRAM
static PipeServer? notifyIconPipeServer;
public static void StopPipeServer() => notifyIconPipeServer?.Dispose();
public static void StartPipeServer()
{
StopPipeServer();
notifyIconPipeServer = new();
notifyIconPipeServer.OnStart();
}
public sealed class PipeServer : PipeCore
{
bool HandlerCommand(string command)
{
switch (command)
{
case CommandNotifyIconClick:
Dispatcher.UIThread.Post(() =>
{
App.Instance.NotifyIcon_Click(this, EventArgs.Empty);
}, DispatcherPriority.MaxValue);
break;
default:
return TaskBarWindowViewModel.OnMenuClick(command);
}
return default;
}
protected override void OnStartCore()
{
if (!OperatingSystem.IsLinux()) return;
var fileName = AppHelper.ProgramPath + "_LinuxTrayIcon";
var unixSetFileAccessResult = IDesktopPlatformService.Instance.UnixSetFileAccess(fileName, IDesktopPlatformService.UnixPermission.Combined755);
if (unixSetFileAccessResult != IDesktopPlatformService.UnixSetFileAccessResult.Success)
return;
Process pipeClient = new();
pipeClient.StartInfo.FileName = fileName;
using (var pipeServer = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable))
{
// Pass the client process a handle to the server.
pipeClient.StartInfo.Arguments = pipeServer.GetClientHandleAsString();
pipeClient.StartInfo.UseShellExecute = false;
pipeClient.Start();
pipeServer.DisposeLocalCopyOfClientHandle();
try
{
// Read user input and send that to the client process.
using var sr = new StreamReader(pipeServer);
// Display the read text to the console
string? command;
// Read the server data and echo to the console.
while ((command = sr.ReadLine()) != null)
{
try
{
cts.Token.ThrowIfCancellationRequested();
if (HandlerCommand(command)) break;
}
catch (OperationCanceledException)
{
break;
}
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException)
{
}
}
pipeClient.WaitForExit();
pipeClient.Close();
}
}
#else
static PipeClient? notifyIconPipeClient;
public static void StopPipeClient() => notifyIconPipeClient?.Dispose();
public static void StartPipeClient(string handle)
{
StopPipeClient();
notifyIconPipeClient = new PipeClient(handle);
notifyIconPipeClient.OnStart();
}
public static PipeClient Client
=> notifyIconPipeClient ?? throw new ArgumentNullException(nameof(notifyIconPipeClient));
public sealed class PipeClient : PipeCore
{
Process? mainProcess;
readonly string pipeHandleAsString;
readonly ConcurrentQueue<string> queue = new();
public PipeClient(string pipeHandleAsString)
{
this.pipeHandleAsString = pipeHandleAsString;
}
private void MainProcess_Exited(object? sender, EventArgs e) => Dispose();
protected override void OnStartCore()
{
try
{
using var pipeClient = new AnonymousPipeClientStream(PipeDirection.Out, pipeHandleAsString);
using var sw = new StreamWriter(pipeClient);
sw.AutoFlush = true;
while (true)
{
try
{
cts.Token.ThrowIfCancellationRequested();
if (!pipeClient.IsConnected) break;
if (queue.TryDequeue(out var result))
{
sw.WriteLine(result);
if (result == TaskBarWindowViewModel.CommandExit) break;
}
}
catch (OperationCanceledException)
{
sw.WriteLine(TaskBarWindowViewModel.CommandExit);
break;
}
}
}
catch (Exception)
{
}
Dispose();
}
/// <summary>
///
/// </summary>
/// <param name="value"></param>
public void Append(string value)
{
if (!disposedValue && !cts.IsCancellationRequested)
{
queue.Enqueue(value);
}
}
bool disposedValue;
protected override void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
if (mainProcess != null)
{
mainProcess.Exited -= MainProcess_Exited;
mainProcess = null;
}
DI.Get<NotifyIcon>().Dispose();
#if LINUX
GtkApplication.Quit();
#endif
#if !TRAY_INDEPENDENT_PROGRAM
if (OperatingSystem2.IsWindows)
{
if (AvaloniaApplication.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
Dispatcher.UIThread.Post(() =>
{
desktop.Shutdown();
}, DispatcherPriority.MaxValue);
}
}
#endif
}
// TODO: 释放未托管的资源(未托管的对象)并重写终结器
// TODO: 将大型字段设置为 null
disposedValue = true;
}
base.Dispose(disposing);
}
}
#endif
#endif
#endregion
}
}
@@ -38,7 +38,7 @@ namespace System.Application.UI
//if (activatedArgs != null) args = OnActivated(args, activatedArgs);
#elif !__MOBILE__
#if MAC
AppDelegateHelper.Init(args);
AppDelegate.Init(/*args*/);
FileSystemDesktopMac.InitFileSystem();
#else
FileSystemDesktop.InitFileSystem();
@@ -58,8 +58,6 @@ namespace System.Application.UI
#endif
//void InitCefNetApp() => CefNetApp.Init(AppHelper.LogDirPath, args);
void InitAvaloniaApp() => BuildAvaloniaAppAndStartWithClassicDesktopLifetime(args);
void InitStartup(DILevel level) => Startup.Init(level);
Startup.InitGlobalExceptionHandler();
try
{
@@ -73,7 +71,7 @@ namespace System.Application.UI
{
args_clt = new[] { command_main };
}
return CommandLineTools.Run(args_clt, InitStartup, InitAvaloniaApp/*, InitCefNetApp*/);
return CommandLineTools.Run(args_clt);
}
catch (Exception ex)
{
@@ -103,5 +101,10 @@ namespace System.Application.UI
/// 当前是否是主进程
/// </summary>
public static bool IsMainProcess { get; private set; }
/// <summary>
/// 当前是否是用于托盘的独立进程
/// </summary>
public static bool IsTrayProcess { get; private set; }
}
}
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;LINUX;</DefineConstants>
<Configuration>Debug</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Debug\Publish\linux-x64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;</DefineConstants>
<DefineConstants>PUBLISH;LINUX;</DefineConstants>
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
<PublishDir>bin\Release\Publish\linux-arm</PublishDir>
@@ -14,6 +14,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>
@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;</DefineConstants>
<DefineConstants>PUBLISH;LINUX;</DefineConstants>
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
<PublishDir>bin\Release\Publish\linux-arm64</PublishDir>
@@ -14,6 +14,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>
@@ -4,7 +4,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;</DefineConstants>
<DefineConstants>PUBLISH;LINUX;</DefineConstants>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\Publish\linux-x64</PublishDir>
@@ -13,6 +13,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishReadyToRun>true</PublishReadyToRun>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>
@@ -11,10 +11,11 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<PublishDir>bin\Release\Publish\osx-arm64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<RuntimeIdentifier>osx.11.0-arm64</RuntimeIdentifier>
<!--<PublishReadyToRun Condition=" '$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' ">true</PublishReadyToRun>-->
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>
@@ -13,6 +13,8 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishReadyToRun>true</PublishReadyToRun>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>
@@ -13,8 +13,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>false</PublishTrimmed>
<EnableCompressionInSingleFile>false</EnableCompressionInSingleFile>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -14,8 +14,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
<!--Single file deployment isn't compatible with Windows 7.-->
<PublishTrimmed>false</PublishTrimmed>
<EnableCompressionInSingleFile>false</EnableCompressionInSingleFile>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -40,12 +40,13 @@
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`osx`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>MAC;$(DefineConstants)</DefineConstants>
<!--<TargetFramework>net6.0-macos</TargetFramework>-->
<TargetFramework>net6.0</TargetFramework>
<!--<TargetFramework>net6.0</TargetFramework>-->
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`linux`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<TargetFramework>net6.0</TargetFramework>
<DefineConstants>LINUX;$(DefineConstants)</DefineConstants>
<!--<TargetFramework>net6.0</TargetFramework>-->
<OutputType>Exe</OutputType>
</PropertyGroup>
@@ -3,11 +3,12 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="1200" Width="995" MinWidth="600"
d:DesignHeight="600" Height="600" MinHeight="400"
d:DesignWidth="1200" Width="900" MinWidth="800"
d:DesignHeight="600" Height="600" MinHeight="500"
xmlns:local="clr-namespace:System.Application.UI.Views;assembly=System.Application.SteamTools.Client.Desktop.Avalonia"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls;assembly=System.Application.SteamTools.Client.Desktop.Avalonia"
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
x:Class="System.Application.UI.Views.MainWindow"
x:Name="MainWindow"
WindowStartupLocation="CenterScreen"
@@ -22,8 +23,13 @@
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" />
</Style>
</Window.Styles>
<Panel Margin="{Binding #MainWindow.OffScreenMargin}">
<!--<Panel ZIndex="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<controls:EmptyControl x:Name="DesktopBackground"
IsVisible="{ReflectionBinding Source={x:Static ms:UISettings.EnableDesktopBackground},Path=Value,Mode=TwoWay}"/>
</Panel>-->
<local:MainView DataContext="{Binding}"/>
<!--<controls:WebView3 IsVisible="False" InitialUrl="chrome://version"></controls:WebView3>-->
</Panel>
@@ -3,16 +3,27 @@ using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using FluentAvalonia.Styling;
using ReactiveUI;
using System.Application.UI.ViewModels;
using System.Application.UI.Views.Controls;
using System.ComponentModel;
namespace System.Application.UI.Views
{
public class MainWindow : FluentWindow<MainWindowViewModel>
{
public IntPtr _backHandle;
public MainWindow() : base()
{
InitializeComponent();
//var background = this.FindControl<EmptyControl>("DesktopBackground");
//_backHandle = background.Handle;
//if (OperatingSystem2.IsWindows && !OperatingSystem2.IsWindows11AtLeast)
//{
// TransparencyLevelHint = WindowTransparencyLevel.Transparent;
//}
#if DEBUG
this.AttachDevTools();
#endif
@@ -48,9 +48,9 @@ namespace System.Application.Converters
TryReset(s);
return GetDecodeBitmap(s, width);
}
else if (value is ImageClipStream ics)
else if (value is ImageSouce.ClipStream clipStream)
{
return GetBitmap(ics);
return GetBitmap(clipStream);
}
else if (value is Guid imageid)
{
@@ -45,25 +45,25 @@ namespace System.Application.Converters
}
}
protected static Bitmap? GetBitmap(ImageClipStream ics, int width = 0)
protected static Bitmap? GetBitmap(ImageSouce.ClipStream clipStream, int width = 0)
{
if (ics.Stream == null)
if (clipStream.Stream == null)
return null;
TryReset(ics.Stream);
TryReset(clipStream.Stream);
using var ms = new MemoryStream();
ics.Stream.CopyTo(ms);
clipStream.Stream.CopyTo(ms);
TryReset(ms);
using var bitmapSource = SKBitmap.Decode(ms);
using var bitmapDest = new SKBitmap(bitmapSource.Width, bitmapSource.Height, SKColorType.Bgra8888, SKAlphaType.Unpremul);
using var canvas = new SKCanvas(bitmapDest);
var rect = ics.Circle ?
var rect = clipStream.Circle ?
new SKRect(0, 0, bitmapSource.Width, bitmapSource.Height) :
new SKRect(ics.Left, ics.Top, ics.Right, ics.Bottom);
var roundRect = ics.Circle ?
new SKRect(clipStream.Left, clipStream.Top, clipStream.Right, clipStream.Bottom);
var roundRect = clipStream.Circle ?
new SKRoundRect(rect, bitmapSource.Width / 2f, bitmapSource.Height / 2f) :
new SKRoundRect(rect, ics.Radius_X, ics.Radius_Y);
new SKRoundRect(rect, clipStream.Radius_X, clipStream.Radius_Y);
canvas.ClipRoundRect(roundRect, antialias: true);
canvas.DrawBitmap(bitmapSource, 0, 0);
@@ -81,8 +81,12 @@ namespace System.Application.Converters
return GetDecodeBitmap(stream, width);
}
protected static Bitmap GetDecodeBitmap(Stream s, int width)
protected static Bitmap? GetDecodeBitmap(Stream s, int width)
{
if (s == null)
{
return null;
}
if (width < 1)
{
return new Bitmap(s);
@@ -98,11 +102,13 @@ namespace System.Application.Converters
return null;
}
protected static Stream OpenAssets(Uri uri)
protected static Stream? OpenAssets(Uri uri)
{
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
var asset = assets.Open(uri);
return asset;
Stream? stream = null;
if (assets.Exists(uri))
stream = assets.Open(uri);
return stream;
}
protected static Uri GetResUri(string relativeUri, string? assemblyName = null)
Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 552 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

@@ -120,10 +120,51 @@ namespace System.Application.UI
private SKTypeface GetSkTypefaceByFontFamily(Typeface typeface)
{
SKTypeface? skTypeface = SKTypeface.FromFamilyName(typeface.FontFamily.Name,
(SKFontStyleWeight)typeface.Weight, SKFontStyleWidth.Normal, (SKFontStyleSlant)typeface.Style);
//SKTypeface? skTypeface = SKTypeface.FromFamilyName(typeface.FontFamily.Name,
// (SKFontStyleWeight)typeface.Weight, SKFontStyleWidth.Normal, (SKFontStyleSlant)typeface.Style);
//if (skTypeface != null && !skTypeface.FamilyName.Equals(typeface.FontFamily.Name, StringComparison.OrdinalIgnoreCase))
//{
// try
// {
// Assembly asm = Assembly.Load("Avalonia.Skia");
// var t = asm?.GetType("Avalonia.Skia.SKTypefaceCollectionCache");
// var fontCollection = t?.InvokeMember("GetOrAddTypefaceCollection", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, new object[] { typeface.FontFamily });
// var type = fontCollection?.GetType();
// var oMethod = type?.GetMethod("Get");
// var r = oMethod?.Invoke(fontCollection, new object[] { typeface });
// skTypeface = r as SKTypeface;
// }
// catch
// {
// //Log.Error(nameof(CustomFontManagerImpl), ex, nameof(GetSkTypefaceByFontFamily));
// skTypeface = null;
// }
//}
if (skTypeface != null && !skTypeface.FamilyName.Equals(typeface.FontFamily.Name, StringComparison.OrdinalIgnoreCase))
SKTypeface? skTypeface = null;
if (typeface.FontFamily.Key == null)
{
var defaultName = SKTypeface.Default.FamilyName;
var fontStyle = new SKFontStyle((SKFontStyleWeight)typeface.Weight, SKFontStyleWidth.Normal, (SKFontStyleSlant)typeface.Style);
foreach (var familyName in typeface.FontFamily.FamilyNames)
{
skTypeface = _skFontManager.MatchFamily(familyName, fontStyle);
if (skTypeface is null
|| (!skTypeface.FamilyName.Equals(familyName, StringComparison.Ordinal)
&& defaultName.Equals(skTypeface.FamilyName, StringComparison.Ordinal)))
{
continue;
}
break;
}
skTypeface ??= _skFontManager.MatchTypeface(SKTypeface.Default, fontStyle);
}
else
{
try
{
@@ -154,15 +195,15 @@ namespace System.Application.UI
{
SKTypeface? skTypeface = null;
switch (typeface.FontFamily.Name)
skTypeface = typeface.FontFamily.Name switch
{
case FontFamily.DefaultFontFamilyName:
case "WenQuanYi Micro Hei": //font family name
skTypeface = GetSkTypefaceByFontFamily(_defaultTypeface);
break;
default:
skTypeface = GetSkTypefaceByFontFamily(typeface);
break;
FontFamily.DefaultFontFamilyName or "WenQuanYi Micro Hei" => GetSkTypefaceByFontFamily(_defaultTypeface),
_ => GetSkTypefaceByFontFamily(typeface),
};
if (skTypeface == null)
{
skTypeface = SKTypeface.Default;
}
return new GlyphTypefaceImpl(skTypeface);
@@ -1,43 +0,0 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;
using System.IO;
namespace System.Application.UI
{
public interface INotifyIcon : INotifyIcon<ContextMenu>
{
static INotifyIcon Instance => DI.Get<INotifyIcon>();
internal sealed class UIFrameworkHelper : IUIFrameworkHelper
{
public Stream OpenAsset(Uri uri)
{
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
return assets.Open(uri);
}
sealed class ActivatedWrapper
{
readonly MenuItem menuItem;
public ActivatedWrapper(MenuItem menuItem)
{
this.menuItem = menuItem;
}
public void Activated() => menuItem.Command?.Execute(null);
}
public void ForEachMenuItems(ContextMenu menu, Action<(object menuItem, string header, Action activated)> action)
{
foreach (MenuItem menuItem in menu.Items)
{
var header = menuItem.Header?.ToString() ?? string.Empty;
var activated = new ActivatedWrapper(menuItem);
action((menuItem, header, activated.Activated));
}
}
}
}
}
@@ -64,53 +64,4 @@
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>
</Style>
<!--<Style Selector="Menu > MenuItem">
<Setter Property="Template">
<ControlTemplate>
<Border Name="PART_LayoutRoot"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Panel>
<ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Margin="{TemplateBinding Padding}">
<ContentPresenter.DataTemplates>
<DataTemplate DataType="sys:String">
<AccessText Text="{Binding}" />
</DataTemplate>
</ContentPresenter.DataTemplates>
</ContentPresenter>
<Popup Name="PART_Popup"
WindowManagerAddShadowHint="False"
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
IsLightDismissEnabled="True"
IsOpen="{TemplateBinding IsSubMenuOpen, Mode=TwoWay}"
OverlayInputPassThroughElement="{Binding $parent[Menu]}">
<Border Background="{DynamicResource MenuFlyoutPresenterBackground}"
BorderBrush="{DynamicResource MenuFlyoutPresenterBorderBrush}"
BorderThickness="{DynamicResource MenuFlyoutPresenterBorderThemeThickness}"
Padding="{DynamicResource MenuFlyoutPresenterThemePadding}"
MaxWidth="{DynamicResource FlyoutThemeMaxWidth}"
MinHeight="{DynamicResource MenuFlyoutThemeMinHeight}"
HorizontalAlignment="Stretch"
CornerRadius="{DynamicResource OverlayCornerRadius}">
<ScrollViewer Classes="menuscroller">
<ItemsControl Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"
ItemTemplate="{TemplateBinding ItemTemplate}"
Margin="{DynamicResource MenuFlyoutScrollerMargin}"
Grid.IsSharedSizeScope="True" />
</ScrollViewer>
</Border>
</Popup>
</Panel>
</Border>
</ControlTemplate>
</Setter>
</Style>-->
</Styles>
@@ -3,11 +3,11 @@
<Design.PreviewWith>
<Border Padding="20" Background="Green" >
<WrapPanel Margin="10" Orientation="Vertical" ItemHeight="30" ItemWidth="30" MaxHeight="200">
<PathIcon Data="{StaticResource CommunityProxySvg}" />
<PathIcon Data="{StaticResource LocalAuthSvg}" />
<PathIcon Data="{StaticResource AboutSvg}" />
<PathIcon Data="{StaticResource ScriptMangeSvg}" />
<PathIcon Data="{StaticResource GameListSvg}" />
<PathIcon Data="{StaticResource CommunityProxyViewModel}" />
<PathIcon Data="{StaticResource LocalAuthViewModel}" />
<PathIcon Data="{StaticResource AboutViewModel}" />
<PathIcon Data="{StaticResource ScriptMangeViewModel}" />
<PathIcon Data="{StaticResource GameListViewModel}" />
<PathIcon Data="{StaticResource NavigationDrawing}" />
<PathIcon Data="{StaticResource SearchDrawing}" />
<PathIcon Data="{StaticResource InfoDrawing}" />
@@ -239,20 +239,20 @@
M3 9.5C3 5.35786 6.35786 2 10.5 2C14.6421 2 18 5.35786 18 9.5C18 13.6421 14.6421 17 10.5 17C10.4668 17 10.4336 16.9998 10.4005 16.9994C10.5633 16.6808 10.6959 16.3442 10.7947 15.9934C14.2478 15.8394 17 12.9911 17 9.5C17 5.91015 14.0899 3 10.5 3C7.00897 3 4.16073 5.75214 4.00657 9.20514C3.6558 9.30386 3.31924 9.43651 3.00064 9.5993C3.00022 9.56625 3 9.53315 3 9.5ZM10.5 5C10.7761 5 11 5.22386 11 5.5V9H13.5C13.7761 9 14 9.22386 14 9.5C14 9.77614 13.7761 10 13.5 10H10.5C10.2239 10 10 9.77614 10 9.5V5.5C10 5.22386 10.2239 5 10.5 5ZM5 10.0275C2.75002 10.2762 1 12.1837 1 14.5C1 16.9853 3.01472 19 5.5 19C7.98528 19 10 16.9853 10 14.5C10 12.1837 8.24998 10.2762 6 10.0275V13.7929L6.64645 13.1464C6.84171 12.9512 7.15829 12.9512 7.35355 13.1464C7.54882 13.3417 7.54882 13.6583 7.35355 13.8536L5.85355 15.3536C5.65829 15.5488 5.34171 15.5488 5.14645 15.3536L3.64645 13.8536C3.45118 13.6583 3.45118 13.3417 3.64645 13.1464C3.84171 12.9512 4.15829 12.9512 4.35355 13.1464L5 13.7929V10.0275ZM3.5 16H7.5C7.77614 16 8 16.2239 8 16.5C8 16.7761 7.77614 17 7.5 17H3.5C3.22386 17 3 16.7761 3 16.5C3 16.2239 3.22386 16 3.5 16Z
</StreamGeometry>
<!--菜单图标-->
<DrawingGroup x:Key="LocalAuthPageSvg">
<!--菜单图标 Start-->
<!--<DrawingGroup x:Key="LocalAuthPageViewModel">
<GeometryDrawing Brush="#D2EEFF" Geometry="M512 914.432l-2.048-0.512c-333.824-111.104-330.24-415.744-329.728-428.544V179.712h10.752c187.904 0 284.672-45.568 317.952-65.024l3.584-2.048 3.584 2.048c32.768 19.456 129.536 65.024 317.952 65.024h10.752v305.152c0 3.584-8.704 323.584-329.728 428.544l-3.072 1.024z"/>
<GeometryDrawing Brush="#5090F3" Geometry="M934.912 89.088c-4.608-4.608-11.776-7.168-18.944-7.168-275.456 6.144-386.048-75.264-386.56-75.776-9.216-7.68-24.064-7.68-33.28 0-1.536 0-103.936 75.776-357.376 75.776-9.728 0-19.968 0-30.72-0.512-7.68 0-13.824 2.56-18.432 7.168-5.12 5.12-8.192 11.776-8.192 18.944v372.224c0 4.096-5.12 405.504 422.4 542.72 2.56 1.024 5.632 1.024 8.192 1.024s5.632-0.512 8.192-1.024c413.184-129.024 422.4-537.6 422.912-542.208V107.52c-0.512-6.656-3.072-13.824-8.192-18.432z m-45.568 45.056v346.112c0 3.584-10.24 370.176-377.344 489.984-381.952-126.976-377.856-474.624-377.856-489.472V134.144h4.096c217.6 0 331.264-51.712 373.248-76.8 42.496 25.088 155.648 76.8 373.248 76.8h4.608z"/>
<GeometryDrawing Brush="#5090F3" Geometry="M844.288 364.032L271.872 750.592c9.728 12.8 20.48 25.088 32.256 37.376l540.16-365.056V364.032zM844.288 206.848L208.896 635.904c10.752 28.672 25.088 58.88 45.056 89.088l590.336-398.848V206.848z"/>
</DrawingGroup>
<DrawingGroup x:Key="AboutPageSvg">
<DrawingGroup x:Key="AboutPageViewModel">
<GeometryDrawing Brush="#2196F3" Geometry="M789.333333 853.333333H234.666667l-128 128V256c0-70.4 57.6-128 128-128h554.666666c70.4 0 128 57.6 128 128v469.333333c0 70.4-57.6 128-128 128z"/>
<GeometryDrawing Brush="#FFFFFF" Geometry="M469.333333 426.666667h85.333334v234.666666h-85.333334z"/>
<GeometryDrawing Brush="#FFFFFF" Geometry="M512 320m-42.666667 0a42.666667 42.666667 0 1 0 85.333334 0 42.666667 42.666667 0 1 0-85.333334 0Z"/>
</DrawingGroup>
<DrawingGroup x:Key="ProxyScriptManagePageSvg">
<DrawingGroup x:Key="ProxyScriptManagePageViewModel">
<GeometryDrawing Brush="#E9EDED" Geometry="M847.872 240.128v688c0 26.56-21.408 48-48 48h-576c-26.56 0-48-21.44-48-48v-832c0-26.592 21.44-48 48-48h432z"/>
<GeometryDrawing Brush="#25B39E" Geometry="M160 768.128v160c0 35.456 28.544 64 64 64h576c35.456 0 64-28.544 64-64v-160H160z"/>
<GeometryDrawing Brush="#25B39E" Geometry="M847.872 240.128h-144c-26.56 0-48-21.44-48-48v-144"/>
@@ -260,13 +260,13 @@
<GeometryDrawing Brush="#E9EDED" Geometry="M335.872 800a16 16 0 0 0-15.744 16.256V912c0 9.152-6.848 16-16 16a15.616 15.616 0 0 1-16-16 16 16 0 0 0-16.256-16.192 16 16 0 0 0-15.744 16.192c0 26.304 21.696 48 48 48 24.768 0 45.12-19.296 47.488-43.52a16 16 0 0 0 0.512-4.224v-96a16 16 0 0 0-16.256-16.256z m94.4 0.128a16 16 0 0 0-2.016 0.384c-24.64 1.92-44.384 22.528-44.384 47.616 0 25.28 20.096 46.08 44.992 47.68a16 16 0 0 0 3.008 0.32h32c9.152 0 16 6.848 16 16 0 9.152-6.848 16-16 16h-64a16 16 0 1 0 0 32h64a16 16 0 0 0 3.328-0.384 48.096 48.096 0 0 0 44.672-47.616c0-25.152-19.84-45.888-44.544-47.68a16 16 0 0 0-3.456-0.32h-30.88a16 16 0 0 0-1.12 0 15.616 15.616 0 0 1-16-16c0-9.152 6.848-16 16-16h64a16 16 0 1 0 0-32h-62.88a16 16 0 0 0-1.12 0 16 16 0 0 0-1.6 0z"/>
</DrawingGroup>
<DrawingGroup x:Key="GameListPageSvg">
<DrawingGroup x:Key="GameListPageViewModel">
<GeometryDrawing Brush="#8C9EFF" Geometry="M912.31 414.51C843.52 269.59 725.6 195.76 648.92 249.6c-0.14 0.1-0.29 0.2-0.43 0.31-35.38 25.12-74.75 40.74-115.72 40.74h-41.54c-40.97 0-80.34-15.62-115.72-40.74-0.14-0.1-0.29-0.2-0.43-0.31-76.67-53.84-194.6 19.99-263.39 164.91-68.79 144.92-62.4 306.05 14.27 359.89 60.52 42.5 146.72 5.43 214.19-83.34 39.88-52.47 97.07-80.37 155.82-80.37h32.05c58.75 0 115.94 27.9 155.82 80.37 67.47 88.77 153.67 125.84 214.19 83.34 76.68-53.84 83.07-214.97 14.28-359.89z"/>
<GeometryDrawing Brush="#546a79" Geometry="M32.786 30.268a4 4 0 1 0 8 0a4 4 0 1 0 -8 0z"/>
--><!--<GeometryDrawing Brush="#546a79" Geometry="M32.786 30.268a4 4 0 1 0 8 0a4 4 0 1 0 -8 0z"/>
<GeometryDrawing Brush="#ebba16" Geometry="M9.786 20.268a4 4 0 1 0 8 0a4 4 0 1 0 -8 0z"/>
<GeometryDrawing Brush="#546a79" Geometry="M41.786 16.268a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z"/>
<GeometryDrawing Brush="#7383bf" Geometry="M37.786 20.268a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z"/>
<GeometryDrawing Brush="#d75a4a" Geometry="M45.786 20.268a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z"/>
<GeometryDrawing Brush="#d75a4a" Geometry="M45.786 20.268a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z"/>--><!--
<GeometryDrawing Brush="#61b872" Geometry="M41.786 24.268a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z"/>
<GeometryDrawing Brush="#313FA0" Geometry="M800.33 500.89m-42 0a42 42 0 1 0 84 0 42 42 0 1 0-84 0Z"/>
<GeometryDrawing Brush="#FFD600" Geometry="M662.6 453.75m-42 0a42 42 0 1 0 84 0 42 42 0 1 0-84 0Z"/>
@@ -274,7 +274,7 @@
<GeometryDrawing Brush="#FFFFFF" Geometry="M391.34 474.75h-168c-11.6 0-21-9.4-21-21s9.4-21 21-21h168c11.6 0 21 9.4 21 21s-9.4 21-21 21z"/>
</DrawingGroup>
<DrawingGroup x:Key="GameRelatedPageSvg">
<DrawingGroup x:Key="GameRelatedPageViewModel">
<GeometryDrawing Brush="#90A4AE" Geometry="M682.666667 170.666667l21.333333 42.666666v320h128V213.333333l23.04-42.666666L832 64h-128l-21.333333 106.666667z"/>
<GeometryDrawing Brush="#B0BEC5" Geometry="M768 192c62.506667 0 64-128 64-128h-128s1.706667 128 64 128z"/>
<GeometryDrawing Brush="#3F51B5" Geometry="M680.746667 533.333333h174.506666l38.826667 183.253334a81.92 81.92 0 0 1 1.92 17.706666V874.666667a85.333333 85.333333 0 0 1-85.333333 85.333333h-85.333334a85.333333 85.333333 0 0 1-85.333333-85.333333v-140.373334a81.92 81.92 0 0 1 1.92-17.706666z"/>
@@ -284,7 +284,7 @@
<GeometryDrawing Brush="#FF9800" Geometry="M466.986667 85.333333v209.92h-208.64V85.333333A234.666667 234.666667 0 0 0 128 294.186667 177.92 177.92 0 0 0 277.333333 469.333333a528 528 0 0 0 85.333334 7.253334 528 528 0 0 0 85.333333-7.253334 177.92 177.92 0 0 0 149.333333-175.36A234.666667 234.666667 0 0 0 466.986667 85.333333z"/>
</DrawingGroup>
<DrawingGroup x:Key="CommunityProxyPageSvg">
<DrawingGroup x:Key="CommunityProxyPageViewModel">
<GeometryDrawing Brush="#e45a6e" Geometry="m221.799 139.528c-2.922-4.879-8.353-7.68-14.024-7.249l-121.895 9.416c-12.341.954-23.334 7.422-30.162 17.748l-51.155 77.372c-5.177 7.831-6.001 17.63-2.203 26.214 3.797 8.584 11.602 14.565 20.877 16.002l98.84 15.309c.769.119 1.537.178 2.299.178 5.063-.001 9.853-2.568 12.636-6.922l84.557-132.283c3.063-4.793 3.151-10.905.23-15.785z"/>
<GeometryDrawing Brush="#d82e44" Geometry="m372.475 290.205c-4.88-2.922-10.993-2.833-15.785.23l-132.282 84.557c-5.009 3.202-7.654 9.06-6.745 14.935l15.308 98.84c1.437 9.276 7.419 17.08 16.004 20.878 3.57 1.579 7.35 2.358 11.112 2.358 5.281 0 10.528-1.538 15.101-4.561l77.373-51.156c10.326-6.826 16.795-17.82 17.747-30.162l9.416-121.894c.439-5.671-2.369-11.102-7.249-14.025z"/>
<GeometryDrawing Brush="#f1f1fb" Geometry="m192.87 412.278c5.97 5.97 14.453 8.763 22.78 7.37 122.112-20.418 218.741-121.522 255.528-192.645 40.849-78.974 42.362-162.43 40.227-201.57-.732-13.412-11.423-24.103-24.835-24.835-39.14-2.134-122.595-.621-201.57 40.228-71.122 36.787-172.226 133.416-192.644 255.528-1.392 8.327 1.4 16.81 7.37 22.78z"/>
@@ -301,32 +301,31 @@
<GeometryDrawing Brush="#0590fb" Geometry="m382.55 129.454-63.639 63.639c17.545 17.545 46.095 17.546 63.639 0 8.499-8.5 13.18-19.8 13.18-31.82s-4.68-23.32-13.18-31.819z"/>
</DrawingGroup>
<DrawingGroup x:Key="SettingsPageSvg">
<DrawingGroup x:Key="SettingsPageViewModel">
<GeometryDrawing Brush="#8C9EFF" Geometry="
M960 568V456c0-15.46-12.54-28-28-28h-94.59c-7.93-30.82-20.2-59.9-35.99-86.63l66.96-66.96c10.93-10.93 10.93-28.66 0-39.6l-79.2-79.2c-10.93-10.93-28.66-10.93-39.6 0l-66.96 66.96c-26.74-15.8-55.81-28.06-86.63-35.99V92c0-15.46-12.54-28-28-28H456c-15.46 0-28 12.54-28 28v94.59c-30.82 7.93-59.9 20.19-86.63 35.99l-66.96-66.96c-10.93-10.93-28.66-10.93-39.6 0l-79.2 79.2c-10.93 10.93-10.93 28.66 0 39.6l66.96 66.96c-15.8 26.73-28.06 55.81-35.99 86.63H92c-15.46 0-28 12.54-28 28v112c0 15.46 12.54 28 28 28h94.59c7.93 30.82 20.19 59.9 35.99 86.63l-66.96 66.96c-10.93 10.93-10.93 28.66 0 39.6l79.2 79.2c10.93 10.93 28.66 10.93 39.6 0l66.96-66.96c26.74 15.8 55.81 28.06 86.63 35.99V932c0 15.46 12.54 28 28 28h112c15.46 0 28-12.54 28-28v-94.59c30.82-7.93 59.9-20.19 86.63-35.99l66.96 66.96c10.93 10.93 28.66 10.93 39.6 0l79.2-79.2c10.93-10.93 10.93-28.66 0-39.6l-66.96-66.96c15.8-26.73 28.06-55.81 35.99-86.63H932c15.46 0.01 28-12.53 28-27.99z"/>
<GeometryDrawing Brush="#FFFFFF" Geometry="M512 512m-168 0a168 168 0 1 0 336 0 168 168 0 1 0-336 0Z"/>
<GeometryDrawing Brush="#FFD600" Geometry="M512 512m-56 0a56 56 0 1 0 112 0 56 56 0 1 0-112 0Z"/>
</DrawingGroup>
<DrawingGroup x:Key="SteamAccountPageSvg">
<DrawingGroup x:Key="SteamAccountPageViewModel">
<GeometryDrawing Brush="#A9D8FF" Geometry="M632 344m-120 0a120 120 0 1 0 240 0 120 120 0 1 0-240 0Z"/>
<GeometryDrawing Brush="#A9D8FF" Geometry="M809 800H503c-48.1 0-87-39-87-87 0-111 90-201 201-201h78c111 0 201 90 201 201 0 48-39 87-87 87z"/>
<GeometryDrawing Brush="#298DF7" Geometry="M440 296m-168 0a168 168 0 1 0 336 0 168 168 0 1 0-336 0Z"/>
<GeometryDrawing Brush="#298DF7" Geometry="M638.2 896H241.8C179 896 128 845 128 782.2 128 633 249 512 398.2 512h83.6C631 512 752 633 752 782.2 752 845 701 896 638.2 896z"/>
</DrawingGroup>
<StreamGeometry x:Key="StartPageSvg">
<StreamGeometry x:Key="StartPageViewModel">
M786.68 960H237.31c-49.93 0-90.55-43.49-90.55-96.95v-484c0-14.55 11.8-26.35 26.35-26.35s26.35 11.8 26.35 26.35v484c0 24.4 16.98 44.24 37.84 44.24h549.37c20.87 0 37.84-19.85 37.84-44.24v-484c0-14.55 11.8-26.35 26.35-26.35s26.35 11.8 26.35 26.35v484c0.02 53.46-40.61 96.95-90.53 96.95z
M621.11 960H402.88c-14.55 0-26.35-11.8-26.35-26.35V696.46C376.53 621.77 437.3 561 512 561s135.47 60.77 135.47 135.46v237.19c0 14.55-11.8 26.35-26.36 26.35z m-191.88-52.71h165.53V696.46c0-45.63-37.12-82.76-82.76-82.76-45.63 0-82.76 37.12-82.76 82.76v210.83zM933.63 472.73c-6.23 0-12.49-2.2-17.51-6.68L534.18 125.78c-13.49-11.99-32.27-11.99-45.74-0.01l-380.56 338.8c-10.87 9.68-27.53 8.71-37.21-2.16-9.68-10.87-8.71-27.53 2.16-37.21L453.39 86.41c33.57-29.89 82.28-29.88 115.84 0.03L951.16 426.7c10.87 9.68 11.84 26.34 2.15 37.21-5.2 5.84-12.43 8.82-19.68 8.82z
</StreamGeometry>
<StreamGeometry x:Key="ArchiSteamFarmPlusPageSvg">
<StreamGeometry x:Key="ArchiSteamFarmPlusPageViewModel">
M100,195.25a18.07,18.07,0,0,1-12.85-5.33L10.08,112.85a18.15,18.15,0,0,1,0-25.7L87.15,10.08a18.19,18.19,0,0,1,25.7,0l77.07,77.07a18.15,18.15,0,0,1,0,25.7h0l-77.07,77.07A18.07,18.07,0,0,1,100,195.25Zm0-182.49a10.13,10.13,0,0,0-7.19,3L15.73,92.81a10.16,10.16,0,0,0,0,14.38l77.08,77.08a10.19,10.19,0,0,0,14.38,0l77.08-77.08a10.16,10.16,0,0,0,0-14.38L107.19,15.73A10.13,10.13,0,0,0,100,12.76ZM91.73,83c.11-.19.15-.23.14-.26-.57-4.67,1.7-8.4,4-12.1.89-1.42,1.86-2.78,2.8-4.17.51-.76,1-.85,1.51,0,1.94,3.38,4.07,6.67,5.76,10.17.75,1.56.63,3.55.9,5.35,0,.19,0,.39.1.86,1.1-.62,2.07-1.18,3-1.72,2-1.1,4-2.2,6-3.27.74-.4,1.37-.32,1.4.7.08,3.16.29,6.32.15,9.46-.26,5.59-3.36,9.45-8.13,12-2.92,1.53-6,2.72-9.07,4a3.39,3.39,0,0,1-2.18,0A42.13,42.13,0,0,1,86.39,98.2a13.87,13.87,0,0,1-5-7.49c-1.2-4-.76-7.91-.43-11.88.1-1.21.63-1.43,1.68-.84L91,82.64A5.76,5.76,0,0,0,91.73,83ZM99.29,143.36c.47-.9.8-1.56,1.16-2.2,1.89-3.34,4.87-5.53,8.06-7.45,2.39-1.44,4.85-2.76,7.27-4.13,1-.59,1.58-.33,1.62.86.1,2.84.27,5.68.21,8.51-.12,5.93-3.23,10-8.3,12.76a66.3,66.3,0,0,1-6.15,2.9,1.56,1.56,0,0,0-1.08,1.73c0,4.88,0,9.76,0,14.64,0,2.28-.25,2.53-2.56,2.53-3.32,0-3.32,0-3.32-3.31,0-4.52,0-9,0-13.56a2.22,2.22,0,0,0-1.52-2.34,72.87,72.87,0,0,1-7.51-3.87,13.5,13.5,0,0,1-5.84-8c-1.18-4-.74-8-.41-12,.09-1,.65-1.34,1.45-.9,4,2.24,8.21,4.24,11.78,7.24a16.58,16.58,0,0,1,4.38,5.46C98.72,142.52,99,142.82,99.29,143.36ZM99.21,117.28c1.11-1.61,2-3.23,3.23-4.65,2.35-2.79,5.52-4.54,8.63-6.32,1.67-1,3.39-1.79,5.07-2.72.79-.44,1.17-.11,1.23.62.31,4.55.86,9.11-.61,13.57a12.94,12.94,0,0,1-4.94,6.46c-3.21,2.29-6.86,3.7-10.46,5.23a5,5,0,0,1-4.36-.06c-3.84-1.59-7.7-3.09-11-5.71a14,14,0,0,1-4.65-7.2c-1.21-4-.71-8-.4-12,.06-.78.51-1.28,1.29-.86,5.16,2.75,10.61,5.09,14.44,9.79A45.61,45.61,0,0,1,99.21,117.28ZM117.33,55.86V68c0,1.68-.45,2.11-2.15,2.12-.68,0-1.35,0-2,0-1.18,0-1.65-.61-1.73-1.68,0-.28,0-.56,0-.84q0-11.69,0-23.37c0-2.24.34-2.55,2.56-2.58,2.75,0,3.45-.16,3.38,3.34S117.33,52.22,117.33,55.86ZM81,55.91V43.8c0-1.67.47-2.13,2.13-2.16.56,0,1.12,0,1.68,0,1.5,0,2,.5,2,2q0,12.23,0,24.45c0,1.46-.56,1.93-2,2H83.43c-2.12,0-2.46-.33-2.46-2.4ZM96.2,44.59c0-4,0-8.07,0-12.11,0-1.71.43-2.11,2.13-2.15,3.45-.07,3.8-.08,3.77,3.67-.06,7.43,0,14.86,0,22.29,0,2.14-.32,2.46-2.39,2.47-3.49,0-3.49,0-3.49-3.51Z
</StreamGeometry>
</StreamGeometry>-->
<!--菜单图标 End-->
<StreamGeometry x:Key="SteamIdlePageSvg">
M56,68H6a3,3,0,0,1-3-3V6A3,3,0,0,1,6,3H56a3,3,0,0,1,3,3V65A3,3,0,0,1,56,68ZM4,5.62V65.38A1.63,1.63,0,0,0,5.62,67H56.38A1.63,1.63,0,0,0,58,65.38V5.62A1.63,1.63,0,0,0,56.38,4H5.62A1.63,1.63,0,0,0,4,5.62ZM56.06,69H5.94A3.93,3.93,0,0,1,2,65.06V5.94A3.93,3.93,0,0,1,5.94,2H56.06A3.93,3.93,0,0,1,60,5.94V65.06A3.93,3.93,0,0,1,56.06,69ZM5,5.65v59.7a.65.65,0,0,0,.65.65h50.7a.65.65,0,0,0,.65-.65V5.65A.65.65,0,0,0,56.35,5H5.65A.65.65,0,0,0,5,5.65ZM56.19,70H5.81A4.81,4.81,0,0,1,1,65.19V5.81A4.81,4.81,0,0,1,5.81,1H56.19A4.81,4.81,0,0,1,61,5.81V65.19A4.81,4.81,0,0,1,56.19,70ZM6,65H56V6H6ZM56.22,71H5.78A5.78,5.78,0,0,1,0,65.22V5.78A5.78,5.78,0,0,1,5.78,0H56.22A5.78,5.78,0,0,1,62,5.78V65.22A5.78,5.78,0,0,1,56.22,71ZM2,5.83V65.16A3.84,3.84,0,0,0,5.84,69H56.16A3.84,3.84,0,0,0,60,65.16V5.83A3.84,3.84,0,0,0,56.17,2H5.83A3.84,3.84,0,0,0,2,5.83ZM57,66H5V5H57ZM7,64H55V7H7ZM47.19,48H14.81A1.81,1.81,0,0,1,13,46.19V16.81A1.81,1.81,0,0,1,14.81,15H47.19A1.81,1.81,0,0,1,49,16.81V46.19A1.81,1.81,0,0,1,47.19,48ZM14,16.86V46.14a.87.87,0,0,0,.86.86H47.14a.87.87,0,0,0,.86-.86V16.86a.87.87,0,0,0-.86-.86H14.86A.87.87,0,0,0,14,16.86ZM47.21,49H14.79A2.79,2.79,0,0,1,12,46.21V16.79A2.79,2.79,0,0,1,14.79,14H47.21A2.79,2.79,0,0,1,50,16.79V46.21A2.79,2.79,0,0,1,47.21,49ZM15,46H47V17H15ZM47.34,50H14.66A3.66,3.66,0,0,1,11,46.34V16.66A3.66,3.66,0,0,1,14.66,13H47.34A3.66,3.66,0,0,1,51,16.66V46.34A3.66,3.66,0,0,1,47.34,50ZM16,45H46V17H16ZM47.37,51H14.63A4.63,4.63,0,0,1,10,46.37V16.63A4.63,4.63,0,0,1,14.63,12H47.37A4.63,4.63,0,0,1,52,16.63V46.37A4.63,4.63,0,0,1,47.37,51ZM12,16.68V46.32A2.68,2.68,0,0,0,14.68,49H47.32A2.68,2.68,0,0,0,50,46.32V16.68A2.68,2.68,0,0,0,47.32,14H14.68A2.68,2.68,0,0,0,12,16.68ZM47,46H15V16H47ZM16,44H45V18H16ZM36.62,34H25.21A3.11,3.11,0,0,1,22,30.69,3,3,0,0,1,25,28H36.41a3.11,3.11,0,0,1,3.17,3.31A3,3,0,0,1,36.62,34ZM24.89,30a1.62,1.62,0,0,0-1.09,1.36c0,.65.49,1.14,1.09.64H36.74c.6.5,1.09,0,1.09-.59A1.63,1.63,0,0,0,36.74,30ZM34,37a3.12,3.12,0,0,1-3.31,3.17,3,3,0,0,1-2.69-3V25.79a3.11,3.11,0,0,1,3.31-3.17,3,3,0,0,1,2.69,3ZM30.84,24.37c-.65,0-1.14.49-.84,1.09V37.31c-.3.6.19,1.09.79,1.09A1.22,1.22,0,0,0,32,37.31V25.46A1.21,1.21,0,0,0,30.84,24.37Z
</StreamGeometry>
<StreamGeometry x:Key="QQ">
M909.937778 664.803556c-18.432-110.876444-95.829333-183.523556-95.829333-183.523556 11.064889-100.664889-29.496889-118.528-29.496889-118.528C776.106667 51.313778 517.432889 56.775111 512 56.917333c-5.432889-0.142222-264.135111-5.603556-272.611556 305.863111 0 0-40.561778 17.863111-29.496889 118.528 0 0-77.397333 72.647111-95.829333 183.523556 0 0-9.841778 187.335111 88.462222 22.954667 0 0 22.129778 62.435556 62.663111 118.528 0 0-72.504889 25.486222-66.332444 91.761778 0 0-2.474667 73.898667 154.823111 68.835556 0 0 110.563556-8.903111 143.758222-57.344l29.240889 0c33.166222 48.440889 143.758222 57.344 143.758222 57.344 157.240889 5.091556 154.794667-68.835556 154.794667-68.835556 6.115556-66.247111-66.332444-91.761778-66.332444-91.761778 40.533333-56.092444 62.663111-118.528 62.663111-118.528C919.751111 852.167111 909.937778 664.803556 909.937778 664.803556L909.937778 664.803556zM909.937778 664.803556
@@ -0,0 +1,62 @@
using System;
using System.Application.Models.Settings;
using System.Application.Services;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Platform;
namespace System.Application.UI.Views.Controls
{
public class EmbedSample : NativeControlHost
{
IntPtr _handle;
//public EmbedSample()
//{
// this.AttachedToVisualTree += EmbedSample_AttachedToVisualTree; ;
//}
//private void EmbedSample_AttachedToVisualTree(object? sender, Avalonia.VisualTreeAttachmentEventArgs e)
//{
// if (UISettings.EnableDesktopBackground.Value)
// {
// DI.Get<ISystemWindowApiService>().SetDesktopBackgroundToWindow(
// this._handle, 600, 900);
// }
//}
IPlatformHandle CreateWin32(IPlatformHandle parent)
{
//var handle = DI.Get<ISystemWindowApiService>().CreateEmptyWindow(parent.Handle);
_handle = parent.Handle;
return new PlatformHandle(_handle, "HWND");
}
void DestroyWin32(IPlatformHandle handle)
{
//DI.Get<ISystemWindowApiService>().CreateEmptyWindow(handle.Handle, false);
}
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return CreateWin32(parent);
//if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// return CreateLinux(parent);
//if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
// return CreateOSX(parent);
return base.CreateNativeControlCore(parent);
}
protected override void DestroyNativeControlCore(IPlatformHandle control)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
DestroyWin32(control);
//else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
// DestroyLinux(control);
//else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
// DestroyOSX(control);
//else
base.DestroyNativeControlCore(control);
}
}
}
@@ -0,0 +1,127 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Markup.Xaml;
using System;
using System.Application.Models.Settings;
using System.Application.Services;
namespace System.Application.UI.Views.Controls
{
public class EmptyControl : TemplatedControl
{
Window window;
Window Parent;
IntPtr _Handle;
public EmptyControl()
{
//this.InitializeComponent();
this.GetObservable(IsVisibleProperty)
.Subscribe(x =>
{
if (x)
{
if (window == null)
{
this.LayoutUpdated += EmptyControl_LayoutUpdated;
this.AttachedToVisualTree += EmptyControl_AttachedToVisualTree;
this.DetachedFromVisualTree += EmptyControl_DetachedFromVisualTree;
window = new Window
{
Width = this.Bounds.Width,
Height = this.Bounds.Height,
Background = Avalonia.Media.Brushes.Transparent,
WindowStartupLocation = WindowStartupLocation.Manual,
WindowState = WindowState.Normal,
ExtendClientAreaToDecorationsHint = true,
ExtendClientAreaChromeHints = Avalonia.Platform.ExtendClientAreaChromeHints.PreferSystemChrome,
SystemDecorations = SystemDecorations.Full,
CanResize = false,
TransparencyLevelHint = WindowTransparencyLevel.Transparent,
ShowInTaskbar = false,
Focusable = false
};
if (Parent != null && VisualRoot != null)
EmptyControl_AttachedToVisualTree(null, new VisualTreeAttachmentEventArgs(Parent, VisualRoot));
}
}
else
{
if (window != null)
{
if (Parent != null && VisualRoot != null)
EmptyControl_DetachedFromVisualTree(null, new VisualTreeAttachmentEventArgs(Parent, VisualRoot));
this.LayoutUpdated -= EmptyControl_LayoutUpdated;
this.AttachedToVisualTree -= EmptyControl_AttachedToVisualTree;
this.DetachedFromVisualTree -= EmptyControl_DetachedFromVisualTree;
window = null;
}
}
});
}
private void EmptyControl_DetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
if (OperatingSystem2.IsWindows && UISettings.EnableDesktopBackground.Value)
{
DI.Get<ISystemWindowApiService>().ReleaseBackground(_Handle);
Parent.PositionChanged -= Parent_PositionChanged;
Close();
}
}
private void EmptyControl_AttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
if (OperatingSystem2.IsWindows && UISettings.EnableDesktopBackground.Value)
{
Show();
Parent = (Window)e.Root;
Parent.PositionChanged += Parent_PositionChanged;
_Handle = Handle;
_Handle = DI.Get<ISystemWindowApiService>().SetDesktopBackgroundToWindow(
_Handle, (int)window.Width, (int)window.Height);
DI.Get<ISystemWindowApiService>().SetWindowPenetrate(Handle);
}
}
private void Parent_PositionChanged(object? sender, PixelPointEventArgs e)
{
window.Position = this.PointToScreen(this.Bounds.Position);
}
private void EmptyControl_LayoutUpdated(object? sender, System.EventArgs e)
{
if (OperatingSystem2.IsWindows && UISettings.EnableDesktopBackground.Value)
{
window.Position = this.PointToScreen(this.Bounds.Position);
window.Width = this.Bounds.Width;
window.Height = this.Bounds.Height;
DI.Get<ISystemWindowApiService>().BackgroundUpdate(_Handle, (int)window.Width, (int)window.Height);
}
//NativeMethods.SetWindowPos(HWND, NativeMethods.HWND_TOPMOST, window.Position.X, window.Position.Y, (int)window.Width, (int)window.Height, 0);
}
public WindowState WindowState
{
get { return window.WindowState; }
set { window.WindowState = value; }
}
public void Show()
{
window.Show();
}
public IntPtr Handle
{
get { return window.PlatformImpl.Handle.Handle; }
}
public void Close()
{
window.Close();
}
}
}
@@ -3,6 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls;assembly=System.Application.SteamTools.Client.Desktop.Avalonia"
mc:Ignorable="d"
x:Name="u"
IsHitTestVisible="False"
@@ -14,6 +15,9 @@
Stretch="UniformToFill"
Opacity="{ReflectionBinding Source={x:Static ms:UISettings.EnableCustomBackgroundImage},Path=Value, Mode=OneWay,Converter={StaticResource IsVisibleToOpacity},ConverterParameter=0.8}"/>
</Panel.Background>
<!--<Panel ZIndex="0">
<controls:EmptyControl/>
</Panel>-->
<!--<Image IsHitTestVisible="False"
IsVisible="{ReflectionBinding Source={x:Static ms:UISettings.EnableCustomBackgroundImage},Path=Value, Mode=OneWay}"
Source="{ReflectionBinding Source={x:Static ms:UISettings.BackgroundImagePath},Path=Value, Mode=OneWay,Converter={StaticResource BitmapAssetValueConverter}}"
@@ -28,7 +32,7 @@
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder DockPanel.Dock="Bottom"
<ExperimentalAcrylicBorder DockPanel.Dock="Bottom"
x:Name="Back"
IsHitTestVisible="False">
<!--Opacity="{StaticResource ContentOpacity}"-->
@@ -168,11 +168,14 @@
Margin="{StaticResource TitleBarAfterMargin}"
Background="Transparent"
PaneDisplayMode="Left"
IsPaneOpen="False"
AlwaysShowHeader="False"
IsSettingsVisible="False"
OpenPaneLength="240"
MenuItems="{Binding TabItems}"
FooterMenuItems="{Binding FooterTabItems}"
IsBackButtonVisible="False"
IsBackEnabled="{Binding #frame.CanGoBack}"
SelectedItem="{Binding SelectedItem}">
<!--<ui:NavigationView.PaneHeader>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Height="110" VerticalAlignment="Top">
@@ -182,7 +185,7 @@
</ui:NavigationView.PaneHeader>-->
<ui:NavigationView.Content>
<ui:Frame Content="{Binding SelectedItem,Mode=OneWay}">
<ui:Frame x:Name="frame" DataContext="{Binding SelectedItem}">
<ui:Frame.DataTemplates>
<DataTemplate DataType="vm:ProxyScriptManagePageViewModel">
<pages:ProxyScriptManagePage/>
@@ -286,12 +289,29 @@
<ui:NavigationView.MenuItemTemplate>
<DataTemplate DataType="{x:Type vm:TabItemViewModel}">
<ui:NavigationViewItem Content="{Binding Name,StringFormat={} {0}}">
<ui:NavigationViewItem>
<ui:NavigationViewItem.Resources>
<x:Double x:Key="NavigationViewItemOnLeftIconBoxHeight">26</x:Double>
</ui:NavigationViewItem.Resources>
<ui:NavigationViewItem.Content>
<!--<DockPanel>
<ui:ImageIcon DockPanel.Dock="Left">
<DrawingImage Drawing="{Binding IconKey,Converter={StaticResource DrawingKeyValueConverter}}"/>
</ui:ImageIcon>-->
<controls:ScrollingTextBlock Text="{Binding Name}"
HorizontalAlignment="Stretch"
IsVisible="{ReflectionBinding Path=!!IsPaneOpen,ElementName=NavigationView}"/>
<!--</DockPanel>-->
</ui:NavigationViewItem.Content>
<ui:NavigationViewItem.Icon>
<!--<ui:PathIcon Data="{Binding IconKey,Converter={StaticResource DrawingKeyValueConverter}}"/>-->
<ui:ImageIcon>
<DrawingImage Drawing="{Binding IconKey,Converter={StaticResource DrawingKeyValueConverter}}"/>
</ui:ImageIcon>
<ui:BitmapIcon UriSource="{Binding IconSource}"
HorizontalAlignment="Center"
Width="26" Height="26"/>
<!--<ui:ImageIcon Margin="3 0 0 0"
Width="16" Height="16">
<DrawingImage Drawing="{Binding IconKey,Converter={StaticResource DrawingKeyValueConverter}}"/>
</ui:ImageIcon>-->
</ui:NavigationViewItem.Icon>
</ui:NavigationViewItem>
</DataTemplate>
@@ -2,11 +2,15 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Platform;
using Avalonia.ReactiveUI;
using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Media.Animation;
using System.Application.UI.ViewModels;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace System.Application.UI.Views
{
@@ -44,7 +48,7 @@ namespace System.Application.UI.Views
});
}
if (back != null && nav != null)
if (avater != null && nav != null)
{
nav.GetObservable(NavigationView.IsPaneOpenProperty)
.Subscribe(x =>
@@ -63,6 +67,30 @@ namespace System.Application.UI.Views
}
});
}
var frame = this.FindControl<Frame>("frame");
if (frame != null && nav != null)
{
if (nav.IsBackButtonVisible)
{
nav.BackRequested += (sender, e) =>
{
frame.GoBack();
};
}
nav.GetObservable(NavigationView.SelectedItemProperty)
.Subscribe(x =>
{
if (x != null)
{
var page = frame.DataTemplates.FirstOrDefault(f => f.Match(x));
if (page is DataTemplate template)
{
frame.Navigate(template.Build(null).GetType());
}
}
});
}
}
private void InitializeComponent()
@@ -6,9 +6,11 @@
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
xmlns:i="using:Avalonia.Xaml.Interactivity"
xmlns:ia="using:Avalonia.Xaml.Interactions.Core"
xmlns:sys="using:System"
x:Name="u"
x:DataType="vm:CommunityProxyPageViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
@@ -21,18 +23,28 @@
Grid.Row="0"
Grid.ColumnSpan="2"
Margin="10"
Padding="20 10"
Padding="10"
Classes="paper"
Background="{DynamicResource ThemeBrushKey}">
<DockPanel>
<!--<DockPanel>
<StackPanel Orientation="Horizontal"
Spacing="15"
Spacing="10"
HorizontalAlignment="Left"
VerticalAlignment="Center">
<!--<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_ProxyMode,Mode=OneWay,Source={x:Static resx:R.Current}}" Margin="0 5"
-->
<!--<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_ProxyMode,Mode=OneWay,Source={x:Static resx:R.Current}}" Margin="0 5"
Foreground="{DynamicResource HighlightForegroundBrushKey}"></TextBlock>-->
<!--
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_Hosts,Mode=OneWay,Source={x:Static resx:R.Current}}" ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_HostsTip,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=!Value, Mode=TwoWay}"></RadioButton>
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystem,Mode=OneWay,Source={x:Static resx:R.Current}}" ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystemTip,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=Value, Mode=TwoWay}"></RadioButton>
<Button Background="Transparent"
Command="{Binding ProxySettingsCommand}"
ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxySettings,Mode=OneWay,Source={x:Static resx:R.Current}}">
<StackPanel Orientation="Horizontal" Spacing="5">
<PathIcon Data="{StaticResource SettingsDrawing}"/>
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_ProxySettings,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
</StackPanel>
</Button>
<Menu Classes="BindMenu">
<MenuItem Items="{Binding MenuItems}"
Classes="BindItem"
@@ -47,16 +59,15 @@
HorizontalAlignment="Right"
VerticalAlignment="Center">
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_EnableScriptService,Mode=OneWay,Source={x:Static resx:R.Current}}"
Margin="0 3 0 0"
VerticalAlignment="Center"/>
<ToggleSwitch Classes="onlyToggleSwitch"
VerticalAlignment="Center"
IsChecked="{Binding Source={x:Static service:ProxyService.Current},Path=IsEnableScript}"
Margin="10 0 15 0"/>
Margin="10 -5 15 0"/>
<Button Classes="action"
Content="{ReflectionBinding Path=Res.CommunityFix_StartProxy,Mode=OneWay,Source={x:Static resx:R.Current}}"
FontSize="16"
MinWidth="150"
MinWidth="50"
Width="200"
MinHeight="40"
HorizontalContentAlignment="Center"
@@ -64,9 +75,126 @@
Command="{Binding StartProxyButton_Click}"
CommandParameter="True"></Button>
<!--<ToggleSwitch Content="{ReflectionBinding Path=Res.CommunityFix_StartProxy,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static service:ProxyService.Current},Path=ProxyStatus}"></ToggleSwitch>-->
-->
<!--<ToggleSwitch Content="{ReflectionBinding Path=Res.CommunityFix_StartProxy,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static service:ProxyService.Current},Path=ProxyStatus}"></ToggleSwitch>-->
<!--
</StackPanel>
</DockPanel>
</DockPanel>-->
<ui:CommandBar DefaultLabelPosition="Right">
<ui:CommandBar.PrimaryCommands>
<!--<ui:CommandBarButton
Command="{Binding StartProxyButton_Click}"
CommandParameter="True"
ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxySettings,Mode=OneWay,Source={x:Static resx:R.Current}}"
Label="{ReflectionBinding Path=Res.CommunityFix_StartProxy,Mode=OneWay,Source={x:Static resx:R.Current}}">
</ui:CommandBarButton>-->
<ui:CommandBarElementContainer>
<Button Classes="action"
Content="{ReflectionBinding Path=Res.CommunityFix_StartProxy,Mode=OneWay,Source={x:Static resx:R.Current}}"
FontSize="16"
Margin="0 0 10 0"
MinWidth="50"
Width="200"
MinHeight="40"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Command="{Binding StartProxyButton_Click}"
CommandParameter="True"/>
</ui:CommandBarElementContainer>
<!--<ui:CommandBarSeparator/>-->
<ui:CommandBarElementContainer>
<StackPanel Orientation="Horizontal" Spacing="8" Margin="10 0">
<ToggleSwitch Content=""
OnContent="{ReflectionBinding Path=Res.CommunityFix_EnableScriptService,Mode=OneWay,Source={x:Static resx:R.Current}}"
OffContent="{ReflectionBinding Path=Res.CommunityFix_EnableScriptService,Mode=OneWay,Source={x:Static resx:R.Current}}"
VerticalAlignment="Center"
Margin="0 -5 0 0"
IsChecked="{Binding Source={x:Static service:ProxyService.Current},Path=IsEnableScript}"/>
<!--<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_EnableScriptService,Mode=OneWay,Source={x:Static resx:R.Current}}" VerticalAlignment="Center"/>-->
</StackPanel>
</ui:CommandBarElementContainer>
<ui:CommandBarSeparator/>
<ui:CommandBarElementContainer Margin="8 0"
HorizontalContentAlignment="Center">
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_Hosts,Mode=OneWay,Source={x:Static resx:R.Current}}" ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_HostsTip,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=!Value, Mode=TwoWay}"></RadioButton>
</ui:CommandBarElementContainer>
<ui:CommandBarElementContainer Margin="8 0"
HorizontalContentAlignment="Center">
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystem,Mode=OneWay,Source={x:Static resx:R.Current}}" ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystemTip,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=Value, Mode=TwoWay}"></RadioButton>
</ui:CommandBarElementContainer>
<!--<ui:CommandBarToggleButton IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=!Value, Mode=TwoWay}"
Label="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_Hosts,Mode=OneWay,Source={x:Static resx:R.Current}}"
ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_HostsTip,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ui:CommandBarToggleButton IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=Value, Mode=TwoWay}"
Label="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystem,Mode=OneWay,Source={x:Static resx:R.Current}}"
ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystemTip,Mode=OneWay,Source={x:Static resx:R.Current}}"/>-->
<ui:CommandBarSeparator/>
<ui:CommandBarButton
Command="{Binding ProxySettingsCommand}"
ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxySettings,Mode=OneWay,Source={x:Static resx:R.Current}}"
Label="{ReflectionBinding Path=Res.CommunityFix_ProxySettings,Mode=OneWay,Source={x:Static resx:R.Current}}">
<ui:CommandBarButton.Icon>
<ui:PathIcon Data="{StaticResource SettingsDrawing}"/>
</ui:CommandBarButton.Icon>
</ui:CommandBarButton>
</ui:CommandBar.PrimaryCommands>
<ui:CommandBar.SecondaryCommands>
<ui:CommandBarToggleButton IsChecked="{Binding Source={x:Static ms:ProxySettings.ProgramStartupRunProxy},Path=Value, Mode=TwoWay}"
Label="{ReflectionBinding Path=Res.CommunityFix_AutoRunProxy,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ui:CommandBarToggleButton IsChecked="{Binding Source={x:Static ms:ProxySettings.OnlyEnableProxyScript},Path=Value, Mode=TwoWay}"
Label="{ReflectionBinding Path=Res.CommunityFix_ProxyOnlyOnScript,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ui:CommandBarSeparator/>
<ui:CommandBarButton Icon="Refresh"
Command="{Binding RefreshCommand}"
Label="{ReflectionBinding Path=Res.Refresh,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ui:CommandBarButton
Command="{Binding SetupCertificateCommand}"
Label="{ReflectionBinding Path=Res.CommunityFix_SetupCertificate,Mode=OneWay,Source={x:Static resx:R.Current}}">
<ui:CommandBarButton.Icon>
<ui:PathIcon Data="{StaticResource CertificateDrawing}"/>
</ui:CommandBarButton.Icon>
</ui:CommandBarButton>
<ui:CommandBarButton IsVisible="{x:Static sys:OperatingSystem2.IsMacOS}"
Command="{Binding TrustCerCommand}"
Label="{ReflectionBinding Path=Res.CommunityFix_CertificateTrust,Mode=OneWay,Source={x:Static resx:R.Current}}">
<ui:CommandBarButton.Icon>
<ui:PathIcon Data="{StaticResource CertificateDrawing}"/>
</ui:CommandBarButton.Icon>
</ui:CommandBarButton>
<ui:CommandBarButton
Command="{Binding DeleteCertificateCommand}"
Label="{ReflectionBinding Path=Res.CommunityFix_DeleteCertificate,Mode=OneWay,Source={x:Static resx:R.Current}}">
<ui:CommandBarButton.Icon>
<ui:PathIcon Data="{StaticResource CertificateDrawing}"/>
</ui:CommandBarButton.Icon>
</ui:CommandBarButton>
<ui:CommandBarButton
Command="{Binding OpenCertificateDirCommand}"
Label="{ReflectionBinding Path=Res.CommunityFix_OpenCertificateDir,Mode=OneWay,Source={x:Static resx:R.Current}}">
<ui:CommandBarButton.Icon>
<ui:PathIcon Data="{StaticResource FolderOpenDrawing}"/>
</ui:CommandBarButton.Icon>
</ui:CommandBarButton>
<ui:CommandBarSeparator/>
<ui:CommandBarButton
Command="{Binding EditHostsFileCommand}"
Label="{ReflectionBinding Path=Res.CommunityFix_EditHostsFile,Mode=OneWay,Source={x:Static resx:R.Current}}">
<ui:CommandBarButton.Icon>
<ui:PathIcon Data="{StaticResource DocumentEditDrawing}"/>
</ui:CommandBarButton.Icon>
</ui:CommandBarButton>
</ui:CommandBar.SecondaryCommands>
</ui:CommandBar>
</Border>
<Border Grid.Column="0"
@@ -158,7 +286,7 @@
<StackPanel Orientation="Horizontal">
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_AlreadyProxy,Mode=OneWay,Source={x:Static resx:R.Current}}"
FontSize="26"
Margin="0 0 10 0"
Margin="0 0 5 0"
VerticalAlignment="Center"></TextBlock>
<TextBlock FontSize="26"
Text="{Binding AccelerateTime,Source={x:Static service:ProxyService.Current},StringFormat={}{0:HH:mm:ss}}" VerticalAlignment="Center"></TextBlock>
@@ -97,11 +97,13 @@
<DockPanel>
<TextBlock VerticalAlignment="Center"
Text="{Binding TypeFilterString}"
DockPanel.Dock="Left"
TextTrimming="CharacterEllipsis"/>
<PathIcon VerticalAlignment="Center"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
Data="{StaticResource ChevronDownDrawing}"
Width="16"></PathIcon>
Width="12"></PathIcon>
</DockPanel>
</Button.Content>
<Button.Styles>
@@ -185,7 +187,7 @@
</Button>
<Button Background="Transparent"
Cursor="Hand"
Command="{ReflectionBinding OpenIdleAppWindow}"
Command="{Binding IdleAppCommand}"
ToolTip.Tip="{ReflectionBinding Path=Res.GameList_IdleGamesManger,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Data="{StaticResource TopSpeedDrawing}" />
</Button>
@@ -276,15 +278,19 @@
</MenuItem.Icon>
</MenuItem>
<!--<MenuItem
Header="{ReflectionBinding Path=Res.GameList_EditAppInfo,Mode=OneWay,Source={x:Static resx:R.Current}}"
Command="{ReflectionBinding #u.DataContext.OfflineModeButton_Click}"
CommandParameter="{Binding}" />-->
Header="{ReflectionBinding Path=Res.GameList_EditAppInfo,Mode=OneWay,Source={x:Static resx:R.Current}}"
Command="{ReflectionBinding #u.DataContext.EditAppInfoClick}"
CommandParameter="{Binding}">
<MenuItem.Icon>
<PathIcon Data="{StaticResource EditDrawing}" Width="14"></PathIcon>
</MenuItem.Icon>
</MenuItem>-->
<MenuItem
Header="{ReflectionBinding Path=Res.Achievement_Manage,Mode=OneWay,Source={x:Static resx:R.Current}}"
Command="{ReflectionBinding #u.DataContext.UnlockAchievement_Click}"
CommandParameter="{Binding}" >
<MenuItem.Icon>
<PathIcon Data="{StaticResource TrophyDrawing}" Width="16"></PathIcon>
<PathIcon Data="{StaticResource TrophyDrawing}" Width="14"></PathIcon>
</MenuItem.Icon>
</MenuItem>
<MenuItem
@@ -333,7 +339,7 @@
<PathIcon Data="{StaticResource GlobeSearchDrawing}" Width="14"></PathIcon>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="-"/>
<MenuItem
Header="{ReflectionBinding Path=Res.GameList_HideTheGame,Mode=OneWay,Source={x:Static resx:R.Current}}"
@@ -18,7 +18,7 @@
</Style>
<Style Selector="TextBlock.prompt">
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="{DynamicResource InactiveForegroundBrushKey}" />
<!--<Setter Property="Foreground" Value="{DynamicResource InactiveForegroundBrushKey}" />-->
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="10 0" />
</Style>
@@ -22,7 +22,7 @@
</Style>
<Style Selector="TextBlock.prompt">
<Setter Property="FontSize" Value="12" />
<Setter Property="Foreground" Value="{DynamicResource InactiveForegroundBrushKey}" />
<!--<Setter Property="Foreground" Value="{DynamicResource InactiveForegroundBrushKey}" />-->
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="10 0" />
</Style>
@@ -48,7 +48,8 @@
<RadioButton x:Name="AccentCustom"
Content="{ReflectionBinding Path=Res.Settings_UI_Custom,Mode=OneWay,Source={x:Static resx:R.Current}}"
IsChecked="{ReflectionBinding Source={x:Static ms:UISettings.GetUserThemeAccent},Path=!Value, Mode=OneWay}"/>
<ui:ColorPickerButton IsEnabled="{ReflectionBinding #AccentCustom.IsChecked}"
<ui:ColorPickerButton IsVisible="{ReflectionBinding #AccentCustom.IsChecked}"
IsEnabled="{ReflectionBinding #AccentCustom.IsChecked}"
Color="{ReflectionBinding Source={x:Static ms:UISettings.ThemeAccent},Converter={StaticResource ColorStringToBrush},Path=Value, Mode=TwoWay}"/>
</StackPanel>
</StackPanel>
@@ -88,7 +89,7 @@
SelectedItem="{Binding SelectFont}"
HorizontalAlignment="Stretch"
AutoScrollToSelectedItem="True"
MaxDropDownHeight="400">
MaxDropDownHeight="300">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key,Mode=OneWay}"
@@ -105,7 +106,14 @@
<Separator Classes="Separator"/>
<StackPanel Orientation="Vertical">
<!--<StackPanel Orientation="Vertical">
<DockPanel>
<TextBlock Text="使用动态桌面背景"/>
<ToggleSwitch IsChecked="{ReflectionBinding Source={x:Static ms:UISettings.EnableDesktopBackground},Path=Value, Mode=TwoWay}"/>
</DockPanel>
</StackPanel>-->
<StackPanel Orientation="Vertical" IsEnabled="{ReflectionBinding Source={x:Static ms:UISettings.EnableDesktopBackground},Path=!Value, Mode=OneWay}">
<DockPanel>
<TextBlock Text="{ReflectionBinding Path=Res.Settings_UI_CustomBackgroundImage,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ToggleSwitch IsChecked="{ReflectionBinding Source={x:Static ms:UISettings.EnableCustomBackgroundImage},Path=Value, Mode=TwoWay}"/>
@@ -0,0 +1,144 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Width="600" Height="450"
x:Class="System.Application.UI.Views.Windows.ProxySettingsWindow"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:ui="using:FluentAvalonia.UI.Controls"
Background="Transparent"
ExtendClientAreaTitleBarHeightHint="30"
Title="{Binding Title}"
x:DataType="vm:ProxySettingsWindowViewModel"
x:CompileBindings="True">
<Panel>
<controls:TitleBar DockPanel.Dock="Top"></controls:TitleBar>
<Border Classes="paper"
Background="{DynamicResource ThemeBrushKey}"
Margin="{StaticResource TitleBarAfterMargin}">
<ScrollViewer Padding="10">
<StackPanel Spacing="20">
<StackPanel.Styles>
<Style Selector="Expander">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<Style Selector="DockPanel > Label">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0 0 0 5" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Top"></Setter>
</Style>
<Style Selector="DockPanel > TextBox">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Bottom"></Setter>
</Style>
<Style Selector="DockPanel > TextBlock">
<Setter Property="Margin" Value="0 0 20 0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Left" />
</Style>
<Style Selector="DockPanel > ToggleSwitch">
<Setter Property="Margin" Value="0 0 -12 0" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="OnContent" Value="{x:Null}" />
<Setter Property="OffContent" Value="{x:Null}" />
</Style>
</StackPanel.Styles>
<Expander Header="加速设置" IsExpanded="True">
<StackPanel Spacing="10">
<DockPanel>
<Label Content="本机监听IP地址"></Label>
<TextBox Text="{ReflectionBinding Source={x:Static ms:ProxySettings.SystemProxyIp},Path=Value, Mode=TwoWay}"></TextBox>
</DockPanel>
<DockPanel>
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_AutoRunProxy,Mode=OneWay,Source={x:Static resx:R.Current}}" ></TextBlock>
<ToggleSwitch
IsChecked="{Binding Source={x:Static ms:ProxySettings.ProgramStartupRunProxy},Path=Value, Mode=TwoWay}"/>
</DockPanel>
<DockPanel>
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_ProxyOnlyOnScript,Mode=OneWay,Source={x:Static resx:R.Current}}" ></TextBlock>
<ToggleSwitch
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.OnlyEnableProxyScript},Path=Value, Mode=TwoWay}"/>
</DockPanel>
<!--<DockPanel>
<Label Content="自定义根证书密码"></Label>
<TextBox></TextBox>
</DockPanel>-->
<!--<DockPanel>
<Label Content="自定义根证书" ></Label>
<Button Content="选择证书"/>
</DockPanel>-->
</StackPanel>
</Expander>
<Expander Header="Socks5本地代理" IsExpanded="True">
<StackPanel Spacing="10">
<DockPanel>
<TextBlock Text="启用" ></TextBlock>
<ToggleSwitch
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.Socks5ProxyEnable},Path=Value, Mode=TwoWay}"/>
</DockPanel>
<DockPanel>
<Label Content="监听端口"></Label>
<NumericUpDown Maximum="65535"
Value="{ReflectionBinding Source={x:Static ms:ProxySettings.Socks5ProxyPortId},Path=Value, Mode=TwoWay}"/>
</DockPanel>
</StackPanel>
</Expander>
<Expander Header="二级代理" IsExpanded="True">
<StackPanel Spacing="10">
<DockPanel>
<TextBlock Text="启用" ></TextBlock>
<ToggleSwitch
IsChecked="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentEnable},Path=Value, Mode=TwoWay}"/>
</DockPanel>
<DockPanel>
<Label Content="代理类型"></Label>
<ComboBox HorizontalAlignment="Stretch"
Items="{Binding ProxyTypes}"
SelectedIndex="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentProxyType},Path=Value, Mode=TwoWay}"/>
</DockPanel>
<DockPanel>
<Label Content="地址"></Label>
<TextBox Text="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentIp},Path=Value, Mode=TwoWay}"></TextBox>
</DockPanel>
<DockPanel>
<Label Content="端口" ></Label>
<NumericUpDown Maximum="65535"
Value="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentPortId},Path=Value, Mode=TwoWay}"/>
</DockPanel>
<DockPanel>
<Label Content="用户名" ></Label>
<TextBox Text="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentUserName},Path=Value, Mode=TwoWay}"></TextBox>
</DockPanel>
<DockPanel>
<Label Content="密码" ></Label>
<TextBox Text="{ReflectionBinding Source={x:Static ms:ProxySettings.TwoLevelAgentPassword},Path=Value, Mode=TwoWay}" PasswordChar="*" Classes="revealPasswordButton"></TextBox>
</DockPanel>
</StackPanel>
</Expander>
<!--<Button Content="保存"
Classes="action"
HorizontalContentAlignment="Center"
HorizontalAlignment="Stretch"></Button>-->
</StackPanel>
</ScrollViewer>
</Border>
</Panel>
</Window>
@@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using System.Application.UI.ViewModels;
namespace System.Application.UI.Views.Windows
{
public class ProxySettingsWindow : FluentWindow<ProxySettingsWindowViewModel>
{
public ProxySettingsWindow() : base()
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}
@@ -3,143 +3,16 @@ using Avalonia.Platform;
using Avalonia.ReactiveUI;
using Avalonia.Styling;
using FluentAvalonia.Styling;
using ReactiveUI;
using System;
using System.Application.Models.Settings;
using System.Application.Services;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
// ReSharper disable once CheckNamespace
namespace Avalonia.Controls
{
public class FluentWindow : Window, IStyleable
{
Type IStyleable.StyleKey => typeof(Window);
public FluentWindow(bool isSaveStatus = true)
{
//if (OperatingSystem2.IsWindows)
//{
ExtendClientAreaToDecorationsHint = true;
ExtendClientAreaTitleBarHeightHint = -1;
//}
SystemDecorations = SystemDecorations.Full;
TransparencyLevelHint = WindowTransparencyLevel.AcrylicBlur;
this.GetObservable(WindowStateProperty)
.Subscribe(x =>
{
PseudoClasses.Set(":maximized", x == WindowState.Maximized);
PseudoClasses.Set(":fullscreen", x == WindowState.FullScreen);
});
//this.GetObservable(IsExtendedIntoWindowDecorationsProperty)
// .Subscribe(x =>
// {
// if (!x)
// {
// SystemDecorations = SystemDecorations.Full;
// //TransparencyLevelHint = WindowTransparencyLevel.Blur;
// }
// });
if (isSaveStatus)
{
this.Opened += FluentWindow_Opened;
this.PositionChanged += FluentWindow_PositionChanged;
}
if (!ViewModelBase.IsInDesignMode)
{
if (OperatingSystem2.IsWindows)
{
DI.Get<IDesktopPlatformService>().FixFluentWindowStyleOnWin7(PlatformImpl.Handle.Handle);
}
if (OperatingSystem2.IsWindows10AtLeast)
{
AvaloniaLocator.Current.GetService<FluentAvaloniaTheme>().ForceNativeTitleBarToTheme(this);
}
}
}
private void FluentWindow_PositionChanged(object? sender, PixelPointEventArgs e)
{
if (_isOpenWindow == false)
return;
if (this.DataContext is WindowViewModel vm)
{
vm.SizePosition.X = e.Point.X;
vm.SizePosition.Y = e.Point.Y;
}
}
protected bool _isOpenWindow;
private void FluentWindow_Opened(object? sender, EventArgs e)
{
_isOpenWindow = true;
if (this.DataContext is WindowViewModel vm)
{
if (vm.SizePosition.X > 0 && vm.SizePosition.Y > 0)
{
var point = new PixelPoint(vm.SizePosition.X, vm.SizePosition.Y);
if (Screens.Primary.WorkingArea.Contains(point))
this.Position = point;
}
if (vm.SizePosition.Width > 0
&& Screens.Primary.WorkingArea.Width >= vm.SizePosition.Width)
this.Width = vm.SizePosition.Width;
if (vm.SizePosition.Height > 0
&& Screens.Primary.WorkingArea.Height >= vm.SizePosition.Height)
this.Height = vm.SizePosition.Height;
HandleResized(new Size(this.Width, this.Height), PlatformResizeReason.Application);
this.GetObservable(WidthProperty).Subscribe(v =>
{
vm.SizePosition.Width = v;
});
this.GetObservable(HeightProperty).Subscribe(v =>
{
vm.SizePosition.Height = v;
});
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
if (OperatingSystem2.IsWindows)
{
ExtendClientAreaChromeHints =
ExtendClientAreaChromeHints.PreferSystemChrome;
}
else if (OperatingSystem2.IsMacOS)
{
ExtendClientAreaChromeHints =
ExtendClientAreaChromeHints.PreferSystemChrome;
}
else
{
ExtendClientAreaChromeHints =
ExtendClientAreaChromeHints.SystemChrome;
}
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
if (DataContext is IDisposable disposable) disposable.Dispose();
}
}
public class FluentWindow<TViewModel> : ReactiveWindow<TViewModel>, IStyleable where TViewModel : class
public abstract class FluentWindow<TViewModel> : ReactiveWindow<TViewModel>, IStyleable where TViewModel : class
{
Type IStyleable.StyleKey => typeof(Window);
@@ -170,9 +43,9 @@ namespace Avalonia.Controls
if (isSaveStatus)
{
this.Opened += FluentWindow_Opened;
if (this.CanResize)
this.PositionChanged += FluentWindow_PositionChanged;
Opened += FluentWindow_Opened;
if (CanResize)
PositionChanged += FluentWindow_PositionChanged;
}
if (!ViewModelBase.IsInDesignMode)
@@ -192,7 +65,7 @@ namespace Avalonia.Controls
{
if (_isOpenWindow == false)
return;
if (this.DataContext is WindowViewModel vm)
if (DataContext is WindowViewModel vm)
{
vm.SizePosition.X = e.Point.X;
vm.SizePosition.Y = e.Point.Y;
@@ -203,40 +76,46 @@ namespace Avalonia.Controls
protected virtual void FluentWindow_Opened(object? sender, EventArgs e)
{
_isOpenWindow = true;
if (this.DataContext is WindowViewModel vm)
if (DataContext is WindowViewModel vm)
{
if (vm.SizePosition.X > 0 && vm.SizePosition.Y > 0)
{
var point = new PixelPoint(vm.SizePosition.X, vm.SizePosition.Y);
if (Screens.Primary.WorkingArea.Contains(point))
this.Position = point;
Position = point;
}
if (vm.SizePosition.Width > 0
&& Screens.Primary.WorkingArea.Width >= vm.SizePosition.Width)
this.Width = vm.SizePosition.Width;
Width = vm.SizePosition.Width;
if (vm.SizePosition.Height > 0
&& Screens.Primary.WorkingArea.Height >= vm.SizePosition.Height)
this.Height = vm.SizePosition.Height;
Height = vm.SizePosition.Height;
HandleResized(new Size(this.Width, this.Height), PlatformResizeReason.Application);
HandleResized(new Size(Width, Height), PlatformResizeReason.Application);
this.GetObservable(WidthProperty).Subscribe(v =>
{
vm.SizePosition.Width = v;
});
this.GetObservable(HeightProperty).Subscribe(v =>
{
vm.SizePosition.Height = v;
});
this.WhenAnyValue(x => x.ClientSize)
.Subscribe(x =>
{
vm.SizePosition.Width = x.Width;
vm.SizePosition.Height = x.Height;
});
//this.GetObservable(WidthProperty).Subscribe(v =>
//{
// vm.SizePosition.Width = v;
//});
//this.GetObservable(HeightProperty).Subscribe(v =>
//{
// vm.SizePosition.Height = v;
//});
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
if (OperatingSystem2.IsWindows)
{
ExtendClientAreaChromeHints =
@@ -260,4 +139,12 @@ namespace Avalonia.Controls
if (DataContext is IDisposable disposable) disposable.Dispose();
}
}
public abstract class FluentWindow : FluentWindow<WindowViewModel>
{
public FluentWindow(bool isSaveStatus = true) : base(isSaveStatus)
{
}
}
}
@@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Width="600" Height="450"
Width="400" Height="600"
x:Class="System.Application.UI.Views.Windows.EditAppInfoWindow"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
@@ -15,12 +15,23 @@
Title="{Binding Title}"
x:DataType="vm:EditAppInfoWindowViewModel"
x:CompileBindings="True">
<DockPanel>
<Panel>
<controls:TitleBar DockPanel.Dock="Top"></controls:TitleBar>
<StackPanel>
<Border Classes="paper" Background="{DynamicResource ThemeBrushKey}">
<TextBox></TextBox>
</Border>
</StackPanel>
</DockPanel>
<Border Classes="paper"
Margin="{StaticResource TitleBarAfterMargin}"
Padding="10"
Background="{DynamicResource ThemeBrushKey}">
<Border.Styles>
</Border.Styles>
<ScrollViewer>
<StackPanel>
<DockPanel>
<TextBlock Text="名称"/>
<TextBox Text="test"/>
</DockPanel>
</StackPanel>
</ScrollViewer>
</Border>
</Panel>
</Window>
@@ -3,7 +3,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Width="600" Height="430"
Width="600" Height="480"
x:Class="System.Application.UI.Views.Windows.EncryptionAuthWindow"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
@@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using System.Application.UI.ViewModels;
namespace System.Application.UI.Views.Windows
{
@@ -9,8 +9,8 @@
xmlns:service="clr-namespace:System.Application.Services;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
FontFamily="{Binding Source={x:Static ms:UISettings.FontName},Path=Value, Mode=OneWay,Converter={StaticResource NameToFontFamilyConverter}}"
x:DataType="vm:TaskBarWindowViewModel"
x:CompileBindings="True"
x:Name="taskbarWindow"
@@ -41,7 +41,7 @@
<Style Selector="Button.MenuButton">
<Setter Property="Command" Value="{Binding MenuClickCommand}"></Setter>
<Setter Property="CommandParameter" Value="{ReflectionBinding $self.Content}"></Setter>
<Setter Property="CommandParameter" Value="{ReflectionBinding $self.Tag}"></Setter>
</Style>
</StackPanel.Styles>
@@ -53,7 +53,7 @@
HorizontalAlignment="Center">
</Image>-->
<StackPanel DockPanel.Dock="Right" Spacing="8" VerticalAlignment="Center">
<controls:ScrollingTextBlock Text="{Binding Title}"
<controls:ScrollingTextBlock Text="{x:Static vm:TaskBarWindowViewModel.TitleString}"
Foreground="{DynamicResource HighlightForegroundBrushKey}"
FontSize="16"/>
<TextBlock Text="{Binding Path=Version, StringFormat=v{0}, Mode=OneWay}"
@@ -62,40 +62,83 @@
</DockPanel>
<Separator Classes="Separator"/>
<StackPanel>
<Button Content="{ReflectionBinding Path=Res.CommunityFix,Mode=OneWay,Source={x:Static resx:R.Current}}"
<ItemsRepeater Items="{Binding Tabs}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Vertical" />
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<Button x:Name="menuItem"
Tag="{Binding}"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
CommandParameter="{Binding Id}"
PointerEnter="MenuButton_PointerEnter"
PointerLeave="MenuButton_PointerLeave"
Command="{ReflectionBinding #taskbarWindow.DataContext.MenuClickCommand}">
<Button.Content>
<DockPanel>
<ui:SymbolIcon Symbol="ChevronRight"
IsVisible="{Binding IsTaskBarSubMenu}"
DockPanel.Dock="Right"
VerticalAlignment="Center"/>
<controls:ScrollingTextBlock Text="{Binding Name}"
VerticalAlignment="Center"
DockPanel.Dock="Left"
HorizontalAlignment="Stretch"/>
</DockPanel>
</Button.Content>
<Button.DataTemplates>
<DataTemplate DataType="{x:Type vm:MenuItemSeparator}">
<ui:MenuFlyoutSeparator/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MenuItemViewModel}">
<ui:MenuFlyoutItem Text="{Binding Header}"
ToolTip.Tip="{Binding ToolTip,Mode=OneWay}"
Command="{Binding Command,Mode=OneWay}"
CommandParameter="{Binding CommandParameter,Mode=OneWay}"/>
</DataTemplate>
</Button.DataTemplates>
<FlyoutBase.AttachedFlyout>
<ui:MenuFlyout Placement="RightEdgeAlignedTop"
Items="{Binding MenuItems}"
ShowMode="TransientWithDismissOnPointerMoveAway">
</ui:MenuFlyout>
</FlyoutBase.AttachedFlyout>
</Button>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<!--<Button Content="{ReflectionBinding Path=Res.CommunityFix,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"></Button>
<Button Content="{ReflectionBinding Path=Res.ScriptConfig,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"></Button>
<Button Content="{ReflectionBinding Path=Res.UserFastChange,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"></Button>
Classes="MenuButton"
x:Name="UserChangeMenu">
</Button>
<Button Content="{ReflectionBinding Path=Res.GameList,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"></Button>
<Button Content="{ReflectionBinding Path=Res.LocalAuth,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"
x:Name="LocalMenu">
x:Name="LocalAuthMenu">
<FlyoutBase.AttachedFlyout>
<MenuFlyout Placement="RightEdgeAlignedTop" ShowMode="TransientWithDismissOnPointerMoveAway">
<MenuItem Header="Item 1">
<MenuItem Header="Subitem 1" />
<MenuItem Header="Subitem 2" />
<MenuItem Header="Subitem 3" />
<MenuItem Header="Subitem 4" />
<MenuItem Header="Subitem 5" />
</MenuItem>
<MenuItem Header="Item 2" InputGesture="Ctrl+A" />
<MenuFlyout Placement="LeftEdgeAlignedTop"
ShowMode="TransientWithDismissOnPointerMoveAway">
<MenuItem Header="Item 3" />
<MenuItem Header="Item 4" />
<MenuItem Header="Item 5" />
<MenuItem Header="Item 6" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
</Button>
</Button>-->
</StackPanel>
<Separator Classes="Separator"/>
<StackPanel>
<Button Content="{ReflectionBinding Path=Res.About,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"></Button>
<Button Content="{ReflectionBinding Path=Res.Exit,Mode=OneWay,Source={x:Static resx:R.Current}}" Command="{Binding MenuClickCommand}" CommandParameter="Exit"></Button>
<Button Content="{ReflectionBinding Path=Res.Settings,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"
Tag="{x:Static vm:TaskBarWindowViewModel.SettingsId}"/>
<Button Content="{ReflectionBinding Path=Res.Exit,Mode=OneWay,Source={x:Static resx:R.Current}}"
Classes="MenuButton"
Tag="{x:Static vm:TaskBarWindowViewModel.CommandExit}"></Button>
</StackPanel>
</StackPanel>
</Panel>
@@ -7,6 +7,7 @@ using FluentAvalonia.Styling;
using ReactiveUI;
using System.Application.Services;
using System.Application.UI.ViewModels;
using System.Threading.Tasks;
namespace System.Application.UI.Views.Windows
{
@@ -31,13 +32,19 @@ namespace System.Application.UI.Views.Windows
this.Opened += Window_Opened;
this.LostFocus += Window_LostFocus;
//var localbtn = this.FindControl<Button>("LocalMenu");
//if (localbtn != null)
//var localAuthbtn = this.FindControl<Button>("LocalAuthMenu");
//var userChangebtn = this.FindControl<Button>("UserChangeMenu");
//if (userChangebtn != null)
//{
// localbtn.PointerEnter += MenuButton_PointerEnter;
// userChangebtn.PointerEnter += MenuButton_PointerEnter;
// //localbtn.PointerLeave += MenuButton_PointerLeave;
//}
//if (localAuthbtn != null)
//{
// localAuthbtn.PointerEnter += MenuButton_PointerEnter;
// //localbtn.PointerLeave += MenuButton_PointerLeave;
//}
#if DEBUG
this.AttachDevTools();
#endif
@@ -48,27 +55,30 @@ namespace System.Application.UI.Views.Windows
}
}
private void MenuButton_PointerLeave(object? sender, Avalonia.Input.PointerEventArgs e)
public void MenuButton_PointerLeave(object? sender, Avalonia.Input.PointerEventArgs e)
{
if (sender is Control c)
{
var flyout = FlyoutBase.GetAttachedFlyout(c);
flyout?.Hide();
IsPointerOverSubMenu = false;
}
//if (sender is Control c)
//{
// //var flyout = FlyoutBase.GetAttachedFlyout(c);
// //flyout?.Hide();
// //IsPointerOverSubMenu = false;
//}
}
private void MenuButton_PointerEnter(object? sender, Avalonia.Input.PointerEventArgs e)
public async void MenuButton_PointerEnter(object? sender, Avalonia.Input.PointerEventArgs e)
{
if (sender is Control c && !IsPointerOverSubMenu)
{
if (c.Tag is TabItemViewModel tab && !tab.IsTaskBarSubMenu) return;
var flyout = FlyoutBase.GetAttachedFlyout(c);
if (flyout is not null)
await Task.Delay(500);
if (flyout is not null && c.IsPointerOver && !IsPointerOverSubMenu)
{
flyout.ShowAt(c);
IsPointerOverSubMenu = flyout.IsOpen;
flyout.Closed += (sender, e) => IsPointerOverSubMenu = flyout.IsOpen;
c.Focus();
//c.Focus();
}
}
}
@@ -114,7 +124,10 @@ namespace System.Application.UI.Views.Windows
});
}
DI.Get<ISystemWindowApiService>().SetActiveWindow(new Models.HandleWindow { Handle = this.PlatformImpl.Handle.Handle });
if (OperatingSystem2.IsWindows)
{
DI.Get<ISystemWindowApiService>().SetActiveWindow(new Models.HandleWindow { Handle = this.PlatformImpl.Handle.Handle });
}
}
private void InitializeComponent()
@@ -29,7 +29,8 @@
Watermark="{Binding Placeholder}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Text="{Binding Value}"
Text="{Binding Value}"
MaxLength="{Binding MaxLength}"
PasswordChar="*"
Classes="revealPasswordButton" />
<TextBox x:Name="DescriptionBox"
@@ -76,19 +76,19 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.7" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.7" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.7" />
<!--<PackageReference Include="Avalonia.AvaloniaEdit" Version="0.10.4" />-->
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.7" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.7" />
<!--<PackageReference Include="CefNet.Avalonia" Version="90.6.21124.1851" />-->
<!--<PackageReference Include="LibVLCSharp.Avalonia" Version="3.5.1" />-->
<!--<PackageReference Include="FluentAvaloniaUI" Version="1.1.1" />-->
<PackageReference Include="Avalonia" />
<PackageReference Include="Avalonia.Desktop" />
<PackageReference Include="Avalonia.Controls.DataGrid" />
<!--<PackageReference Include="Avalonia.AvaloniaEdit" />-->
<PackageReference Include="Avalonia.ReactiveUI" />
<PackageReference Include="Avalonia.Xaml.Behaviors" />
<!--<PackageReference Include="CefNet.Avalonia" />-->
<!--<PackageReference Include="LibVLCSharp.Avalonia" />-->
<!--<PackageReference Include="FluentAvaloniaUI" />-->
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.7" />
<PackageReference Include="Avalonia.Diagnostics" />
</ItemGroup>
<ItemGroup>
@@ -104,6 +104,9 @@
</ItemGroup>
<ItemGroup>
<Compile Update="Application\UI\Views\Windows\CommunityProxyPage\ProxySettingsWindow.axaml.cs">
<DependentUpon>ProxySettingsWindow.axaml</DependentUpon>
</Compile>
<Compile Update="Application\UI\Views\Windows\GameListPage\SteamShutdownWindow.axaml.cs">
<DependentUpon>SteamShutdownWindow.axaml</DependentUpon>
</Compile>
@@ -28,32 +28,6 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
/// <summary>
/// 添加托盘图标
/// </summary>
/// <typeparam name="TNotifyIcon"></typeparam>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddNotifyIcon<TNotifyIcon>(this IServiceCollection services) where TNotifyIcon : class, INotifyIcon
{
services.AddSingleton<INotifyIcon<ContextMenu>.IUIFrameworkHelper, INotifyIcon.UIFrameworkHelper>();
services.AddSingleton<TNotifyIcon>();
services.AddSingleton<INotifyIcon>(s => s.GetRequiredService<TNotifyIcon>());
services.AddSingleton<INotifyIcon<ContextMenu>>(s => s.GetRequiredService<TNotifyIcon>());
return services;
}
/// <summary>
/// 添加适用于桌面端的 <see cref="INotificationService"/>
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddNotificationService(this IServiceCollection services)
{
services.AddSingleton<INotificationService, PlatformNotificationServiceImpl>();
return services;
}
public static IServiceCollection AddFontManager(this IServiceCollection services, bool useGdiPlusFirst)
{
services.AddSingleton<IFontManager>(new AvaloniaFontManagerImpl(useGdiPlusFirst));
@@ -0,0 +1,39 @@
using System;
using System.Application.UI;
using System.Linq;
using System.Windows;
using GtkApplication = Gtk.Application;
if (!OperatingSystem.IsLinux()) return;
try
{
var handle = args.FirstOrDefault();
if (string.IsNullOrWhiteSpace(handle)) return;
// https://www.mono-project.com/docs/gui/gtksharp/widgets/notification-icon/
// Initialize GTK#
GtkApplication.Init();
DI.Init(services =>
{
services.AddNotifyIcon();
});
NotifyIconHelper.StartPipeClient(handle);
(var notifyIcon, var menuItemDisposable) = NotifyIconHelper.Init(NotifyIconHelper.GetIcon);
notifyIcon.Click += (_, _) =>
{
NotifyIconHelper.Client.Append(NotifyIconHelper.PipeCore.CommandNotifyIconClick);
};
GtkApplication.Run();
menuItemDisposable?.Dispose();
notifyIcon.Dispose();
NotifyIconHelper.StopPipeClient();
}
catch (Exception e)
{
Console.WriteLine(e);
}
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;LINUX;TRAY_INDEPENDENT_PROGRAM;</DefineConstants>
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
<PublishDir>bin\Release\Publish\linux-arm</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<!-- Linux distributions running on ARM like Raspbian on Raspberry Pi Model 2+ -->
<RuntimeIdentifier>linux-arm</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<AutoreleasePoolSupport>false</AutoreleasePoolSupport>
<DebuggerSupport>false</DebuggerSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseNativeHttpHandler>true</UseNativeHttpHandler>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<PublishReadyToRun>false</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;LINUX;TRAY_INDEPENDENT_PROGRAM;</DefineConstants>
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
<PublishDir>bin\Release\Publish\linux-arm64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<!-- Linux distributions running on ARM64 like Raspbian on Raspberry Pi Model 3+ -->
<RuntimeIdentifier>linux-arm64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<AutoreleasePoolSupport>false</AutoreleasePoolSupport>
<DebuggerSupport>false</DebuggerSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseNativeHttpHandler>true</UseNativeHttpHandler>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<PublishReadyToRun>false</PublishReadyToRun>
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
</PropertyGroup>
</Project>
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DefineConstants>PUBLISH;LINUX;TRAY_INDEPENDENT_PROGRAM;</DefineConstants>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\Publish\linux-x64</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<TargetFramework>net6.0</TargetFramework>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
<AutoreleasePoolSupport>false</AutoreleasePoolSupport>
<DebuggerSupport>false</DebuggerSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseNativeHttpHandler>true</UseNativeHttpHandler>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
<PublishReadyToRun>false</PublishReadyToRun>
</PropertyGroup>
</Project>
@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Application.UI.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SR {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SR() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Application.UI.Properties.SR", typeof(SR).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找 System.Byte[] 类型的本地化资源。
/// </summary>
internal static byte[] Icon {
get {
object obj = ResourceManager.GetObject("Icon", resourceCulture);
return ((byte[])(obj));
}
}
}
}
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Icon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
@@ -0,0 +1,74 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>System.Application.UI</RootNamespace>
<AssemblyName>Steam++_LinuxTrayIcon</AssemblyName>
<DefineConstants>LINUX;TRAY_INDEPENDENT_PROGRAM;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.Version.cs">
<Link>Properties\AssemblyInfo.Version.cs</Link>
</Compile>
<Compile Include="..\ST.Client.Desktop.Avalonia.App\NotifyIconHelper.cs" />
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Windows\TaskBarWindowViewModel.TrayIcon.cs">
<LinkBase>ViewModels</LinkBase>
</Compile>
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Base\TabItemViewModel.IdName.cs">
<LinkBase>ViewModels</LinkBase>
</Compile>
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Base\TabItemViewModel.DisplayName.cs">
<LinkBase>ViewModels</LinkBase>
</Compile>
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\MainWindowViewModel.TabItemsWithFooterTabItems.cs">
<LinkBase>ViewModels</LinkBase>
</Compile>
<EmbeddedResource Include="..\ST.Client.Desktop\UI\Resx\*.resx">
<LinkBase>Resx</LinkBase>
</EmbeddedResource>
<Compile Include="..\ST.Client.Desktop\UI\Resx\AppResources.Designer.cs">
<LinkBase>Resx</LinkBase>
</Compile>
<Compile Include="..\Common.CoreLib\Properties\ThisAssembly.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\Common.CoreLib\Properties\ThisAssembly.Version.cs">
<LinkBase>Properties</LinkBase>
</Compile>
<Compile Include="..\Common.CoreLib\DI.cs">
<LinkBase>Common</LinkBase>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="NotifyIcon.Linux" />
<PackageReference Include="GtkSharp" />
<PackageReference Include="ReactiveUI" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\SR.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>SR.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\SR.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>SR.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>
@@ -0,0 +1,10 @@
namespace System.Application.UI.ViewModels
{
partial class MainWindowViewModel
{
public MainWindowViewModel()
{
FooterTabItems = InitTabItemsWithReturnFooterTabItems();
}
}
}
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace System.Application.UI.ViewModels
{
abstract partial class TabItemViewModel
{
}
}
@@ -0,0 +1,6 @@
namespace System.Application.UI.ViewModels
{
static partial class TaskBarWindowViewModel
{
}
}
+2
View File
@@ -0,0 +1,2 @@
killall Steam++
killall Steam++_LinuxTrayIcon
@@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.Desktop.Linux</AssemblyName>
<DefineConstants>LINUX;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
@@ -16,13 +17,27 @@
<Compile Include="..\ST\Properties\InternalsVisibleTo.cs">
<Link>Properties\InternalsVisibleTo.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Eto.Forms" Version="2.5.11" />
<Compile Include="..\ST.Client.Desktop\ServiceCollectionExtensions.AddGeneralLogging.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ST.Client.Desktop\ST.Client.Desktop.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Steam++.sh">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Exit.sh">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico">
<Link>Steam.ico</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Internals\" />
</ItemGroup>
</Project>

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