mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-26 20:20:14 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0509d2b843 | ||
|
|
8aa450f25f | ||
|
|
81aaa50508 | ||
|
|
927b652c42 | ||
|
|
4de1ac13f0 | ||
|
|
46de667c17 | ||
|
|
9d14dce321 | ||
|
|
ea33fa3444 | ||
|
|
9b980427f6 | ||
|
|
451d707626 | ||
|
|
f483a5dcba | ||
|
|
31c4111495 | ||
|
|
f0a14e332d | ||
|
|
d382d70487 | ||
|
|
c438656378 | ||
|
|
035b1a6421 | ||
|
|
f3db1a23ed | ||
|
|
59096c898c | ||
|
|
4d76decf73 | ||
|
|
c2d95a1833 | ||
|
|
fd6f5ff3ea | ||
|
|
5bd381f553 | ||
|
|
55bad031df | ||
|
|
866ad1a821 | ||
|
|
948016c84f | ||
|
|
9fbe6408ab | ||
|
|
c8ea806360 | ||
|
|
a8b0f9877c | ||
|
|
d82f94f95d | ||
|
|
a40fb84783 | ||
|
|
c9cbf696e4 | ||
|
|
98da730c18 | ||
|
|
cc86913b72 | ||
|
|
ba02250f61 | ||
|
|
451de6ca55 | ||
|
|
691fb360bb | ||
|
|
686e3987f8 | ||
|
|
79871c3bcb | ||
|
|
c1b19b4929 | ||
|
|
c564ea10eb | ||
|
|
d5006da378 | ||
|
|
ab6bfd45b7 | ||
|
|
878e9dbd32 | ||
|
|
bd7f9e76b8 | ||
|
|
fc285cf583 | ||
|
|
3ab0ae46c0 | ||
|
|
4550ff1621 | ||
|
|
1663bd4277 | ||
|
|
8abfc81ba2 | ||
|
|
679afdef1b | ||
|
|
d38588d45c | ||
|
|
42b11ce241 | ||
|
|
c01512bcf6 | ||
|
|
dd89595629 | ||
|
|
94b5539823 | ||
|
|
317baff79c | ||
|
|
f702c3ae62 | ||
|
|
177216a51e | ||
|
|
46b1c01107 | ||
|
|
798355e342 | ||
|
|
ee741d3138 | ||
|
|
e31b668beb | ||
|
|
c00955205c | ||
|
|
5345926c8b | ||
|
|
0987f58fee | ||
|
|
715737bce2 | ||
|
|
d4d6c2fb51 | ||
|
|
44245aa2b7 | ||
|
|
97e6b92ef6 | ||
|
|
445f130272 | ||
|
|
8da01ac3dd | ||
|
|
39fcc4d9a8 | ||
|
|
b4a755a647 | ||
|
|
083189c264 | ||
|
|
676c628b6f | ||
|
|
43ca455e70 | ||
|
|
95e834a188 | ||
|
|
e9d822bb0c | ||
|
|
2ab26f7848 | ||
|
|
d646eacda1 | ||
|
|
fb029f729b | ||
|
|
5ef6663269 | ||
|
|
5c86b53000 | ||
|
|
efb6adbd9b | ||
|
|
209202b5cf | ||
|
|
c0a081e226 |
@@ -1,13 +0,0 @@
|
||||
### 该问题是怎么引起的?
|
||||
|
||||
|
||||
|
||||
### 重现步骤
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
### 相关的Issue
|
||||
|
||||
|
||||
### 原因(目的、解决的问题等)
|
||||
|
||||
|
||||
### 描述(做了什么,变更了什么)
|
||||
|
||||
|
||||
### 测试用例(新增、改动、可能影响的功能)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[submodule "references/Titanium-Web-Proxy"]
|
||||
path = references/Titanium-Web-Proxy
|
||||
url = https://github.com/rmbadmin/Titanium-Web-Proxy.git
|
||||
[submodule "references/MetroRadiance"]
|
||||
path = references/MetroRadiance
|
||||
url = https://github.com/rmbadmin/MetroRadiance.git
|
||||
@@ -1,155 +0,0 @@
|
||||
[
|
||||
{
|
||||
"Index": 1,
|
||||
"Name": "*瑞",
|
||||
"Amount": 5,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "请大佬喝瓶饮料",
|
||||
"PayTime": "2020-12-17 19:41:57"
|
||||
},
|
||||
{
|
||||
"Index": 2,
|
||||
"Name": "**耀",
|
||||
"Amount": 5,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "小小支持一波!",
|
||||
"PayTime": "2020-12-17 20:46:01"
|
||||
},
|
||||
{
|
||||
"Index": 3,
|
||||
"Name": "**皓",
|
||||
"Amount": 1,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "2077掏空了我,等挂卡出来。在。。em",
|
||||
"PayTime": "2020-12-17 22:41:27"
|
||||
},
|
||||
{
|
||||
"Index": 4,
|
||||
"Name": "**宇",
|
||||
"Amount": 1,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "",
|
||||
"PayTime": "2020-12-18 08:39:42"
|
||||
},
|
||||
{
|
||||
"Index": 5,
|
||||
"Name": "*钊",
|
||||
"Amount": 20,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "其乐坛友bzll6538一点心意",
|
||||
"PayTime": "2020-12-19 17:10:44"
|
||||
},
|
||||
{
|
||||
"Index": 6,
|
||||
"Name": "R*n",
|
||||
"Amount": 20,
|
||||
"OrderNumber": "",
|
||||
"PayType": 2,
|
||||
"Remark": "绿豆",
|
||||
"PayTime": "2020-12-17 14:32:00"
|
||||
},
|
||||
{
|
||||
"Index": 7,
|
||||
"Name": "*炜",
|
||||
"Amount": 100,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "其乐坛友Davyheaven",
|
||||
"PayTime": "2020-12-20 12:02:17"
|
||||
},
|
||||
{
|
||||
"Index": 8,
|
||||
"Name": "**智",
|
||||
"Amount": 20,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "派大星",
|
||||
"PayTime": "2020-12-20 12:21:04"
|
||||
},
|
||||
{
|
||||
"Index": 9,
|
||||
"Name": "*森",
|
||||
"Amount": 66,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "区区心意,不成敬意(三个六给不起)",
|
||||
"PayTime": "2020-12-21 23:03:26"
|
||||
},
|
||||
{
|
||||
"Index": 10,
|
||||
"Name": "*珂",
|
||||
"Amount": 50,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "其乐YK93,支持大佬",
|
||||
"PayTime": "2020-12-21 23:18:09"
|
||||
},
|
||||
{
|
||||
"Index": 11,
|
||||
"Name": "**丰",
|
||||
"Amount": 1,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "",
|
||||
"PayTime": "2020-12-22 12:33:46"
|
||||
},
|
||||
{
|
||||
"Index": 12,
|
||||
"Name": "Ruby",
|
||||
"Amount": 77,
|
||||
"OrderNumber": "",
|
||||
"PayType": 2,
|
||||
"Remark": "资瓷一下",
|
||||
"PayTime": "2020-12-24 19:40:25"
|
||||
},
|
||||
{
|
||||
"Index": 13,
|
||||
"Name": "**桐",
|
||||
"Amount": 1,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "",
|
||||
"PayTime": "2020-12-26 09:32:57"
|
||||
},
|
||||
{
|
||||
"Index": 14,
|
||||
"Name": "**珂",
|
||||
"Amount": 5,
|
||||
"OrderNumber": "",
|
||||
"PayType": 1,
|
||||
"Remark": "其乐坛友wjkhj123,小小支持一波",
|
||||
"PayTime": "2020-12-26 13:28:07"
|
||||
},
|
||||
{
|
||||
"Index": 15,
|
||||
"Name": "z.w",
|
||||
"Amount": 10,
|
||||
"OrderNumber": "",
|
||||
"PayType": 2,
|
||||
"Remark": "滋瓷一下",
|
||||
"PayTime": "2020-12-26 15:34:50"
|
||||
},
|
||||
{
|
||||
"Index": 16,
|
||||
"Name": "**林",
|
||||
"Amount": 6,
|
||||
"OrderNumber": "",
|
||||
"PayType": 2,
|
||||
"Remark": "一丶心意,大佬加油!",
|
||||
"PayTime": "2020-12-26 18:25:06"
|
||||
},
|
||||
{
|
||||
"Index": 17,
|
||||
"Name": "**立",
|
||||
"Amount": 1,
|
||||
"OrderNumber": "",
|
||||
"PayType": 2,
|
||||
"Remark": "",
|
||||
"PayTime": "2020-12-26 18:56:57"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<LangVersion>9.0</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="Exists('..\Unicorn.pfx')">
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<DelaySign>false</DelaySign>
|
||||
<AssemblyOriginatorKeyFile>..\Unicorn.pfx</AssemblyOriginatorKeyFile>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
+80
-62
@@ -1,78 +1,78 @@
|
||||
# Steam++ SteamTools
|
||||
<h1 align="center">Steam++ Tools 🧰</h1>
|
||||
|
||||
<div align="center">
|
||||
|
||||
「Steam++」是一个包含多种Steam工具功能的工具箱。
|
||||
「Steam++」is a toolkit that contains a variety of Steam tools, most of which require you to download and install Steam in order to use them.
|
||||
|
||||
此工具的大部分功能都是需要您下载安装Steam才能使用。
|
||||

|
||||
[](https://github.com/rmbadmin/SteamTools/releases/latest)
|
||||
[](LICENSE)
|
||||
[](https://github.com/rmbadmin/SteamTools/stargazers)
|
||||
[](https://github.com/rmbadmin/SteamTools/network/members)
|
||||

|
||||
|
||||
------
|
||||
</div>
|
||||
|
||||
## 核心功能
|
||||
English | [简体中文](./README.md)
|
||||
|
||||
### 1. 反代Steam的社区网页使其能正常访问
|
||||
## ✨ Functions
|
||||
1. Local reverse proxy for Steam's community webpage to enable normal access in **the Chinese Mainland, Mainland of China**
|
||||
2. Quickly switch the Steam account that the current PC has remembered to log into
|
||||
- This feature is to read the local user login records stored under the Steam path to directly display the operation, you can switch between multiple accounts without re-entering passwords and tokens.
|
||||
3. Achievement stat modifications for Steam games
|
||||
- Function reference SteamAchievementManager for secondary development, modified the game list loading and operation ease of use.
|
||||
4. Steam Local Two-Step Authenticator
|
||||
- The function reference [WinAuth](https://github.com/winauth/winauth) is developed to enable you to view your token without launching the mobile version of Steam App, similar function software are [WinAuth](https://github.com/winauth/winauth), [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator).
|
||||
5. Some game tools
|
||||
- Currently there is a forced game borderless windowing, CSGO fix VAC shield.
|
||||
|
||||
功能类似羽翼城大佬的Steam302,使用[Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)开源项目进行本地反代,相比302工具具有更快的启动速度,以及支持简单的脚本注入。
|
||||
<!--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)-->
|
||||
## 🖥 Operating Environment
|
||||
- Windows 10 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)
|
||||
- ~~macOS 10.13 High Sierra Or Higher~~
|
||||
<!--
|
||||
- ~~Alpine Linux 3.11+~~
|
||||
- ~~CentOS 7+~~
|
||||
- ~~Debian 9+~~
|
||||
- ~~Fedora 32+~~
|
||||
- ~~Linux Mint 18+~~
|
||||
- ~~openSUSE 15+~~
|
||||
- ~~Red Hat Enterprise Linux 7+~~
|
||||
- ~~SUSE Enterprise Linux (SLES) 12 SP2+~~
|
||||
- ~~Ubuntu 20.10, 20.04, 18.04, 16.04~~
|
||||
- ~~Android 5.0+~~
|
||||
- ~~iOS 10.0+~~
|
||||
-->
|
||||
|
||||
---
|
||||
### 2. 快速切换当前PC已经记住登陆的Steam账号
|
||||
## 🌎 Roadmap
|
||||
Read what we [milestones](https://github.com/SteamTools-Team/SteamTools/milestones), and feel free to ask questions.
|
||||
|
||||
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。
|
||||
## ⌨️ Development Environment
|
||||
[Visual Studio 2019 Version 16.8 Or Higher](https://visualstudio.microsoft.com/vs/) Or [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/) Or [JetBrains Rider](https://www.jetbrains.com/rider/) Or [Visual Studio Code](https://code.visualstudio.com/)
|
||||
- Workload
|
||||
- Web and Cloud
|
||||
- ASP.NET and Web Development
|
||||
- Desktop and Mobile Applications
|
||||
- .NET Desktop Development
|
||||
- Mobile Development using .Net
|
||||
- Other Toolsets
|
||||
- .NET Core Cross Platform Development
|
||||
- Single Component
|
||||
- GitHub Extension for Visual Studio
|
||||
- [Visual Studio Marketplace](https://marketplace.visualstudio.com/)
|
||||
- [Avalonia for Visual Studio](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
|
||||
- [NUnit VS Templates](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
|
||||
|
||||
---
|
||||
### 3. Steam游戏的成就统计管理功能
|
||||
功能参考[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)进行二次开发,修改了游戏列表的加载和操作易用性。
|
||||
|
||||
---
|
||||
|
||||
### 4. Steam本地两步身份验证器
|
||||
功能参考[WinAuth](https://github.com/winauth/winauth)开发,可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
|
||||
---
|
||||
|
||||
### 5. 一些游戏工具
|
||||
目前已有强制游戏无边框窗口化,CSGO修复VAC屏蔽。
|
||||
这一块是随缘做一些我经常用或者闲着没事捣鼓的功能。
|
||||
|
||||
---
|
||||
|
||||
## 预计后续添加的功能
|
||||
|
||||
### Steam自动挂卡
|
||||
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内登录Steam即可直接获取徽章卡片信息并开始挂卡。
|
||||
|
||||
### Steam皮肤设计器
|
||||
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
|
||||
|
||||
### 插件形式加载运行ASF
|
||||
以插件形式支持ASF在工具内运行并增强ASF在Windows Desktop环境下的使用。
|
||||
|
||||
### Steam自定义封面管理
|
||||
增强Steam自定义封面的管理以及从[SteamGridDB](https://www.steamgriddb.com/)快速匹配下载应用封面。
|
||||
|
||||
### 更多其它游戏平台功能
|
||||
|
||||
|
||||
### 更多非作弊游戏功能
|
||||
|
||||
---
|
||||
|
||||
## 运行环境
|
||||
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
> [GPL-3.0 License](LICENSE.txt)
|
||||
> 根据GPLv3许可发布的开源/免费软件。
|
||||
|
||||
---
|
||||
|
||||
## 感谢以下开源项目
|
||||
## 📄 Thanks to the following Open Source Projects
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
* [MetroRadiance](https://github.com/Grabacr07/MetroRadiance)
|
||||
* [MetroTrilithon](https://github.com/Grabacr07/MetroTrilithon)
|
||||
* [Livet](https://github.com/runceel/Livet)
|
||||
* [StatefulModel](https://github.com/Grabacr07/MetroTrilithonhttps://github.com/ugaya40/StatefulModel)
|
||||
* [StatefulModel](https://github.com/ugaya40/StatefulModel)
|
||||
* [Hardcodet.NotifyIcon](https://github.com/HavenDV/Hardcodet.NotifyIcon.Wpf.NetCore)
|
||||
* [System.Reactive](https://github.com/dotnet/reactive)
|
||||
* [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)
|
||||
@@ -82,4 +82,22 @@
|
||||
* [SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)
|
||||
* [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm)
|
||||
* [WinAuth](https://github.com/winauth/winauth)
|
||||
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
|
||||
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
|
||||
* [Gameloop.Vdf](https://github.com/shravan2x/Gameloop.Vdf)
|
||||
* [Costura.Fody](https://github.com/Fody/Costura)
|
||||
* [MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp)
|
||||
* [Nito.Comparers](https://github.com/StephenCleary/Comparers)
|
||||
* [Crc32.NET](https://github.com/force-net/Crc32.NET)
|
||||
* [gfoidl.Base64](https://github.com/gfoidl/Base64)
|
||||
* [sqlite-net-pcl](https://github.com/praeclarum/sqlite-net)
|
||||
* [Polly](https://github.com/App-vNext/Polly)
|
||||
* [NLog](https://github.com/nlog/NLog)
|
||||
* [NUnit](https://github.com/nunit/nunit)
|
||||
* [ReactiveUI](https://github.com/reactiveui/reactiveui)
|
||||
* [MessageBox.Avalonia](https://github.com/AvaloniaUtils/MessageBox.Avalonia)
|
||||
* [AvaloniaUI](https://github.com/AvaloniaUI/Avalonia)
|
||||
* [EntityFrameworkCore](https://github.com/dotnet/efcore)
|
||||
* [ASP.NET Core](https://github.com/dotnet/aspnetcore)
|
||||
* [Xamarin.Essentials](https://github.com/xamarin/essentials)
|
||||
* [.NET Extensions](https://github.com/dotnet/extensions)
|
||||
* [.NET Runtime](https://github.com/dotnet/runtime)
|
||||
|
||||
@@ -1,80 +1,88 @@
|
||||
# Steam++工具箱
|
||||
<h1 align="center">Steam++ 工具箱 🧰</h1>
|
||||
|
||||
「Steam++」是一个包含多种Steam工具功能的工具箱。
|
||||
<div align="center">
|
||||
|
||||
此工具的大部分功能都是需要您下载安装Steam才能使用。
|
||||
「Steam++」是一个包含多种Steam工具功能的工具箱,此工具的大部分功能都是需要您下载安装Steam才能使用。
|
||||
|
||||
------
|
||||

|
||||
[](https://github.com/rmbadmin/SteamTools/releases/latest)
|
||||
[](LICENSE)
|
||||
[](https://github.com/rmbadmin/SteamTools/stargazers)
|
||||
[](https://github.com/rmbadmin/SteamTools/network/members)
|
||||

|
||||
|
||||
## 核心功能
|
||||
</div>
|
||||
|
||||
### 1. 反代Steam的社区网页使其能正常访问
|
||||
<div align="center"><img src="./resources/screenshots.jpg" /></div>
|
||||
|
||||
功能类似羽翼城大佬的Steam302,使用[Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)开源项目进行本地反代,相比302工具具有更快的启动速度,以及支持简单的脚本注入。
|
||||
[English](./README.en.md) | 简体中文
|
||||
|
||||
---
|
||||
### 2. 快速切换当前PC已经记住登陆的Steam账号
|
||||
## ✨ 功能
|
||||
1. 反代 Steam 的社区网页使其能正常访问
|
||||
- 功能类似羽翼城大佬的 [steamcommunity_302](https://www.dogfight360.com/blog/686/)
|
||||
- 使用 [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy) 开源项目进行本地反代,使国内用户可以正常访问steam社区页
|
||||
- 相比 **302工具** 具有更快的启动速度,以及支持简单的脚本注入(还顺便支持了Pixiv、Discord、Twitch等网站的反代支持)
|
||||
2. 快速切换当前设备已记住登陆的 Steam 账号
|
||||
- 该功能是读取 Steam 路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌
|
||||
3. Steam游戏的成就统计管理功能
|
||||
- 功能参考 [SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager) 进行二次开发,修改了游戏列表的加载和操作易用性
|
||||
4. Steam本地两步身份验证器
|
||||
- 功能参考 [WinAuth](https://github.com/winauth/winauth) 开发,可以使您不用启动移动版 Steam App 也能查看您的令牌
|
||||
- 本地令牌交易市场报价确认
|
||||
- 功能类似的软件例如:
|
||||
- [WinAuth](https://github.com/winauth/winauth)
|
||||
- [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
|
||||
5. 其他游戏工具
|
||||
- 目前已有强制游戏无边框窗口化,CSGO 修复 VAC 屏蔽
|
||||
|
||||
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。
|
||||
<!--发布配置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)-->
|
||||
## 🖥 系统要求
|
||||
- Windows 10 1607+
|
||||
- Windows 8.1 / Windows Server 2012 R2
|
||||
- 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)
|
||||
- ~~macOS 10.13 High Sierra 或更高版本~~
|
||||
<!--
|
||||
- ~~Alpine Linux 3.11+~~
|
||||
- ~~CentOS 7+~~
|
||||
- ~~Debian 9+~~
|
||||
- ~~Fedora 32+~~
|
||||
- ~~Linux Mint 18+~~
|
||||
- ~~openSUSE 15+~~
|
||||
- ~~Red Hat Enterprise Linux 7+~~
|
||||
- ~~SUSE Enterprise Linux (SLES) 12 SP2+~~
|
||||
- ~~Ubuntu 20.10, 20.04, 18.04, 16.04~~
|
||||
- ~~Android 5.0+~~
|
||||
- ~~iOS 10.0+~~
|
||||
-->
|
||||
|
||||
---
|
||||
### 3. Steam游戏的成就统计管理功能
|
||||
功能参考[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)进行二次开发,修改了游戏列表的加载和操作易用性。
|
||||
## 🌎 路线图
|
||||
查看这个 [milestones](https://github.com/SteamTools-Team/SteamTools/milestones) 来了解我们下一步的开发计划,并随时提出问题。
|
||||
|
||||
---
|
||||
## ⌨️ 开发环境
|
||||
[Visual Studio 2019 版本 16.8 或更高版本](https://visualstudio.microsoft.com/zh-hans/vs/) 或 [Visual Studio for Mac](https://visualstudio.microsoft.com/zh-hans/vs/mac/) 或 [JetBrains Rider](https://www.jetbrains.com/rider/) 或 [Visual Studio Code](https://code.visualstudio.com/)
|
||||
- 工作负载
|
||||
- Web 和云
|
||||
- ASP.NET 和 Web 开发
|
||||
- 桌面应用和移动应用
|
||||
- .NET 桌面开发
|
||||
- 使用 .NET 的移动开发
|
||||
- 其他工具集
|
||||
- .NET Core 跨平台开发
|
||||
- 单个组件
|
||||
- GitHub Extension for Visual Studio
|
||||
- [Visual Studio Marketplace](https://marketplace.visualstudio.com/)
|
||||
- [Avalonia for Visual Studio](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
|
||||
- [NUnit VS Templates](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
|
||||
|
||||
### 4. Steam本地两步身份验证器
|
||||
功能参考[WinAuth](https://github.com/winauth/winauth)开发,可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
|
||||
|
||||
---
|
||||
|
||||
### 5. 一些游戏工具
|
||||
目前已有强制游戏无边框窗口化,CSGO修复VAC屏蔽。
|
||||
这一块是随缘做一些我经常用或者闲着没事捣鼓的功能。
|
||||
|
||||
---
|
||||
|
||||
## 预计后续添加的功能
|
||||
|
||||
### Steam自动挂卡
|
||||
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内无需登录Steam帐户即可直接获取徽章卡片信息并开始挂卡。
|
||||
|
||||
### Steam皮肤设计器
|
||||
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
|
||||
|
||||
### 插件形式加载运行ASF
|
||||
以插件形式支持ASF在工具内运行并增强ASF在Windows Desktop环境下的使用。
|
||||
|
||||
### Steam自定义封面管理
|
||||
增强Steam自定义封面的管理以及从[SteamGridDB](https://www.steamgriddb.com/)快速匹配下载应用封面。
|
||||
|
||||
### 更多其它游戏平台功能
|
||||
|
||||
|
||||
### 更多非作弊游戏功能
|
||||
|
||||
---
|
||||
|
||||
## 运行环境
|
||||
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
|
||||
> 缺失的程序集为我自己修改后的项目
|
||||
* [Titanium-Web-Proxy](https://github.com/rmbadmin/Titanium-Web-Proxy)
|
||||
* [MetroRadiance](https://github.com/rmbadmin/MetroRadiance)
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
> [GPL-3.0 License](LICENSE.txt)
|
||||
> 根据GPLv3许可发布的开源/免费软件。
|
||||
|
||||
---
|
||||
|
||||
## 感谢以下开源项目
|
||||
## 📄 感谢以下开源项目
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
* [MetroRadiance](https://github.com/Grabacr07/MetroRadiance)
|
||||
* [MetroTrilithon](https://github.com/Grabacr07/MetroTrilithon)
|
||||
* [Livet](https://github.com/runceel/Livet)
|
||||
* [StatefulModel](https://github.com/Grabacr07/MetroTrilithonhttps://github.com/ugaya40/StatefulModel)
|
||||
* [StatefulModel](https://github.com/ugaya40/StatefulModel)
|
||||
* [Hardcodet.NotifyIcon](https://github.com/HavenDV/Hardcodet.NotifyIcon.Wpf.NetCore)
|
||||
* [System.Reactive](https://github.com/dotnet/reactive)
|
||||
* [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)
|
||||
@@ -86,4 +94,20 @@
|
||||
* [WinAuth](https://github.com/winauth/winauth)
|
||||
* [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
|
||||
* [Gameloop.Vdf](https://github.com/shravan2x/Gameloop.Vdf)
|
||||
* [Costura.Fody](https://github.com/Fody/Costura)
|
||||
* [Costura.Fody](https://github.com/Fody/Costura)
|
||||
* [MessagePack-CSharp](https://github.com/neuecc/MessagePack-CSharp)
|
||||
* [Nito.Comparers](https://github.com/StephenCleary/Comparers)
|
||||
* [Crc32.NET](https://github.com/force-net/Crc32.NET)
|
||||
* [gfoidl.Base64](https://github.com/gfoidl/Base64)
|
||||
* [sqlite-net-pcl](https://github.com/praeclarum/sqlite-net)
|
||||
* [Polly](https://github.com/App-vNext/Polly)
|
||||
* [NLog](https://github.com/nlog/NLog)
|
||||
* [NUnit](https://github.com/nunit/nunit)
|
||||
* [ReactiveUI](https://github.com/reactiveui/reactiveui)
|
||||
* [MessageBox.Avalonia](https://github.com/AvaloniaUtils/MessageBox.Avalonia)
|
||||
* [AvaloniaUI](https://github.com/AvaloniaUI/Avalonia)
|
||||
* [EntityFrameworkCore](https://github.com/dotnet/efcore)
|
||||
* [ASP.NET Core](https://github.com/dotnet/aspnetcore)
|
||||
* [Xamarin.Essentials](https://github.com/xamarin/essentials)
|
||||
* [.NET Extensions](https://github.com/dotnet/extensions)
|
||||
* [.NET Runtime](https://github.com/dotnet/runtime)
|
||||
|
||||
@@ -1,880 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Colin Mackie.
|
||||
* This software is distributed under the terms of the GNU General Public License.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Cache;
|
||||
using System.Security.Cryptography;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using System.Xml.XPath;
|
||||
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Engines;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Paddings;
|
||||
using Org.BouncyCastle.Crypto.Digests;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
#if NUNIT
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
#if NETCF
|
||||
using OpenNETCF.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
namespace WinAuth
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that implements Steam's SteamGuadrd version of the RFC6238 Authenticator
|
||||
/// </summary>
|
||||
public class SteamAuthenticator : Authenticator
|
||||
{
|
||||
/// <summary>
|
||||
/// Number of characters in code
|
||||
/// </summary>
|
||||
private const int CODE_DIGITS = 5;
|
||||
|
||||
/// <summary>
|
||||
/// Number of minutes to ignore syncing if network error
|
||||
/// </summary>
|
||||
private const int SYNC_ERROR_MINUTES = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Number of attempts to activate
|
||||
/// </summary>
|
||||
private const int ENROLL_ACTIVATE_RETRIES = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Incorrect activation code
|
||||
/// </summary>
|
||||
private const int INVALID_ACTIVATION_CODE = 89;
|
||||
|
||||
/// <summary>
|
||||
/// Time for http request when calling Sync in ms
|
||||
/// </summary>
|
||||
private const int SYNC_TIMEOUT = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// Steam issuer for KeyUri
|
||||
/// </summary>
|
||||
private const string STEAM_ISSUER = "Steam";
|
||||
|
||||
/// <summary>
|
||||
/// URLs for all mobile services
|
||||
/// </summary>
|
||||
private static string COMMUNITY_BASE = "https://steamcommunity.com";
|
||||
private static string WEBAPI_BASE = "https://api.steampowered.com";
|
||||
private static string SYNC_URL = "https://api.steampowered.com:443/ITwoFactorService/QueryTime/v0001";
|
||||
|
||||
/// <summary>
|
||||
/// Character set for authenticator code
|
||||
/// </summary>
|
||||
private static char[] STEAMCHARS = new char[] {
|
||||
'2', '3', '4', '5', '6', '7', '8', '9', 'B', 'C',
|
||||
'D', 'F', 'G', 'H', 'J', 'K', 'M', 'N', 'P', 'Q',
|
||||
'R', 'T', 'V', 'W', 'X', 'Y'};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Enrolling state
|
||||
/// </summary>
|
||||
public class EnrollState
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string Password { get; set; }
|
||||
public string CaptchaId { get; set; }
|
||||
public string CaptchaUrl { get; set; }
|
||||
public string CaptchaText { get; set; }
|
||||
public string EmailDomain { get; set; }
|
||||
public string EmailAuthText { get; set; }
|
||||
public string ActivationCode { get; set; }
|
||||
public CookieContainer Cookies { get; set; }
|
||||
|
||||
public string SteamId { get; set; }
|
||||
public string OAuthToken { get; set; }
|
||||
|
||||
public bool RequiresLogin { get; set; }
|
||||
public bool RequiresCaptcha { get; set; }
|
||||
public bool Requires2FA { get; set; }
|
||||
public bool RequiresEmailAuth { get; set; }
|
||||
public bool RequiresActivation { get; set; }
|
||||
|
||||
public string RevocationCode { get; set; }
|
||||
public string SecretKey { get; set; }
|
||||
public bool Success { get; set; }
|
||||
|
||||
public string Error { get; set; }
|
||||
}
|
||||
|
||||
#region Authenticator data
|
||||
|
||||
/// <summary>
|
||||
/// Time of last Sync error
|
||||
/// </summary>
|
||||
private static DateTime _lastSyncError = DateTime.MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// Returned serial number of authenticator
|
||||
/// </summary>
|
||||
public string Serial { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Random device ID we created and registered
|
||||
/// </summary>
|
||||
public string DeviceId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// JSON steam data
|
||||
/// </summary>
|
||||
public string SteamData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// JSON session data
|
||||
/// </summary>
|
||||
public string SessionData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string PollData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Current Steam client instance
|
||||
/// </summary>
|
||||
public SteamClient Client { get; protected set; }
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Expanding offsets to retry when creating first code
|
||||
/// </summary>
|
||||
private int[] ENROLL_OFFSETS = new int[] { 0, -30, 30, -60, 60, -90, 90, -120, 120};
|
||||
|
||||
/// <summary>
|
||||
/// Create a new Authenticator object
|
||||
/// </summary>
|
||||
public SteamAuthenticator()
|
||||
: base(CODE_DIGITS)
|
||||
{
|
||||
Issuer = STEAM_ISSUER;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get/set the combined secret data value
|
||||
/// </summary>
|
||||
public override string SecretData
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.Client != null && this.Client.Session != null)
|
||||
{
|
||||
this.SessionData = this.Client.Session.ToString();
|
||||
}
|
||||
|
||||
//if (Logger != null)
|
||||
//{
|
||||
// Logger.Debug("Get Steam data: {0}, Session:{1}", (SteamData ?? string.Empty).Replace("\n"," ").Replace("\r",""), (SessionData ?? string.Empty).Replace("\n", " ").Replace("\r", ""));
|
||||
//}
|
||||
|
||||
// this is the key | serial | deviceid
|
||||
return base.SecretData
|
||||
+ "|" + Authenticator.ByteArrayToString(Encoding.UTF8.GetBytes(Serial))
|
||||
+ "|" + Authenticator.ByteArrayToString(Encoding.UTF8.GetBytes(DeviceId))
|
||||
+ "|" + Authenticator.ByteArrayToString(Encoding.UTF8.GetBytes(SteamData))
|
||||
+ "|" + (string.IsNullOrEmpty(SessionData) == false ? Authenticator.ByteArrayToString(Encoding.UTF8.GetBytes(SessionData)) : string.Empty);
|
||||
}
|
||||
set
|
||||
{
|
||||
// extract key + serial + deviceid
|
||||
if (string.IsNullOrEmpty(value) == false)
|
||||
{
|
||||
string[] parts = value.Split('|');
|
||||
base.SecretData = value;
|
||||
Serial = (parts.Length > 1 ? Encoding.UTF8.GetString(Authenticator.StringToByteArray(parts[1])) : null);
|
||||
DeviceId = (parts.Length > 2 ? Encoding.UTF8.GetString(Authenticator.StringToByteArray(parts[2])) : null);
|
||||
SteamData = (parts.Length > 3 ? Encoding.UTF8.GetString(Authenticator.StringToByteArray(parts[3])) : string.Empty);
|
||||
|
||||
if (string.IsNullOrEmpty(SteamData) == false && SteamData[0] != '{')
|
||||
{
|
||||
// convert old recovation code into SteamData json
|
||||
SteamData = "{\"revocation_code\":\"" + SteamData + "\"}";
|
||||
}
|
||||
string session = (parts.Length > 4 ? Encoding.UTF8.GetString(Authenticator.StringToByteArray(parts[4])) : null);
|
||||
|
||||
//if (Logger != null)
|
||||
//{
|
||||
// Logger.Debug("Set Steam data: {0}, Session:{1}", (SteamData ?? string.Empty).Replace("\n", " ").Replace("\r", ""), (SessionData ?? string.Empty).Replace("\n", " ").Replace("\r", ""));
|
||||
//}
|
||||
|
||||
if (string.IsNullOrEmpty(session) == false)
|
||||
{
|
||||
SessionData = session;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SecretKey = null;
|
||||
Serial = null;
|
||||
DeviceId = null;
|
||||
SteamData = null;
|
||||
SessionData = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get (or create) the current Steam client for this Authenticator
|
||||
/// </summary>
|
||||
/// <returns>current or new SteamClient</returns>
|
||||
public SteamClient GetClient()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
if (this.Client == null)
|
||||
{
|
||||
this.Client = new SteamClient(this, this.SessionData);
|
||||
}
|
||||
|
||||
return this.Client;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a request to the Steam WebAPI service
|
||||
/// </summary>
|
||||
/// <param name="url">API url</param>
|
||||
/// <param name="method">GET or POST</param>
|
||||
/// <param name="data">Name-data pairs</param>
|
||||
/// <param name="cookies">current cookie container</param>
|
||||
/// <returns>response body</returns>
|
||||
private string Request(string url, string method, NameValueCollection data = null, CookieContainer cookies = null, NameValueCollection headers = null, int timeout = 0)
|
||||
{
|
||||
// create form-encoded data for query or body
|
||||
string query = (data == null ? string.Empty : string.Join("&", Array.ConvertAll(data.AllKeys, key => String.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(data[key])))));
|
||||
if (string.Compare(method, "GET", true) == 0)
|
||||
{
|
||||
url += (url.IndexOf("?") == -1 ? "?" : "&") + query;
|
||||
}
|
||||
|
||||
// call the server
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.Method = method;
|
||||
request.Accept = "text/javascript, text/html, application/xml, text/xml, */*";
|
||||
request.ServicePoint.Expect100Continue = false;
|
||||
request.UserAgent = "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Google Nexus 4 - 4.1.1 - API 16 - 768x1280 Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30";
|
||||
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
|
||||
request.Referer = COMMUNITY_BASE; // + "/mobilelogin?oauth_client_id=DE45CD61&oauth_scope=read_profile%20write_profile%20read_client%20write_client";
|
||||
if (headers != null)
|
||||
{
|
||||
request.Headers.Add(headers);
|
||||
}
|
||||
if (cookies != null)
|
||||
{
|
||||
request.CookieContainer = cookies;
|
||||
}
|
||||
if (timeout != 0)
|
||||
{
|
||||
request.Timeout = timeout;
|
||||
}
|
||||
|
||||
if (string.Compare(method, "POST", true) == 0)
|
||||
{
|
||||
request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
|
||||
request.ContentLength = query.Length;
|
||||
|
||||
StreamWriter requestStream = new StreamWriter(request.GetRequestStream());
|
||||
requestStream.Write(query);
|
||||
requestStream.Close();
|
||||
}
|
||||
|
||||
try {
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
LogRequest(method, url, cookies, data, response.StatusCode.ToString() + " " + response.StatusDescription);
|
||||
|
||||
// OK?
|
||||
if (response.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new InvalidRequestException(string.Format("{0}: {1}", (int)response.StatusCode, response.StatusDescription));
|
||||
}
|
||||
|
||||
// load the response
|
||||
using (StreamReader responseStream = new StreamReader(response.GetResponseStream()))
|
||||
{
|
||||
string responseData = responseStream.ReadToEnd();
|
||||
LogRequest(method, url, cookies, data, responseData);
|
||||
return responseData;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogException(method, url, cookies, data, ex);
|
||||
|
||||
if (ex is WebException && ((WebException)ex).Response != null && ((HttpWebResponse)((WebException)ex).Response).StatusCode == HttpStatusCode.Forbidden)
|
||||
{
|
||||
throw new UnauthorisedRequestException(ex);
|
||||
}
|
||||
|
||||
throw new InvalidRequestException(ex.Message, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enroll the authenticator with the server
|
||||
/// </summary>
|
||||
public bool Enroll(EnrollState state)
|
||||
{
|
||||
// clear error
|
||||
state.Error = null;
|
||||
|
||||
try
|
||||
{
|
||||
var data = new NameValueCollection();
|
||||
var cookies = state.Cookies = state.Cookies ?? new CookieContainer();
|
||||
string response;
|
||||
|
||||
if (string.IsNullOrEmpty(state.OAuthToken) == true)
|
||||
{
|
||||
// get session
|
||||
if (cookies.Count == 0)
|
||||
{
|
||||
cookies.Add(new Uri(COMMUNITY_BASE + "/"), new Cookie("mobileClientVersion", "3067969+%282.1.3%29"));
|
||||
cookies.Add(new Uri(COMMUNITY_BASE + "/"), new Cookie("mobileClient", "android"));
|
||||
cookies.Add(new Uri(COMMUNITY_BASE + "/"), new Cookie("steamid", ""));
|
||||
cookies.Add(new Uri(COMMUNITY_BASE + "/"), new Cookie("steamLogin", ""));
|
||||
cookies.Add(new Uri(COMMUNITY_BASE + "/"), new Cookie("Steam_Language", "english"));
|
||||
cookies.Add(new Uri(COMMUNITY_BASE + "/"), new Cookie("dob", ""));
|
||||
|
||||
NameValueCollection headers = new NameValueCollection();
|
||||
headers.Add("X-Requested-With", "com.valvesoftware.android.steam.community");
|
||||
|
||||
response = Request("https://steamcommunity.com/mobilelogin?oauth_client_id=DE45CD61&oauth_scope=read_profile%20write_profile%20read_client%20write_client", "GET", null, cookies, headers);
|
||||
}
|
||||
|
||||
// Steam strips any non-ascii chars from username and password
|
||||
state.Username = Regex.Replace(state.Username, @"[^\u0000-\u007F]", string.Empty);
|
||||
state.Password = Regex.Replace(state.Password, @"[^\u0000-\u007F]", string.Empty);
|
||||
|
||||
// get the user's RSA key
|
||||
data.Add("username", state.Username);
|
||||
response = Request(COMMUNITY_BASE + "/mobilelogin/getrsakey", "POST", data, cookies);
|
||||
var rsaresponse = JObject.Parse(response);
|
||||
if (rsaresponse.SelectToken("success").Value<bool>() != true)
|
||||
{
|
||||
throw new InvalidEnrollResponseException("Cannot get steam information for user: " + state.Username);
|
||||
}
|
||||
|
||||
// encrypt password with RSA key
|
||||
RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
|
||||
byte[] encryptedPassword;
|
||||
using (var rsa = new RSACryptoServiceProvider())
|
||||
{
|
||||
var passwordBytes = Encoding.ASCII.GetBytes(state.Password);
|
||||
var p = rsa.ExportParameters(false);
|
||||
p.Exponent = Authenticator.StringToByteArray(rsaresponse.SelectToken("publickey_exp").Value<string>());
|
||||
p.Modulus = Authenticator.StringToByteArray(rsaresponse.SelectToken("publickey_mod").Value<string>());
|
||||
rsa.ImportParameters(p);
|
||||
encryptedPassword = rsa.Encrypt(passwordBytes, false);
|
||||
}
|
||||
|
||||
// login request
|
||||
data = new NameValueCollection();
|
||||
data.Add("password", Convert.ToBase64String(encryptedPassword));
|
||||
data.Add("username", state.Username);
|
||||
data.Add("twofactorcode", "");
|
||||
data.Add("emailauth", (state.EmailAuthText != null ? state.EmailAuthText : string.Empty));
|
||||
data.Add("loginfriendlyname", "#login_emailauth_friendlyname_mobile");
|
||||
data.Add("captchagid", (state.CaptchaId != null ? state.CaptchaId : "-1"));
|
||||
data.Add("captcha_text", (state.CaptchaText != null ? state.CaptchaText : "enter above characters"));
|
||||
data.Add("emailsteamid", (state.EmailAuthText != null ? state.SteamId ?? string.Empty : string.Empty));
|
||||
data.Add("rsatimestamp", rsaresponse.SelectToken("timestamp").Value<string>());
|
||||
data.Add("remember_login", "false");
|
||||
data.Add("oauth_client_id", "DE45CD61");
|
||||
data.Add("oauth_scope", "read_profile write_profile read_client write_client");
|
||||
data.Add("donotache", new DateTime().ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds.ToString());
|
||||
response = Request(COMMUNITY_BASE + "/mobilelogin/dologin/", "POST", data, cookies);
|
||||
Dictionary<string, object> loginresponse = JsonConvert.DeserializeObject<Dictionary<string, object>>(response);
|
||||
|
||||
if (loginresponse.ContainsKey("emailsteamid") == true)
|
||||
{
|
||||
state.SteamId = loginresponse["emailsteamid"] as string;
|
||||
}
|
||||
|
||||
// require captcha
|
||||
if (loginresponse.ContainsKey("captcha_needed") == true && (bool)loginresponse["captcha_needed"] == true)
|
||||
{
|
||||
state.RequiresCaptcha = true;
|
||||
state.CaptchaId = (string)loginresponse["captcha_gid"];
|
||||
state.CaptchaUrl = COMMUNITY_BASE + "/public/captcha.php?gid=" + state.CaptchaId;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.RequiresCaptcha = false;
|
||||
state.CaptchaId = null;
|
||||
state.CaptchaUrl = null;
|
||||
state.CaptchaText = null;
|
||||
}
|
||||
|
||||
// require email auth
|
||||
if (loginresponse.ContainsKey("emailauth_needed") == true && (bool)loginresponse["emailauth_needed"] == true)
|
||||
{
|
||||
if (loginresponse.ContainsKey("emaildomain") == true)
|
||||
{
|
||||
var emaildomain = (string)loginresponse["emaildomain"];
|
||||
if (string.IsNullOrEmpty(emaildomain) == false)
|
||||
{
|
||||
state.EmailDomain = emaildomain;
|
||||
}
|
||||
}
|
||||
state.RequiresEmailAuth = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.EmailDomain = null;
|
||||
state.RequiresEmailAuth = false;
|
||||
}
|
||||
|
||||
// require email auth
|
||||
if (loginresponse.ContainsKey("requires_twofactor") == true && (bool)loginresponse["requires_twofactor"] == true)
|
||||
{
|
||||
state.Requires2FA = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
state.Requires2FA = false;
|
||||
}
|
||||
|
||||
// if we didn't login, return the result
|
||||
if (loginresponse.ContainsKey("login_complete") == false || (bool)loginresponse["login_complete"] == false || loginresponse.ContainsKey("oauth") == false)
|
||||
{
|
||||
if (loginresponse.ContainsKey("oauth") == false)
|
||||
{
|
||||
state.Error = "Invalid response from Steam (No OAuth token)";
|
||||
}
|
||||
if (loginresponse.ContainsKey("message") == true)
|
||||
{
|
||||
state.Error = (string)loginresponse["message"];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the OAuth token - is stringified json
|
||||
string oauth = (string)loginresponse["oauth"];
|
||||
var oauthjson = JObject.Parse(oauth);
|
||||
state.OAuthToken = oauthjson.SelectToken("oauth_token").Value<string>();
|
||||
if (oauthjson.SelectToken("steamid") != null)
|
||||
{
|
||||
state.SteamId = oauthjson.SelectToken("steamid").Value<string>();
|
||||
}
|
||||
}
|
||||
|
||||
// login to webapi
|
||||
data.Clear();
|
||||
data.Add("access_token", state.OAuthToken);
|
||||
response = Request(WEBAPI_BASE + "/ISteamWebUserPresenceOAuth/Logon/v0001", "POST", data);
|
||||
|
||||
var sessionid = cookies.GetCookies(new Uri(COMMUNITY_BASE + "/"))["sessionid"].Value;
|
||||
|
||||
if (state.RequiresActivation == false)
|
||||
{
|
||||
data.Clear();
|
||||
data.Add("op", "has_phone");
|
||||
data.Add("arg", "null");
|
||||
data.Add("sessionid", sessionid);
|
||||
|
||||
response = Request(COMMUNITY_BASE + "/steamguard/phoneajax", "POST", data, cookies);
|
||||
var jsonresponse = JObject.Parse(response);
|
||||
bool hasPhone = jsonresponse.SelectToken("has_phone").Value<Boolean>();
|
||||
if (hasPhone == false)
|
||||
{
|
||||
state.OAuthToken = null; // force new login
|
||||
state.RequiresLogin = true;
|
||||
state.Cookies = null;
|
||||
state.Error = "Your Steam account must have a SMS-capable phone number attached. Go into Account Details of the Steam client or Steam website and click Add a Phone Number.";
|
||||
return false;
|
||||
}
|
||||
|
||||
//response = Request(COMMUNITY_BASE + "/steamguard/phone_checksms?bForTwoFactor=1&bRevoke2fOnCancel=", "GET", null, cookies);
|
||||
|
||||
// add a new authenticator
|
||||
data.Clear();
|
||||
string deviceId = BuildRandomId();
|
||||
data.Add("access_token", state.OAuthToken);
|
||||
data.Add("steamid", state.SteamId);
|
||||
data.Add("authenticator_type", "1");
|
||||
data.Add("device_identifier", deviceId);
|
||||
data.Add("sms_phone_id", "1");
|
||||
response = Request(WEBAPI_BASE + "/ITwoFactorService/AddAuthenticator/v0001", "POST", data);
|
||||
var tfaresponse = JObject.Parse(response);
|
||||
if (response.IndexOf("status") == -1 && tfaresponse.SelectToken("response.status").Value<int>() == 84)
|
||||
{
|
||||
// invalid response
|
||||
state.OAuthToken = null; // force new login
|
||||
state.RequiresLogin = true;
|
||||
state.Cookies = null;
|
||||
state.Error = "Unable to send SMS. Check your phone is registered on your Steam account.";
|
||||
return false;
|
||||
}
|
||||
if (response.IndexOf("shared_secret") == -1)
|
||||
{
|
||||
// invalid response
|
||||
state.OAuthToken = null; // force new login
|
||||
state.RequiresLogin = true;
|
||||
state.Cookies = null;
|
||||
state.Error = "Invalid response from Steam: " + response;
|
||||
return false;
|
||||
}
|
||||
|
||||
// save data into this authenticator
|
||||
var secret = tfaresponse.SelectToken("response.shared_secret").Value<string>();
|
||||
this.SecretKey = Convert.FromBase64String(secret);
|
||||
this.Serial = tfaresponse.SelectToken("response.serial_number").Value<string>();
|
||||
this.DeviceId = deviceId;
|
||||
state.RevocationCode = tfaresponse.SelectToken("response.revocation_code").Value<string>();
|
||||
|
||||
// add the steamid into the data
|
||||
var steamdata = JObject.Parse(tfaresponse.SelectToken("response").ToString());
|
||||
if (steamdata.SelectToken("steamid") == null)
|
||||
{
|
||||
steamdata.Add("steamid", state.SteamId);
|
||||
}
|
||||
if (steamdata.SelectToken("steamguard_scheme") == null)
|
||||
{
|
||||
steamdata.Add("steamguard_scheme", "2");
|
||||
}
|
||||
this.SteamData = steamdata.ToString(Newtonsoft.Json.Formatting.None);
|
||||
|
||||
// calculate server drift
|
||||
long servertime = tfaresponse.SelectToken("response.server_time").Value<long>() * 1000;
|
||||
ServerTimeDiff = servertime - CurrentTime;
|
||||
LastServerTime = DateTime.Now.Ticks;
|
||||
|
||||
state.RequiresActivation = true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// finalize adding the authenticator
|
||||
data.Clear();
|
||||
data.Add("access_token", state.OAuthToken);
|
||||
data.Add("steamid", state.SteamId);
|
||||
data.Add("activation_code", state.ActivationCode);
|
||||
|
||||
// try and authorise
|
||||
var retries = 0;
|
||||
while (state.RequiresActivation == true && retries < ENROLL_ACTIVATE_RETRIES)
|
||||
{
|
||||
data.Add("authenticator_code", this.CalculateCode(false));
|
||||
data.Add("authenticator_time", this.ServerTime.ToString());
|
||||
response = Request(WEBAPI_BASE + "/ITwoFactorService/FinalizeAddAuthenticator/v0001", "POST", data);
|
||||
var finalizeresponse = JObject.Parse(response);
|
||||
if (response.IndexOf("status") != -1 && finalizeresponse.SelectToken("response.status").Value<int>() == INVALID_ACTIVATION_CODE)
|
||||
{
|
||||
state.Error = "Invalid activation code";
|
||||
return false;
|
||||
}
|
||||
|
||||
// reset our time
|
||||
if (response.IndexOf("server_time") != -1)
|
||||
{
|
||||
long servertime = finalizeresponse.SelectToken("response.server_time").Value<long>() * 1000;
|
||||
ServerTimeDiff = servertime - CurrentTime;
|
||||
LastServerTime = DateTime.Now.Ticks;
|
||||
}
|
||||
|
||||
// check success
|
||||
if (finalizeresponse.SelectToken("response.success").Value<bool>() == true)
|
||||
{
|
||||
if (response.IndexOf("want_more") != -1 && finalizeresponse.SelectToken("response.want_more").Value<bool>() == true)
|
||||
{
|
||||
ServerTimeDiff += ((long)this.Period * 1000L);
|
||||
retries++;
|
||||
continue;
|
||||
}
|
||||
state.RequiresActivation = false;
|
||||
break;
|
||||
}
|
||||
|
||||
ServerTimeDiff += ((long)this.Period * 1000L);
|
||||
retries++;
|
||||
}
|
||||
if (state.RequiresActivation == true)
|
||||
{
|
||||
state.Error = "There was a problem activating. There might be an issue with the Steam servers. Please try again later.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// mark and successful and return key
|
||||
state.Success = true;
|
||||
state.SecretKey = Authenticator.ByteArrayToString(this.SecretKey);
|
||||
|
||||
// send confirmation email
|
||||
data.Clear();
|
||||
data.Add("access_token", state.OAuthToken);
|
||||
data.Add("steamid", state.SteamId);
|
||||
data.Add("email_type", "2");
|
||||
response = Request(WEBAPI_BASE + "/ITwoFactorService/SendEmail/v0001", "POST", data);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (UnauthorisedRequestException ex)
|
||||
{
|
||||
throw new InvalidEnrollResponseException("You are not allowed to add an authenticator. Have you enabled 'community-generated content' in Family View?", ex);
|
||||
}
|
||||
catch (InvalidRequestException ex)
|
||||
{
|
||||
throw new InvalidEnrollResponseException("Error enrolling new authenticator", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Synchronise this authenticator's time with Steam.
|
||||
/// </summary>
|
||||
public override void Sync()
|
||||
{
|
||||
// check if data is protected
|
||||
if (this.SecretKey == null && this.EncryptedData != null)
|
||||
{
|
||||
throw new EncryptedSecretDataException();
|
||||
}
|
||||
|
||||
// don't retry for 5 minutes
|
||||
if (_lastSyncError >= DateTime.Now.AddMinutes(0 - SYNC_ERROR_MINUTES))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var response = Request(SYNC_URL, "POST", null, null, null, SYNC_TIMEOUT);
|
||||
var json = JObject.Parse(response);
|
||||
|
||||
// get servertime in ms
|
||||
long servertime = json.SelectToken("response.server_time").Value<long>() * 1000;
|
||||
|
||||
// get the difference between the server time and our current time
|
||||
ServerTimeDiff = servertime - CurrentTime;
|
||||
LastServerTime = DateTime.Now.Ticks;
|
||||
|
||||
// clear any sync error
|
||||
_lastSyncError = DateTime.MinValue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// don't retry for a while after error
|
||||
_lastSyncError = DateTime.Now;
|
||||
throw ex;
|
||||
// set to zero to force reset
|
||||
//ServerTimeDiff = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the current code for the authenticator.
|
||||
/// </summary>
|
||||
/// <param name="resyncTime">flag to resync time</param>
|
||||
/// <returns>authenticator code</returns>
|
||||
protected override string CalculateCode(bool resyncTime = false, long interval = -1)
|
||||
{
|
||||
// sync time if required
|
||||
if (resyncTime == true || ServerTimeDiff == 0)
|
||||
{
|
||||
if (interval > 0)
|
||||
{
|
||||
ServerTimeDiff = (interval * ((long)this.Period * 1000L)) - CurrentTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
HMac hmac = new HMac(new Sha1Digest());
|
||||
hmac.Init(new KeyParameter(SecretKey));
|
||||
|
||||
byte[] codeIntervalArray = BitConverter.GetBytes(CodeInterval);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(codeIntervalArray);
|
||||
}
|
||||
hmac.BlockUpdate(codeIntervalArray, 0, codeIntervalArray.Length);
|
||||
|
||||
byte[] mac = new byte[hmac.GetMacSize()];
|
||||
hmac.DoFinal(mac, 0);
|
||||
|
||||
// the last 4 bits of the mac say where the code starts (e.g. if last 4 bit are 1100, we start at byte 12)
|
||||
int start = mac[19] & 0x0f;
|
||||
|
||||
// extract those 4 bytes
|
||||
byte[] bytes = new byte[4];
|
||||
Array.Copy(mac, start, bytes, 0, 4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(bytes);
|
||||
}
|
||||
uint fullcode = BitConverter.ToUInt32(bytes, 0) & 0x7fffffff;
|
||||
|
||||
// build the alphanumeric code
|
||||
StringBuilder code = new StringBuilder();
|
||||
for (var i=0; i<CODE_DIGITS; i++)
|
||||
{
|
||||
code.Append(STEAMCHARS[fullcode % STEAMCHARS.Length]);
|
||||
fullcode /= (uint)STEAMCHARS.Length;
|
||||
}
|
||||
|
||||
return code.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a random Device ID string for Enrolling
|
||||
/// </summary>
|
||||
/// <returns>Random string</returns>
|
||||
private static string BuildRandomId()
|
||||
{
|
||||
return "android:" + Guid.NewGuid().ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log an exception from a Request
|
||||
/// </summary>
|
||||
/// <param name="method">Get or POST</param>
|
||||
/// <param name="url">Request URL</param>
|
||||
/// <param name="cookies">cookie container</param>
|
||||
/// <param name="request">Request data</param>
|
||||
/// <param name="ex">Thrown exception</param>
|
||||
private static void LogException(string method, string url, CookieContainer cookies, NameValueCollection request, Exception ex)
|
||||
{
|
||||
StringBuilder data = new StringBuilder();
|
||||
if (cookies != null)
|
||||
{
|
||||
foreach (Cookie cookie in cookies.GetCookies(new Uri(url)))
|
||||
{
|
||||
if (data.Length == 0)
|
||||
{
|
||||
data.Append("Cookies:");
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Append("&");
|
||||
}
|
||||
data.Append(cookie.Name + "=" + cookie.Value);
|
||||
}
|
||||
data.Append(" ");
|
||||
}
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
foreach (var key in request.AllKeys)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
{
|
||||
data.Append("Req:");
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Append("&");
|
||||
}
|
||||
data.Append(key + "=" + request[key]);
|
||||
}
|
||||
data.Append(" ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log a normal response
|
||||
/// </summary>
|
||||
/// <param name="method">Get or POST</param>
|
||||
/// <param name="url">Request URL</param>
|
||||
/// <param name="cookies">cookie container</param>
|
||||
/// <param name="request">Request data</param>
|
||||
/// <param name="response">response body</param>
|
||||
private static void LogRequest(string method, string url, CookieContainer cookies, NameValueCollection request, string response)
|
||||
{
|
||||
StringBuilder data = new StringBuilder();
|
||||
if (cookies != null)
|
||||
{
|
||||
foreach (Cookie cookie in cookies.GetCookies(new Uri(url)))
|
||||
{
|
||||
if (data.Length == 0)
|
||||
{
|
||||
data.Append("Cookies:");
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Append("&");
|
||||
}
|
||||
data.Append(cookie.Name + "=" + cookie.Value);
|
||||
}
|
||||
data.Append(" ");
|
||||
}
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
foreach (var key in request.AllKeys)
|
||||
{
|
||||
if (data.Length == 0)
|
||||
{
|
||||
data.Append("Req:");
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Append("&");
|
||||
}
|
||||
data.Append(key + "=" + request[key]);
|
||||
}
|
||||
data.Append(" ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Our custom exception for the internal Http Request
|
||||
/// </summary>
|
||||
class InvalidRequestException : ApplicationException
|
||||
{
|
||||
public InvalidRequestException(string msg = null, Exception ex = null) : base(msg, ex) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 403 forbidden responses
|
||||
/// </summary>
|
||||
class UnauthorisedRequestException : InvalidRequestException
|
||||
{
|
||||
public UnauthorisedRequestException(Exception ex = null) : base("Unauthorised", ex) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.IO;
|
||||
using SteamTools.Model;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SteamTools.Helper
|
||||
{
|
||||
public static class ConfigHelper
|
||||
{
|
||||
private const string ConfigFileName = "SteamToolData.dat";
|
||||
|
||||
private static readonly string ConfigPath =
|
||||
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), ConfigFileName);
|
||||
|
||||
public static SteamToolConfig SteamToolConfig { get; set; }
|
||||
|
||||
public static void SaveConfig()
|
||||
{
|
||||
var jsonData = JsonConvert.SerializeObject(SteamToolConfig);
|
||||
File.WriteAllText(ConfigPath, jsonData, Encoding.UTF8);
|
||||
}
|
||||
|
||||
public static SteamToolConfig ReadConfig()
|
||||
{
|
||||
SteamToolConfig = JsonConvert.DeserializeObject<SteamToolConfig>(File.ReadAllText(ConfigPath, Encoding.UTF8));
|
||||
return SteamToolConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace SteamTools.Helper
|
||||
{
|
||||
public static class RegistryKeyHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 创建注册表项
|
||||
/// </summary>
|
||||
/// <param name="registryKey"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static RegistryKey CreateRegistryKey(RegistryKey registryKey, string path)
|
||||
{
|
||||
return registryKey.CreateSubKey(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除注册表项
|
||||
/// </summary>
|
||||
/// <param name="registryKey"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <returns></returns>
|
||||
public static void DeleteRegistryKey(RegistryKey registryKey, string path)
|
||||
{
|
||||
registryKey.DeleteSubKey(path, true); //该方法无返回值,直接调用即可
|
||||
registryKey.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取注册表值
|
||||
/// </summary>
|
||||
/// <param name="registryKey"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string ReadRegistryKey(RegistryKey registryKey, string path, string key)
|
||||
{
|
||||
var myreg = registryKey.OpenSubKey(path);
|
||||
|
||||
if (myreg != null)
|
||||
{
|
||||
var info = myreg.GetValue(key).ToString();
|
||||
myreg.Close();
|
||||
return info;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新增或修改注册表值
|
||||
/// </summary>
|
||||
/// <param name="registryKey"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="registryValueKind"></param>
|
||||
/// <returns></returns>
|
||||
public static void AddOrUpdateRegistryKey(RegistryKey registryKey, string path, string key, string value, RegistryValueKind registryValueKind)
|
||||
{
|
||||
RegistryKey myreg = registryKey.OpenSubKey(path, true); //该项必须已存在
|
||||
if (myreg != null)
|
||||
{
|
||||
myreg.SetValue(key, value, registryValueKind);
|
||||
myreg.Close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Gameloop.Vdf.Linq;
|
||||
using Microsoft.Win32;
|
||||
using SteamTool.Common.Helper;
|
||||
using SteamTools.Model;
|
||||
|
||||
namespace SteamTools.Helper
|
||||
{
|
||||
public class SteamHelper
|
||||
{
|
||||
public static readonly SteamHelper Instance = new SteamHelper();
|
||||
|
||||
public string SteamPath { get; set; }
|
||||
|
||||
public string SteamExePath { get; set; }
|
||||
|
||||
private const string SteamRegistryPath = @"SOFTWARE\Valve\Steam";
|
||||
|
||||
public SteamHelper()
|
||||
{
|
||||
var steamExePath = RegistryKeyHelper.ReadRegistryKey(Registry.CurrentUser, SteamRegistryPath, "SteamExe");
|
||||
var steamPath = RegistryKeyHelper.ReadRegistryKey(Registry.CurrentUser, SteamRegistryPath, "SteamPath");
|
||||
if (File.Exists(steamExePath))
|
||||
{
|
||||
SteamExePath = steamExePath;
|
||||
}
|
||||
if (Directory.Exists(steamPath))
|
||||
{
|
||||
SteamPath = steamPath;
|
||||
}
|
||||
}
|
||||
|
||||
public void KillSteamProcess()
|
||||
{
|
||||
Process[] processes = Process.GetProcesses();
|
||||
foreach (Process process in processes)
|
||||
{
|
||||
if (process.ProcessName == "Steam" || process.ProcessName == "SteamService" || process.ProcessName == "steamwebhelper")
|
||||
{
|
||||
process.Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void StartSteam(string param = "")
|
||||
{
|
||||
if (!string.IsNullOrEmpty(SteamExePath))
|
||||
{
|
||||
Process.Start(SteamExePath, param);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取最后一次自动登陆steam用户名称
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetLastLoginUserName()
|
||||
{
|
||||
return RegistryKeyHelper.ReadRegistryKey(Registry.CurrentUser, SteamRegistryPath, "AutoLoginUser");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取所有记住登陆steam用户信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<SteamUser> GetAllUser()
|
||||
{
|
||||
var users = new List<SteamUser>();
|
||||
if (SteamPath != null)
|
||||
{
|
||||
var v = VdfHelper.GetVdfModelByPath(SteamPath + "/config/loginusers.vdf");
|
||||
|
||||
foreach (var item in v.Value)
|
||||
{
|
||||
var i = item.Value;
|
||||
var user = new SteamUser
|
||||
{
|
||||
AccountName = i.AccountName.ToString(),
|
||||
PersonaName = i.PersonaName.ToString(),
|
||||
RememberPassword = Convert.ToBoolean(Convert.ToInt64(i.RememberPassword.ToString())),
|
||||
MostRecent = Convert.ToBoolean(Convert.ToInt64(i.MostRecent.ToString())),
|
||||
Timestamp = Convert.ToInt64(i.Timestamp.ToString())
|
||||
};
|
||||
user.LastLoginTime= new DateTime(1970, 1, 1, 8, 0, 0).AddSeconds(user.Timestamp);
|
||||
users.Add(user);
|
||||
}
|
||||
}
|
||||
|
||||
return users;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置下次登陆steam用户
|
||||
/// </summary>
|
||||
public void SetCurrentUser(string username)
|
||||
{
|
||||
RegistryKeyHelper.AddOrUpdateRegistryKey(Registry.CurrentUser, SteamRegistryPath, "AutoLoginUser", username, RegistryValueKind.String);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Gameloop.Vdf;
|
||||
using Gameloop.Vdf.Linq;
|
||||
|
||||
namespace SteamTool.Common.Helper
|
||||
{
|
||||
public static class VdfHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取VDF类型内容
|
||||
/// </summary>
|
||||
/// <param name="path">vdf文件内容</param>
|
||||
/// <returns></returns>
|
||||
public static dynamic GetVdfModel(string text)
|
||||
{
|
||||
return VdfConvert.Deserialize(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据路径获取VDF类型内容
|
||||
/// </summary>
|
||||
/// <param name="path">vdf文件路径</param>
|
||||
/// <returns></returns>
|
||||
public static dynamic GetVdfModelByPath(string path)
|
||||
{
|
||||
string text = File.ReadAllText(path,Encoding.UTF8);
|
||||
return GetVdfModel(text); ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamTools.Model
|
||||
{
|
||||
public class SteamToolConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// 启动参数
|
||||
/// </summary>
|
||||
public string SteamRunParam { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 保存用户
|
||||
/// </summary>
|
||||
public List<SteamUser> SteamUsers { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamTools.Model
|
||||
{
|
||||
public class SteamUser
|
||||
{
|
||||
|
||||
public string SteamId3 { get; set; }
|
||||
public int SteamId3_Int { get; }
|
||||
|
||||
public string SteamId32 { get; set; }
|
||||
public int SteamId32_Int { get; }
|
||||
|
||||
public long SteamId64 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 个人资料链接
|
||||
/// </summary>
|
||||
public string ProfileUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 昵称
|
||||
/// </summary>
|
||||
public string PersonaName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 用户名
|
||||
/// </summary>
|
||||
public string AccountName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否记住密码
|
||||
/// </summary>
|
||||
public bool RememberPassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 密码
|
||||
/// </summary>
|
||||
public string PassWord { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登录时间戳
|
||||
/// </summary>
|
||||
public long Timestamp { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后登录时间
|
||||
/// </summary>
|
||||
public DateTime LastLoginTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最近登录
|
||||
/// </summary>
|
||||
public bool MostRecent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 备注
|
||||
/// </summary>
|
||||
public string Remark { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("SteamTool.Common")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SteamTool.Common")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("75e148c7-5f32-4f01-9444-cedefa28748a")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamTool.Common.Service
|
||||
{
|
||||
public class SteamToolsService
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{75E148C7-5F32-4F01-9444-CEDEFA28748A}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SteamTool.Common</RootNamespace>
|
||||
<AssemblyName>SteamTool.Common</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == '发布|AnyCPU'">
|
||||
<OutputPath>bin\发布\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Gameloop.Vdf, Version=0.6.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Gameloop.Vdf.0.6.1\lib\net45\Gameloop.Vdf.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Helper\ConfigHelper.cs" />
|
||||
<Compile Include="Helper\RegistryKeyHelper.cs" />
|
||||
<Compile Include="Helper\SteamHelper.cs" />
|
||||
<Compile Include="Helper\VdfHelper.cs" />
|
||||
<Compile Include="Model\SteamToolConfig.cs" />
|
||||
<Compile Include="Model\SteamUser.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Service\SteamToolsService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup />
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Gameloop.Vdf" version="0.6.1" targetFramework="net46" />
|
||||
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net46" />
|
||||
</packages>
|
||||
@@ -1,26 +0,0 @@
|
||||
using SteamTool.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
|
||||
namespace SteamTool.Proxy
|
||||
{
|
||||
public static class CertificateEx
|
||||
{
|
||||
public static string GetPublicPemCertificateString(this X509Certificate2 @this)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.AppendLine(Const.HOST_TAG);
|
||||
builder.AppendLine("-----BEGIN CERTIFICATE-----");
|
||||
builder.AppendLine(
|
||||
Convert.ToBase64String(@this.RawData, Base64FormattingOptions.InsertLineBreaks));
|
||||
builder.AppendLine("-----END CERTIFICATE-----");
|
||||
builder.AppendLine(Const.HOST_TAG);
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
+105
-240
@@ -7,382 +7,189 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{45E5B6B2-0A6D-
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{350F425C-AF5A-4ED2-BDDC-B905A4E63A14}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Proxy", "SteamTool.Proxy\SteamTool.Proxy.csproj", "{A70C148D-042C-48DA-9963-0B777FC60215}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Proxy", "source\SteamTool.Proxy\SteamTool.Proxy.csproj", "{A70C148D-042C-48DA-9963-0B777FC60215}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Composition", "Composition", "{F62E508E-B374-4149-B9AC-0A8090AA6CD1}"
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reference", "Reference", "{F62E508E-B374-4149-B9AC-0A8090AA6CD1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam.Service", "SteamTool.Steam.Service\SteamTool.Steam.Service.csproj", "{2A155A7B-3DFD-4F16-929D-9693D2411B83}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam.Service", "source\SteamTool.Steam.Service\SteamTool.Steam.Service.csproj", "{2A155A7B-3DFD-4F16-929D-9693D2411B83}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Core", "SteamTool.Core\SteamTool.Core.csproj", "{23E26040-19A5-4623-8863-B9ED539403B0}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Core", "source\SteamTool.Core\SteamTool.Core.csproj", "{23E26040-19A5-4623-8863-B9ED539403B0}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTools", "SteamTools\SteamTools.csproj", "{0663899A-2EC5-4929-868C-9D9620FEA4FE}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTools", "source\SteamTools\SteamTools.csproj", "{0663899A-2EC5-4929-868C-9D9620FEA4FE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam4NET.Test", "SteamTool.Steam4NET.Test\SteamTool.Steam4NET.Test.csproj", "{790D22D4-94B0-4575-8E2D-C451EC520407}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam4NET.Test", "source\SteamTool.Steam4NET.Test\SteamTool.Steam4NET.Test.csproj", "{790D22D4-94B0-4575-8E2D-C451EC520407}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam4NET", "SteamTool.Steam4NET\SteamTool.Steam4NET.csproj", "{D4157059-D31A-4A21-AF4C-2D458F768041}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steam4NET", "source\SteamTool.Steam4NET\SteamTool.Steam4NET.csproj", "{D4157059-D31A-4A21-AF4C-2D458F768041}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{D245A82C-66B2-4CD5-881C-3ED4332FC91D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steamworks.Test", "SteamTool.Steamworks.Test\SteamTool.Steamworks.Test.csproj", "{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Steamworks.Test", "source\SteamTool.Steamworks.Test\SteamTool.Steamworks.Test.csproj", "{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{868B3B33-14B3-49AF-AE01-28D85FD98C1F}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
Lib\MetroRadiance.Chrome.dll = Lib\MetroRadiance.Chrome.dll
|
||||
Lib\MetroRadiance.Core.dll = Lib\MetroRadiance.Core.dll
|
||||
Lib\MetroRadiance.dll = Lib\MetroRadiance.dll
|
||||
C:\Users\Dark\Desktop\Titanium-Web-Proxy-master\Titanium-Web-Proxy-master\src\Titanium.Web.Proxy\obj\Debug\netstandard2.0\Titanium.Web.Proxy.dll = C:\Users\Dark\Desktop\Titanium-Web-Proxy-master\Titanium-Web-Proxy-master\src\Titanium.Web.Proxy\obj\Debug\netstandard2.0\Titanium.Web.Proxy.dll
|
||||
EndProjectSection
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Proxy.Test", "source\SteamTool.Proxy.Test\SteamTool.Proxy.Test.csproj", "{4C441E34-FA65-4425-8242-4EB767BA9B95}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Proxy.Test", "SteamTool.Proxy.Test\SteamTool.Proxy.Test.csproj", "{4C441E34-FA65-4425-8242-4EB767BA9B95}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Model", "source\SteamTool.Model\SteamTool.Model.csproj", "{BDBACE3A-0138-4930-95F6-82562EA03F7A}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Model", "SteamTool.Model\SteamTool.Model.csproj", "{BDBACE3A-0138-4930-95F6-82562EA03F7A}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.SteamAPI", "source\SteamTool.SteamAPI\SteamTool.SteamAPI.csproj", "{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.SteamAPI", "SteamTool.SteamAPI\SteamTool.SteamAPI.csproj", "{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Authenticator", "source\SteamTool.Authenticator\SteamTool.Authenticator.csproj", "{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SteamTool.Authenticator", "SteamTool.Authenticator\SteamTool.Authenticator.csproj", "{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}"
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "SteamTools.UWP", "source\SteamTools.UWP\SteamTools.UWP.wapproj", "{2E755C75-E472-44E0-8AC4-F40209A60172}"
|
||||
EndProject
|
||||
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "SteamTools.UWP", "SteamTools.UWP\SteamTools.UWP.wapproj", "{2E755C75-E472-44E0-8AC4-F40209A60172}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Titanium.Web.Proxy", "references\Titanium-Web-Proxy\src\Titanium.Web.Proxy\Titanium.Web.Proxy.csproj", "{BBB75CAC-2BA3-473D-935D-0E59406F5E61}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MetroRadiance", "MetroRadiance", "{2B74A2B2-148D-4518-BF74-3408095E920B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetroTrilithon.Desktop", "references\MetroRadiance\source\MetroTrilithon.Desktop\MetroTrilithon.Desktop.csproj", "{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetroRadiance.Core", "references\MetroRadiance\source\MetroRadiance.Core\MetroRadiance.Core.csproj", "{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetroRadiance.Chrome", "references\MetroRadiance\source\MetroRadiance.Chrome\MetroRadiance.Chrome.csproj", "{DE0B3A58-C301-4671-8B32-4F195C9457A7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetroRadiance", "references\MetroRadiance\source\MetroRadiance\MetroRadiance.csproj", "{2E226B1E-80F6-448D-B02B-0A029C5BC09E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MetroTrilithon", "references\MetroRadiance\source\MetroTrilithon\MetroTrilithon.csproj", "{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
发布|Any CPU = 发布|Any CPU
|
||||
发布|ARM = 发布|ARM
|
||||
发布|ARM64 = 发布|ARM64
|
||||
发布|x64 = 发布|x64
|
||||
发布|x86 = 发布|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Debug|x86.Build.0 = Debug|x86
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|x86.ActiveCfg = Release|x86
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.Release|x86.Build.0 = Release|x86
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|Any CPU.ActiveCfg = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|Any CPU.Build.0 = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|ARM.ActiveCfg = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|ARM.Build.0 = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|ARM64.ActiveCfg = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|ARM64.Build.0 = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|x64.ActiveCfg = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|x64.Build.0 = 发布|Any CPU
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|x86.ActiveCfg = 发布|x86
|
||||
{A70C148D-042C-48DA-9963-0B777FC60215}.发布|x86.Build.0 = 发布|x86
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Debug|x86.Build.0 = Debug|x86
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|x86.ActiveCfg = Release|x86
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.Release|x86.Build.0 = Release|x86
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|Any CPU.ActiveCfg = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|Any CPU.Build.0 = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|ARM.ActiveCfg = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|ARM.Build.0 = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|ARM64.ActiveCfg = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|ARM64.Build.0 = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|x64.ActiveCfg = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|x64.Build.0 = 发布|Any CPU
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|x86.ActiveCfg = 发布|x86
|
||||
{2A155A7B-3DFD-4F16-929D-9693D2411B83}.发布|x86.Build.0 = 发布|x86
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Debug|x86.Build.0 = Debug|x86
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|x86.ActiveCfg = Release|x86
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.Release|x86.Build.0 = Release|x86
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|x64.Build.0 = Release|Any CPU
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|x86.ActiveCfg = Debug|x86
|
||||
{23E26040-19A5-4623-8863-B9ED539403B0}.发布|x86.Build.0 = Debug|x86
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Debug|x86.Build.0 = Debug|x86
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|x86.ActiveCfg = Release|x86
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.Release|x86.Build.0 = Release|x86
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|x64.Build.0 = Release|Any CPU
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|x86.ActiveCfg = Debug|x86
|
||||
{0663899A-2EC5-4929-868C-9D9620FEA4FE}.发布|x86.Build.0 = Debug|x86
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Debug|x86.Build.0 = Debug|x86
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|x86.ActiveCfg = Release|x86
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.Release|x86.Build.0 = Release|x86
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|x86.ActiveCfg = Debug|x86
|
||||
{790D22D4-94B0-4575-8E2D-C451EC520407}.发布|x86.Build.0 = Debug|x86
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Debug|x86.Build.0 = Debug|x86
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|x86.ActiveCfg = Release|x86
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.Release|x86.Build.0 = Release|x86
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|x64.Build.0 = Release|Any CPU
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|x86.ActiveCfg = Debug|x86
|
||||
{D4157059-D31A-4A21-AF4C-2D458F768041}.发布|x86.Build.0 = Debug|x86
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Debug|x86.Build.0 = Debug|x86
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|x86.ActiveCfg = Release|x86
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.Release|x86.Build.0 = Release|x86
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|x86.ActiveCfg = Debug|x86
|
||||
{C03E4CF5-D68F-4CAC-B002-3A6799ED9E15}.发布|x86.Build.0 = Debug|x86
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Debug|x86.Build.0 = Debug|x86
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|x86.ActiveCfg = Release|x86
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.Release|x86.Build.0 = Release|x86
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|x64.Build.0 = Release|Any CPU
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|x86.ActiveCfg = Debug|x86
|
||||
{4C441E34-FA65-4425-8242-4EB767BA9B95}.发布|x86.Build.0 = Debug|x86
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Debug|x86.Build.0 = Debug|x86
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|x86.ActiveCfg = Release|x86
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.Release|x86.Build.0 = Release|x86
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|x64.Build.0 = Release|Any CPU
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|x86.ActiveCfg = Debug|x86
|
||||
{BDBACE3A-0138-4930-95F6-82562EA03F7A}.发布|x86.Build.0 = Debug|x86
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Debug|x86.Build.0 = Debug|x86
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|x86.ActiveCfg = Release|x86
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.Release|x86.Build.0 = Release|x86
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|x64.Build.0 = Release|Any CPU
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|x86.ActiveCfg = Debug|x86
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F}.发布|x86.Build.0 = Debug|x86
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Debug|x86.Build.0 = Debug|x86
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|x64.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.Release|x86.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|Any CPU.Build.0 = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|ARM.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|ARM.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|ARM64.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|ARM64.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|x64.ActiveCfg = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|x64.Build.0 = Release|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|x86.ActiveCfg = Debug|Any CPU
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666}.发布|x86.Build.0 = Debug|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|x64.Build.0 = Debug|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Debug|x64.Deploy.0 = Debug|x64
|
||||
@@ -392,33 +199,84 @@ Global
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|ARM.Build.0 = Release|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|x64.ActiveCfg = Release|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|x64.Build.0 = Release|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|x64.Deploy.0 = Release|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|x86.ActiveCfg = Release|x86
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|x86.Build.0 = Release|x86
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.Release|x86.Deploy.0 = Release|x86
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|Any CPU.Build.0 = Release|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|ARM.ActiveCfg = Debug|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|ARM.Build.0 = Debug|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|ARM.Deploy.0 = Debug|ARM
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|ARM64.Build.0 = Debug|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|ARM64.Deploy.0 = Debug|ARM64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|x64.ActiveCfg = Debug|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|x64.Build.0 = Debug|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|x64.Deploy.0 = Debug|x64
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|x86.ActiveCfg = Debug|x86
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|x86.Build.0 = Debug|x86
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172}.发布|x86.Deploy.0 = Debug|x86
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67}.Release|x86.Build.0 = Release|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Release|x64.Build.0 = Release|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -436,6 +294,13 @@ Global
|
||||
{4E66F4F4-7771-4FFA-A907-3F99A95C6A7F} = {F62E508E-B374-4149-B9AC-0A8090AA6CD1}
|
||||
{86F6CF23-35C4-45AD-BC0D-6BD50C03F666} = {F62E508E-B374-4149-B9AC-0A8090AA6CD1}
|
||||
{2E755C75-E472-44E0-8AC4-F40209A60172} = {45E5B6B2-0A6D-4D57-804B-7B8313145B62}
|
||||
{BBB75CAC-2BA3-473D-935D-0E59406F5E61} = {F62E508E-B374-4149-B9AC-0A8090AA6CD1}
|
||||
{2B74A2B2-148D-4518-BF74-3408095E920B} = {F62E508E-B374-4149-B9AC-0A8090AA6CD1}
|
||||
{4E2EB2E0-E5FE-4FEB-A3E5-5F2F05CD1A67} = {2B74A2B2-148D-4518-BF74-3408095E920B}
|
||||
{AF006EF5-D4BC-49C6-8E0E-DC2B882BE767} = {2B74A2B2-148D-4518-BF74-3408095E920B}
|
||||
{DE0B3A58-C301-4671-8B32-4F195C9457A7} = {2B74A2B2-148D-4518-BF74-3408095E920B}
|
||||
{2E226B1E-80F6-448D-B02B-0A029C5BC09E} = {2B74A2B2-148D-4518-BF74-3408095E920B}
|
||||
{2EE1744F-2D3C-4032-9A9E-C57FA3B512B3} = {2B74A2B2-148D-4518-BF74-3408095E920B}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5214732D-5A99-44C5-9F02-56348CC457EF}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
using MetroTrilithon.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamTools.Models.Settings
|
||||
{
|
||||
public static class AuthSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// ÁîÅÆÊý¾Ý(ѹËõ´æ´¢£©
|
||||
/// </summary>
|
||||
public static SerializableProperty<string> Authenticators { get; }
|
||||
= new SerializableProperty<string>(GetKey(), Providers.Local) { AutoSave = true };
|
||||
|
||||
|
||||
private static string GetKey([CallerMemberName] string propertyName = "")
|
||||
{
|
||||
return nameof(GeneralSettings) + "." + propertyName;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
using SteamTool.Core.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamTools
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (args.ContainsArg("-log"))
|
||||
{
|
||||
Logger.EnableTextLog = true;
|
||||
}
|
||||
App app = new App();
|
||||
app.InitializeComponent();
|
||||
app.Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"profiles": {
|
||||
"SteamTools": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "-log"
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 510 B |
@@ -1,120 +0,0 @@
|
||||
using SteamTool.Core;
|
||||
using SteamTool.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using SteamTool.Model.ToolModel;
|
||||
using SteamTools.Models;
|
||||
using SteamTool.Core.Common;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using Livet;
|
||||
using SteamTools.Properties;
|
||||
|
||||
namespace SteamTools.Services
|
||||
{
|
||||
public class AutoUpdateService : NotificationObject
|
||||
{
|
||||
#region static members
|
||||
public static AutoUpdateService Current { get; } = new AutoUpdateService();
|
||||
#endregion
|
||||
|
||||
private readonly HttpServices httpServices = SteamToolCore.Instance.Get<HttpServices>();
|
||||
|
||||
#region 更新进度变更通知
|
||||
private double _ProgressValue;
|
||||
public double ProgressValue
|
||||
{
|
||||
get => this._ProgressValue;
|
||||
set
|
||||
{
|
||||
if (this._ProgressValue != value)
|
||||
{
|
||||
this._ProgressValue = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 是否有更新
|
||||
private bool _IsExistUpdate;
|
||||
public bool IsExistUpdate
|
||||
{
|
||||
get => this._IsExistUpdate;
|
||||
set
|
||||
{
|
||||
if (this._IsExistUpdate != value)
|
||||
{
|
||||
this._IsExistUpdate = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public async void CheckUpdate()
|
||||
{
|
||||
try
|
||||
{
|
||||
StatusService.Current.Notify("正在从Github检查更新...");
|
||||
var result = await httpServices.Get(Const.GITHUB_LATEST_RELEASEAPI_URL);
|
||||
var model = JsonConvert.DeserializeObject<GithubReleaseModel>(result);
|
||||
if (!(ProductInfo.Version < model.version))
|
||||
{
|
||||
IsExistUpdate = false;
|
||||
StatusService.Current.Notify("当前已是最新版本");
|
||||
return;
|
||||
}
|
||||
IsExistUpdate = true;
|
||||
DownloadUpdate(model);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("更新出错:", ex);
|
||||
WindowService.Current.ShowDialogWindow($"更新出错:{ex.Message}");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public async void DownloadUpdate(GithubReleaseModel model)
|
||||
{
|
||||
if (WindowService.Current.ShowDialogWindow($"检测到新版本更新内容:{model.body}\r\n是否立即更新?", $"{ProductInfo.Title} | 更新提示") == true)
|
||||
{
|
||||
//var name = model.assets.FirstOrDefault()?.name;
|
||||
var name = Path.Combine(AppContext.BaseDirectory, @$"{ProductInfo.Title} {model.version}.zip");
|
||||
if (File.Exists(name))
|
||||
{
|
||||
StatusService.Current.Notify("更新文件已经存在,不需要下载");
|
||||
return;
|
||||
}
|
||||
var fileReq = WebRequest.Create(model.assets.FirstOrDefault()?.browser_download_url);
|
||||
await fileReq?.GetResponseAsync().ContinueWith(s =>
|
||||
{
|
||||
long totalBytes = s.Result.ContentLength;
|
||||
using Stream responseStream = s.Result.GetResponseStream();
|
||||
using FileStream fileStream = new FileStream(name, FileMode.Create, FileAccess.Write);
|
||||
long totalDownloadBytes = 0;
|
||||
byte[] bs = new byte[4096];
|
||||
int size = responseStream.Read(bs, 0, bs.Length);
|
||||
while (size > 0)
|
||||
{
|
||||
totalDownloadBytes += size;
|
||||
fileStream.Write(bs, 0, size);
|
||||
ProgressValue = ((double)totalDownloadBytes / (double)totalBytes);
|
||||
StatusService.Current.Set($"下载更新{ProgressValue:P}");
|
||||
size = responseStream.Read(bs, 0, bs.Length);
|
||||
}
|
||||
fileStream.Flush();
|
||||
fileStream.Close();
|
||||
StatusService.Current.Set(Resources.Ready);
|
||||
StatusService.Current.Notify($"{ProductInfo.Title} {model.version}版本已经下载到程序根目录下,暂时请手动替换更新");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Livet;
|
||||
using SteamTool.Core.Common;
|
||||
using SteamTool.Model;
|
||||
using SteamTool.Steam.Service;
|
||||
using SteamTool.Steam.Service.Local;
|
||||
using SteamTool.Steam.Service.Web;
|
||||
using SteamTools.Properties;
|
||||
using SteamTools.ViewModels;
|
||||
|
||||
namespace SteamTools.Services
|
||||
{
|
||||
public class SteamConnectService : NotificationObject
|
||||
{
|
||||
#region static members
|
||||
public static SteamConnectService Current { get; } = new SteamConnectService();
|
||||
#endregion
|
||||
|
||||
//public readonly SteamDLLService DLLService = SteamService.Instance.Get<SteamDLLService>();
|
||||
public readonly SteamworksApiService ApiService = SteamService.Instance.Get<SteamworksApiService>();
|
||||
|
||||
public readonly SteamworksWebApiService SteamworksWebApiService = SteamService.Instance.Get<SteamworksWebApiService>();
|
||||
public readonly SteamDbApiService steamDbApiService = SteamService.Instance.Get<SteamDbApiService>();
|
||||
|
||||
#region Steam游戏列表
|
||||
private IReadOnlyCollection<SteamApp> _SteamApps;
|
||||
public IReadOnlyCollection<SteamApp> SteamApps
|
||||
{
|
||||
get => _SteamApps;
|
||||
set
|
||||
{
|
||||
if (_SteamApps != value)
|
||||
{
|
||||
_SteamApps = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 运行中的游戏列表
|
||||
private IList<SteamApp> _RuningSteamApps = new List<SteamApp>();
|
||||
public IList<SteamApp> RuningSteamApps
|
||||
{
|
||||
get => _RuningSteamApps;
|
||||
set
|
||||
{
|
||||
if (_RuningSteamApps != value)
|
||||
{
|
||||
_RuningSteamApps = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 当前steam登录用户
|
||||
private SteamUser _CurrentSteamUser;
|
||||
public SteamUser CurrentSteamUser
|
||||
{
|
||||
get => _CurrentSteamUser;
|
||||
set
|
||||
{
|
||||
if (_CurrentSteamUser != value)
|
||||
{
|
||||
_CurrentSteamUser = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 连接steamclient是否成功
|
||||
private bool _IsConnectToSteam;
|
||||
public bool IsConnectToSteam
|
||||
{
|
||||
get => _IsConnectToSteam;
|
||||
set
|
||||
{
|
||||
if (_IsConnectToSteam != value)
|
||||
{
|
||||
_IsConnectToSteam = value;
|
||||
this.RaisePropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var t = new Task(async () =>
|
||||
{
|
||||
Thread.CurrentThread.IsBackground = true;
|
||||
while (true)
|
||||
{
|
||||
if (Process.GetProcessesByName("steam").Length > 0)
|
||||
{
|
||||
if (!IsConnectToSteam)
|
||||
{
|
||||
if (ApiService.Initialize())
|
||||
{
|
||||
var id = ApiService.GetSteamId64();
|
||||
if (id == 76561197960265728)
|
||||
{
|
||||
//该64位id的steamID3等于0,是steam未获取到当前登录用户的默认返回值,所以直接重新获取,
|
||||
//希望这位用户不会用steam++,嗯...
|
||||
ApiService.SteamClient.Dispose();
|
||||
continue;
|
||||
}
|
||||
IsConnectToSteam = true;
|
||||
CurrentSteamUser = await steamDbApiService.GetUserInfo(id);
|
||||
CurrentSteamUser.IPCountry = ApiService.GetIPCountry();
|
||||
|
||||
var mainViewModel = (WindowService.Current.MainWindow as MainWindowViewModel);
|
||||
await mainViewModel.SteamAppPage.Initialize();
|
||||
#if DEBUG
|
||||
await mainViewModel.SystemTabItems[mainViewModel.SystemTabItems.Count - 1].Initialize();
|
||||
#endif
|
||||
SteamConnectService.Current.DisposeSteamClient();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
IsConnectToSteam = false;
|
||||
//StatusService.Current.Notify(Resources.Steam_Not_Runing);
|
||||
}
|
||||
await Task.Delay(1500);
|
||||
}
|
||||
}, TaskCreationOptions.LongRunning);
|
||||
|
||||
t.ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted);
|
||||
t.Start();
|
||||
}
|
||||
|
||||
public void Initialize(int appid)
|
||||
{
|
||||
if (Process.GetProcessesByName("steam").Length > 0)
|
||||
{
|
||||
IsConnectToSteam = ApiService.Initialize(appid);
|
||||
}
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
foreach (var app in SteamConnectService.Current.RuningSteamApps)
|
||||
{
|
||||
if (!app.Process.HasExited)
|
||||
app.Process.Kill();
|
||||
}
|
||||
}
|
||||
|
||||
public void DisposeSteamClient()
|
||||
{
|
||||
ApiService.SteamClient.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using System.Windows;
|
||||
using SteamTools.Win32;
|
||||
using MetroRadiance.Interop.Win32;
|
||||
using System.Diagnostics;
|
||||
using SteamTool.Core.Common;
|
||||
using System.Runtime.InteropServices;
|
||||
using SteamTools.Services;
|
||||
using SteamTool.Steam.Service.Web;
|
||||
using SteamTool.Core;
|
||||
using SteamTool.Steam.Service;
|
||||
using SteamTool.Model;
|
||||
using Newtonsoft.Json;
|
||||
using SteamTools.Models.Settings;
|
||||
using System.IO;
|
||||
|
||||
namespace SteamTools.ViewModels
|
||||
{
|
||||
public class SettingsGeneralViewModel : Livet.ViewModel
|
||||
{
|
||||
private SteamworksWebApiService SteamworksWebApi => SteamService.Instance.Get<SteamworksWebApiService>();
|
||||
private SteamToolService SteamTool => SteamToolCore.Instance.Get<SteamToolService>();
|
||||
|
||||
private bool IsRefreshGameListCache;
|
||||
|
||||
public void RefreshGameListCache()
|
||||
{
|
||||
if (SteamConnectService.Current.IsConnectToSteam)
|
||||
{
|
||||
if (IsRefreshGameListCache)
|
||||
{
|
||||
StatusService.Current.Notify("正在下载Steam游戏数据中...");
|
||||
return;
|
||||
}
|
||||
StatusService.Current.Notify("刷新Steam游戏数据");
|
||||
IsRefreshGameListCache = true;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var result = await SteamworksWebApi.GetAllSteamAppsString();
|
||||
if (GeneralSettings.IsSteamAppListLocalCache)
|
||||
SteamTool.UpdateAppListJson(result, Path.Combine(AppContext.BaseDirectory, Const.APP_LIST_FILE));
|
||||
var apps = JsonConvert.DeserializeObject<SteamApps>(result).AppList.Apps;
|
||||
apps = apps.DistinctBy(d => d.AppId).ToList();
|
||||
//SteamConnectService.Current.SteamApps = apps;
|
||||
SteamConnectService.Current.SteamApps = SteamConnectService.Current.ApiService.OwnsApps(apps);
|
||||
}).ContinueWith(s => { Logger.Error(s.Exception); WindowService.Current.ShowDialogWindow(s.Exception.Message); }, TaskContinuationOptions.OnlyOnFaulted).ContinueWith(s =>
|
||||
{
|
||||
StatusService.Current.Notify("刷新Steam游戏数据完成");
|
||||
IsRefreshGameListCache = false;
|
||||
s.Dispose();
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
StatusService.Current.Notify("未检测到Steam运行");
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckUpdate_Click()
|
||||
{
|
||||
AutoUpdateService.Current.CheckUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SteamTools.ViewModels
|
||||
{
|
||||
public class SteamIdlePageViewModel : TabItemViewModel
|
||||
{
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return Properties.Resources.IdleCard; }
|
||||
protected set { throw new NotImplementedException(); }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
using Microsoft.Win32;
|
||||
using SteamTools.Models;
|
||||
using SteamTools.Models.Settings;
|
||||
using SteamTools.Properties;
|
||||
using SteamTools.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SteamTool.Core.Common;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using WinAuth;
|
||||
|
||||
namespace SteamTools.ViewModels
|
||||
{
|
||||
public class AuthTradeWindowViewModel : MainWindowViewModelBase
|
||||
{
|
||||
private SteamAuthenticator _Authenticator;
|
||||
|
||||
public AuthTradeWindowViewModel()
|
||||
{
|
||||
this.Title = ProductInfo.Title + " | " + Resources.Auth_TradeTitle;
|
||||
}
|
||||
|
||||
public AuthTradeWindowViewModel(WinAuthAuthenticator auth)
|
||||
{
|
||||
_Authenticator = auth.AuthenticatorData as SteamAuthenticator;
|
||||
this.Title = ProductInfo.Title + " | " + Resources.Auth_TradeTitle;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
<UserControl x:Class="SteamTools.Views.Content.AboutUpdateHistory"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SteamTools.Views.Content"
|
||||
xmlns:viewModel="clr-namespace:SteamTools.ViewModels"
|
||||
xmlns:services="clr-namespace:SteamTools.Services"
|
||||
xmlns:metro="http://schemes.grabacr.net/winfx/2014/controls"
|
||||
xmlns:metro2="http://schemes.grabacr.net/winfx/2015/personal/controls"
|
||||
xmlns:model="clr-namespace:SteamTool.Model;assembly=SteamTool.Model"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:livet="http://schemas.livet-mvvm.net/2011/wpf"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
Background="{DynamicResource ThemeBrushKey}">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="..\Common.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<DockPanel Margin="8">
|
||||
<TextBlock DockPanel.Dock="Top" Text="{Binding Resources.AboutUpdateHistory, Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
Style="{DynamicResource SettingsHeaderTextStyleKey}" />
|
||||
<Border Grid.Column="1">
|
||||
<FlowDocumentScrollViewer Padding="0,-18,0,0"
|
||||
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Auto">
|
||||
<FlowDocument FontSize="12"
|
||||
Foreground="{DynamicResource ForegroundBrushKey}"
|
||||
FontFamily="Meiryo UI"
|
||||
TextAlignment="Left"
|
||||
MaxPageWidth="900">
|
||||
<Paragraph Language="zh-cn">
|
||||
<Run Text="Steam++ v1.0.3" FontSize="16"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="2020-12-26" FontSize="10" />
|
||||
<LineBreak />
|
||||
<Run Text="更新内容"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增pixiv本地反代服务支持" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增在欢迎页steam昵称后显示steam的登陆区域" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="添加steam图片修复的本地反代支持" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复最小化恢复时UI边框错位的BUG"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复令牌编辑和导入时出现的非空报错"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="帐户切换功能的最近登陆时间从北京时间改为当前系统时区时间"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复一个因为DNS解析错误会导致程序内存溢出闪退的BUG"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="SDA令牌导入不再支持导入加密文件,如果要导入加密的maFile请先在SDA移除加密"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修改初始化的方式和steam api的连接逻辑来避免steam游戏掉帧的BUG"></Run>
|
||||
<LineBreak/>
|
||||
<LineBreak />
|
||||
<Run Text="已知的未修复问题"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="部分用户无法加载游戏列表,无法复现,原因暂时不明。(也可能是加载太慢,过半小时才能加载出来)" />
|
||||
</Paragraph>
|
||||
<Paragraph Language="zh-cn">
|
||||
<Run Text="Steam++ v1.0.2" FontSize="16"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="2020-12-21" FontSize="10" />
|
||||
<LineBreak />
|
||||
<Run Text="更新内容"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="更新了由Benares制作的图标" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增帐户切换删除功能" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="添加github图片资源文件代理服务与discord代理服务支持" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="因为有问题暂时去掉了GOG Galaxy代理选项"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复一个会导致程序启动没有反应的bug"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="修复托盘菜单steam昵称过长ui错位bug"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增steam启动参数设置"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增启动时程序最小化到托盘菜单设置"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增捐助列表的展示"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="新增工具自动更新功能"></Run>
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Run Text="已知的未修复问题"></Run>
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="(严重)经反馈,程序运行时可能会影响部分steam游戏掉帧,GPU占用率变低,这个BUG目前在作者的机器上无法复现所以暂时没有修复,如果你遇到这个问题可以手动关闭steam++解决。" />
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="程序在高DPI缩放分辨率下可能会UI布局错位,目前暂时拖动程序可恢复。" />
|
||||
<LineBreak />
|
||||
<Run Text="    "/>
|
||||
<Run Text="部分用户无法加载游戏列表,无法复现,原因暂时不明。" />
|
||||
</Paragraph>
|
||||
<Paragraph Language="zh-cn">
|
||||
<Run Text="Steam++ v1.0.0" FontSize="16"/>
|
||||
<Run Text=" "/>
|
||||
<Run Text="2020-12-14" FontSize="10" />
|
||||
<LineBreak />
|
||||
<Run Text="发布第一个版本" />
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="主要功能:社区反代,帐户切换,成就解锁,本地令牌。"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="    "/>
|
||||
<Run Text="次要功能:强制无边框窗口化以及CSGO VAC屏蔽修复。"></Run>
|
||||
</Paragraph>
|
||||
</FlowDocument>
|
||||
</FlowDocumentScrollViewer>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</UserControl>
|
||||
@@ -1,144 +0,0 @@
|
||||
<UserControl x:Class="SteamTools.Views.Content.GameCommon"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SteamTools.Views.Content"
|
||||
xmlns:viewModel="clr-namespace:SteamTools.ViewModels"
|
||||
xmlns:services="clr-namespace:SteamTools.Services"
|
||||
xmlns:metro="http://schemes.grabacr.net/winfx/2014/controls"
|
||||
xmlns:metro2="http://schemes.grabacr.net/winfx/2015/personal/controls"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:livet="http://schemas.livet-mvvm.net/2011/wpf"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="400"
|
||||
d:DesignWidth="600"
|
||||
d:DataContext="{d:DesignInstance viewModel:GameRelatedPageViewModel}"
|
||||
Background="{DynamicResource ThemeBrushKey}">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="..\Common.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Resources.BorderlessWindow, Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
Style="{DynamicResource SettingsHeaderTextStyleKey}" />
|
||||
|
||||
<StackPanel Orientation="Vertical" Visibility="{Binding Path=SelectWindow,Mode=OneWay,Converter={StaticResource NullToVisibilityConverter}}"
|
||||
Margin="20,0,10,00">
|
||||
<TextBlock Margin="0,0,10,0" TextWrapping="WrapWithOverflow">
|
||||
<Run Text="标题 :"></Run>
|
||||
<Run Text="{Binding SelectWindow.Title,Mode=OneWay}"></Run>
|
||||
<LineBreak></LineBreak>
|
||||
<LineBreak></LineBreak>
|
||||
<Run Text="类名 :"></Run>
|
||||
<Run Text="{Binding SelectWindow.ClassName,Mode=OneWay}"></Run>
|
||||
<LineBreak></LineBreak>
|
||||
<LineBreak></LineBreak>
|
||||
<Run Text="进程 :"></Run>
|
||||
<Run Text="{Binding SelectWindow.Name,Mode=OneWay}"></Run>
|
||||
<LineBreak></LineBreak>
|
||||
<LineBreak></LineBreak>
|
||||
<Run Text="程序路径 :"></Run>
|
||||
<!--<Run Text="{Binding SelectWindow.Path,Mode=OneWay}"></Run>-->
|
||||
<!--<LineBreak></LineBreak>-->
|
||||
</TextBlock>
|
||||
<TextBlock Margin="0,0,10,0" TextWrapping="WrapWithOverflow" Text="{Binding SelectWindow.Path,Mode=OneWay}"></TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="20,10,0,00">
|
||||
<Image Width="64" HorizontalAlignment="Left" Source="/Resources/Asstes/movecross.png">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonDown">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="Cross_MouseDown"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Image>
|
||||
<TextBlock Margin="10,0" Text="拖拽十字到游戏窗口,即可获取游戏信息执行对应操作。"></TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="20,20,0,0">
|
||||
<Button Height="30" Content="结束进程">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="WindowKill_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="无边框窗口化">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="BorderlessWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="最大化">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="MaximizeWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="还原最大化">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="NormalWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="隐藏">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="HideWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="显示">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="ShowWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="置于壁纸层">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="ToWallerpaperWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
<Button Height="30" Content="刷新壁纸">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction
|
||||
MethodName="ResetWallerpaperWindow_Click"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
<TextBlock Style="{StaticResource DetailTextStyleKey}" Margin="20,6,0,0">
|
||||
<Run Text="*置于壁纸层的游戏可能会无法操控,这个问题可以解决但是目前开发精力不在这,目前这个功能就这样了。游戏结束后桌面会依然留下冻结的画面,这时可以点击刷新壁纸来恢复默认壁纸。"/>
|
||||
<Run Text="并且将窗口放置于桌面壁纸层功能与Wallpaper Engine和其它动态桌面软件不兼容,使用时注意关掉Wallpaper Engine等软件。"/>
|
||||
</TextBlock>
|
||||
<Rectangle Style="{DynamicResource SeparatorStyleKey}" />
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -1,79 +0,0 @@
|
||||
<UserControl x:Class="SteamTools.Views.Controls.StatusBar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SteamTools.Views.Controls"
|
||||
xmlns:metro="http://schemes.grabacr.net/winfx/2014/controls"
|
||||
xmlns:services="clr-namespace:SteamTools.Services"
|
||||
xmlns:vm="clr-namespace:SteamTools.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="25" d:DesignWidth="780"
|
||||
d:DataContext="{d:DesignInstance vm:StatusBarViewModel}">
|
||||
<Grid Grid.Row="2" Background="{DynamicResource AccentBrushKey}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="23" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0"
|
||||
FontSize="13"
|
||||
Style="{DynamicResource DefaultTextStyleKey}"
|
||||
Foreground="{DynamicResource AccentForegroundBrushKey}"
|
||||
TextWrapping="NoWrap"
|
||||
Margin="8,0" >
|
||||
<Run
|
||||
Text="{Binding Source={x:Static services:StatusService.Current}, Path=Message}"/>
|
||||
|
||||
</TextBlock>
|
||||
<ContentControl Grid.Column="1"
|
||||
Content="{Binding}">
|
||||
<ContentControl.Resources>
|
||||
<DataTemplate DataType="{x:Type vm:WelcomePageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:CommunityProxyPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:SteamAccountPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:SteamAppPageViewModel}" >
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<StackPanel.Resources>
|
||||
<Style TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource AccentForegroundBrushKey}" />
|
||||
<Setter Property="FontFamily"
|
||||
Value="{DynamicResource DefaultFontFamilyKey}" />
|
||||
<Setter Property="FontSize"
|
||||
Value="{DynamicResource DefaultFontSizeKey}" />
|
||||
<Setter Property="VerticalAlignment"
|
||||
Value="Center" />
|
||||
</Style>
|
||||
</StackPanel.Resources>
|
||||
<TextBlock VerticalAlignment="Center" Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.Steam_Not_Runing_Tips}"
|
||||
Visibility="{Binding Source={x:Static services:SteamConnectService.Current}, Path=IsConnectToSteam,Mode=OneWay,Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.Game_Total, StringFormat='{}{0}: '}" />
|
||||
<TextBlock Text="{Binding Games.Count,Mode=OneWay}"
|
||||
MinWidth="45" />
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.Game_Install, StringFormat='{}{0}: '}" />
|
||||
<TextBlock Text="{Binding InstalledCount,Mode=OneWay}"
|
||||
MinWidth="65" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
<DataTemplate DataType="{x:Type vm:SettingsPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:OtherPlatformPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:LocalAuthPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:GameRelatedPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:ArchiSteamFarmPlusPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:AboutPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:DebugPageViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:AchievementWindowViewModel}" />
|
||||
<DataTemplate DataType="{x:Type vm:SteamIdlePageViewModel}" />
|
||||
</ContentControl.Resources>
|
||||
</ContentControl>
|
||||
<!--<metro:CaptionButton Grid.Column="2" VerticalAlignment="Center"
|
||||
ToolTip="{Binding Path=Badge,StringFormat=Resources.NotificationString,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"
|
||||
Style="{DynamicResource StatusButtonStyleKey}" >
|
||||
<svgc:SvgViewbox IsHitTestVisible="False" Source="pack://application:,,,/Resources/Asstes/bell.svg" Width="11" />
|
||||
</metro:CaptionButton>-->
|
||||
<metro:ResizeGrip Grid.Column="3" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -1,208 +0,0 @@
|
||||
<UserControl x:Class="SteamTools.Views.Controls.TaskBarPopup"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:metro2="http://schemes.grabacr.net/winfx/2015/personal/controls"
|
||||
xmlns:vm="clr-namespace:SteamTools.ViewModels"
|
||||
xmlns:services="clr-namespace:SteamTools.Services"
|
||||
xmlns:metro="http://schemes.grabacr.net/winfx/2014/controls"
|
||||
xmlns:models="clr-namespace:SteamTools.Models"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:livet="http://schemas.livet-mvvm.net/2011/wpf"
|
||||
mc:Ignorable="d"
|
||||
Height="350" Width="180"
|
||||
FontSize="14"
|
||||
UseLayoutRounding="True"
|
||||
TextOptions.TextFormattingMode="Display"
|
||||
TextOptions.TextRenderingMode="Auto"
|
||||
SnapsToDevicePixels="True"
|
||||
Foreground="{DynamicResource ForegroundBrushKey}"
|
||||
d:DataContext="{d:DesignInstance vm:TaskBarViewModel}">
|
||||
<Border>
|
||||
<Grid>
|
||||
<Rectangle Stroke="{DynamicResource AccentBrushKey}"
|
||||
StrokeThickness="3">
|
||||
<Rectangle.Effect>
|
||||
<BlurEffect Radius="8" />
|
||||
</Rectangle.Effect>
|
||||
</Rectangle>
|
||||
<Border Background="{DynamicResource ThemeBrushKey}"
|
||||
BorderBrush="{DynamicResource AccentBrushKey}"
|
||||
BorderThickness=".99">
|
||||
<Grid Margin="8,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="70"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<DockPanel Grid.Row="0" Margin="0,8,0,0" Visibility="{Binding ElementName=user,Path=IsVisible,Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
|
||||
<Image Source="pack://application:,,,/Resources/Asstes/app.ico" Width="64" Height="64" Cursor="Hand">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonDown">
|
||||
<livet:LivetCallMethodAction MethodName="ShowUrl"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Image>
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.WinTitle,Mode=OneWay}"
|
||||
Foreground="{DynamicResource HighlightForegroundBrushKey}" Style="{StaticResource HeaderTextStyleKey}" FontSize="16"/>
|
||||
<TextBlock Text="{Binding Source={x:Static models:ProductInfo.VersionString}, StringFormat=版本 {0}, Mode=OneWay}"
|
||||
Foreground="{DynamicResource HighlightForegroundBrushKey}" Style="{StaticResource DetailTextStyleKey}"/>
|
||||
</StackPanel>
|
||||
|
||||
</DockPanel>
|
||||
<DockPanel x:Name="user" Grid.Row="0" Margin="0,8,0,0" Visibility="{Binding CurrentSteamUser,Source={x:Static services:SteamConnectService.Current},Mode=OneWay,Converter={StaticResource NullToVisibilityConverter}}">
|
||||
<Image Source="{Binding CurrentSteamUser.AvatarMedium,Source={x:Static services:SteamConnectService.Current},Mode=OneWay}" Width="64" Height="64" Cursor="Hand">
|
||||
<Image.Clip>
|
||||
<!--设置图像如何显示-->
|
||||
<EllipseGeometry RadiusX="32" RadiusY="32" Center="32,32"/>
|
||||
</Image.Clip>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonDown">
|
||||
<livet:LivetCallMethodAction MethodName="ShowUrl"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</Image>
|
||||
<StackPanel VerticalAlignment="Center" Margin="8,0,0,0">
|
||||
<TextBlock Text="{Binding CurrentSteamUser.SteamID,Source={x:Static services:SteamConnectService.Current},Mode=OneWay}" VerticalAlignment="Center" TextTrimming="CharacterEllipsis"
|
||||
Foreground="{DynamicResource HighlightForegroundBrushKey}"
|
||||
Style="{StaticResource HeaderTextStyleKey}" FontSize="16"></TextBlock>
|
||||
<TextBlock
|
||||
Foreground="{DynamicResource HighlightForegroundBrushKey}"
|
||||
Style="{StaticResource DetailTextStyleKey}">
|
||||
<Run Text="{Binding Source={x:Static models:ProductInfo.Title}, Mode=OneWay}"></Run>
|
||||
<LineBreak/>
|
||||
<Run Text="{Binding Source={x:Static models:ProductInfo.VersionString}, StringFormat=版本 {0}, Mode=OneWay}"></Run>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
<StackPanel Grid.Row="1">
|
||||
<Rectangle Height=".99"
|
||||
Fill="{DynamicResource InactiveForegroundBrushKey}"
|
||||
Margin="0,8" />
|
||||
<DockPanel>
|
||||
<TextBlock VerticalAlignment="Center" Foreground="{DynamicResource HighlightForegroundBrushKey}" FontFamily="{StaticResource DefaultFontFamilyKey}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding ProxyStatus,Source={x:Static services:ProxyService.Current},Mode=OneWay}" Value="False">
|
||||
<Setter Property="Text" Value="{Binding Resources.StartService,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"></Setter>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding ProxyStatus,Source={x:Static services:ProxyService.Current},Mode=OneWay}" Value="True">
|
||||
<Setter Property="Text" Value="{Binding Resources.StopService,Source={x:Static services:ResourceService.Current}, Mode=OneWay}"></Setter>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<CheckBox x:Name="service" Style="{DynamicResource SliderCheckBox}" Margin="5" HorizontalAlignment="Right"
|
||||
IsChecked="{Binding ProxyStatus,Source={x:Static services:ProxyService.Current},Mode=TwoWay}">
|
||||
</CheckBox>
|
||||
</DockPanel>
|
||||
<!--<metro:LinkButton Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.Exit}">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="Click">
|
||||
<livet:LivetCallMethodAction MethodName="ExitApplication"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</metro:LinkButton>-->
|
||||
<Rectangle Height=".99"
|
||||
Fill="{DynamicResource InactiveForegroundBrushKey}"
|
||||
Margin="0,8" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Row="2" VerticalAlignment="Bottom">
|
||||
<ListBox Style="{StaticResource MetroListBox}" FontSize="12" FontFamily="{StaticResource CaptionFontFamilyKey}" BorderThickness="0" Margin="-8,0">
|
||||
<ListBoxItem>
|
||||
<Border Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.CommunityFix}" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction MethodName="NavigateTabItem"
|
||||
MethodTarget="{Binding}" MethodParameter="1"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem>
|
||||
<Border Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.UserFastChange}" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction MethodName="NavigateTabItem"
|
||||
MethodTarget="{Binding}" MethodParameter="2"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem>
|
||||
<Border Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.GameList}" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction MethodName="NavigateTabItem"
|
||||
MethodTarget="{Binding}" MethodParameter="3"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem>
|
||||
<Border Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.SteamAuth}" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction MethodName="NavigateTabItem"
|
||||
MethodTarget="{Binding}" MethodParameter="4"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem IsEnabled="False" Margin="0,5">
|
||||
<Rectangle Height=".99"
|
||||
Fill="{DynamicResource InactiveForegroundBrushKey}"
|
||||
Margin="8,0" />
|
||||
</ListBoxItem>
|
||||
<ListBoxItem>
|
||||
<Border Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.Settings}" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction MethodName="NavigateTabItem"
|
||||
MethodTarget="{Binding}" MethodParameter="-1"/>
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBoxItem>
|
||||
<ListBoxItem>
|
||||
<Border Padding="8">
|
||||
<StackPanel>
|
||||
<TextBlock Text="{Binding Source={x:Static services:ResourceService.Current}, Path=Resources.Exit}" VerticalAlignment="Center"></TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="MouseLeftButtonUp">
|
||||
<livet:LivetCallMethodAction MethodName="ExitApplication"
|
||||
MethodTarget="{Binding}" />
|
||||
</i:EventTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
</ListBoxItem>
|
||||
</ListBox>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</UserControl>
|
||||
@@ -1,97 +0,0 @@
|
||||
<metro:MetroWindow x:Class="SteamTools.AuthTradeWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||
xmlns:livet="http://schemas.livet-mvvm.net/2011/wpf"
|
||||
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"
|
||||
xmlns:metro="http://schemes.grabacr.net/winfx/2014/controls"
|
||||
xmlns:metro2="clr-namespace:MetroTrilithon.UI.Controls;assembly=MetroTrilithon.Desktop"
|
||||
xmlns:viewModel="clr-namespace:SteamTools.ViewModels"
|
||||
xmlns:prop="clr-namespace:SteamTools.Properties"
|
||||
xmlns:services="clr-namespace:SteamTools.Services"
|
||||
xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCore"
|
||||
xmlns:controls="clr-namespace:SteamTools.Views.Controls"
|
||||
xmlns:models="clr-namespace:SteamTools.Models"
|
||||
mc:Ignorable="d"
|
||||
Width="600"
|
||||
Height="400"
|
||||
IsRestoringWindowPlacement="True"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Title="{Binding Title}"
|
||||
Background="{DynamicResource ThemeBrushKey}"
|
||||
Foreground="{DynamicResource ActiveForegroundBrushKey}"
|
||||
FontFamily="{StaticResource DefaultFontFamilyKey}"
|
||||
FontSize="16"
|
||||
ResizeMode="NoResize"
|
||||
UseLayoutRounding="True"
|
||||
TextOptions.TextFormattingMode="Display"
|
||||
SnapsToDevicePixels="True"
|
||||
d:DataContext="{d:DesignInstance viewModel:ShowAuthWindowViewModel}">
|
||||
<i:Interaction.Triggers>
|
||||
<i:EventTrigger EventName="ContentRendered">
|
||||
<livet:LivetCallMethodAction MethodTarget="{Binding}"
|
||||
MethodName="Initialize" />
|
||||
</i:EventTrigger>
|
||||
|
||||
<i:EventTrigger EventName="Closed">
|
||||
<livet:DataContextDisposeAction />
|
||||
</i:EventTrigger>
|
||||
<livet:InteractionMessageTrigger Messenger="{Binding Messenger, Mode=OneWay}"
|
||||
MessageKey="Window.Activate">
|
||||
<livet:WindowInteractionMessageAction InvokeActionOnlyWhenWindowIsActive="False" />
|
||||
</livet:InteractionMessageTrigger>
|
||||
<livet:InteractionMessageTrigger Messenger="{Binding Messenger}"
|
||||
MessageKey="Window.Transition">
|
||||
<livet:TransitionInteractionMessageAction InvokeActionOnlyWhenWindowIsActive="False"
|
||||
IsOwned="False" />
|
||||
</livet:InteractionMessageTrigger>
|
||||
<livet:InteractionMessageTrigger Messenger="{Binding Messenger}"
|
||||
MessageKey="Window.Transition.Child">
|
||||
<livet:TransitionInteractionMessageAction InvokeActionOnlyWhenWindowIsActive="False"
|
||||
IsOwned="True" />
|
||||
</livet:InteractionMessageTrigger>
|
||||
</i:Interaction.Triggers>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<!--Title-->
|
||||
<Border Grid.Row="0"
|
||||
metro:MetroWindow.IsCaptionBar="True" >
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<metro:CaptionIcon Grid.Column="0" Padding="6,3">
|
||||
<Image Source="pack://application:,,,/Resources/Asstes/app.ico" Width="32" Height="32"></Image>
|
||||
</metro:CaptionIcon>
|
||||
<TextBlock Grid.Column="1"
|
||||
Grid.Row="0"
|
||||
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Title}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Foreground="{DynamicResource ForegroundBrushKey}"
|
||||
FontSize="16"
|
||||
VerticalAlignment="Center" />
|
||||
<metro:SystemButtons Grid.Column="2"
|
||||
Grid.Row="0"
|
||||
VerticalAlignment="Top" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!--Body-->
|
||||
|
||||
<Grid Grid.Row="1">
|
||||
<Grid Margin="0,8,0,0">
|
||||
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</metro:MetroWindow>
|
||||
@@ -1,15 +0,0 @@
|
||||
// ==UserScript==
|
||||
// @name GM
|
||||
// @namespace
|
||||
// @version 0.1
|
||||
// @description 基础脚本框架
|
||||
// @author 软妹币玩家
|
||||
// @match *
|
||||
// @enable true
|
||||
// @grant GM_xmlhttpRequest
|
||||
// ==/UserScript==
|
||||
|
||||
var unsafeWindow = this;
|
||||
function GM_xmlhttpRequest(details)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31005.135
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.Repositories.sqlite-net-pcl", "System.Application.Repositories.sqlite-net-pcl\System.Application.Repositories.sqlite-net-pcl.csproj", "{512B0511-41AB-444D-BAD8-E19B7D3B52CB}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Common.ClientLib", "System.Common.ClientLib\System.Common.ClientLib.csproj", "{8B9F2E93-B31B-4BA7-920D-732695A473E6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Common.CoreLib", "System.Common.CoreLib\System.Common.CoreLib.csproj", "{E7468FDD-75F7-4B08-BA47-B715BBCFCC11}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Common.ClientLib.Droid", "System.Common.ClientLib.Droid\System.Common.ClientLib.Droid.csproj", "{7C8D906E-426B-49AB-9072-178555370F62}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Common.ClientLib.iOS", "System.Common.ClientLib.iOS\System.Common.ClientLib.iOS.csproj", "{F8F6973C-5831-43D1-89C2-1AD543CE7408}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0_Common", "0_Common", "{2D44BDCF-B70C-4C02-BDC8-4F1DD5066A75}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0_Shared", "0_Shared", "{D40853F1-B3C5-418A-B1D3-E0FB70B2F394}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2_Client", "2_Client", "{9AF522B5-8923-41E6-8A0A-FAE8E8F83439}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "4_Repositories.Implementation", "4_Repositories.Implementation", "{DA8EFCA8-5396-48C7-8DC0-CB28A09488D9}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1_SteamTools", "1_SteamTools", "{B43459A1-709B-4623-9677-AAC2FEE4FBA3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Services.CloudService.Models", "System.Application.SteamTools.Services.CloudService.Models\System.Application.SteamTools.Services.CloudService.Models.csproj", "{6CD71E14-5036-4A16-8084-4AD108D34FF7}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Services.CloudService", "System.Application.SteamTools.Services.CloudService\System.Application.SteamTools.Services.CloudService.csproj", "{65DE552F-5E62-4E4F-ADCB-F19AD3DB3F78}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1_ServerApiClient", "1_ServerApiClient", "{F7AFD002-B231-4A5E-B320-56EFC3210E2C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0_Launch", "0_Launch", "{1460800B-D9ED-4147-B1E7-ABF502BEF59A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3_Test", "3_Test", "{EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Common.UnitTest", "System.Common.UnitTest\System.Common.UnitTest.csproj", "{B9D4C8C7-BF96-417B-A7F8-9A67AE75A38B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Common.UnitTest.Droid", "System.Common.UnitTest.Droid\System.Common.UnitTest.Droid.csproj", "{0073A08E-6336-4C09-99F9-2E808889D715}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Common.UnitTest.Droid.App", "System.Common.UnitTest.Droid.App\System.Common.UnitTest.Droid.App.csproj", "{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools", "System.Application.SteamTools\System.Application.SteamTools.csproj", "{66B7BFD6-6D4D-421B-BA5B-915348E53708}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client", "System.Application.SteamTools.Client\System.Application.SteamTools.Client.csproj", "{0A624994-B0A9-4F1F-B7D0-97FE2929936B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop", "System.Application.SteamTools.Client.Desktop\System.Application.SteamTools.Client.Desktop.csproj", "{D1F15D97-802E-4AA3-A4A5-B890ABE32897}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop.Avalonia.App", "System.Application.SteamTools.Client.Desktop.Avalonia.App\System.Application.SteamTools.Client.Desktop.Avalonia.App.csproj", "{2FFA5BCE-B3C3-46EA-8830-838C938BF814}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B4B548C1-9AFE-4EBB-96E4-990B57C0A953}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.gitignore = .gitignore
|
||||
Directory.Build.props = Directory.Build.props
|
||||
global.json = global.json
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop.Avalonia", "System.Application.SteamTools.Client.Desktop.Avalonia\System.Application.SteamTools.Client.Desktop.Avalonia.csproj", "{4F09B6D1-3F83-45A0-AEC8-0F243E7CD263}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop.Platform", "System.Application.SteamTools.Client.Desktop.Platform\System.Application.SteamTools.Client.Desktop.Platform.csproj", "{DD2973AE-D1FC-4307-AFE2-EE2945183D3D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop.Platform.Linux", "System.Application.SteamTools.Client.Desktop.Platform.Linux\System.Application.SteamTools.Client.Desktop.Platform.Linux.csproj", "{D4CF08F5-8EAB-48FB-AAA3-1A221F7B2A82}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop.Platform.Mac", "System.Application.SteamTools.Client.Desktop.Platform.Mac\System.Application.SteamTools.Client.Desktop.Platform.Mac.csproj", "{948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Application.SteamTools.Client.Desktop.Platform.Windows", "System.Application.SteamTools.Client.Desktop.Platform.Windows\System.Application.SteamTools.Client.Desktop.Platform.Windows.csproj", "{141532E1-540E-4E50-8723-96936C191281}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Win7Troubleshoot", "Win7Troubleshoot\Win7Troubleshoot.csproj", "{60530AF8-4790-4A85-BCE2-C5673E9C601B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{512B0511-41AB-444D-BAD8-E19B7D3B52CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{512B0511-41AB-444D-BAD8-E19B7D3B52CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{512B0511-41AB-444D-BAD8-E19B7D3B52CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{512B0511-41AB-444D-BAD8-E19B7D3B52CB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8B9F2E93-B31B-4BA7-920D-732695A473E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8B9F2E93-B31B-4BA7-920D-732695A473E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8B9F2E93-B31B-4BA7-920D-732695A473E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8B9F2E93-B31B-4BA7-920D-732695A473E6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E7468FDD-75F7-4B08-BA47-B715BBCFCC11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E7468FDD-75F7-4B08-BA47-B715BBCFCC11}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E7468FDD-75F7-4B08-BA47-B715BBCFCC11}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E7468FDD-75F7-4B08-BA47-B715BBCFCC11}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C8D906E-426B-49AB-9072-178555370F62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C8D906E-426B-49AB-9072-178555370F62}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C8D906E-426B-49AB-9072-178555370F62}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C8D906E-426B-49AB-9072-178555370F62}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F8F6973C-5831-43D1-89C2-1AD543CE7408}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F8F6973C-5831-43D1-89C2-1AD543CE7408}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F8F6973C-5831-43D1-89C2-1AD543CE7408}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F8F6973C-5831-43D1-89C2-1AD543CE7408}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6CD71E14-5036-4A16-8084-4AD108D34FF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6CD71E14-5036-4A16-8084-4AD108D34FF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6CD71E14-5036-4A16-8084-4AD108D34FF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6CD71E14-5036-4A16-8084-4AD108D34FF7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65DE552F-5E62-4E4F-ADCB-F19AD3DB3F78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65DE552F-5E62-4E4F-ADCB-F19AD3DB3F78}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65DE552F-5E62-4E4F-ADCB-F19AD3DB3F78}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65DE552F-5E62-4E4F-ADCB-F19AD3DB3F78}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B9D4C8C7-BF96-417B-A7F8-9A67AE75A38B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B9D4C8C7-BF96-417B-A7F8-9A67AE75A38B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B9D4C8C7-BF96-417B-A7F8-9A67AE75A38B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B9D4C8C7-BF96-417B-A7F8-9A67AE75A38B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0073A08E-6336-4C09-99F9-2E808889D715}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0073A08E-6336-4C09-99F9-2E808889D715}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0073A08E-6336-4C09-99F9-2E808889D715}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0073A08E-6336-4C09-99F9-2E808889D715}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{66B7BFD6-6D4D-421B-BA5B-915348E53708}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{66B7BFD6-6D4D-421B-BA5B-915348E53708}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{66B7BFD6-6D4D-421B-BA5B-915348E53708}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{66B7BFD6-6D4D-421B-BA5B-915348E53708}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0A624994-B0A9-4F1F-B7D0-97FE2929936B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0A624994-B0A9-4F1F-B7D0-97FE2929936B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A624994-B0A9-4F1F-B7D0-97FE2929936B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A624994-B0A9-4F1F-B7D0-97FE2929936B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4F09B6D1-3F83-45A0-AEC8-0F243E7CD263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4F09B6D1-3F83-45A0-AEC8-0F243E7CD263}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4F09B6D1-3F83-45A0-AEC8-0F243E7CD263}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4F09B6D1-3F83-45A0-AEC8-0F243E7CD263}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DD2973AE-D1FC-4307-AFE2-EE2945183D3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DD2973AE-D1FC-4307-AFE2-EE2945183D3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DD2973AE-D1FC-4307-AFE2-EE2945183D3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DD2973AE-D1FC-4307-AFE2-EE2945183D3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D4CF08F5-8EAB-48FB-AAA3-1A221F7B2A82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D4CF08F5-8EAB-48FB-AAA3-1A221F7B2A82}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D4CF08F5-8EAB-48FB-AAA3-1A221F7B2A82}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D4CF08F5-8EAB-48FB-AAA3-1A221F7B2A82}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{141532E1-540E-4E50-8723-96936C191281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{141532E1-540E-4E50-8723-96936C191281}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{141532E1-540E-4E50-8723-96936C191281}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{141532E1-540E-4E50-8723-96936C191281}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{60530AF8-4790-4A85-BCE2-C5673E9C601B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{60530AF8-4790-4A85-BCE2-C5673E9C601B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{60530AF8-4790-4A85-BCE2-C5673E9C601B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{60530AF8-4790-4A85-BCE2-C5673E9C601B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{512B0511-41AB-444D-BAD8-E19B7D3B52CB} = {DA8EFCA8-5396-48C7-8DC0-CB28A09488D9}
|
||||
{8B9F2E93-B31B-4BA7-920D-732695A473E6} = {9AF522B5-8923-41E6-8A0A-FAE8E8F83439}
|
||||
{E7468FDD-75F7-4B08-BA47-B715BBCFCC11} = {D40853F1-B3C5-418A-B1D3-E0FB70B2F394}
|
||||
{7C8D906E-426B-49AB-9072-178555370F62} = {9AF522B5-8923-41E6-8A0A-FAE8E8F83439}
|
||||
{F8F6973C-5831-43D1-89C2-1AD543CE7408} = {9AF522B5-8923-41E6-8A0A-FAE8E8F83439}
|
||||
{D40853F1-B3C5-418A-B1D3-E0FB70B2F394} = {2D44BDCF-B70C-4C02-BDC8-4F1DD5066A75}
|
||||
{9AF522B5-8923-41E6-8A0A-FAE8E8F83439} = {2D44BDCF-B70C-4C02-BDC8-4F1DD5066A75}
|
||||
{DA8EFCA8-5396-48C7-8DC0-CB28A09488D9} = {2D44BDCF-B70C-4C02-BDC8-4F1DD5066A75}
|
||||
{6CD71E14-5036-4A16-8084-4AD108D34FF7} = {F7AFD002-B231-4A5E-B320-56EFC3210E2C}
|
||||
{65DE552F-5E62-4E4F-ADCB-F19AD3DB3F78} = {F7AFD002-B231-4A5E-B320-56EFC3210E2C}
|
||||
{F7AFD002-B231-4A5E-B320-56EFC3210E2C} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{1460800B-D9ED-4147-B1E7-ABF502BEF59A} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1} = {2D44BDCF-B70C-4C02-BDC8-4F1DD5066A75}
|
||||
{B9D4C8C7-BF96-417B-A7F8-9A67AE75A38B} = {EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}
|
||||
{0073A08E-6336-4C09-99F9-2E808889D715} = {EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}
|
||||
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA} = {EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}
|
||||
{66B7BFD6-6D4D-421B-BA5B-915348E53708} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{0A624994-B0A9-4F1F-B7D0-97FE2929936B} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{D1F15D97-802E-4AA3-A4A5-B890ABE32897} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{2FFA5BCE-B3C3-46EA-8830-838C938BF814} = {1460800B-D9ED-4147-B1E7-ABF502BEF59A}
|
||||
{4F09B6D1-3F83-45A0-AEC8-0F243E7CD263} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{DD2973AE-D1FC-4307-AFE2-EE2945183D3D} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{D4CF08F5-8EAB-48FB-AAA3-1A221F7B2A82} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{948C1EA8-12DB-4F8A-A190-8615DFBD9FE4} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{141532E1-540E-4E50-8723-96936C191281} = {B43459A1-709B-4623-9677-AAC2FEE4FBA3}
|
||||
{60530AF8-4790-4A85-BCE2-C5673E9C601B} = {1460800B-D9ED-4147-B1E7-ABF502BEF59A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3833E7C5-69BC-4CB3-92CE-A8854AA35D8A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
using Polly;
|
||||
using SQLite;
|
||||
using System.Application.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Application.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// 由 sqlite-net-pcl 实现的仓储层
|
||||
/// </summary>
|
||||
public abstract class Repository : IRepository
|
||||
{
|
||||
#region https://codetraveler.io/2019/11/26/efficiently-initializing-sqlite-database/
|
||||
|
||||
static string? mDataBaseDirectory;
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设定数据库目录,默认值为 <see cref="IOPath.AppDataDirectory"/>
|
||||
/// </summary>
|
||||
public static string DataBaseDirectory
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(mDataBaseDirectory)) mDataBaseDirectory = IOPath.AppDataDirectory;
|
||||
return mDataBaseDirectory;
|
||||
}
|
||||
set
|
||||
{
|
||||
mDataBaseDirectory = value;
|
||||
}
|
||||
}
|
||||
|
||||
static SQLiteAsyncConnection GetConnection()
|
||||
{
|
||||
var dbPath = DataBaseDirectory;
|
||||
IOPath.DirCreateByNotExists(dbPath);
|
||||
dbPath = Path.Combine(dbPath, "application.dbf");
|
||||
return new SQLiteAsyncConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);
|
||||
}
|
||||
|
||||
static readonly Lazy<SQLiteAsyncConnection> dbConnection = new Lazy<SQLiteAsyncConnection>(GetConnection);
|
||||
|
||||
static SQLiteAsyncConnection DbConnection => dbConnection.Value;
|
||||
|
||||
protected static async ValueTask<SQLiteAsyncConnection> GetDbConnection<T>()
|
||||
{
|
||||
if (!DbConnection.TableMappings.Any(x => x.MappedType == typeof(T)))
|
||||
{
|
||||
// On sqlite-net v1.6.0+, enabling write-ahead logging allows for faster database execution
|
||||
await DbConnection.EnableWriteAheadLoggingAsync().ConfigureAwait(false);
|
||||
await DbConnection.CreateTablesAsync(CreateFlags.None, typeof(T)).ConfigureAwait(false);
|
||||
}
|
||||
return DbConnection;
|
||||
}
|
||||
|
||||
protected static Task<T> AttemptAndRetry<T>(Func<Task<T>> action, int numRetries = 10)
|
||||
{
|
||||
return Policy.Handle<SQLiteException>().WaitAndRetryAsync(numRetries, pollyRetryAttempt).ExecuteAsync(action);
|
||||
static TimeSpan pollyRetryAttempt(int attemptNumber) => TimeSpan.FromMilliseconds(Math.Pow(2, attemptNumber));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="Repository"/>
|
||||
public abstract class Repository<TEntity> : Repository, IRepository<TEntity> where TEntity : class, new()
|
||||
{
|
||||
protected static ValueTask<SQLiteAsyncConnection> GetDbConnection() => GetDbConnection<TEntity>();
|
||||
|
||||
#region 增(Insert Funs) 立即执行并返回受影响的行数
|
||||
|
||||
public virtual async Task<int> InsertAsync(TEntity entity)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.InsertAsync(entity)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public virtual async Task<int> InsertRangeAsync(IEnumerable<TEntity> entities)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.InsertAllAsync(entities)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 删(Delete Funs) 立即执行并返回受影响的行数
|
||||
|
||||
public virtual async Task<int> DeleteAsync(TEntity entity)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.DeleteAsync(entity)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 改(Update Funs) 立即执行并返回受影响的行数
|
||||
|
||||
public virtual async Task<int> UpdateAsync(TEntity entity)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.UpdateAsync(entity)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public virtual async Task<int> UpdateRangeAsync(IEnumerable<TEntity> entities)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.UpdateAllAsync(entities)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 查(通用查询)
|
||||
|
||||
public virtual async Task<TEntity?> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.FindAsync(predicate)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IRepository"/>
|
||||
public abstract class Repository<TEntity, TPrimaryKey> : Repository<TEntity>, IRepository<TEntity, TPrimaryKey>
|
||||
where TEntity : class, IEntity<TPrimaryKey>, new()
|
||||
where TPrimaryKey : IEquatable<TPrimaryKey>
|
||||
{
|
||||
object IGetPrimaryKey<TEntity>.GetPrimaryKey(TEntity entity) => GetPrimaryKey(entity);
|
||||
|
||||
protected TPrimaryKey GetPrimaryKey(TEntity entity)
|
||||
{
|
||||
IGetPrimaryKey<TEntity, TPrimaryKey> getPrimaryKey = this;
|
||||
return getPrimaryKey.GetPrimaryKey(entity);
|
||||
}
|
||||
|
||||
#region 删(Delete Funs) 立即执行并返回受影响的行数
|
||||
|
||||
public override Task<int> DeleteAsync(TEntity entity)
|
||||
{
|
||||
var primaryKey = GetPrimaryKey(entity);
|
||||
return DeleteAsync(primaryKey);
|
||||
}
|
||||
|
||||
public virtual async Task<int> DeleteAsync(TPrimaryKey primaryKey)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.DeleteAsync<TEntity>(primaryKey)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 查(通用查询)
|
||||
|
||||
public virtual async ValueTask<TEntity?> FindAsync(TPrimaryKey primaryKey)
|
||||
{
|
||||
if (IRepository<TEntity, TPrimaryKey>.IsDefault(primaryKey)) return default;
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
return await AttemptAndRetry(() => dbConnection.FindAsync<TEntity>(primaryKey)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public virtual async ValueTask<bool> ExistAsync(TPrimaryKey primaryKey)
|
||||
{
|
||||
if (IRepository<TEntity, TPrimaryKey>.IsDefault(primaryKey)) return false;
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
var count = await AttemptAndRetry(CountAsync).ConfigureAwait(false);
|
||||
return count > 0;
|
||||
Task<int> CountAsync() => dbConnection.Table<TEntity>().CountAsync(IRepository<TEntity, TPrimaryKey>.LambdaEqualId(primaryKey));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 增或改(InsertOrUpdate Funs) 立即执行并返回受影响的行数
|
||||
|
||||
public virtual async Task<(int rowCount, DbRowExecResult result)> InsertOrUpdateAsync(TEntity entity)
|
||||
{
|
||||
var dbConnection = await GetDbConnection().ConfigureAwait(false);
|
||||
var rowCount = await AttemptAndRetry(() => dbConnection.InsertOrReplaceAsync(entity)).ConfigureAwait(false);
|
||||
return (rowCount, DbRowExecResult.InsertOrUpdate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using SQLite;
|
||||
using System.Application.Models;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System
|
||||
{
|
||||
public static class AsyncTableQueryExtensions
|
||||
{
|
||||
#region WhereOr
|
||||
|
||||
/// <inheritdoc cref="QueryableExtensions.WhereOr{T}(IReadOnlyList{Expression{Func{T, bool}}})"/>
|
||||
public static AsyncTableQuery<T> WhereOr<T>(this AsyncTableQuery<T> source, IReadOnlyList<Expression<Func<T, bool>>> predicates) where T : new()
|
||||
{
|
||||
var predicate = ExpressionHelper.WhereOr(predicates);
|
||||
return source.Where(predicate);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="QueryableExtensions.WhereOr{T}(IReadOnlyList{Expression{Func{T, bool}}})"/>
|
||||
public static AsyncTableQuery<T> WhereOr<T>(this AsyncTableQuery<T> source, IEnumerable<Expression<Func<T, bool>>> predicates) where T : new()
|
||||
=> source.WhereOr(predicates.ToArray());
|
||||
|
||||
/// <inheritdoc cref="QueryableExtensions.WhereOr{T}(IReadOnlyList{Expression{Func{T, bool}}})"/>
|
||||
public static AsyncTableQuery<T> WhereOr<T>(this AsyncTableQuery<T> source, params Expression<Func<T, bool>>[] predicates) where T : new()
|
||||
{
|
||||
IReadOnlyList<Expression<Func<T, bool>>> _predicates = predicates;
|
||||
return source.WhereOr(_predicates);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Paging
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询,调用此方法前必须进行排序
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <param name="source"></param>
|
||||
/// <param name="current"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<PagedModel<TEntity>> PagingAsync<TEntity>(
|
||||
this AsyncTableQuery<TEntity> source,
|
||||
int current = IPagedModel.DefaultCurrent,
|
||||
int pageSize = IPagedModel.DefaultPageSize) where TEntity : new()
|
||||
{
|
||||
var skipCount = (pageSize - 1) * pageSize;
|
||||
var total = await source.CountAsync();
|
||||
var dataSource = await source.Skip(skipCount).Take(pageSize).ToListAsync();
|
||||
var pagedModel = new PagedModel<TEntity>
|
||||
{
|
||||
Current = current,
|
||||
PageSize = pageSize,
|
||||
Total = total,
|
||||
DataSource = dataSource,
|
||||
};
|
||||
return pagedModel;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
using System.Application.Columns;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System
|
||||
{
|
||||
/// <summary>
|
||||
/// SQL语句字符串常量,使用字符串拼接时应注意防止 SQL注入攻击
|
||||
/// <para>EFCore 可采用 <see cref="FormattableString"/> 参数化传入参数</para>
|
||||
/// </summary>
|
||||
public static partial class SQLStrings
|
||||
{
|
||||
/// <summary>
|
||||
/// "select * from "
|
||||
/// <para>查询所有列</para>
|
||||
/// </summary>
|
||||
public const string SelectALLFrom = "select * from ";
|
||||
|
||||
/// <summary>
|
||||
/// "select count(Id) from "
|
||||
/// <para>查询总数,仅Id列</para>
|
||||
/// </summary>
|
||||
public const string SelectCountFrom = "select count(Id) from ";
|
||||
|
||||
/// <summary>
|
||||
/// "select count({0}) from "
|
||||
/// <para>查询总数,仅某一列</para>
|
||||
/// <para>注意:参数仅使用列名固定值,不可传递变量,防止SQL注入攻击</para>
|
||||
/// </summary>
|
||||
public const string SelectCountFrom_0 = "select count({0}) from ";
|
||||
|
||||
/// <summary>
|
||||
/// " order by CreationTime desc"
|
||||
/// <para>根据 创建时间 倒序</para>
|
||||
/// </summary>
|
||||
public const string OrderByCreationTimeDescending = " order by CreationTime desc";
|
||||
|
||||
/// <summary>
|
||||
/// " order by ReceiveTime, CreationTime desc"
|
||||
/// <para>根据 接收时间, 创建时间 倒序</para>
|
||||
/// </summary>
|
||||
public const string OrderByReceiveTimeThenByCreationTimeDescending = " order by ReceiveTime, CreationTime desc";
|
||||
|
||||
/// <summary>
|
||||
/// " order by {0} desc"
|
||||
/// <para>根据 某一列 倒序</para>
|
||||
/// <para>注意:参数仅使用列名固定值,不可传递变量,防止SQL注入攻击</para>
|
||||
/// </summary>
|
||||
public const string OrderBy_Descending_0 = " order by {0} desc";
|
||||
|
||||
/// <summary>
|
||||
/// "delete from "
|
||||
/// </summary>
|
||||
public const string DeleteFrom = "delete from ";
|
||||
|
||||
/// <summary>
|
||||
/// " where Id = {0}"
|
||||
/// <para>注意:参数仅使用列名固定值,不可传递变量,防止SQL注入攻击</para>
|
||||
/// </summary>
|
||||
public const string WhereIdEqual_0 = " where Id = {0}";
|
||||
|
||||
/// <summary>
|
||||
/// "delete from {tableName} where Id = {0}"
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static FormattableString DeleteFromTableNameWhereIdEqual(string tableName, object id)
|
||||
{
|
||||
var sql = DeleteFrom + tableName + WhereIdEqual_0;
|
||||
return FormattableStringFactory.Create(sql, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "update from {tableName} set IsSoftDeleted = 1 where Id = {0}"
|
||||
/// </summary>
|
||||
/// <param name="tableName"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
public static FormattableString SoftDeleteFromTableNameWhereIdEqual(string tableName, object id)
|
||||
{
|
||||
var sql = UpdateFrom + tableName + " set " + nameof(ISoftDeleted.SoftDeleted) + " = 1" + WhereIdEqual_0;
|
||||
return FormattableStringFactory.Create(sql, id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// "update from "
|
||||
/// </summary>
|
||||
public const string UpdateFrom = "update from ";
|
||||
|
||||
/// <summary>
|
||||
/// " where Id in ("
|
||||
/// </summary>
|
||||
public const string WhereInIds_ = " where Id in (";
|
||||
|
||||
/// <summary>
|
||||
/// 右括号
|
||||
/// </summary>
|
||||
public const char RightBracket = ')';
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\InternalsVisibleTo.cs">
|
||||
<Link>Properties\InternalsVisibleTo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Common.CoreLib\System.Common.CoreLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="sqlite-net-pcl" Version="1.7.335" />
|
||||
<PackageReference Include="Polly" Version="7.2.1" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,17 @@
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:ui="clr-namespace:System.Application.UI"
|
||||
x:Class="System.Application.UI.App">
|
||||
<Application.DataTemplates>
|
||||
<ui:ViewLocator/>
|
||||
</Application.DataTemplates>
|
||||
<Application.Styles>
|
||||
<FluentTheme Mode="Dark" />
|
||||
<StyleInclude Source="/Styles/Styles.xaml" />
|
||||
<StyleInclude Source="/Styles/SideBar.xaml" />
|
||||
<!--<StyleInclude Source="avares://AvaloniaEdit/AvaloniaEdit.xaml"/>-->
|
||||
<Style Selector="Window">
|
||||
<Setter Property="Icon" Value="/Assets/Icon.ico"/>
|
||||
</Style>
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
@@ -0,0 +1,36 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Application.UI.Views;
|
||||
using AvaloniaApplication = Avalonia.Application;
|
||||
|
||||
namespace System.Application.UI
|
||||
{
|
||||
public class App : AvaloniaApplication
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
// ÔÚUIÔ¤ÀÀÖУ¬ApplicationLifetime Ϊ null
|
||||
ViewModelBase.IsInDesignMode = ApplicationLifetime == null;
|
||||
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
desktop.MainWindow = new MainWindow
|
||||
{
|
||||
DataContext = DataContext = DI.Get<MainWindowViewModel>(),
|
||||
};
|
||||
desktop.ShutdownMode = ShutdownMode.OnMainWindowClose;
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
|
||||
public static async void SetClipboardText(string s) => await Current.Clipboard.SetTextAsync(s);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 364 KiB After Width: | Height: | Size: 364 KiB |
@@ -0,0 +1,46 @@
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Styling;
|
||||
using System;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Avalonia.Controls
|
||||
{
|
||||
public class FluentWindow : Window, IStyleable
|
||||
{
|
||||
Type IStyleable.StyleKey => typeof(Window);
|
||||
|
||||
public FluentWindow()
|
||||
{
|
||||
ExtendClientAreaToDecorationsHint = true;
|
||||
ExtendClientAreaTitleBarHeightHint = -1;
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
ExtendClientAreaChromeHints =
|
||||
ExtendClientAreaChromeHints.PreferSystemChrome |
|
||||
ExtendClientAreaChromeHints.OSXThickTitleBar;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:System.Application.UI.ViewModels"
|
||||
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"
|
||||
x:Class="System.Application.UI.Pages.SettingsPage">
|
||||
<Design.DataContext>
|
||||
<vm:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
<StackPanel HorizontalAlignment="Stretch" Margin="{StaticResource PageMargin}" Background="Transparent" Spacing="20">
|
||||
<Grid RowDefinitions="Auto, Auto, Auto, Auto, Auto, Auto">
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="16">
|
||||
<TextBlock FontSize="18" Text="{Binding Path=SettingsPage.Settings_General}"/>
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock Text="{Binding Path=SettingsPage.Language}" Margin="0 0 0 20"/>
|
||||
<ComboBox HorizontalAlignment="Stretch"
|
||||
SelectedIndex="{Binding Path=SettingsPage.CurrentLanguageIndex}"
|
||||
Items="{Binding Path=SettingsPage.Languages}" />
|
||||
</StackPanel>
|
||||
<Border Background="{DynamicResource SystemControlHighlightBaseLowBrush}" BorderThickness="1" Margin="15"/>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Vertical"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="16"
|
||||
Grid.Row="1">
|
||||
<TextBlock FontSize="18" Text="{Binding Path=SettingsPage.Settings_Auth}"/>
|
||||
<StackPanel Orientation="Vertical">
|
||||
</StackPanel>
|
||||
<Border Background="{DynamicResource SystemControlHighlightBaseLowBrush}" BorderThickness="1" Margin="15"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,19 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
namespace System.Application.UI.Pages
|
||||
{
|
||||
public class SettingsPage : UserControl
|
||||
{
|
||||
public SettingsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Avalonia;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
namespace System.Application.UI
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
// Initialization code. Don't use any Avalonia, third-party APIs or any
|
||||
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
|
||||
// yet and stuff might break.
|
||||
[STAThread]
|
||||
static void Main(string[] args)
|
||||
{
|
||||
ModelValidatorProvider.Init();
|
||||
DI.Init(ConfigureServices);
|
||||
BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
|
||||
// Avalonia configuration, don't remove; also used by visual designer.
|
||||
static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.With(new SkiaOptions { MaxGpuResourceSizeBytes = 8096000 })
|
||||
.With(new Win32PlatformOptions { AllowEglInitialization = true })
|
||||
.LogToTrace()
|
||||
.UseReactiveUI();
|
||||
|
||||
static void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddLogging(l => l.AddProvider(NullLoggerProvider.Instance));
|
||||
services.AddDesktopPlatformService();
|
||||
services.TryAddModelValidator();
|
||||
services.AddLocalizationService();
|
||||
services.AddMainThreadPlatformService();
|
||||
services.AddViewModelCollectionService();
|
||||
services.AddViewModel<MainWindowViewModel>();
|
||||
services.AddViewModel<SettingsPageViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?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;$(DefineConstants)</DefineConstants>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\Publish\linux-x64</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>True</PublishTrimmed>
|
||||
<TrimMode>link</TrimMode>
|
||||
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?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;$(DefineConstants)</DefineConstants>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\Publish\osx-x64</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>True</PublishTrimmed>
|
||||
<TrimMode>link</TrimMode>
|
||||
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
+31
@@ -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;$(DefineConstants)</DefineConstants>
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Any CPU</Platform>
|
||||
<PublishDir>bin\Release\Publish\win-x64</PublishDir>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
<!--可以通过将应用程序集编译为 ReadyToRun (R2R) 格式来改进 .NET Core 应用程序的启动时间和延迟。 R2R 是一种预先 (AOT) 编译形式 https://docs.microsoft.com/zh-cn/dotnet/core/deploying/ready-to-run-->
|
||||
<PublishTrimmed>True</PublishTrimmed>
|
||||
<TrimMode>link</TrimMode>
|
||||
<TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>
|
||||
<!--剪裁框架库功能 https://docs.microsoft.com/zh-cn/dotnet/core/deploying/trimming-options#trimming-framework-library-features-->
|
||||
<DebuggerSupport>false</DebuggerSupport>
|
||||
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
|
||||
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
|
||||
<SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
|
||||
<EventSourceSupport>false</EventSourceSupport>
|
||||
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
|
||||
<UseSystemResourceKeys>true</UseSystemResourceKeys>
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC 清单选项
|
||||
如果想要更改 Windows 用户帐户控制级别,请使用
|
||||
以下节点之一替换 requestedExecutionLevel 节点。n
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false"/>
|
||||
|
||||
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
|
||||
如果你的应用程序需要此虚拟化来实现向后兼容性,则删除此
|
||||
元素。
|
||||
-->
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
|
||||
Windows 版本的列表。取消评论适当的元素,
|
||||
Windows 将自动选择最兼容的环境。 -->
|
||||
|
||||
<!-- Windows Vista -->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
|
||||
|
||||
<!--Windows 7-->
|
||||
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
|
||||
|
||||
<!--Windows 8-->
|
||||
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
|
||||
|
||||
<!--Windows 8.1-->
|
||||
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
|
||||
|
||||
<!--Windows 10-->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
|
||||
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
|
||||
选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
|
||||
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->
|
||||
<!--
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
-->
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
|
||||
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
|
||||
<!--
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"/>
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
-->
|
||||
</assembly>
|
||||
@@ -0,0 +1,74 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<TabControl Classes="sidebar">
|
||||
<TabItem Header="Item1"/>
|
||||
<TabItem Header="Item2"/>
|
||||
</TabControl>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Style Selector="TabControl.sidebar">
|
||||
<Setter Property="TabStripPlacement" Value="Left"/>
|
||||
<Setter Property="Padding" Value="0 0 0 0"/>
|
||||
<Setter Property="Background" Value="{x:Null}"/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
Margin="{TemplateBinding Margin}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}">
|
||||
<DockPanel>
|
||||
<ScrollViewer Width="240" Margin="0 30 0 0"
|
||||
Name="PART_ScrollViewer"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}"
|
||||
Background="{TemplateBinding Background}"
|
||||
DockPanel.Dock="Left">
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Items="{TemplateBinding Items}"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}"
|
||||
ItemTemplate="{TemplateBinding ItemTemplate}">
|
||||
</ItemsPresenter>
|
||||
</ScrollViewer>
|
||||
<ContentControl Content="{TemplateBinding Tag}" HorizontalContentAlignment="Right" DockPanel.Dock="Bottom"/>
|
||||
<ScrollViewer Background="{x:Null}"
|
||||
HorizontalScrollBarVisibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.(ScrollViewer.HorizontalScrollBarVisibility)}"
|
||||
VerticalScrollBarVisibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.(ScrollViewer.VerticalScrollBarVisibility)}">
|
||||
<ContentPresenter
|
||||
Name="PART_SelectedContentHost"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding SelectedContent}"
|
||||
ContentTemplate="{TemplateBinding SelectedContentTemplate}">
|
||||
</ContentPresenter>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TabControl.sidebar > TabItem">
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="FontSize" Value="14"/>
|
||||
<Setter Property="Margin" Value="0"/>
|
||||
<Setter Property="Padding" Value="16"/>
|
||||
<Setter Property="Width" Value="240" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="(ScrollViewer.HorizontalScrollBarVisibility)" Value="Auto"/>
|
||||
<Setter Property="(ScrollViewer.VerticalScrollBarVisibility)" Value="Auto"/>
|
||||
</Style>
|
||||
<Style Selector="TabControl.sidebar > TabItem:selected /template/ Border#PART_SelectedPipe">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="TabControl.sidebar > TabItem:selected">
|
||||
<Setter Property="Background" Value="#1fffffff"/>
|
||||
</Style>
|
||||
|
||||
<Style Selector="TabControl.sidebar > TabItem:pointerover /template/ Border#PART_LayoutRoot">
|
||||
<Setter Property="Background" Value="#3fffffff"/>
|
||||
</Style>
|
||||
</Styles>
|
||||
@@ -0,0 +1,18 @@
|
||||
<Styles xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
<Border Padding="20">
|
||||
<StackPanel Spacing="5">
|
||||
<TextBlock Text="Code Font Family" FontFamily="{StaticResource CodeFontFamily}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
<Styles.Resources>
|
||||
<Thickness x:Key="PageMargin">40 0 40 0</Thickness>
|
||||
<!--<FontFamily x:Key="CodeFontFamily">avares://Steam++/Assets/Fonts#Source Code Pro</FontFamily>-->
|
||||
</Styles.Resources>
|
||||
|
||||
<Style Selector="TextBlock.code">
|
||||
<!--<Setter Property="FontFamily" Value="{StaticResource CodeFontFamily}" />-->
|
||||
</Style>
|
||||
</Styles>
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<SignAssembly>false</SignAssembly>
|
||||
<!--(SignAssembly)对此程序集进行签名会导致编译失败(CompileAvaloniaXamlTask)-->
|
||||
<RootNamespace>System.Application.UI</RootNamespace>
|
||||
<AssemblyName>Steam++</AssemblyName>
|
||||
<ApplicationIcon>Assets\Icon.ico</ApplicationIcon>
|
||||
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Avalonia\System.Application.SteamTools.Client.Desktop.Avalonia.csproj" />
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform\System.Application.SteamTools.Client.Desktop.Platform.csproj" />
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop\System.Application.SteamTools.Client.Desktop.csproj" />
|
||||
<ProjectReference Include="..\System.Common.CoreLib\System.Common.CoreLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform.Windows\System.Application.SteamTools.Client.Desktop.Platform.Windows.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`osx`)) Or ('$(OS)' == 'OSX' And !$(DefineConstants.Contains(`PUBLISH`))) ">
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform.Mac\System.Application.SteamTools.Client.Desktop.Platform.Mac.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`linux`)) Or ('$(OS)' == 'Unix' And !$(DefineConstants.Contains(`PUBLISH`))) ">
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform.Linux\System.Application.SteamTools.Client.Desktop.Platform.Linux.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="1.0.5">
|
||||
<Aliases>MessageBox_Avalonia</Aliases>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="**\*.xaml.cs">
|
||||
<DependentUpon>%(Filename)</DependentUpon>
|
||||
</Compile>
|
||||
<AvaloniaResource Include="**\*.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
</AvaloniaResource>
|
||||
<AvaloniaResource Include="Assets\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Remove="Styles\SideBar.axaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaXaml Remove="Styles\SideBar.axaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\Resources\AppIcon\VisualElements_150.png">
|
||||
<Link>Assets\VisualElements_150.png</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\Resources\AppIcon\VisualElements_70.png">
|
||||
<Link>Assets\VisualElements_70.png</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Include="..\Resources\AppIcon\visualelementsmanifest.xml">
|
||||
<Link>steam++.visualelementsmanifest.xml</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,33 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
namespace System.Application.UI
|
||||
{
|
||||
public class ViewLocator : IDataTemplate
|
||||
{
|
||||
#pragma warning disable CA1822 // 将成员标记为 static
|
||||
public bool SupportsRecycling => false;
|
||||
#pragma warning restore CA1822 // 将成员标记为 static
|
||||
|
||||
public IControl Build(object data)
|
||||
{
|
||||
var name = data.GetType().FullName?.Replace("ViewModel", "View");
|
||||
var type = name == null ? null : Type.GetType(name);
|
||||
if (type != null)
|
||||
{
|
||||
var view = (Control?)Activator.CreateInstance(type);
|
||||
if (view != null)
|
||||
{
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return new TextBlock { Text = "Not Found: " + name };
|
||||
}
|
||||
|
||||
public bool Match(object data)
|
||||
{
|
||||
return data is ViewModelBase;
|
||||
}
|
||||
}
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
using ReactiveUI;
|
||||
using System.Properties;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
public class MainWindowViewModel : WindowViewModel
|
||||
{
|
||||
bool mTopmost;
|
||||
|
||||
public bool Topmost
|
||||
{
|
||||
get => mTopmost;
|
||||
set => this.RaiseAndSetIfChanged(ref mTopmost, value);
|
||||
}
|
||||
|
||||
public MainWindowViewModel() : base()
|
||||
{
|
||||
Title = ThisAssembly.AssemblyTrademark;
|
||||
SettingsPage = GetViewModel<SettingsPageViewModel>();
|
||||
}
|
||||
|
||||
#region ResStrings
|
||||
|
||||
string mWelcome = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string Welcome
|
||||
{
|
||||
get => mWelcome;
|
||||
set => this.RaiseAndSetIfChanged(ref mWelcome, value);
|
||||
}
|
||||
|
||||
string mCommunityFix = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string CommunityFix
|
||||
{
|
||||
get => mCommunityFix;
|
||||
set => this.RaiseAndSetIfChanged(ref mCommunityFix, value);
|
||||
}
|
||||
|
||||
string mUserFastChange = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string UserFastChange
|
||||
{
|
||||
get => mUserFastChange;
|
||||
set => this.RaiseAndSetIfChanged(ref mUserFastChange, value);
|
||||
}
|
||||
|
||||
string mSteamApps = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string SteamApps
|
||||
{
|
||||
get => mSteamApps;
|
||||
set => this.RaiseAndSetIfChanged(ref mSteamApps, value);
|
||||
}
|
||||
|
||||
string mSteamAuth = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string SteamAuth
|
||||
{
|
||||
get => mSteamAuth;
|
||||
set => this.RaiseAndSetIfChanged(ref mSteamAuth, value);
|
||||
}
|
||||
|
||||
string mGameRelated = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string GameRelated
|
||||
{
|
||||
get => mGameRelated;
|
||||
set => this.RaiseAndSetIfChanged(ref mGameRelated, value);
|
||||
}
|
||||
|
||||
string mSettings = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string Settings
|
||||
{
|
||||
get => mSettings;
|
||||
set => this.RaiseAndSetIfChanged(ref mSettings, value);
|
||||
}
|
||||
|
||||
string mAbout = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string About
|
||||
{
|
||||
get => mAbout;
|
||||
set => this.RaiseAndSetIfChanged(ref mAbout, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public SettingsPageViewModel SettingsPage { get; }
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
using Avalonia.Controls;
|
||||
using ReactiveUI;
|
||||
using System.Application.Services;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
public class SettingsPageViewModel : ViewModelBase, ILocalizationViewModel
|
||||
{
|
||||
#region ResStrings
|
||||
|
||||
string mSettings_General = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string Settings_General
|
||||
{
|
||||
get => mSettings_General;
|
||||
set => this.RaiseAndSetIfChanged(ref mSettings_General, value);
|
||||
}
|
||||
|
||||
string mSettings_Auth = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string Settings_Auth
|
||||
{
|
||||
get => mSettings_Auth;
|
||||
set => this.RaiseAndSetIfChanged(ref mSettings_Auth, value);
|
||||
}
|
||||
|
||||
string mLanguage = string.Empty;
|
||||
|
||||
[ResString]
|
||||
public string Language
|
||||
{
|
||||
get => mLanguage;
|
||||
set => this.RaiseAndSetIfChanged(ref mLanguage, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public SettingsPageViewModel()
|
||||
{
|
||||
Languages = ILocalizationService.Languages.Select(Convert).ToList();
|
||||
}
|
||||
|
||||
int mCurrentLanguageIndex;
|
||||
|
||||
public int CurrentLanguageIndex
|
||||
{
|
||||
get => mCurrentLanguageIndex;
|
||||
set
|
||||
{
|
||||
this.RaiseAndSetIfChanged(ref mCurrentLanguageIndex, value);
|
||||
if (!IsInDesignMode)
|
||||
{
|
||||
var localizationService = DI.Get<ILocalizationService>();
|
||||
var cultureName = Languages[value].Tag?.ToString();
|
||||
if (string.IsNullOrWhiteSpace(cultureName))
|
||||
{
|
||||
cultureName = localizationService.DefaultCurrentUICulture?.Name;
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(cultureName))
|
||||
{
|
||||
localizationService.ChangeLanguage(cultureName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<ComboBoxItem> Languages { get; }
|
||||
|
||||
static ComboBoxItem Convert(KeyValuePair<string, string> pair)
|
||||
=> new ComboBoxItem { Tag = pair.Key, Content = pair.Value };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:System.Application.UI.ViewModels"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="1350" d:DesignHeight="700"
|
||||
xmlns:pages="clr-namespace:System.Application.UI.Pages"
|
||||
x:Class="System.Application.UI.Views.MainView"
|
||||
FontSize="14"
|
||||
Foreground="{StaticResource SystemBaseHighColor}">
|
||||
<Design.DataContext>
|
||||
<vm:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
<Panel>
|
||||
<DockPanel HorizontalAlignment="Stretch">
|
||||
<ExperimentalAcrylicBorder DockPanel.Dock="Left" Width="240">
|
||||
<ExperimentalAcrylicBorder.Material>
|
||||
<ExperimentalAcrylicMaterial TintColor="Black" MaterialOpacity="0.85" TintOpacity="1"/>
|
||||
</ExperimentalAcrylicBorder.Material>
|
||||
<!--<AutoCompleteBox HorizontalAlignment="Stretch" Margin="20 40 20 0" Watermark="Search" Items="{Binding SearchItems}" />-->
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Height="110" VerticalAlignment="Top">
|
||||
<Image Source="/Assets/Icon.ico" Height="64" Width="64" VerticalAlignment="Center" Margin="-8,0,0,0"/>
|
||||
<Label Content="Steam++" VerticalContentAlignment="Center" FontSize="20" Margin="8,0,0,0"/>
|
||||
</StackPanel>
|
||||
</ExperimentalAcrylicBorder>
|
||||
<ExperimentalAcrylicBorder IsHitTestVisible="False">
|
||||
<ExperimentalAcrylicBorder.Material>
|
||||
<ExperimentalAcrylicMaterial TintColor="#222222" MaterialOpacity="0.85" TintOpacity="1"/>
|
||||
</ExperimentalAcrylicBorder.Material>
|
||||
<TextBlock Text="{Binding #TabControl.SelectedItem.Header}" Margin="40 20" FontSize="32" FontWeight="Light"/>
|
||||
</ExperimentalAcrylicBorder>
|
||||
</DockPanel>
|
||||
|
||||
<TabControl x:Name="TabControl" Classes="sidebar" Margin="0 40 0 20">
|
||||
<TabItem Header="{Binding Path=Welcome}">
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=CommunityFix}">
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=UserFastChange}">
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=SteamAuth}">
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=SteamAuth}">
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=GameRelated}">
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=Settings}">
|
||||
<pages:SettingsPage />
|
||||
</TabItem>
|
||||
<TabItem Header="{Binding Path=About}">
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Panel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,18 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace System.Application.UI.Views
|
||||
{
|
||||
public class MainView : UserControl
|
||||
{
|
||||
public MainView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<FluentWindow xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="clr-namespace:System.Application.UI.ViewModels"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
d:DesignWidth="1350" Width="1400" MinWidth="800"
|
||||
d:DesignHeight="700" Height="800" MinHeight="600"
|
||||
xmlns:pages="clr-namespace:System.Application.UI.Pages"
|
||||
xmlns:local="clr-namespace:System.Application.UI.Views"
|
||||
x:Class="System.Application.UI.Views.MainWindow"
|
||||
x:Name="MainWindow"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Background="{x:Null}"
|
||||
Title="{Binding Title}"
|
||||
Topmost="{Binding Topmost}">
|
||||
<FluentWindow.Styles>
|
||||
<Style Selector="TitleBar:fullscreen">
|
||||
<Setter Property="Background" Value="#7f000000" />
|
||||
</Style>
|
||||
</FluentWindow.Styles>
|
||||
|
||||
<Design.DataContext>
|
||||
<vm:MainWindowViewModel/>
|
||||
</Design.DataContext>
|
||||
|
||||
<Panel Margin="{Binding #MainWindow.OffScreenMargin}">
|
||||
<local:MainView />
|
||||
</Panel>
|
||||
</FluentWindow>
|
||||
@@ -0,0 +1,23 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
namespace System.Application.UI.Views
|
||||
{
|
||||
public class MainWindow : FluentWindow
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class MainThreadPlatformServiceImpl : IMainThreadPlatformService
|
||||
{
|
||||
public bool PlatformIsMainThread => Dispatcher.UIThread.CheckAccess();
|
||||
|
||||
public void PlatformBeginInvokeOnMainThread(Action action) => Dispatcher.UIThread.Post(action);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using Avalonia.Input;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Application.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// 拖拽功能工具类
|
||||
/// https://github.com/AvaloniaUI/Avalonia/blob/0.10.0-preview6/samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
|
||||
/// </summary>
|
||||
public static class DragDropUtil
|
||||
{
|
||||
public static void InitDragDrop(this IOnDragDropListener listener,
|
||||
InputElement element)
|
||||
{
|
||||
element.PointerPressed += async (_, e)
|
||||
=> await DragDrop.DoDragDrop(e, new DataObject(), DragDropEffects.Copy);
|
||||
element.AddHandler(DragDrop.DropEvent, Drop);
|
||||
element.AddHandler(DragDrop.DragOverEvent, DragOver);
|
||||
|
||||
void DragOver(object? s, DragEventArgs? e)
|
||||
{
|
||||
if (e?.Data == null) return;
|
||||
listener.DragOver(s is InputElement el ? el : element, e);
|
||||
}
|
||||
|
||||
void Drop(object? s, DragEventArgs? e)
|
||||
{
|
||||
if (e?.Data == null) return;
|
||||
listener.Drop(s is InputElement el ? el : element, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitDragDrop(this IOnDragDropListener listener,
|
||||
IEnumerable<InputElement> elements)
|
||||
{
|
||||
foreach (var element in elements)
|
||||
{
|
||||
listener.InitDragDrop(element);
|
||||
}
|
||||
}
|
||||
|
||||
public static void InitDragDrop(this IOnDragDropListener listener,
|
||||
params InputElement[] elements)
|
||||
{
|
||||
IEnumerable<InputElement> elements_ = elements;
|
||||
listener.InitDragDrop(elements_);
|
||||
}
|
||||
|
||||
public interface IOnDragDropListener
|
||||
{
|
||||
void DragOver(InputElement sender, DragEventArgs e)
|
||||
{
|
||||
// Only allow Copy or Link as Drop Operations.
|
||||
e.DragEffects &= (DragDropEffects.Copy | DragDropEffects.Link);
|
||||
|
||||
// Only allow if the dragged data contains text or filenames.
|
||||
if (!e.Data.Contains(DataFormats.Text)
|
||||
&& !e.Data.Contains(DataFormats.FileNames))
|
||||
e.DragEffects = DragDropEffects.None;
|
||||
}
|
||||
|
||||
void Drop(InputElement sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.Contains(DataFormats.Text))
|
||||
{
|
||||
var text = e.Data.GetText();
|
||||
if (text != null)
|
||||
{
|
||||
DropText(sender, text);
|
||||
}
|
||||
}
|
||||
else if (e.Data.Contains(DataFormats.FileNames))
|
||||
{
|
||||
var fileNames = e.Data.GetFileNames();
|
||||
if (fileNames != null)
|
||||
{
|
||||
DropFileNames(sender, fileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拖拽文本
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="text"></param>
|
||||
void DropText(InputElement sender, string text);
|
||||
|
||||
/// <summary>
|
||||
/// 拖拽路径,路径可能是文件也可能是文件夹
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="fileNames"></param>
|
||||
void DropFileNames(InputElement sender, IEnumerable<string> fileNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddMainThreadPlatformService(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IMainThreadPlatformService, MainThreadPlatformServiceImpl>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>System</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop\System.Application.SteamTools.Client.Desktop.csproj" />
|
||||
<ProjectReference Include="..\System.Common.CoreLib\System.Common.CoreLib.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.10.0" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.10.0" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.0" />
|
||||
<PackageReference Include="MessageBox.Avalonia" Version="1.0.5">
|
||||
<Aliases>MessageBox_Avalonia</Aliases>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,113 @@
|
||||
extern alias MessageBox_Avalonia;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using MessageBox_Avalonia::MessageBox.Avalonia;
|
||||
using MessageBox_Avalonia::MessageBox.Avalonia.BaseWindows.Base;
|
||||
using MessageBox_Avalonia::MessageBox.Avalonia.DTO;
|
||||
using MessageBox_Avalonia::MessageBox.Avalonia.Enums;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 显示消息框。
|
||||
/// </summary>
|
||||
public static class MessageBox
|
||||
{
|
||||
static ButtonEnum GetButtonEnum(this MessageBoxButton button) => button switch
|
||||
{
|
||||
MessageBoxButton.OK => ButtonEnum.Ok,
|
||||
MessageBoxButton.OKCancel => ButtonEnum.OkCancel,
|
||||
MessageBoxButton.YesNo => ButtonEnum.YesNo,
|
||||
MessageBoxButton.YesNoCancel => ButtonEnum.YesNoCancel,
|
||||
#pragma warning disable CS0618 // 类型或成员已过时
|
||||
MessageBoxButton.OkAbort => ButtonEnum.OkAbort,
|
||||
MessageBoxButton.YesNoAbort => ButtonEnum.YesNoAbort,
|
||||
#pragma warning restore CS0618 // 类型或成员已过时
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(button), $"value: {button}"),
|
||||
};
|
||||
|
||||
static Icon GetIcon(this MessageBoxImage icon) => icon switch
|
||||
{
|
||||
MessageBoxImage.Asterisk => Icon.Info,
|
||||
MessageBoxImage.Error => Icon.Error,
|
||||
MessageBoxImage.Exclamation => Icon.Warning,
|
||||
MessageBoxImage.None => Icon.None,
|
||||
#pragma warning disable CS0618 // 类型或成员已过时
|
||||
MessageBoxImage.Question => Icon.Info,
|
||||
MessageBoxImage.Battery => Icon.Battery,
|
||||
MessageBoxImage.Database => Icon.Database,
|
||||
MessageBoxImage.Folder => Icon.Folder,
|
||||
MessageBoxImage.Forbidden => Icon.Forbidden,
|
||||
MessageBoxImage.Plus => Icon.Plus,
|
||||
MessageBoxImage.Setting => Icon.Setting,
|
||||
MessageBoxImage.SpeakerLess => Icon.SpeakerLess,
|
||||
MessageBoxImage.SpeakerMore => Icon.SpeakerMore,
|
||||
MessageBoxImage.Stop2 => Icon.Stop,
|
||||
MessageBoxImage.Stopwatch => Icon.Stopwatch,
|
||||
MessageBoxImage.Wifi => Icon.Wifi,
|
||||
#pragma warning restore CS0618 // 类型或成员已过时
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(icon), $"value: {icon}"),
|
||||
};
|
||||
|
||||
static MessageBoxResult GetResult(this ButtonResult result) => result switch
|
||||
{
|
||||
ButtonResult.Ok => MessageBoxResult.OK,
|
||||
ButtonResult.Yes => MessageBoxResult.Yes,
|
||||
ButtonResult.No => MessageBoxResult.No,
|
||||
#pragma warning disable CS0618 // 类型或成员已过时
|
||||
ButtonResult.Abort => MessageBoxResult.Abort,
|
||||
#pragma warning restore CS0618 // 类型或成员已过时
|
||||
ButtonResult.Cancel => MessageBoxResult.Cancel,
|
||||
ButtonResult.None => MessageBoxResult.None,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(result), $"value: {result}"),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 显示一个消息框,该消息框包含消息、标题栏标题、按钮和图标,并且返回结果。
|
||||
/// </summary>
|
||||
/// <param name="messageBoxText">一个 <see cref="string"/>,用于指定要显示的文本。</param>
|
||||
/// <param name="caption">一个 <see cref="string"/>,用于指定要显示的标题栏标题。</param>
|
||||
/// <param name="button">一个 <see cref="MessageBoxButton"/> 值,用于指定要显示哪个按钮或哪些按钮。</param>
|
||||
/// <param name="icon">一个 <see cref="MessageBoxImage"/> 值,用于指定要显示的图标。</param>
|
||||
/// <returns>一个 <see cref="MessageBoxResult"/> 值,用于指定用户单击了哪个消息框按钮。</returns>
|
||||
public static async Task<MessageBoxResult> ShowAsync(
|
||||
string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon)
|
||||
{
|
||||
var parms = new MessageBoxStandardParams
|
||||
{
|
||||
ButtonDefinitions = button.GetButtonEnum(),
|
||||
ContentTitle = caption,
|
||||
ContentMessage = messageBoxText,
|
||||
Icon = icon.GetIcon(),
|
||||
Style = Style.None,
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen,
|
||||
};
|
||||
var msBoxStandardWindow = MessageBoxManager.GetMessageBoxStandardWindow(parms);
|
||||
var window = GetWindow(msBoxStandardWindow);
|
||||
if (window != null)
|
||||
{
|
||||
window.Topmost = true;
|
||||
window.SetResizeMode(ResizeMode.NoResize);
|
||||
window.SetDefaultFontFamily();
|
||||
}
|
||||
var result = await msBoxStandardWindow.Show();
|
||||
return GetResult(result);
|
||||
}
|
||||
|
||||
static Window? GetWindow(IMsBoxWindow<ButtonResult> window)
|
||||
{
|
||||
var _window = window.GetType().GetField("_window", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (_window != null && _window.FieldType.IsSubclassOf(typeof(Window)))
|
||||
{
|
||||
if (_window.GetValue(window) is Window w)
|
||||
{
|
||||
return w;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定显示在消息框上的按钮。 用作 <see cref="MessageBox"/>.Show... 方法的参数。
|
||||
/// </summary>
|
||||
public enum MessageBoxButton
|
||||
{
|
||||
OK = 0,
|
||||
OKCancel = 1,
|
||||
YesNo = 4,
|
||||
YesNoCancel = 3,
|
||||
|
||||
[Obsolete("non-standard api")]
|
||||
OkAbort = 1000,
|
||||
[Obsolete("non-standard api")]
|
||||
YesNoAbort = 1001,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定消息框所显示的图标。
|
||||
/// </summary>
|
||||
public enum MessageBoxImage
|
||||
{
|
||||
#pragma warning disable CA1069 // 不应复制枚举值
|
||||
Asterisk = 64,
|
||||
Error = 16,
|
||||
Exclamation = 48,
|
||||
Hand = 16,
|
||||
Information = 64,
|
||||
None = 0,
|
||||
[Obsolete("The question mark message icon is no longer recommended because it does not clearly represent a specific type of message and because the phrasing of a message as a question could apply to any message type. In addition, users can confuse the question mark symbol with a help information symbol. Therefore, do not use this question mark symbol in your message boxes. The system continues to support its inclusion only for backward compatibility.")]
|
||||
Question = 32,
|
||||
Stop = 16,
|
||||
Warning = 48,
|
||||
|
||||
[Obsolete("non-standard api")]
|
||||
Battery = 1000,
|
||||
[Obsolete("non-standard api")]
|
||||
Database,
|
||||
[Obsolete("non-standard api")]
|
||||
Folder,
|
||||
[Obsolete("non-standard api")]
|
||||
Forbidden,
|
||||
[Obsolete("non-standard api")]
|
||||
Plus,
|
||||
[Obsolete("non-standard api")]
|
||||
Setting,
|
||||
[Obsolete("non-standard api")]
|
||||
SpeakerLess,
|
||||
[Obsolete("non-standard api")]
|
||||
SpeakerMore,
|
||||
[Obsolete("non-standard api")]
|
||||
Stop2,
|
||||
[Obsolete("non-standard api")]
|
||||
Stopwatch,
|
||||
[Obsolete("non-standard api")]
|
||||
Wifi,
|
||||
#pragma warning restore CA1069 // 不应复制枚举值
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定用户单击的消息框按钮。 由 <see cref="MessageBox"/>.Show... 方法返回。
|
||||
/// </summary>
|
||||
public enum MessageBoxResult
|
||||
{
|
||||
Cancel = 2,
|
||||
No = 7,
|
||||
None = 0,
|
||||
OK = 1,
|
||||
Yes = 6,
|
||||
|
||||
[Obsolete("non-standard api")]
|
||||
Abort = 1000,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Application.Services;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 指定是否可以调整窗口大小,并在可调整大小的情况下指定如何调整窗口大小。由 SetResizeMode 使用。
|
||||
/// </summary>
|
||||
public enum ResizeMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户无法调整窗口的大小。 不显示 "最大化" 和 "最小化" 框。
|
||||
/// </summary>
|
||||
NoResize = IDesktopPlatformService.ResizeMode_NoResize,
|
||||
|
||||
/// <summary>
|
||||
/// 用户只能最小化窗口并从任务栏还原。 同时显示 "最小化" 和 "最大化" 框,但只启用 "最小化" 框。
|
||||
/// </summary>
|
||||
CanMinimize = IDesktopPlatformService.ResizeMode_CanMinimize,
|
||||
|
||||
/// <summary>
|
||||
/// 用户可以通过使用 "最小化" 和 "最大化" 框以及围绕窗口的可拖动轮廓来完全调整窗口的大小。 显示和启用 "最小化" 和 "最大化" 框。 (默认) 。
|
||||
/// </summary>
|
||||
CanResize = IDesktopPlatformService.ResizeMode_CanResize,
|
||||
|
||||
/// <summary>
|
||||
/// 此选项具有与相同的功能 <see cref="CanResize"/> ,但会将 "调整手柄" 添加到窗口的右下角。
|
||||
/// </summary>
|
||||
[Obsolete("not implemented")]
|
||||
CanResizeWithGrip = IDesktopPlatformService.ResizeMode_CanResizeWithGrip,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
using System.Application.Services;
|
||||
using System.IO;
|
||||
using FontFamily = Avalonia.Media.FontFamily;
|
||||
using Window = Avalonia.Controls.Window;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
/// <summary>
|
||||
/// 通过扩展兼容WPF部分API的内容
|
||||
/// </summary>
|
||||
public static partial class WpfCompatExtensions
|
||||
{
|
||||
static readonly Lazy<bool> lazy_has_msyh = new Lazy<bool>(() =>
|
||||
{
|
||||
if (DI.Platform == Platform.Windows)
|
||||
{
|
||||
var fontsPath = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
|
||||
var msyhFilePath = Path.Combine(fontsPath, "msyh.ttc");
|
||||
return File.Exists(msyhFilePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
public static bool HAS_FONT_MSYH => lazy_has_msyh.Value;
|
||||
|
||||
public static void SetDefaultFontFamily(this Window window)
|
||||
{
|
||||
if (DI.Platform == Platform.Windows)
|
||||
{
|
||||
if (HAS_FONT_MSYH) // (版权、许可)不能在非WinOS上使用 微软雅黑字体,不可将字体嵌入程序
|
||||
{
|
||||
string name;
|
||||
var major = Environment.OSVersion.Version.Major;
|
||||
if (major > 6 || (major == 6 && Environment.OSVersion.Version.Minor >= 2))
|
||||
{
|
||||
name = "Microsoft YaHei UI";
|
||||
}
|
||||
else
|
||||
{
|
||||
name = "Microsoft YaHei";
|
||||
}
|
||||
window.FontFamily = new FontFamily(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置调整大小模式。
|
||||
/// </summary>
|
||||
/// <param name="window"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void SetResizeMode(this Window window, ResizeMode value)
|
||||
{
|
||||
var p = DI.Get<IDesktopPlatformService>();
|
||||
switch (value)
|
||||
{
|
||||
case ResizeMode.NoResize:
|
||||
case ResizeMode.CanMinimize:
|
||||
window.CanResize = false;
|
||||
break;
|
||||
case ResizeMode.CanResize:
|
||||
#pragma warning disable CS0618 // 类型或成员已过时
|
||||
case ResizeMode.CanResizeWithGrip:
|
||||
#pragma warning restore CS0618 // 类型或成员已过时
|
||||
window.CanResize = true;
|
||||
break;
|
||||
}
|
||||
p.SetResizeMode(window.PlatformImpl.Handle.Handle, (int)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class LinuxDesktopPlatformServiceImpl : IDesktopPlatformService
|
||||
{
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddDesktopPlatformService(this IServiceCollection services)
|
||||
{
|
||||
if (DI.Platform == Platform.Linux)
|
||||
{
|
||||
services.AddSingleton<IDesktopPlatformService, LinuxDesktopPlatformServiceImpl>();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>System.Application.Services</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform\System.Application.SteamTools.Client.Desktop.Platform.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class MacDesktopPlatformServiceImpl : IDesktopPlatformService
|
||||
{
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddDesktopPlatformService(this IServiceCollection services)
|
||||
{
|
||||
if (DI.Platform == Platform.Apple)
|
||||
{
|
||||
services.AddSingleton<IDesktopPlatformService, MacDesktopPlatformServiceImpl>();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>System.Application.Services</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform\System.Application.SteamTools.Client.Desktop.Platform.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
[SupportedOSPlatform("Windows")]
|
||||
internal sealed class WindowsDesktopPlatformServiceImpl : IDesktopPlatformService
|
||||
{
|
||||
#region 窗口右上角的三个按钮(最小化,最大化,关闭)
|
||||
|
||||
// https://stackoverflow.com/questions/339620/how-do-i-remove-minimize-and-maximize-from-a-resizable-window-in-wpf
|
||||
// https://blog.magnusmontin.net/2014/11/30/disabling-or-hiding-the-minimize-maximize-or-close-button-of-a-wpf-window/
|
||||
|
||||
public const int MF_BYCOMMAND = 0x00000000;
|
||||
public const int SC_CLOSE = 0xF060;
|
||||
public const int SC_MINIMIZE = 0xF020;
|
||||
public const int SC_MAXIMIZE = 0xF030;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern int DeleteMenu(IntPtr hMenu, int nPosition, int wFlags);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
|
||||
|
||||
public const int GWL_STYLE = -16,
|
||||
WS_MAXIMIZEBOX = 0x10000,
|
||||
WS_MINIMIZEBOX = 0x20000;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public extern static int GetWindowLong(IntPtr hwnd, int index);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public extern static int SetWindowLong(IntPtr hwnd, int index, int value);
|
||||
|
||||
public const int WS_SYSMENU = 0x80000;
|
||||
|
||||
public static void EnableMinimizeButton(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_MINIMIZEBOX);
|
||||
}
|
||||
|
||||
public static void EnableMaximizeButton(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_MAXIMIZEBOX);
|
||||
}
|
||||
|
||||
public static void ShowMinimizeAndMaximizeButtons(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
|
||||
}
|
||||
|
||||
public static void ShowAllButtons(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) | WS_SYSMENU);
|
||||
}
|
||||
|
||||
public static void HideMinimizeAndMaximizeButtons(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX);
|
||||
}
|
||||
|
||||
public static void DisableMinimizeButton(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_MINIMIZEBOX);
|
||||
}
|
||||
|
||||
public static void DisableMaximizeButton(IntPtr hWnd)
|
||||
{
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);
|
||||
}
|
||||
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case IDesktopPlatformService.ResizeMode_NoResize:
|
||||
_ = DeleteMenu(GetSystemMenu(hWnd, false), SC_MAXIMIZE, MF_BYCOMMAND);
|
||||
_ = DeleteMenu(GetSystemMenu(hWnd, false), SC_MINIMIZE, MF_BYCOMMAND);
|
||||
HideMinimizeAndMaximizeButtons(hWnd);
|
||||
break;
|
||||
case IDesktopPlatformService.ResizeMode_CanMinimize:
|
||||
_ = DeleteMenu(GetSystemMenu(hWnd, false), SC_MAXIMIZE, MF_BYCOMMAND);
|
||||
DisableMaximizeButton(hWnd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
public static IServiceCollection AddDesktopPlatformService(this IServiceCollection services)
|
||||
{
|
||||
if (DI.Platform == Platform.Windows)
|
||||
{
|
||||
services.AddSingleton<IDesktopPlatformService, WindowsDesktopPlatformServiceImpl>();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>System.Application.Services</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform\System.Application.SteamTools.Client.Desktop.Platform.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
using ResizeMode = System.Int32;
|
||||
|
||||
namespace System.Application.Services
|
||||
{
|
||||
public interface IDesktopPlatformService
|
||||
{
|
||||
void SetResizeMode(IntPtr hWnd, ResizeMode value);
|
||||
|
||||
public const ResizeMode ResizeMode_NoResize = 0;
|
||||
public const ResizeMode ResizeMode_CanMinimize = 1;
|
||||
public const ResizeMode ResizeMode_CanResize = 2;
|
||||
public const ResizeMode ResizeMode_CanResizeWithGrip = 3;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
public class DesktopPlatformServiceImpl : IDesktopPlatformService
|
||||
{
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>System.Application.Services</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client\System.Application.SteamTools.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,133 @@
|
||||
using System.Threading.Tasks;
|
||||
using static System.Application.Services.IMainThreadPlatformService;
|
||||
|
||||
namespace System.Application
|
||||
{
|
||||
/// <summary>
|
||||
/// 适用于桌面端的主线程帮助类,参考 Xamarin.Essentials.MainThread
|
||||
/// <para><see cref="https://github.com/xamarin/Essentials/blob/main/Xamarin.Essentials/MainThread/MainThread.shared.cs"/></para>
|
||||
/// </summary>
|
||||
public static class MainThreadDesktop
|
||||
{
|
||||
public static bool IsMainThread => Instance.PlatformIsMainThread;
|
||||
|
||||
public static void BeginInvokeOnMainThread(Action action)
|
||||
{
|
||||
if (IsMainThread)
|
||||
{
|
||||
action();
|
||||
}
|
||||
else
|
||||
{
|
||||
Instance.PlatformBeginInvokeOnMainThread(action);
|
||||
}
|
||||
}
|
||||
|
||||
public static Task InvokeOnMainThreadAsync(Action action)
|
||||
{
|
||||
if (IsMainThread)
|
||||
{
|
||||
action();
|
||||
#if NETSTANDARD1_0
|
||||
return Task.FromResult(true);
|
||||
#else
|
||||
return Task.CompletedTask;
|
||||
#endif
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
|
||||
BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
action();
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public static Task<T> InvokeOnMainThreadAsync<T>(Func<T> func)
|
||||
{
|
||||
if (IsMainThread)
|
||||
{
|
||||
return Task.FromResult(func());
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<T>();
|
||||
|
||||
BeginInvokeOnMainThread(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = func();
|
||||
tcs.TrySetResult(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tcs.TrySetException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public static Task InvokeOnMainThreadAsync(Func<Task> funcTask)
|
||||
{
|
||||
if (IsMainThread)
|
||||
{
|
||||
return funcTask();
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<object?>();
|
||||
|
||||
BeginInvokeOnMainThread(
|
||||
async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await funcTask().ConfigureAwait(false);
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
tcs.SetException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public static Task<T> InvokeOnMainThreadAsync<T>(Func<Task<T>> funcTask)
|
||||
{
|
||||
if (IsMainThread)
|
||||
{
|
||||
return funcTask();
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<T>();
|
||||
|
||||
BeginInvokeOnMainThread(
|
||||
async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var ret = await funcTask().ConfigureAwait(false);
|
||||
tcs.SetResult(ret);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
tcs.SetException(e);
|
||||
}
|
||||
});
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加本地化、多语言服务
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddLocalizationService(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<ILocalizationService, LocalizationServiceImpl>();
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加视图模型组服务
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddViewModelCollectionService(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(new ViewModelCollectionServiceImpl(services));
|
||||
services.AddSingleton<IViewModelCollectionService>(s => s.GetRequiredService<ViewModelCollectionServiceImpl>());
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加视图模型
|
||||
/// </summary>
|
||||
/// <typeparam name="TViewModel"></typeparam>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddViewModel<TViewModel>(this IServiceCollection services) where TViewModel : ViewModelBase
|
||||
{
|
||||
services.AddSingleton<TViewModel>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Application.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 本地化、多语言服务
|
||||
/// </summary>
|
||||
public interface ILocalizationService
|
||||
{
|
||||
CultureInfo DefaultCurrentUICulture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 更改语言
|
||||
/// </summary>
|
||||
/// <param name="cultureName"></param>
|
||||
void ChangeLanguage(string cultureName);
|
||||
|
||||
/// <summary>
|
||||
/// 绑定资源字符串的视图模型组
|
||||
/// </summary>
|
||||
ILocalizationViewModel[] ViewModels { get; }
|
||||
|
||||
public static IList<KeyValuePair<string, string>> Languages;
|
||||
|
||||
static ILocalizationService()
|
||||
{
|
||||
Languages = new Dictionary<string, string>()
|
||||
{
|
||||
{ "", "Auto" },
|
||||
{ "en", "English" },
|
||||
{ "zh-Hans", "Chinese(Simplified)" },
|
||||
{ "zh-Hant", "Chinese(Traditional)" },
|
||||
}.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace System.Application.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 由平台实现的主线程帮助类
|
||||
/// </summary>
|
||||
public interface IMainThreadPlatformService
|
||||
{
|
||||
bool PlatformIsMainThread { get; }
|
||||
|
||||
void PlatformBeginInvokeOnMainThread(Action action);
|
||||
|
||||
public static IMainThreadPlatformService Instance => DI.Get<IMainThreadPlatformService>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Application.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// 视图模型组服务
|
||||
/// </summary>
|
||||
public interface IViewModelCollectionService
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取所有的视图模型
|
||||
/// </summary>
|
||||
IEnumerable<ViewModelBase> ViewModels { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 根据类型过滤获取视图模型
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
IEnumerable<T> GetViewModels<T>();
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class LocalizationServiceImpl : ILocalizationService
|
||||
{
|
||||
readonly IViewModelCollectionService vmss;
|
||||
|
||||
public LocalizationServiceImpl(IViewModelCollectionService vmss)
|
||||
{
|
||||
this.vmss = vmss;
|
||||
DefaultCurrentUICulture = CultureInfo.CurrentUICulture;
|
||||
}
|
||||
|
||||
public CultureInfo DefaultCurrentUICulture { get; }
|
||||
|
||||
ILocalizationViewModel[]? viewModels;
|
||||
|
||||
public ILocalizationViewModel[] ViewModels
|
||||
{
|
||||
get
|
||||
{
|
||||
if (viewModels == null)
|
||||
{
|
||||
viewModels = vmss.GetViewModels<ILocalizationViewModel>().ToArray();
|
||||
}
|
||||
return viewModels;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsMatch(CultureInfo cultureInfo, string cultureName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(cultureInfo.Name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (cultureInfo.Name == cultureName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return IsMatch(cultureInfo.Parent, cultureName);
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeLanguage(string cultureName)
|
||||
{
|
||||
if (IsMatch(CultureInfo.CurrentUICulture, cultureName)) return;
|
||||
if (!ViewModels.Any()) return;
|
||||
void ChangeLanguage()
|
||||
{
|
||||
CultureInfo.CurrentUICulture = new CultureInfo(cultureName);
|
||||
foreach (var viewModel in ViewModels)
|
||||
{
|
||||
viewModel.OnChangeLanguage();
|
||||
}
|
||||
}
|
||||
MainThreadDesktop.BeginInvokeOnMainThread(ChangeLanguage);
|
||||
}
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class ViewModelCollectionServiceImpl : IViewModelCollectionService
|
||||
{
|
||||
readonly IEnumerable<ServiceDescriptor> services;
|
||||
|
||||
public ViewModelCollectionServiceImpl(IEnumerable<ServiceDescriptor> services)
|
||||
{
|
||||
this.services = services;
|
||||
}
|
||||
|
||||
public IEnumerable<ViewModelBase> ViewModels => GetViewModels<ViewModelBase>();
|
||||
|
||||
public IEnumerable<T> GetViewModels<T>()
|
||||
{
|
||||
var tType = typeof(T);
|
||||
var vType = typeof(ViewModelBase);
|
||||
var tIsvType = tType == vType;
|
||||
return from s in services
|
||||
where s.ServiceType == s.ImplementationType &&
|
||||
s.Lifetime == ServiceLifetime.Singleton &&
|
||||
tType.IsAssignableFrom(s.ImplementationType) &&
|
||||
(tIsvType || vType.IsAssignableFrom(s.ImplementationType))
|
||||
select (T)DI.Get(s.ServiceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RootNamespace>System.Application</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\System.Common.CoreLib\Properties\AssemblyInfo.cs">
|
||||
<Link>Properties\AssemblyInfo.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI" Version="13.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client.Desktop.Platform\System.Application.SteamTools.Client.Desktop.Platform.csproj" />
|
||||
<ProjectReference Include="..\System.Application.SteamTools.Client\System.Application.SteamTools.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="UI\Resx\AppResources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>AppResources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="UI\Resx\AppResources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>AppResources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本:4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能会导致不正确的行为,并且如果
|
||||
// 重新生成代码,这些更改将会丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Application.UI.Resx {
|
||||
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()]
|
||||
public class AppResources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal AppResources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存的 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public 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.Resx.AppResources", typeof(AppResources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 关于 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string About {
|
||||
get {
|
||||
return ResourceManager.GetString("About", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 社区加速 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string CommunityFix {
|
||||
get {
|
||||
return ResourceManager.GetString("CommunityFix", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 库存游戏 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameList {
|
||||
get {
|
||||
return ResourceManager.GetString("GameList", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 游戏功能 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string GameRelated {
|
||||
get {
|
||||
return ResourceManager.GetString("GameRelated", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 语言 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Language {
|
||||
get {
|
||||
return ResourceManager.GetString("Language", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 设置 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Settings {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 令牌设置 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Settings_Auth {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings_Auth", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 基本设置 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Settings_General {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings_General", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 本地令牌 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string SteamAuth {
|
||||
get {
|
||||
return ResourceManager.GetString("SteamAuth", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 账号切换 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string UserFastChange {
|
||||
get {
|
||||
return ResourceManager.GetString("UserFastChange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查找类似 起始页 的本地化字符串。
|
||||
/// </summary>
|
||||
public static string Welcome {
|
||||
get {
|
||||
return ResourceManager.GetString("Welcome", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?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>
|
||||
<data name="About" xml:space="preserve">
|
||||
<value>About</value>
|
||||
</data>
|
||||
<data name="CommunityFix" xml:space="preserve">
|
||||
<value>Fix Steam 302 Error</value>
|
||||
</data>
|
||||
<data name="GameList" xml:space="preserve">
|
||||
<value>My Games</value>
|
||||
</data>
|
||||
<data name="GameRelated" xml:space="preserve">
|
||||
<value>Game Related</value>
|
||||
</data>
|
||||
<data name="Language" xml:space="preserve">
|
||||
<value>Language</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
<data name="Settings_Auth" xml:space="preserve">
|
||||
<value>Auth Settings</value>
|
||||
</data>
|
||||
<data name="Settings_General" xml:space="preserve">
|
||||
<value>General Settings</value>
|
||||
</data>
|
||||
<data name="SteamAuth" xml:space="preserve">
|
||||
<value>Steam Auth</value>
|
||||
</data>
|
||||
<data name="UserFastChange" xml:space="preserve">
|
||||
<value>Account Change</value>
|
||||
</data>
|
||||
<data name="Welcome" xml:space="preserve">
|
||||
<value>Start Page</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,153 @@
|
||||
<?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>
|
||||
<data name="About" xml:space="preserve">
|
||||
<value>关于</value>
|
||||
</data>
|
||||
<data name="CommunityFix" xml:space="preserve">
|
||||
<value>社区加速</value>
|
||||
</data>
|
||||
<data name="GameList" xml:space="preserve">
|
||||
<value>库存游戏</value>
|
||||
</data>
|
||||
<data name="GameRelated" xml:space="preserve">
|
||||
<value>游戏功能</value>
|
||||
</data>
|
||||
<data name="Language" xml:space="preserve">
|
||||
<value>语言</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>设置</value>
|
||||
</data>
|
||||
<data name="Settings_Auth" xml:space="preserve">
|
||||
<value>令牌设置</value>
|
||||
</data>
|
||||
<data name="Settings_General" xml:space="preserve">
|
||||
<value>基本设置</value>
|
||||
</data>
|
||||
<data name="SteamAuth" xml:space="preserve">
|
||||
<value>本地令牌</value>
|
||||
</data>
|
||||
<data name="UserFastChange" xml:space="preserve">
|
||||
<value>账号切换</value>
|
||||
</data>
|
||||
<data name="Welcome" xml:space="preserve">
|
||||
<value>起始页</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,153 @@
|
||||
<?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>
|
||||
<data name="About" xml:space="preserve">
|
||||
<value>關於</value>
|
||||
</data>
|
||||
<data name="CommunityFix" xml:space="preserve">
|
||||
<value>社區加速</value>
|
||||
</data>
|
||||
<data name="GameList" xml:space="preserve">
|
||||
<value>遊戲列表</value>
|
||||
</data>
|
||||
<data name="GameRelated" xml:space="preserve">
|
||||
<value>遊戲功能</value>
|
||||
</data>
|
||||
<data name="Language" xml:space="preserve">
|
||||
<value>語言</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>設定</value>
|
||||
</data>
|
||||
<data name="Settings_Auth" xml:space="preserve">
|
||||
<value>令牌設定</value>
|
||||
</data>
|
||||
<data name="Settings_General" xml:space="preserve">
|
||||
<value>基本設定</value>
|
||||
</data>
|
||||
<data name="SteamAuth" xml:space="preserve">
|
||||
<value>本地令牌</value>
|
||||
</data>
|
||||
<data name="UserFastChange" xml:space="preserve">
|
||||
<value>帳號切換</value>
|
||||
</data>
|
||||
<data name="Welcome" xml:space="preserve">
|
||||
<value>起始頁</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Application.UI.Resx;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
/// <summary>
|
||||
/// 本地化、多语言视图模型
|
||||
/// </summary>
|
||||
public interface ILocalizationViewModel
|
||||
{
|
||||
public void OnChangeLanguage()
|
||||
{
|
||||
var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
var query = from p in properties
|
||||
let attr = p.GetCustomAttribute<ResStringAttribute>()
|
||||
where p.PropertyType == typeof(string) && attr != null
|
||||
select (p, attr.ResId);
|
||||
foreach (var (p, ResId) in query)
|
||||
{
|
||||
var resId = ResId ?? p.Name;
|
||||
var value = AppResources.ResourceManager.GetString(resId);
|
||||
p.SetValue(this, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public sealed class ResStringAttribute : Attribute
|
||||
{
|
||||
public string? ResId { get; }
|
||||
|
||||
public ResStringAttribute(string? resId = null)
|
||||
{
|
||||
ResId = resId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using ReactiveUI;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
public class ViewModelBase : ReactiveObject, ILocalizationViewModel
|
||||
{
|
||||
public ViewModelBase()
|
||||
{
|
||||
ILocalizationViewModel localization = this;
|
||||
localization.OnChangeLanguage();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否在设计器的上下文中运行
|
||||
/// </summary>
|
||||
public static bool IsInDesignMode { get; set; }
|
||||
|
||||
protected static TViewModel GetViewModel<TViewModel>() where TViewModel : ViewModelBase, new()
|
||||
{
|
||||
if (IsInDesignMode) return new TViewModel();
|
||||
return DI.Get<TViewModel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using ReactiveUI;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
public class WindowViewModel : ViewModelBase
|
||||
{
|
||||
string title = string.Empty;
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => title;
|
||||
set => this.RaiseAndSetIfChanged(ref title, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user