Compare commits

...
33 Commits
Author SHA1 Message Date
Aigio Liu 152c60a9c3 fix ci 2021-05-05 21:53:33 +08:00
rmbgame 6581d67f14 update 2021-05-05 21:52:33 +08:00
Aigio Liu cc5b161d92 v2.1.0 2021-05-05 21:45:07 +08:00
Aigio Liu c1f9d31e6d update cmd 2021-05-05 21:34:03 +08:00
rmbgame 1d09ec05ec update ui 2021-05-05 21:07:38 +08:00
rmbgame 4ced8453cf update Avalonia package 2021-05-05 20:22:46 +08:00
rmbgame a9b6774210 用户steam头像 2021-05-05 19:33:44 +08:00
Aigio Liu cad359bd91 无手机号时隐藏换绑手机 2021-05-05 19:06:30 +08:00
Aigio Liu d2918a9221 Steam 快速登录 2021-05-05 18:35:23 +08:00
rmbgame 276aa4fe15 steam login ui 2021-05-05 18:29:09 +08:00
rmbgame 24e98078ef fix file error 2021-05-05 18:29:09 +08:00
rmbgame d75420f255 修复了多个导致闪退的错误 2021-05-05 15:38:03 +08:00
rmbgame 236ed0a5f8 fix proxy crash error 2021-05-05 15:38:03 +08:00
rmbgame f3033498fb merger 2021-05-05 04:02:02 +08:00
rmbgame f739a5f387 调整脚本列表UI 2021-05-05 03:59:25 +08:00
rmbgame 0f0f50dcd5 close #179 2021-05-05 03:59:25 +08:00
rmbgame 8f6d4378fa 新增背景透明度UI设置 2021-05-05 03:59:25 +08:00
rmbgame da7d5ec814 修复成就解锁窗口不显示的问题 2021-05-05 03:57:33 +08:00
Aigio Liu 171705992b fix macos ci 2021-05-05 02:05:31 +08:00
Aigio Liu 398282f656 Steam 登录状态 Cookie + WebView3 2021-05-05 01:56:31 +08:00
Mossimo 17261c7706 fix tipsmsg 2021-05-04 23:40:52 +08:00
Aigio Liu 2e99ac9899 改进 手机号码号段
改进 UA
2021-05-04 21:18:55 +08:00
Aigio Liu 51dd188141 Steam 快速登录 for WebView3 100% 2021-05-04 18:58:16 +08:00
Aigio Liu 49e5e56fb1 Update ScreenShorts 2021-05-04 12:19:49 +08:00
rmbgame dcea1c6fbc fix other Platform 2021-05-04 06:29:46 +08:00
Mossimo fd3a5129ca fix Gmjs repeat only one remove other 2021-05-04 06:23:26 +08:00
rmbgame a811e5e43a 修复系统关机时应正确关闭掉启用的windows代理 2021-05-04 06:22:38 +08:00
rmbgame 44c3c27315 Absolute path 2021-05-04 06:22:38 +08:00
Aigio Liu 7642eea09d 更正资源文本 2021-05-04 02:40:05 +08:00
Aigio Liu 997f9f9282 Steam 快速登录 95% 2021-05-04 02:30:05 +08:00
Aigio Liu 55067a198a 改进 自动更新 2021-05-04 00:27:29 +08:00
Mossimo 6fd5338f4c fix script Build 2021-05-03 23:48:09 +08:00
Mossimo ea277b218b sfix RefreshScriptItemButton 2021-05-03 23:01:04 +08:00
121 changed files with 2126 additions and 996 deletions
+5
View File
@@ -49,8 +49,13 @@ jobs:
run: dotnet build ./tests/Common.UnitTest/Common.UnitTest.csproj
- name: dotnet ST.Client.UnitTest build
run: dotnet build ./tests/ST.Client.UnitTest/ST.Client.UnitTest.csproj
- name: dotnet ST.Client.Desktop.UnitTest build
run: dotnet build ./tests/ST.Client.Desktop.UnitTest/ST.Client.Desktop.UnitTest.csproj
- name: dotnet CommonUnit test
run: dotnet test ./tests/Common.UnitTest/Common.UnitTest.csproj
- name: dotnet ST.Client.UnitTest test
run: dotnet test ./tests/ST.Client.UnitTest/ST.Client.UnitTest.csproj
- name: dotnet ST.Client.Desktop.UnitTest test
if: matrix.os != 'windows-latest'
run: dotnet test ./tests/ST.Client.Desktop.UnitTest/ST.Client.Desktop.UnitTest.csproj
+3
View File
@@ -24,6 +24,8 @@
[![Gitee Star](https://gitee.com/rmbgame/SteamTools/badge/star.svg)](https://gitee.com/rmbgame/SteamTools)
</div>
<div align="center"><img src="./resources/screenshots.en.jpg" /></div>
English | [简体中文](./README.md)
## ✨ Functions
@@ -139,6 +141,7 @@ Read what we [milestones](https://github.com/SteamTools-Team/SteamTools/mileston
* [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)
* [AspNet.Security.OpenId.Providers](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers)
* [CefNet](https://github.com/CefNet/CefNet)
* [CefSharp](https://github.com/cefsharp/CefSharp)
* [React](https://github.com/facebook/react)
* [Ant Design](https://github.com/ant-design/ant-design)
* [Ant Design Blazor](https://github.com/ant-design-blazor/ant-design-blazor)
+1
View File
@@ -153,6 +153,7 @@
* [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore)
* [AspNet.Security.OpenId.Providers](https://github.com/aspnet-contrib/AspNet.Security.OpenId.Providers)
* [CefNet](https://github.com/CefNet/CefNet)
* [CefSharp](https://github.com/cefsharp/CefSharp)
* [React](https://github.com/facebook/react)
* [Ant Design](https://github.com/ant-design/ant-design)
* [Ant Design Blazor](https://github.com/ant-design-blazor/ant-design-blazor)
-125
View File
@@ -1,125 +0,0 @@
## 前言
### 发布至今
Steam++从去年年底12月18日发布了[第一个版本](https://keylol.com/t667906-1-1)至今,已经过去了3个多月。这段时间我肝代码肝的特别勤快,游戏也不咋玩了。在此是感谢keylol的各位老哥对我发布时的支持,发布后短短一天时间就加了1k多体力。以及坛子里各位老哥对我的捐助支持,都非常感谢!
这段时间也发生了许多事情,目前软件没有任何服务器,所以凭下载量判断可能有几万用户吧。还是有10个以内的人与我反馈被盗号了,再此只能表示开源软件想盗号那是真的难如登天了。
### 后续计划
在此为了对得起大家的鼓励和捐助的支持,所以决定并启用了Steam++v2.0版本的开发,短期计划为之前所描述的预计推出功能以及答应大家添加的所有功能,并且做到支持全平台Windows Mac Linux Android iOS版本支持。
### 现在状况
我拉了我几位朋友来一起开发,现在有3个人参与到此项目了,所以开发速度也不会太慢。
## 问卷调查
我们对于2.0的设计开发目前作了一些计划,但更希望能够听到用户朋友们的宝贵意见和建议。为此我们做了一份问卷调查,希望大家能够来填写。
问卷地址:[https://www.wjx.cn/vj/Y0zCByQ.aspx](https://keylol.com/t667906-1-1)
或者扫码 [attachimg]1320065[/attachimg]
## Steam++v2.0 前瞻
### 界面大改
第一个改动最明显的地方就是界面。原先的界面UI不是很美观,文字堆砌太过复杂,在2.0版本将这些文字都简略化,改用更合适的布局界面。
### 多平台
Steam++将会支持Linux、macOS,也会登录安卓平台、IOS平台,由于各个平台兼容性不同以及开发速度的不足,这些平台会删减部分Windows平台上拥有的功能,当然后续会不断增加功能进行完善。
[attachimg]1320063[/attachimg]
### Steam++账号
2.0版本中将开放Steam++账号注册,账号注册登录后将能使用新增的各种联网服务,例如云同步、云挂卡、交易市场等。也能将自己的配置设置同步到多平台。
### 令牌云同步
在新版本中,大家可以使用Steam++生成自己的Steam令牌,并且将自己保存在电脑上的本地令牌加密上传到云端。这样可以在我们的各个平台上看到自己的令牌,无需频繁的导入导出。
在手机App上,大家可以导入PC端生成的令牌,也可以通过云同步获取到自己的令牌,解决了很多用户手机、电脑、平板无法同时查看令牌的尴尬问题。
关于安全问题:令牌将采用加密算法,通过含有用户自己添加的密匙来进行加密,服务器中只会保留加密后的数据。如果没有用户的密匙,任何人(包括Steam++开发组)都无法解开加密,从而使令牌无法读取直接作废。
这个功能将在2.0版本上线,手机端可能会延后上线。
### 本地反代加速改动
在界面上进行了大改,将同类反代(如Steam社区、Steam商店)合并到了一个按钮中,可以一次性全部启动也可以在设置中单独启动某一项反代功能。并且也会推出服务器加速的模式,可供选择使用。
### 本地令牌改动
在界面上进行了调整,使其更加美观。
添加了令牌生成功能,可以直接在Steam++中生成Steam令牌,无需从其他地方生成后再导入。而且之后做了手机端,可以形成互补,大概目标是取代steam手机app,真的不好用。
[attachimg]1320062[/attachimg]
### 云挂卡服务
在2.0版本推出后不久,将会更新云挂卡功能。大家可以使用我们的服务器进行24小时不间断地挂卡挂时长,并且可以用电脑客户端或者手机App来管理云挂卡进度。
这个功能预计在2.1版本上线。
### 云存档服务
大家可以上传自己的游戏存档进行备份保存,也可以选择分享自己的存档给其他人,或者在我们的Steam++社区内浏览下载其他人分享的存档。
Steam++会自动导入存档到正确的位置,保证能够让游戏正常读取。
这个功能还没开始做,估计要等一段时间才能发布。
### 交易市场
可以在交易市场上购买、出售自己多余的CDKey、Steam余额。在Steam++交易市场上能找到由个人卖家挂售游戏和余额。买家可以直接私聊卖家进行砍价,也可以查看到卖家的rep值,也能在交易后给对方好评或者差评,这将直接影响到被评论方的rep值。
同时Steam++也会作为中间担保人,杜绝欺骗行为的发生。
### 其它
更多的小功能就不太值一提了,但是因为太多,短期也不一定搞得完,再此列个说明,Steam下载完成自动关机、Steam Edit编辑Steam游戏信息、自动白嫖epic、steam游戏,Steam封面管理等等等有更多未列出。以及当我们在Steam平台做的差不多的时候,就会更多的开始钻研做其它平台功能。
## 写在最后
再此我可以保证程序将永远良心收费,不流氓不捆绑,所有本地功能永久免费,只有需要成本的服务端功能才会进行收费。并且程序依然开源发布,不会闭源。
(本来以前一直是想做游戏,但是低成本确实太难做好了,一个人开发独立游戏再怎么努力,依然问题太多,并且我得美术是在是差的离谱,就算是像素画自己都没眼看,退而求其次,先尝试别的,如果真的能赚钱,那就再接着做单机游戏!梦想不能放弃)
官网:[http://www.steamtool.net](http://www.steamtool.net)
目前临时使用此域名,后续迁移到steampp.net
GitHub:[https://github.com/rmbadmin/SteamTools/releases](https://github.com/rmbadmin/SteamTools/releases)
官方QQ群:479036439(1群已经满员,新开了2群)
又不知不觉肝了一通宵代码,因为确实需要了解大家对于收费的态度问题,所以发个帖做个小调查,睡醒了才能回复。
实在不知道发在什么区,那就当水贴了。
睡了,大家晚安{:17_1052:} 。
+37
View File
@@ -103,6 +103,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefNet.Avalonia", "referenc
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Tools.MinifyStaticSites", "src\ST.Tools.MinifyStaticSites\ST.Tools.MinifyStaticSites.csproj", "{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.Console.App", "src\ST.Client.Desktop.Console.App\ST.Client.Desktop.Console.App.csproj", "{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.UnitTest", "tests\ST.Client.Desktop.UnitTest\ST.Client.Desktop.UnitTest.csproj", "{E21D0376-0A18-4F46-9ED7-BE4466763B2D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -759,6 +763,38 @@ Global
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}.Release|x86.ActiveCfg = Release|Any CPU
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}.Release|x86.Build.0 = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|iPhone.Build.0 = Debug|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|x86.ActiveCfg = Debug|x86
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Debug|x86.Build.0 = Debug|x86
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|Any CPU.Build.0 = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|iPhone.ActiveCfg = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|iPhone.Build.0 = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|x86.ActiveCfg = Release|x86
{CFDEC4A2-2757-403D-B90B-1846BCEE1EC4}.Release|x86.Build.0 = Release|x86
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|iPhone.Build.0 = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|x86.ActiveCfg = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Debug|x86.Build.0 = Debug|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|Any CPU.Build.0 = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|iPhone.ActiveCfg = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|iPhone.Build.0 = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|x86.ActiveCfg = Release|Any CPU
{E21D0376-0A18-4F46-9ED7-BE4466763B2D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -800,6 +836,7 @@ Global
{09591D9E-2186-42F1-B6C6-375326E2CF2E} = {8EB91F53-1062-4E9B-8E4A-096F35EA688D}
{38A8EE9F-81A8-4B11-A6E9-864A12C43089} = {8EB91F53-1062-4E9B-8E4A-096F35EA688D}
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1} = {5A7A506C-4DFF-4941-A9A6-B1182C7D5825}
{E21D0376-0A18-4F46-9ED7-BE4466763B2D} = {EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3833E7C5-69BC-4CB3-92CE-A8854AA35D8A}
+80
View File
@@ -63,6 +63,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Tools.AreaImport", "src\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefNet.Avalonia", "references\CefNet\CefNet.Avalonia\CefNet.Avalonia.csproj", "{9A533027-82BD-40CB-BB32-77F75F6FDDC7}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.Console.App", "src\ST.Client.Desktop.Console.App\ST.Client.Desktop.Console.App.csproj", "{A621E551-010C-4397-9C15-66D470B4D98E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AvaloniaGif", "references\AvaloniaGif\AvaloniaGif\AvaloniaGif.csproj", "{FD444E97-E851-4FF2-A3F1-498C6A3BF098}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.UnitTest", "tests\ST.Client.Desktop.UnitTest\ST.Client.Desktop.UnitTest.csproj", "{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -559,6 +565,78 @@ Global
{9A533027-82BD-40CB-BB32-77F75F6FDDC7}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{9A533027-82BD-40CB-BB32-77F75F6FDDC7}.Release|x86.ActiveCfg = Release|Any CPU
{9A533027-82BD-40CB-BB32-77F75F6FDDC7}.Release|x86.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|iPhone.Build.0 = Debug|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|x86.ActiveCfg = Debug|x86
{A621E551-010C-4397-9C15-66D470B4D98E}.Debug|x86.Build.0 = Debug|x86
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|Any CPU.ActiveCfg = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|Any CPU.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|iPhone.ActiveCfg = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|iPhone.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|x86.ActiveCfg = Release|x86
{A621E551-010C-4397-9C15-66D470B4D98E}.Nuget_Release|x86.Build.0 = Release|x86
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|Any CPU.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|iPhone.ActiveCfg = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|iPhone.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|x86.ActiveCfg = Release|x86
{A621E551-010C-4397-9C15-66D470B4D98E}.Release|x86.Build.0 = Release|x86
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|iPhone.Build.0 = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|x86.ActiveCfg = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Debug|x86.Build.0 = Debug|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|Any CPU.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|Any CPU.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|iPhone.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|iPhone.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|iPhoneSimulator.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|x86.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Nuget_Release|x86.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|Any CPU.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|iPhone.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|iPhone.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|x86.ActiveCfg = Release|Any CPU
{FD444E97-E851-4FF2-A3F1-498C6A3BF098}.Release|x86.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|iPhone.Build.0 = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|x86.ActiveCfg = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Debug|x86.Build.0 = Debug|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|Any CPU.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|Any CPU.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|iPhone.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|iPhone.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|iPhoneSimulator.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|x86.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Nuget_Release|x86.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|Any CPU.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|iPhone.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|iPhone.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|x86.ActiveCfg = Release|Any CPU
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -582,6 +660,8 @@ Global
{4190F5AE-FFF1-4CB5-A433-FF5403E2BE24} = {2D44BDCF-B70C-4C02-BDC8-4F1DD5066A75}
{536A0A61-97A8-44E9-8258-9D508D54B44B} = {5A7A506C-4DFF-4941-A9A6-B1182C7D5825}
{9A533027-82BD-40CB-BB32-77F75F6FDDC7} = {8EB91F53-1062-4E9B-8E4A-096F35EA688D}
{FD444E97-E851-4FF2-A3F1-498C6A3BF098} = {8EB91F53-1062-4E9B-8E4A-096F35EA688D}
{B8597B2B-12B4-4B44-9F37-98BAF3CCD560} = {EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3833E7C5-69BC-4CB3-92CE-A8854AA35D8A}
+37
View File
@@ -107,6 +107,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CefNet.Avalonia", "referenc
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Tools.MinifyStaticSites", "src\ST.Tools.MinifyStaticSites\ST.Tools.MinifyStaticSites.csproj", "{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.Console.App", "src\ST.Client.Desktop.Console.App\ST.Client.Desktop.Console.App.csproj", "{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Desktop.UnitTest", "tests\ST.Client.Desktop.UnitTest\ST.Client.Desktop.UnitTest.csproj", "{F544C06A-152E-48CE-9716-8B92F5CB51FF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -795,6 +799,38 @@ Global
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}.Release|x86.ActiveCfg = Release|Any CPU
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1}.Release|x86.Build.0 = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|iPhone.Build.0 = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Debug|x86.Build.0 = Debug|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|Any CPU.Build.0 = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|iPhone.ActiveCfg = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|iPhone.Build.0 = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|x86.ActiveCfg = Release|Any CPU
{7F104A37-93AF-4EF8-93EA-E8BD76FE8973}.Release|x86.Build.0 = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|iPhone.Build.0 = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|x86.ActiveCfg = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Debug|x86.Build.0 = Debug|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|Any CPU.Build.0 = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|iPhone.ActiveCfg = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|iPhone.Build.0 = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|x86.ActiveCfg = Release|Any CPU
{F544C06A-152E-48CE-9716-8B92F5CB51FF}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -838,6 +874,7 @@ Global
{09591D9E-2186-42F1-B6C6-375326E2CF2E} = {8EB91F53-1062-4E9B-8E4A-096F35EA688D}
{38A8EE9F-81A8-4B11-A6E9-864A12C43089} = {8EB91F53-1062-4E9B-8E4A-096F35EA688D}
{5E8F54E8-02A6-45D9-A7F9-7C9B43705BE1} = {5A7A506C-4DFF-4941-A9A6-B1182C7D5825}
{F544C06A-152E-48CE-9716-8B92F5CB51FF} = {EBC9DD0C-F7D0-4A00-B263-E69CF4E194F1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3833E7C5-69BC-4CB3-92CE-A8854AA35D8A}
+44 -43
View File
@@ -6,14 +6,35 @@ Steam++项目创建于2018年5月8日,不过并不是耗时三年才做出来
在每人每天近16小时的高强度爆肝下,我们使用了最新的技术、最新的框架,将Steam++原先的代码全部重写,重新制作了UI。于是乎,Steam++2.0崭新出炉了。
Steam++目前处于一个完全开源的状态,所以对于软件报毒可以不用担心安全问题。我们也制作了自己的产品官网https://www.steampp.net,大家可以去官网下载到我们的工具。
Steam++目前处于一个完全开源的状态,所以对于软件报毒可以不用担心安全问题。我们也制作了自己的产品[官网](https://www.steampp.net),大家可以去官网下载到我们的工具。
# Steam++工具箱
## 更新内容
### 2.0.0.6
### 2.0.0.8
```
1. 更换整体架构,提高软件兼容性
2. 重做UI界面,适应跨平台
3. 新增软件热更新支持
4. 新增账号切换界面动态头像支持
5. 新增从云端获取加速列表功能
6. 新增用户登录/注册功能,并且有了用户面板,将支持用户云同步数据
7. 新增脚本商店,用户可以从脚本商店下载更多脚本
8. 优化库存游戏列表加载速度
9. 优化GM0.2脚本
10. 修复1.1.4版本已出现的各种错误
11. 新增 CSGO 市场查看磨损与印花脚本适配
12. 新增 窗口位置保存功能
13. 修复 加速证书安装失败的问题
14. 修复 账号切换离线登录失效的问题
15. 修复 Windows 代理加速导致断网的问题
16. 修复 Discord 客户端代理失效的问题
17. 修复 多个 UI 错误
18. 修复 脚本以及备注无法保存的问题
19. 修复 多个可能导致闪退的问题
20. 修复 更新进度条显示不正确的问题
21. 改进 当 hosts 文件不存在时自动创建空文件而不是返回错误
```
@@ -37,59 +58,44 @@ Steam++目前处于一个完全开源的状态,所以对于软件报毒可以
## 核心功能
### 1. 反代Steam的社区网页使其能正常访问
### 1. 通过本地反代理Steam的社区等网页使其能正常访问
功能类似羽翼城大佬的[steamcommunity_302](https://www.dogfight360.com/blog/686/),使用[Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy)开源项目进行本地反代,相比302工具具有更快的启动速度,以及支持简单的脚本注入。该功能也可以配合羽翼城大佬的[UsbEAm Hosts Editor](https://www.dogfight360.com/blog/475/)里的网页相关-steamcommunity_302 社区/api/商店加载速度选项的hosts提升加载速度。
功能使用Titanium-Web-Proxy开源项目进行本地反代,相比SteamCommunity302工具具有更快的启动速度。让用户能够连接上诸如Steam社区(个人资料页)、Discord语音聊天、Twitch直播观看、Origin下载加速、谷歌验证码、Pixiv图片等。
[attachimg]1228388[/attachimg]
### 2. 快速切换当前PC已经记住登陆的Steam账号
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。
该功能是读取Steam路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌。如果您的ip地址更换,会导致登陆状态失效。在Steam++2.0新版本支持了动态头像。
[attachimg]1228389[/attachimg]
### 3. Steam游戏的成就统计管理功能
功能参考[SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager)进行二次开发,修复了成就语言有中文却依然是英文成就信息的BUG,修改了游戏列表的加载和操作易用性。
能够读取任何游戏的成就信息(包括隐藏成就),并且能进行成就修改,包括成就解锁以及成就反解锁,还能够修改成就统计信息
参考SAM(SteamAchievementManager)进行二次开发,修复了成就语言有中文却依然是英文成就信息的BUG,修改了游戏列表的加载和操作易用性。
注意:滥用成就管理功能可能会导致开发者封禁!
[attachimg]1228390[/attachimg]
### 4. Steam本地两步身份验证器
功能参考[WinAuth](https://github.com/winauth/winauth)开发,可以使您不用启动移动版Steam App也能查看您的令牌,功能类似的软件有[WinAuth](https://github.com/winauth/winauth)、[SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)。
该功能能够将Steam手机令牌储存到您的电脑中,并能够进行与手机端一样的操作。
不仅能查看手机令牌,还能进行交易报价确认,并且能一键全部确认
功能参考WinAuth开发,功能类似的软件有WinAuth、SteamDesktopAuthenticator。
[attachimg]1228391[/attachimg]
本地令牌交易市场报价确认
[attachimg]1262615[/attachimg]
### 5. 一些游戏工具
### 5. Steam内置浏览器脚本注入
目前已有强制游戏无边框窗口化,CSGO修复VAC屏蔽。
这一块是随缘做一些我经常用或者闲着没事捣鼓的功能。
将任何游戏强制无边框窗口化
[attachimg]1228392[/attachimg]
使任何窗口化游戏变成动态桌面壁纸(终于可以用《山》当壁纸了)
[attachimg]1228393[/attachimg]
通过反代加速功能将js脚本内置插入了Steam客户端内的浏览器,达到了与油猴类似的效果。目前2.0.0.6版本新增了脚本工坊,可以从我们的服务器上下载到已经兼容的脚本。我们也会不断添加新的脚本,同时也会对旧的脚本进行维护。
------
## 预计后续添加的功能
### Steam自动挂卡
尝试用社区反代功能结合成就解锁功能来重新实现,目的是实现在软件内不用登录Steam即可直接获取徽章卡片信息并开始挂卡。
### Steam皮肤设计器
挖坑画大饼,可视化编辑Steam皮肤,而且如果软件能上架Steam的话打算支持创意工坊分享设计的Steam皮肤,短期内肯定做不完。
### 插件形式加载运行ASF
以插件形式支持ASF在工具内运行并增强ASF在Windows Desktop环境下的使用。
### Steam自定义封面管理
增强Steam自定义封面的管理以及从[SteamGridDB](https://www.steamgriddb.com/)快速匹配下载应用封面。
### 6. 更新计划(画饼时间到)
我们预计会在6月份将推出本地挂卡、挂时长功能。并且同步推出iOS、安卓端App,用户可以利用手机查看多个账号的令牌,一键确认上架,并且支持手机挂卡。
#### 并且,以上功能全部免费!
------
@@ -99,16 +105,11 @@ Steam++目前处于一个完全开源的状态,所以对于软件报毒可以
> 程序使用C# WPF在 .NET Framework4.7.2环境下开发,如果无法运行请下载安装[.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)。
## 下载
> [官网](https://steampp.net/)
> [Github](https://github.com/rmbadmin/SteamTools/releases)
> 分流下载:
> [hide]
> [蓝奏云](https://wws.lanzous.com/iFkh4lyooeh)
> [百度云](链接: https://pan.baidu.com/s/1mD-C_Ndc332oq_XnFVBLrQ)
> 提取码:2uxe
> [蓝奏云](https://cliencer.lanzous.com/b0165duja)
> 提取码:1234
> [/hide]
> EXE 大小:4.83MB
> EXE MD5:4149DC37BF24DD10181E32450290FEF6
> ZIP MD5:202F62682379566DBCD48C65917D4FFF
> [查毒链接](https://www.virustotal.com/gui/file/8d6da4a3fe7b1738aa5725e9797a86f8b5c668920d1449594279ea7bb262e4ef/detection)
虽然没有什么杀毒软件报毒,但是使用过程中可能遇到windows defender误报,您可以选择添加信任。
+28
View File
@@ -0,0 +1,28 @@
1. 修复 多个 GM.js 同时存在
2. 修复 GM.js 打包错误
3. 修复 手动添加 GM.js 重名替换导致出错
4. 修复 成就解锁窗口不显示
5. 新增 背景透明度 UI 设置
6. 调整 脚本列表 UI
7. 修复 代理过程中的闪退错误
8. 修复 库存游戏闪退错误
9. 修复 Discord 更新代理失效
10. 修复 hosts 闪退错误
11. 新增 Steam 快速登录
| File | Checksum (SHA256) |
| ---- | ---- |
| Steam++_win_x86_v2.1.0.7z | SHA256 |
| Steam++_win_x86_v2.1.0.exe | SHA256 |
| Steam++_linux_x64_v2.1.0.7z | SHA256 |
| Steam++_linux_x64_v2.1.0.deb | SHA256 |
| Steam++_macos_x64_v2.1.0.dmg | SHA256 |
| Steam++_macos_arm64_v2.1.0.dmg | SHA256 |
| Steam++_android_arm_v2.1.0.apk | SHA256 |
| Steam++_android_arm64_v2.1.0.apk | SHA256 |
| Steam++_win_arm64_v2.1.0.7z | SHA256 |
| Steam++_win_arm64_v2.1.0.exe | SHA256 |
***
由于程序体积较大,推荐从 [官网 https://steampp.net](https://steampp.net) 中下载
Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 780 KiB

@@ -94,21 +94,22 @@ namespace System.Application
/// <summary>
/// 中国移动
/// </summary>
public static byte[] ChinaMobile = { 139, 138, 137, 136, 135, 134, 147, 150, 151, 152, 157, 158, 159, 178, 182, 183, 184, 187, 188, 198, 148, 172 };
public static byte[] ChinaMobile = { 139, 138, 137, 136, 135, 134, 147, 150, 151, 152, 157, 158, 159, 178, 182, 183, 184, 187, 188, 198 };
/// <summary>
/// 虚拟运营商
/// </summary>
public static byte[] MobileVirtualNetwork = { 170, 171 };
public static byte[] MobileVirtualNetwork = { 170, 171, 172 };
public static byte[] Other = { 190, 197, 196, 192 };
public static byte[] Other = { 190, 191, 192, 193, 195, 196, 197, 198, 199 };
static Lazy<byte[]> mSummary = new(() => new[]
static readonly Lazy<byte[]> mSummary = new(() => new[]
{
ChinaTelecom,
ChinaUnicom,
ChinaMobile,
MobileVirtualNetwork
MobileVirtualNetwork,
Other,
}.SelectMany(b => b).ToArray());
/// <summary>
@@ -127,7 +128,7 @@ namespace System.Application
/// <summary>
/// 中国大陆地区手机号码号段验证使用 黑名单(<see langword="true"/>) 或 白名单(<see langword="false"/>)
/// </summary>
public static bool ChineseMainlandPhoneNumberSegmentVerifyUseBlacklistOrWhitelist { get; set; }
public static bool ChineseMainlandPhoneNumberSegmentVerifyUseBlacklistOrWhitelist { get; set; } = true;
/// <summary>
/// 中国大陆地区手机号码号段验证(通常仅服务端验证)
+3 -1
View File
@@ -1,4 +1,4 @@
namespace System
namespace System
{
/// <summary>
/// 文件扩展名(FileExtensions)
@@ -52,5 +52,7 @@
public const string BIN = ".bin";
public const string APNG = ".apng";
public const string EXE = ".exe";
}
}
@@ -9,7 +9,7 @@ namespace System.Net.Http
{
protected readonly ILogger logger;
protected readonly IHttpPlatformHelper http_helper;
readonly IHttpClientFactory _clientFactory;
protected readonly IHttpClientFactory _clientFactory;
public GeneralHttpClientFactory(
ILogger logger,
@@ -29,9 +29,9 @@ namespace System.Net.Http
protected virtual string? DefaultClientName { get; }
/// <summary>
/// 默认超时时间,19秒
/// 默认超时时间,16秒
/// </summary>
public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(19);
public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(16);
static readonly Lazy<int> mDefaultTimeoutTotalMilliseconds = new(() => DefaultTimeout.TotalMilliseconds.ToInt32());
@@ -1,15 +1,15 @@
using System.Globalization;
using System.Globalization;
using System.IO;
using System.IO.FileFormats;
namespace System.Net.Http
{
/// <inheritdoc cref="IHttpPlatformHelper"/>
public class HttpPlatformHelper : IHttpPlatformHelper
public abstract class HttpPlatformHelper : IHttpPlatformHelper
{
const string DefaultUserAgent = "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263";
protected const string DefaultUserAgent = "Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263";
public virtual string UserAgent => DefaultUserAgent;
public abstract string UserAgent { get; }
public virtual string AcceptImages => "image/png, image/*; q=0.8";
@@ -2,7 +2,7 @@ namespace System.Properties
{
public static class ThisAssembly
{
public const string Version = "2.0.0.8";
public const string Version = "2.1.0";
public const string InfoVersion = Version + "-beta";
+5 -1
View File
@@ -1,4 +1,4 @@
#if !NOT_MP
#if !NOT_MP
using MessagePack;
#endif
#if !NOT_NJSON
@@ -147,6 +147,10 @@ namespace System
public static byte[] SMP<T>(T value, CancellationToken cancellationToken = default)
=> MessagePackSerializer.Serialize(value, options: lz4Options, cancellationToken: cancellationToken);
/// <inheritdoc cref="SMP{T}(T, CancellationToken)"/>
public static byte[] SMP(Type type, object value, CancellationToken cancellationToken = default)
=> MessagePackSerializer.Serialize(type, value, options: lz4Options, cancellationToken: cancellationToken);
/// <summary>
/// (Serialize)MessagePack 序列化 + Base64Url Encode
/// </summary>
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Application.Services;
using System.Application.Services.Implementation;
using System.Net.Http;
@@ -19,17 +19,6 @@ namespace Microsoft.Extensions.DependencyInjection
return services;
}
/// <summary>
/// 尝试添加 <see cref="IHttpPlatformHelper"/>
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection TryAddHttpPlatformHelper(this IServiceCollection services)
{
services.TryAddSingleton<IHttpPlatformHelper, HttpPlatformHelper>();
return services;
}
//public static IServiceCollection AddHttpService(this IServiceCollection services, string name)
//{
// // 此函数为添加HTTP服务模板
+16 -13
View File
@@ -138,24 +138,17 @@ namespace System.Application.UI
#endif
var windowService = IWindowService.Instance;
windowService.Init();
DI.Get<IDesktopPlatformService>().SetSystemSessionEnding(() =>
{
compositeDisposable.Dispose();
});
#if StartupTrace
StartupTrace.Restart("WindowService.Init");
#endif
SettingsHost.Load();
#if StartupTrace
StartupTrace.Restart("SettingsHost.Init");
#endif
#if !UI_DEMO
if (GeneralSettings.IsStartupAppMinimized.Value)
{
Program.IsMinimize = true;
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = null;
}
#endif
Theme = (AppTheme)UISettings.Theme.Value;
#if StartupTrace
StartupTrace.Restart("Theme");
@@ -176,11 +169,18 @@ namespace System.Application.UI
default:
#region 主窗口启动时加载的资源
#if !UI_DEMO
compositeDisposable.Add(SettingsHost.Save);
compositeDisposable.Add(ProxyService.Current.Dispose);
compositeDisposable.Add(AuthService.Current.SaveEditNameAuthenticators);
compositeDisposable.Add(SteamConnectService.Current.Dispose);
if (GeneralSettings.IsStartupAppMinimized.Value)
{
Program.IsMinimize = true;
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
desktop.MainWindow = null;
}
#endif
#endregion
MainWindow = new MainWindow
{
@@ -313,7 +313,10 @@ namespace System.Application.UI
if (Program.IsMainProcess)
{
Startup.ActiveUserPost(ActiveUserType.OnStartup);
IAppUpdateService.Instance.CheckUpdate(showIsExistUpdateFalse: false);
if (GeneralSettings.IsAutoCheckUpdate.Value)
{
IAppUpdateService.Instance.CheckUpdate(showIsExistUpdateFalse: false);
}
#if StartupTrace
StartupTrace.Restart("Desktop_Startup.MainProcess");
#endif
@@ -0,0 +1,48 @@
using NLog;
using NLog.Common;
using NLog.Config;
using NLog.Targets;
using System.Application.UI;
using System.IO;
using NLogLevel = NLog.LogLevel;
#if CONSOLEAPP
namespace System.Application
#else
namespace System.Application.UI
#endif
{
static partial class Program
{
public static Logger? logger;
public static string InitLogDir(string? alias = null)
{
var logDirPath = Path.Combine(AppContext.BaseDirectory, "Logs");
IOPath.DirCreateByNotExists(logDirPath);
#if StartupTrace
StartupTrace.Restart("InitLogDir.IO");
#endif
var logDirPath_ = logDirPath + Path.DirectorySeparatorChar;
InternalLogger.LogFile = logDirPath_ + "internal-nlog" + alias + ".txt";
InternalLogger.LogLevel = NLogLevel.Error;
var objConfig = new LoggingConfiguration();
var logfile = new FileTarget("logfile")
{
FileName = logDirPath_ + "nlog-all-${shortdate}" + alias + ".log",
Layout = "${longdate}|${level}|${logger}|${message} |${all-event-properties} ${exception:format=tostring}",
};
objConfig.AddTarget(logfile);
objConfig.AddRule(NLogLevel.Error, NLogLevel.Fatal, logfile, "Microsoft.*");
objConfig.AddRule(NLogLevel.Error, NLogLevel.Fatal, logfile, "System.Net.Http.*");
objConfig.AddRule(AppHelper.DefaultNLoggerMinLevel, NLogLevel.Fatal, logfile, "*");
#if StartupTrace
StartupTrace.Restart("InitLogDir.CreateLoggingConfiguration");
#endif
LogManager.Configuration = objConfig;
return logDirPath;
}
}
}
+1 -30
View File
@@ -5,6 +5,7 @@ using NLog.Targets;
using ReactiveUI;
using System.Application.Services;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reactive;
@@ -15,7 +16,6 @@ namespace System.Application.UI
{
static partial class Program
{
static Logger? logger;
static readonly HashSet<Exception> exceptions = new();
static readonly object lock_global_ex_log = new();
@@ -166,35 +166,6 @@ namespace System.Application.UI
}
}
static string InitLogDir()
{
var logDirPath = Path.Combine(AppContext.BaseDirectory, "Logs");
IOPath.DirCreateByNotExists(logDirPath);
#if StartupTrace
StartupTrace.Restart("InitLogDir.IO");
#endif
var logDirPath_ = logDirPath + Path.DirectorySeparatorChar;
InternalLogger.LogFile = logDirPath_ + "internal-nlog.txt";
InternalLogger.LogLevel = NLogLevel.Error;
var objConfig = new LoggingConfiguration();
var logfile = new FileTarget("logfile")
{
FileName = logDirPath_ + "nlog-all-${shortdate}.log",
Layout = "${longdate}|${level}|${logger}|${message} |${all-event-properties} ${exception:format=tostring}",
};
objConfig.AddTarget(logfile);
objConfig.AddRule(NLogLevel.Error, NLogLevel.Fatal, logfile, "Microsoft.*");
objConfig.AddRule(NLogLevel.Error, NLogLevel.Fatal, logfile, "System.Net.Http.*");
objConfig.AddRule(AppHelper.DefaultNLoggerMinLevel, NLogLevel.Fatal, logfile, "*");
#if StartupTrace
StartupTrace.Restart("InitLogDir.CreateLoggingConfiguration");
#endif
LogManager.Configuration = objConfig;
return logDirPath;
}
/// <summary>
/// 是否最小化启动
/// </summary>
@@ -11,57 +11,57 @@
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition=" $(DefineConstants.Contains(`StartupTrace`)) ">
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup Condition=" $(DefineConstants.Contains(`StartupTrace`)) ">
<OutputType>Exe</OutputType>
</PropertyGroup>
<!--<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<!--<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<AllowedReferenceRelatedFileExtensions>
-->
<!-- Prevent default XML and PDB files copied to output in RELEASE.
<!-- Prevent default XML and PDB files copied to output in RELEASE.
Only *.allowedextension files will be included, which doesn't exist in my case.
-->
<!--
<!--
.allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>-->
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>WINDOWS;$(DefineConstants)</DefineConstants>
<ApplicationIcon>..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico</ApplicationIcon>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
<!--<TargetFramework>net5.0-windows10.0.19041.0</TargetFramework>
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>WINDOWS;$(DefineConstants)</DefineConstants>
<ApplicationIcon>..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico</ApplicationIcon>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
<!--<TargetFramework>net5.0-windows10.0.19041.0</TargetFramework>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>-->
<Platforms>AnyCPU;x86</Platforms>
<PlatformTarget>x86</PlatformTarget>
<!-- 注意:RuntimeIdentifier win-x86 会导致亚克力效果会丢失 -->
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<!--<UseWindowsForms>false</UseWindowsForms>-->
<!--<UseWPF>false</UseWPF>-->
</PropertyGroup>
<Platforms>AnyCPU;x86</Platforms>
<PlatformTarget>x86</PlatformTarget>
<!-- 注意:RuntimeIdentifier win-x86 会导致亚克力效果会丢失 -->
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<!--<UseWindowsForms>false</UseWindowsForms>-->
<!--<UseWPF>false</UseWPF>-->
</PropertyGroup>
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`osx`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>MAC;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`osx`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>MAC;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" $(DefineConstants.Contains(`PUBLISH`)) ">
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
<!--目前裁剪存在问题,禁用-->
<PublishTrimmed>false</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>
<PropertyGroup Condition=" $(DefineConstants.Contains(`PUBLISH`)) ">
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
<!--目前裁剪存在问题,禁用-->
<PublishTrimmed>false</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>
<!--<ItemGroup>
<TrimmerRootAssembly Include="CefNet"/>
@@ -121,21 +121,21 @@
<AvaloniaResource Include="Assets\**"/>
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<!--Win8.1/10的开始菜单磁贴配置-->
<None Include="..\..\Resources\AppIcon\visualelementsmanifest.xml">
<Link>steam++.visualelementsmanifest.xml</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<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>
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<!--Win8.1/10的开始菜单磁贴配置-->
<None Include="..\..\Resources\AppIcon\visualelementsmanifest.xml">
<Link>steam++.visualelementsmanifest.xml</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<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>
</ItemGroup>
<ItemGroup Condition="Exists('$(MSBuildProjectDirectory)\..\..\aes-key.pfx')">
<EmbeddedResource Include="..\..\aes-key.pfx" Link="Resources\3A613E8D"/>
@@ -3,8 +3,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="1200" Width="1200" MinWidth="995"
d:DesignHeight="600" Height="800" MinHeight="600"
d:DesignWidth="1200" Width="995" MinWidth="995"
d:DesignHeight="600" Height="600" MinHeight="600"
xmlns:local="clr-namespace:System.Application.UI.Views;assembly=System.Application.SteamTools.Client.Desktop.Avalonia"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
x:Class="System.Application.UI.Views.MainWindow"
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<SignAssembly>false</SignAssembly>
<!--(SignAssembly)对此程序集进行签名会导致编译失败(CompileAvaloniaXamlTask)-->
<RootNamespace>System.Application.UI</RootNamespace>
@@ -1,5 +1,7 @@
using Avalonia.Threading;
using CefNet;
using CefNet.Input;
using System;
using System.Application.Models;
using System.Globalization;
using System.IO;
@@ -51,6 +53,8 @@ namespace System.Application.UI
// commandLine.AppendSwitch("no-zygote");
// commandLine.AppendSwitch("no-sandbox");
//}
//commandLine.AppendSwitch("disable-web-security"); // LoginUsingSteamClient
}
protected override void OnContextCreated(CefBrowser browser, CefFrame frame, CefV8Context context)
@@ -166,6 +170,8 @@ navigator.__proto__ = newProto;
}
};
KeycodeConverter.Default = new FixChineseInptKeycodeConverter();
app = new CefNetApp
{
ScheduleMessagePumpWorkCallback = async delayMs =>
@@ -245,4 +251,34 @@ navigator.__proto__ = newProto;
/// </summary>
Complete,
}
}
namespace CefNet.Input
{
/// <summary>
/// https://github.com/CefNet/CefNet/issues/21
/// </summary>
public class FixChineseInptKeycodeConverter : KeycodeConverter
{
public override VirtualKeys CharacterToVirtualKey(char character)
{
// https://github.com/CefNet/CefNet/blob/master/CefNet/Input/KeycodeConverter.cs#L41
// https://github.com/CefNet/CefNet/blob/90.5.21109.1453/CefNet/Input/KeycodeConverter.cs#L41
try
{
return base.CharacterToVirtualKey(character);
}
catch (Exception e)
{
if (PlatformInfo.IsWindows)
{
if (e.Message == "Incompatible input locale.")
{
return VirtualKeys.None;
}
}
throw;
}
}
}
}
@@ -1,74 +0,0 @@
<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 50 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>
@@ -1,87 +1,89 @@
<Styles xmlns="https://github.com/avaloniaui"
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith>
<Border Padding="20" Background="White">
<Border Padding="20" Classes="paper">
<TextBox Text="Code Font Family"/>
</Border>
</Border>
</Design.PreviewWith>
<Style Selector="TabControl.flat">
<Setter Property="FontSize" Value="18"></Setter>
<Setter Property="Padding" Value="0"></Setter>
</Style>
<Style Selector="TabControl.flat /template/ DockPanel">
<Setter Property="Margin" Value="0 -10 0 0"></Setter>
</Style>
<Style Selector="TabControl.flat /template/ ItemsPresenter">
<Setter Property="Margin" Value="{StaticResource PageMargin}"></Setter>
</Style>
<Design.PreviewWith>
<Border Padding="20" Background="White">
<Border Padding="20" Classes="paper">
<TextBox Text="Code Font Family"/>
</Border>
</Border>
</Design.PreviewWith>
<Style Selector="TabControl.flat">
<Setter Property="Padding" Value="0"></Setter>
</Style>
<Style Selector="TabControl.flat TabItem">
<Setter Property="FontSize" Value="16"></Setter>
</Style>
<Style Selector="TabControl.flat /template/ DockPanel">
<Setter Property="Margin" Value="0 -10 0 0"></Setter>
</Style>
<Style Selector="TabControl.flat /template/ ItemsPresenter">
<Setter Property="Margin" Value="{StaticResource PageMargin}"></Setter>
</Style>
<Style Selector="TabControl.NavBar">
<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 50 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}"
<Style Selector="TabControl.NavBar">
<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 50 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>
<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.NavBar > 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.NavBar > TabItem:selected /template/ Border#PART_SelectedPipe">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="TabControl.NavBar > TabItem:selected">
<Setter Property="Background" Value="#1fffffff"/>
</Style>
<Style Selector="TabControl.NavBar > 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.NavBar > TabItem:pointerover /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="#3fffffff"/>
</Style>
<Style Selector="TabControl.NavBar > TabItem:selected /template/ Border#PART_SelectedPipe">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="TabControl.NavBar > TabItem:selected">
<Setter Property="Background" Value="#1fffffff"/>
</Style>
<Style Selector="TabControl.NavBar > TabItem:pointerover /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="#3fffffff"/>
</Style>
</Styles>
@@ -135,7 +135,7 @@ namespace System.Application.UI.Views.Controls
var constraints = this.Bounds.Deflate(Padding);
var constraintsWidth = constraints.Width;
//让文字不要在宽度合适的时候滚动
//让文字不要在宽度合适的时候滚动
_isConstrained = _textWidth > constraintsWidth + 1;
if (_isConstrained & !_waiting)
@@ -154,7 +154,7 @@ namespace System.Application.UI.Views.Controls
if (nC.Intersects(nR))
using (context.PushPostTransform(Matrix.CreateTranslation(offset, padding.Top)))
TextLayout.Draw(context);
TextLayout.Draw(context, new Point(Padding.Left, Padding.Top));
}
}
else
@@ -162,7 +162,7 @@ namespace System.Application.UI.Views.Controls
_animate = false;
using (context.PushPostTransform(Matrix.CreateTranslation(padding.Left, padding.Top)))
TextLayout.Draw(context);
TextLayout.Draw(context, new Point(Padding.Left, Padding.Top));
}
}
}
@@ -2,6 +2,7 @@
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:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
mc:Ignorable="d"
x:Name="u" IsHitTestVisible="False"
Background="Transparent"
@@ -9,7 +10,7 @@
<DockPanel HorizontalAlignment="Stretch">
<ExperimentalAcrylicBorder DockPanel.Dock="Top" IsHitTestVisible="False" Height="{StaticResource TitleBarHeight}">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="0.80" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="10 6 10 6">
<Image Source="/Application/UI/Assets/Icon.ico" Height="18" Width="18" Margin="0,0,10,0"/>
@@ -18,7 +19,7 @@
</ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder DockPanel.Dock="Bottom" IsHitTestVisible="False" Opacity="{StaticResource ContentOpacity}">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="0.75" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
</DockPanel>
@@ -65,11 +65,22 @@ namespace System.Application.UI.Views.Controls
/// <summary>
/// 拦截响应流的处理
/// </summary>
public Action<string, byte[]>? OnStreamResponseFilterResourceLoadComplete { get; set; }
public Action<string, Stream>? OnStreamResponseFilterResourceLoadComplete { get; set; }
public bool IsSecurity { get; set; }
public Aes? Aes { get; internal set; }
protected override void Dispose(bool disposing)
{
if (disposing)
{
Aes?.Dispose();
StreamResponseFilterUrls = null;
OnStreamResponseFilterResourceLoadComplete = null;
}
base.Dispose(disposing);
}
}
public class FullscreenModeChangeEventArgs : RoutedEventArgs
@@ -217,8 +228,10 @@ namespace System.Application.UI.Views.Controls
request.SetHeaderByName(Headers.Request.AppVersion, sc.Settings.AppVersionStr, true);
if (webView.IsSecurity)
{
webView.Aes?.Dispose();
webView.Aes = AESUtils.Create();
if (webView.Aes == null)
{
webView.Aes = AESUtils.Create();
}
var skey_bytes = webView.Aes.ToParamsByteArray();
var conn_helper = DI.Get<IApiConnectionPlatformHelper>();
var skey_str = conn_helper.RSA.EncryptToString(skey_bytes);
@@ -274,7 +287,7 @@ namespace System.Application.UI.Views.Controls
protected override CefResponseFilter GetResourceResponseFilter(CefBrowser browser, CefFrame frame, CefRequest request, CefResponse response)
{
if (webView.StreamResponseFilterUrls != null && webView.StreamResponseFilterUrls.Contains(request.Url, StringComparer.OrdinalIgnoreCase))
if (webView.StreamResponseFilterUrls != null && webView.StreamResponseFilterUrls.Any(x => request.Url.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
{
var rspIsCiphertext = false;
if (webView.IsSecurity)
@@ -308,6 +321,7 @@ namespace System.Application.UI.Views.Controls
public StreamResponseFilter(WebView3 webView, bool rspIsCiphertext)
{
this.webView = webView;
this.rspIsCiphertext = rspIsCiphertext;
}
protected override bool InitFilter()
@@ -366,33 +380,36 @@ namespace System.Application.UI.Views.Controls
{
if (memoryStream != null)
{
memoryStream.Dispose();
memoryStream?.Dispose();
memoryStream = null;
stream?.Dispose();
stream = null;
}
}
}
base.Dispose(disposing);
}
byte[]? data;
Stream? stream;
public byte[] Data
public Stream Data
{
get
{
if (data == null) data = GetData();
return data;
if (stream == null) stream = GetStream();
return stream;
}
}
byte[] GetData()
Stream GetStream()
{
var value = memoryStream!.ToArray();
if (rspIsCiphertext && webView.Aes != null)
{
value = webView.Aes.Decrypt(value);
memoryStream!.Position = 0;
var cryptoStream = new CryptoStream(memoryStream, webView.Aes.CreateDecryptor(), CryptoStreamMode.Read);
return cryptoStream;
}
return value;
return memoryStream!;
}
}
}
@@ -27,12 +27,12 @@
<DockPanel HorizontalAlignment="Stretch">
<ExperimentalAcrylicBorder IsHitTestVisible="False" DockPanel.Dock="Left" Width="240">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="0.8" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder IsHitTestVisible="False">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="0.8" TintOpacity="1" BackgroundSource="Digger" PlatformTransparencyCompensationLevel="0.5"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
</DockPanel>
@@ -43,7 +43,8 @@
<Image Source="/Application/UI/Assets/Icon.ico" Height="64" Width="64" VerticalAlignment="Center" Margin="-8,0,0,0"/>
<Label Content="{ReflectionBinding Path=Title}" Foreground="{DynamicResource HighlightForegroundBrushKey}" VerticalContentAlignment="Center" FontSize="20" Margin="8,0,0,0"/>
</StackPanel>
<TextBlock IsHitTestVisible="False" Grid.Column="1" Text="{ReflectionBinding SelectedItem.Name}" Foreground="{DynamicResource HighlightForegroundBrushKey}" Padding="15 8 0 0" FontSize="28"/>
<TextBlock IsHitTestVisible="False" Grid.Column="1" Text="{ReflectionBinding SelectedItem.Name}" Foreground="{DynamicResource HighlightForegroundBrushKey}"
Padding="15 8 0 0" FontSize="24" FontWeight="Regular"/>
<StackPanel Grid.Column="2" x:Name="titleMenu" Orientation="Horizontal" VerticalAlignment="Top">
<!--<Menu Items="{Binding SelectedItem.MenuItems}" IsVisible="{Binding !SelectedItem.MenuItems,Converter={StaticResource IsNullConverter}}" Classes="BindMenu">
</Menu>-->
@@ -81,7 +82,7 @@
<StackPanel>
<Panel x:Name="UserMenu" Width="300" Margin="0 20">
<StackPanel Spacing="15">
<Image Source="{ReflectionBinding Path=AvaterPath, Source={x:Static service:UserService.Current},Mode=OneWay,Converter={StaticResource BitmapAssetValueConverter},ConverterParameter=100}"
<Image Source="{ReflectionBinding Path=AvaterPath, Source={x:Static service:UserService.Current},Mode=OneWay,Converter={StaticResource BitmapAssetValueConverter},ConverterParameter=80}"
Stretch="Uniform"
Height="80" Width="80"
HorizontalAlignment="Center">
@@ -113,7 +114,7 @@
Command="{ReflectionBinding Path=ShowWindow,Source={x:Static service:UserService.Current}}"
CommandParameter="UserProfile"></Button>
</ListBoxItem>
<ListBoxItem>
<ListBoxItem IsVisible="{ReflectionBinding Path=HasPhoneNumber,Source={x:Static service:UserService.Current}}}">
<Button
Classes="CodeButton"
Content="{ReflectionBinding Path=Res.User_ChangePhoneNum,Mode=OneWay,Source={x:Static resx:R.Current}}"
@@ -144,7 +145,7 @@
<TabControl
Items="{Binding TabItems}"
SelectedItem="{Binding SelectedItem}"
Margin="0 25 0 0"
Margin="0 22 0 0"
Classes="NavBar">
<TabControl.DataTemplates>
<DataTemplate DataType="vm:DebugWebViewPageViewModel">
@@ -89,8 +89,8 @@
<StackPanel HorizontalAlignment="Right">
<TextBlock Text="{ReflectionBinding Path=Res.CommunityFix_ProxyMode,Mode=OneWay,Source={x:Static resx:R.Current}}" Margin="0 5"
Foreground="{DynamicResource HighlightForegroundBrushKey}"></TextBlock>
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_Hosts,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=!Value, Mode=TwoWay}"></RadioButton>
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystem,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=Value, Mode=TwoWay}"></RadioButton>
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_Hosts,Mode=OneWay,Source={x:Static resx:R.Current}}" ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_HostsTip,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=!Value, Mode=TwoWay}"></RadioButton>
<RadioButton Content="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystem,Mode=OneWay,Source={x:Static resx:R.Current}}" ToolTip.Tip="{ReflectionBinding Path=Res.CommunityFix_ProxyMode_WinSystemTip,Mode=OneWay,Source={x:Static resx:R.Current}}" IsChecked="{Binding Source={x:Static ms:ProxySettings.EnableWindowsProxy},Path=Value, Mode=TwoWay}"></RadioButton>
</StackPanel>
</WrapPanel>
</Border>
@@ -17,9 +17,7 @@
x:CompileBindings="True"
x:Class="System.Application.UI.Views.Pages.ProxyScriptManagePage">
<DockPanel>
<Border DockPanel.Dock="Top" Classes="paper" Background="{DynamicResource ThemeBrushKey}" Padding="10" Margin="20 0 20 10">
<DockPanel>
<StackPanel Orientation="Horizontal" Spacing="8" HorizontalAlignment="Left">
<ToggleSwitch Content="" OnContent="" OffContent=""
@@ -70,115 +68,116 @@
<ScrollViewer HorizontalScrollBarVisibility="Disabled" Padding="{StaticResource ScrollMargin}">
<ItemsRepeater Items="{Binding ProxyScripts}">
<ItemsRepeater.Layout>
<WrapLayout HorizontalSpacing="20" VerticalSpacing="20" Orientation="Horizontal"/>
<StackLayout Spacing="20" Orientation="Vertical"/>
<!--<UniformGridLayout ItemsJustification="Start" ItemsStretch="Uniform" MinColumnSpacing="20" MinRowSpacing="20" MaximumRowsOrColumns="2" Orientation="Horizontal"/>-->
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<Border Width="450" Classes="paper" Background="{DynamicResource ThemeBrushKey}" Padding="20 10">
<DockPanel>
<Image Source="{Binding Icon}" DockPanel.Dock="Left"></Image>
<StackPanel Spacing="8" DockPanel.Dock="Right">
<DockPanel>
<controls:ScrollingTextBlock
Width="{Binding $parent.Width}"
Text="{Binding Name,Mode=OneWay}"
FontSize="16"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<WrapPanel HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock
Text="{Binding Author}"
FontSize="14"
<Border Classes="paper" Background="{DynamicResource ThemeBrushKey}" Padding="20 10">
<DockPanel>
<Image Source="{Binding Icon}" DockPanel.Dock="Left"></Image>
<StackPanel Spacing="8" DockPanel.Dock="Right">
<DockPanel>
<controls:ScrollingTextBlock
Width="{Binding $parent.Width}"
Text="{Binding Name,Mode=OneWay}"
FontSize="16"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<TextBlock Text=" / v" FontSize="14"></TextBlock>
<TextBlock
Text="{Binding Version}"
FontSize="14"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
</WrapPanel>
</DockPanel>
<WrapPanel HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock
Text="{Binding Author}"
FontSize="14"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<Separator Classes="Separator" Margin="0 0 0 5"></Separator>
<TextBlock Text=" / v" FontSize="14"></TextBlock>
<TextBlock
Text="{Binding Version}"
FontSize="14"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
</WrapPanel>
</DockPanel>
<TextBlock
Width="{Binding $parent.Width}"
TextWrapping="WrapWithOverflow"
Text="{Binding Description}"
FontSize="12"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<Separator Classes="Separator" Margin="0 0 0 5"></Separator>
<TextBlock
Width="{Binding $parent.Width}"
TextWrapping="WrapWithOverflow"
Text="{Binding Description}"
FontSize="12"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<DockPanel VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal" Spacing="10">
<ToggleSwitch OnContent="" OffContent="" IsChecked="{Binding Enable,Mode=TwoWay}">
</ToggleSwitch>
<Button Background="Transparent" Cursor="Hand"
Command="{ReflectionBinding #u.DataContext.EditScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Edit,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="20" Data="{StaticResource CodeDrawing}" />
</Button>
<DockPanel VerticalAlignment="Bottom">
<StackPanel Orientation="Horizontal" Spacing="10">
<ToggleSwitch OnContent="" OffContent="" IsChecked="{Binding Enable,Mode=TwoWay}">
</ToggleSwitch>
<Button Background="Transparent" Cursor="Hand"
Command="{ReflectionBinding #u.DataContext.EditScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Edit,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="20" Data="{StaticResource CodeDrawing}" />
</Button>
<Button Background="Transparent" Cursor="Hand"
Command="{ReflectionBinding #u.DataContext.RefreshScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Refresh,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="16" Data="{StaticResource RefreshDrawing}" />
</Button>
<Button Background="Transparent" Cursor="Hand"
Command="{ReflectionBinding #u.DataContext.RefreshScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Refresh,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="16" Data="{StaticResource RefreshDrawing}" />
</Button>
<Button Background="Transparent" Cursor="Hand"
Command="{ReflectionBinding #u.DataContext.OpenHomeScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Home,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="16" Data="{StaticResource HomeDrawing}" />
</Button>
<Button Background="Transparent" Cursor="Hand"
Command="{ReflectionBinding #u.DataContext.OpenHomeScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Home,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="16" Data="{StaticResource HomeDrawing}" />
</Button>
<Button Background="Transparent" IsVisible="{Binding !IsBasics}" Cursor="Hand" HorizontalAlignment="Right"
Command="{ReflectionBinding #u.DataContext.DeleteScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Delete,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="20" Data="{StaticResource DeleteDrawing}" />
</Button>
<Button Background="Transparent" IsVisible="{Binding !IsBasics}" Cursor="Hand" HorizontalAlignment="Right"
Command="{ReflectionBinding #u.DataContext.DeleteScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Delete,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="20" Data="{StaticResource DeleteDrawing}" />
</Button>
</StackPanel>
</StackPanel>
<WrapPanel
DockPanel.Dock="Right"
HorizontalAlignment="Right"
VerticalAlignment="Center"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Update,Mode=OneWay,Source={x:Static resx:R.Current}}"
IsVisible="{Binding IsUpdate}">
<!--<Button Background="Transparent" IsVisible="{Binding IsUpdate}" Cursor="Hand" HorizontalAlignment="Right"
<WrapPanel
DockPanel.Dock="Right"
HorizontalAlignment="Right"
VerticalAlignment="Center"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Update,Mode=OneWay,Source={x:Static resx:R.Current}}"
IsVisible="{Binding IsUpdate}">
<!--<Button Background="Transparent" IsVisible="{Binding IsUpdate}" Cursor="Hand" HorizontalAlignment="Right"
Command="{ReflectionBinding #u.DataContext.DownloadScriptItemButton}"
CommandParameter="{Binding}"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_Update,Mode=OneWay,Source={x:Static resx:R.Current}}">
<PathIcon Width="20" Height="20" Data="{StaticResource DownloadDrawing}" />
</Button>-->
<controls:ProgressRing IsIndeterminate="True"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_ImportLoading,Mode=OneWay,Source={x:Static resx:R.Current}}" HorizontalAlignment="Stretch" Height="30" Width="30"
IsVisible="{Binding IsLoading}" />
<Button Classes="Hyperlink"
Command="{ReflectionBinding #u.DataContext.DownloadScriptItemButton}"
CommandParameter="{Binding}"
Content="{Binding NewVersion,StringFormat={}v{0}}"
FontSize="{DynamicResource FontSizeH7}"
VerticalContentAlignment="Center"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<Ellipse VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="6" Width="6" Margin="5 0"
Fill="{DynamicResource ValidationErrorColorKey}">
</Ellipse>
</WrapPanel>
</DockPanel>
</StackPanel>
</DockPanel>
</Border>
<controls:ProgressRing IsIndeterminate="True"
ToolTip.Tip="{ReflectionBinding Path=Res.Script_ImportLoading,Mode=OneWay,Source={x:Static resx:R.Current}}" HorizontalAlignment="Stretch" Height="30" Width="30"
IsVisible="{Binding IsLoading}" />
<Button Classes="Hyperlink"
Command="{ReflectionBinding #u.DataContext.DownloadScriptItemButton}"
CommandParameter="{Binding}"
Content="{Binding NewVersion,StringFormat={}v{0}}"
FontSize="{DynamicResource FontSizeH7}"
VerticalContentAlignment="Center"
VerticalAlignment="Center"
Foreground="{DynamicResource HighlightForegroundBrushKey}"/>
<Ellipse VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="6" Width="6" Margin="5 0"
Fill="{DynamicResource ValidationErrorColorKey}">
</Ellipse>
</WrapPanel>
</DockPanel>
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
@@ -7,64 +7,70 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="System.Application.UI.Views.Pages.Settings_UI">
<ScrollViewer>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Spacing="20">
<StackPanel.Styles>
<Style Selector="TextBlock">
<Setter Property="FontSize" Value="{StaticResource FontSizeH7}"/>
<Setter Property="Foreground" Value="{DynamicResource HighlightForegroundBrushKey}" />
</Style>
<Style Selector="DockPanel > TextBlock">
<Setter Property="Margin" Value="0 0 20 0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Left" />
</Style>
<Style Selector="DockPanel > ToggleSwitch">
<Setter Property="Margin" Value="0 0 -12 0" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="OnContent" Value="{x:Null}" />
<Setter Property="OffContent" Value="{x:Null}" />
</Style>
</StackPanel.Styles>
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Language,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ComboBox HorizontalAlignment="Stretch" SelectedItem="{Binding SelectLanguage, Mode=TwoWay}" Items="{Binding Mode=OneWay,Source={x:Static resx:R.Languages}}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value,Mode=OneWay}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<ScrollViewer>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Spacing="20">
<StackPanel.Styles>
<Style Selector="TextBlock">
<Setter Property="FontSize" Value="{StaticResource FontSizeH7}"/>
<Setter Property="Foreground" Value="{DynamicResource HighlightForegroundBrushKey}" />
</Style>
<Style Selector="DockPanel > TextBlock">
<Setter Property="Margin" Value="0 0 20 0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Left" />
</Style>
<Style Selector="DockPanel > ToggleSwitch">
<Setter Property="Margin" Value="0 0 -12 0" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="OnContent" Value="{x:Null}" />
<Setter Property="OffContent" Value="{x:Null}" />
</Style>
</StackPanel.Styles>
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Theme,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ComboBox x:Name="Themes"
SelectedIndex="{Binding Source={x:Static ms:UISettings.Theme},Path=Value, Mode=TwoWay}"
HorizontalAlignment="Stretch">
<ComboBoxItem Content="{ReflectionBinding Path=Res.Settings_UI_SystemDefault,Mode=OneWay,Source={x:Static resx:R.Current}}"></ComboBoxItem>
<ComboBoxItem Content="{ReflectionBinding Path=Res.Settings_UI_Light,Mode=OneWay,Source={x:Static resx:R.Current}}"></ComboBoxItem>
<ComboBoxItem Content="{ReflectionBinding Path=Res.Settings_UI_Dark,Mode=OneWay,Source={x:Static resx:R.Current}}"></ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="10" Margin="0 5 0 0">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Language,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ComboBox HorizontalAlignment="Stretch" SelectedItem="{Binding SelectLanguage, Mode=TwoWay}" Items="{Binding Mode=OneWay,Source={x:Static resx:R.Languages}}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Value,Mode=OneWay}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Fonts,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ComboBox
Items="{Binding Mode=OneWay,Source={x:Static resx:R.Fonts}}"
SelectedItem="{Binding SelectFont}"
HorizontalAlignment="Stretch"
MaxDropDownHeight="450">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key,Mode=OneWay}"
FontFamily="{Binding Value,Mode=OneWay,Converter={StaticResource NameToFontFamilyConverter}}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<Separator Classes="Separator"/>
</StackPanel>
</ScrollViewer>
</UserControl>
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Theme,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ComboBox x:Name="Themes"
SelectedIndex="{Binding Source={x:Static ms:UISettings.Theme},Path=Value, Mode=TwoWay}"
HorizontalAlignment="Stretch">
<ComboBoxItem Content="{ReflectionBinding Path=Res.Settings_UI_SystemDefault,Mode=OneWay,Source={x:Static resx:R.Current}}"></ComboBoxItem>
<ComboBoxItem Content="{ReflectionBinding Path=Res.Settings_UI_Light,Mode=OneWay,Source={x:Static resx:R.Current}}"></ComboBoxItem>
<ComboBoxItem Content="{ReflectionBinding Path=Res.Settings_UI_Dark,Mode=OneWay,Source={x:Static resx:R.Current}}"></ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="10">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_Fonts,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<ComboBox
Items="{Binding Mode=OneWay,Source={x:Static resx:R.Fonts}}"
SelectedItem="{Binding SelectFont}"
HorizontalAlignment="Stretch"
MaxDropDownHeight="450">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Key,Mode=OneWay}"
FontFamily="{Binding Value,Mode=OneWay,Converter={StaticResource NameToFontFamilyConverter}}"></TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<Separator Classes="Separator"/>
<StackPanel Orientation="Vertical" Spacing="8">
<TextBlock Text="{ReflectionBinding Path=Res.Settings_UI_AcrylicTransparency,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<Slider Value="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=TwoWay}" Minimum="0" Maximum="1.0"></Slider>
</StackPanel>
<Separator Classes="Separator"/>
</StackPanel>
</ScrollViewer>
</UserControl>
@@ -45,7 +45,11 @@ namespace Avalonia.Controls
if (this.DataContext is WindowViewModel vm)
{
if (vm.SizePosition.X > 0 && vm.SizePosition.Y > 0)
this.Position = new PixelPoint(vm.SizePosition.X, vm.SizePosition.Y);
{
var point = new PixelPoint(vm.SizePosition.X, vm.SizePosition.Y);
if (Screens.Primary.WorkingArea.Contains(point))
this.Position = point;
}
if (vm.SizePosition.Width > 0)
this.Width = vm.SizePosition.Width;
@@ -54,6 +58,7 @@ namespace Avalonia.Controls
this.Height = vm.SizePosition.Height;
HandleResized(new Size(this.Width, this.Height));
this.GetObservable(WidthProperty).Subscribe(v =>
{
vm.SizePosition.Width = v;
@@ -36,7 +36,7 @@
<DockPanel HorizontalAlignment="Stretch">
<ExperimentalAcrylicBorder DockPanel.Dock="Top" IsHitTestVisible="False" Height="80">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="0.85" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="10 8 10 8">
<Image Source="/Application/UI/Assets/Icon.ico" Height="24" Width="24" Margin="0,0,10,0"/>
@@ -45,7 +45,7 @@
</ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder DockPanel.Dock="Bottom" IsHitTestVisible="False" Opacity="{StaticResource ContentOpacity}">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="0.85" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
</DockPanel>
@@ -26,7 +26,7 @@
<DockPanel HorizontalAlignment="Stretch">
<ExperimentalAcrylicBorder DockPanel.Dock="Top" IsHitTestVisible="False" Height="95">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="0.85" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource BackgroundColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="10 8 10 8">
<Image Source="/Application/UI/Assets/Icon.ico" Height="24" Width="24" Margin="0,0,10,0"/>
@@ -35,7 +35,7 @@
</ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder DockPanel.Dock="Bottom" IsHitTestVisible="False" Opacity="{StaticResource ContentOpacity}">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="0.85" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
</DockPanel>
@@ -22,69 +22,84 @@
x:DataType="vm:LoginOrRegisterWindowViewModel"
x:CompileBindings="True"
Title="{Binding Title}">
<Panel>
<controls:TitleBar />
<Panel>
<controls:TitleBar />
<Panel>
<controls:ProgressRing IsIndeterminate="True" HorizontalAlignment="Stretch" Height="100" Width="100" IsVisible="{Binding IsLoading}" />
<Grid RowDefinitions="*,Auto" IsVisible="{Binding !IsLoading}">
<StackPanel VerticalAlignment="Center" Spacing="8" IsVisible="{Binding !IsLoading}" Margin="60 0">
<Image Source="/Application/UI/Assets/Icon.ico" Height="128" Width="128" HorizontalAlignment="Center" Margin="0 0 0 25">
<!--<Image.Clip>
<controls:ProgressRing IsIndeterminate="True" HorizontalAlignment="Stretch" Height="100" Width="100" IsVisible="{Binding IsLoading}" />
<Grid RowDefinitions="*,Auto" IsVisible="{Binding !IsLoading}">
<StackPanel VerticalAlignment="Center" Spacing="8" IsVisible="{Binding !IsLoading}" Margin="60 0">
<Image Source="/Application/UI/Assets/Icon.ico" Height="128" Width="128" HorizontalAlignment="Center" Margin="0 0 0 25">
<!--<Image.Clip>
<EllipseGeometry Rect="0,0,128,128"/>
</Image.Clip>-->
</Image>
<TextBox
x:Name="TbPhoneNumber"
Watermark="{ReflectionBinding Path=Res.User_Phone,Mode=OneWay,Source={x:Static resx:R.Current}}"
Text="{Binding PhoneNumber}"
MaxLength="{ReflectionBinding Path=PhoneNumber,Mode=OneTime,Source={x:Static ccl_services:InputLengthConstants.Current}}" />
<Panel>
<TextBox
x:Name="TbSmsCode"
Watermark="{ReflectionBinding Path=Res.User_SMSCode,Mode=OneWay,Source={x:Static resx:R.Current}}"
Text="{Binding SmsCode}"
MaxLength="{ReflectionBinding Path=SMS_CAPTCHA,Mode=OneTime,Source={x:Static ccl_services:InputLengthConstants.Current}}" />
<Border HorizontalAlignment="Right" Cursor="Hand">
<Button Classes="CodeButton"
Content="{Binding BtnSendSmsCodeText}"
HorizontalAlignment="Right"
Command="{ReflectionBinding SendSms}"
IsEnabled="{Binding !IsUnTimeLimit}" />
</Border>
</Panel>
</Image>
<TextBox
x:Name="TbPhoneNumber"
Watermark="{ReflectionBinding Path=Res.User_Phone,Mode=OneWay,Source={x:Static resx:R.Current}}"
Text="{Binding PhoneNumber}"
MaxLength="{ReflectionBinding Path=PhoneNumber,Mode=OneTime,Source={x:Static ccl_services:InputLengthConstants.Current}}" />
<Panel>
<TextBox
x:Name="TbSmsCode"
Watermark="{ReflectionBinding Path=Res.User_SMSCode,Mode=OneWay,Source={x:Static resx:R.Current}}"
Text="{Binding SmsCode}"
MaxLength="{ReflectionBinding Path=SMS_CAPTCHA,Mode=OneTime,Source={x:Static ccl_services:InputLengthConstants.Current}}" />
<Border HorizontalAlignment="Right" Cursor="Hand">
<Button Classes="CodeButton"
Content="{Binding BtnSendSmsCodeText}"
HorizontalAlignment="Right"
Command="{ReflectionBinding SendSms}"
IsEnabled="{Binding !IsUnTimeLimit}" />
</Border>
</Panel>
<!--<Panel Margin="2 0 6 0">
<!--<Panel Margin="2 0 6 0">
<CheckBox Content="{ReflectionBinding Path=Res.User_Rememberme,Mode=OneWay,Source={x:Static resx:R.Current}}"></CheckBox>
<Button Classes="Hyperlink" Content="{ReflectionBinding Path=Res.User_LoginTroubleshoot,Mode=OneWay,Source={x:Static resx:R.Current}}" HorizontalAlignment="Right"></Button>
</Panel>-->
<Button Classes="action"
Content="{ReflectionBinding Path=Res.LoginAndRegister,Mode=OneWay,Source={x:Static resx:R.Current}}"
Command="{ReflectionBinding Submit}"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center">
</Button>
<Button Classes="action"
Content="{ReflectionBinding Path=Res.LoginAndRegister,Mode=OneWay,Source={x:Static resx:R.Current}}"
Command="{ReflectionBinding Submit}"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center">
</Button>
<WrapPanel HorizontalAlignment="Center" Margin="2 0 6 0">
<TextBlock Text="{ReflectionBinding Path=Res.User_RegisterAgreed,Mode=OneWay,Source={x:Static resx:R.Current}}" FontSize="12"/>
<Button FontSize="12" Classes="Hyperlink" Margin="5,0" Content="{ReflectionBinding Path=Res.User_Agreement,Mode=OneWay,Source={x:Static resx:R.Current}}" Command="{ReflectionBinding OpenHyperlink}" CommandParameter="https://steampp.net/AgreementBox"/>
<TextBlock FontSize="12" Text="{ReflectionBinding Path=Res.And,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<Button FontSize="12" Classes="Hyperlink" Margin="5,0" Content="{ReflectionBinding Path=Res.User_Privacy,Mode=OneWay,Source={x:Static resx:R.Current}}" Command="{ReflectionBinding OpenHyperlink}" CommandParameter="https://steampp.net/PrivacyBox"/>
</WrapPanel>
</StackPanel>
<!--<StackPanel Grid.Row="1" Margin="0 0 0 10">
<Button
HorizontalAlignment="Center" HorizontalContentAlignment="Center" Background="Transparent" BorderThickness="0" Cursor="Hand" Command="{Binding SteamFastLogin}">
<StackPanel Orientation="Horizontal" Spacing="10">
<PathIcon Data="{StaticResource SteamDrawing}" Width="18"></PathIcon>
<TextBlock Text="{ReflectionBinding Path=Res.User_SteamFastLogin,Mode=OneWay,Source={x:Static resx:R.Current}}"></TextBlock>
</StackPanel>
</Button>
</StackPanel>-->
</Grid>
</Panel>
<!--Toast-->
<controls:ToastMessage />
<WrapPanel HorizontalAlignment="Center" Margin="2 0 6 0">
<TextBlock Text="{ReflectionBinding Path=Res.User_RegisterAgreed,Mode=OneWay,Source={x:Static resx:R.Current}}" FontSize="12"/>
<Button FontSize="12" Classes="Hyperlink" Margin="5,0" Content="{ReflectionBinding Path=Res.User_Agreement,Mode=OneWay,Source={x:Static resx:R.Current}}" Command="{ReflectionBinding OpenHyperlink}" CommandParameter="https://steampp.net/AgreementBox"/>
<TextBlock FontSize="12" Text="{ReflectionBinding Path=Res.And,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<Button FontSize="12" Classes="Hyperlink" Margin="5,0" Content="{ReflectionBinding Path=Res.User_Privacy,Mode=OneWay,Source={x:Static resx:R.Current}}" Command="{ReflectionBinding OpenHyperlink}" CommandParameter="https://steampp.net/PrivacyBox"/>
</WrapPanel>
</StackPanel>
<StackPanel HorizontalAlignment="Center" Grid.Row="1" Margin="0 0 0 10" Orientation="Horizontal" Spacing="10">
<Button HorizontalContentAlignment="Center"
Background="Transparent"
BorderThickness="0"
Cursor="Hand"
Command="{ReflectionBinding SteamFastLogin}">
<StackPanel Orientation="Horizontal" Spacing="10">
<PathIcon Data="{StaticResource SteamDrawing}" Width="18"></PathIcon>
<TextBlock Text="{ReflectionBinding Path=Res.User_SteamFastLogin,Mode=OneWay,Source={x:Static resx:R.Current}}"></TextBlock>
</StackPanel>
</Button>
<!--<Button Classes="plain"
HorizontalContentAlignment="Center"
Command="{ReflectionBinding SteamFastLogin}">
<TextBlock Text="{ReflectionBinding Path=Res.User_FastLogin,Mode=OneWay,Source={x:Static resx:R.Current}}"></TextBlock>
</Button>
<Separator Classes="Separator" Height="{ReflectionBinding $parent.Height}" Width="0.88"></Separator>
<Button Classes="plain"
HorizontalContentAlignment="Center"
Command="{ReflectionBinding SteamFastLogin}">
<TextBlock Text="{ReflectionBinding Path=Res.User_PhoneLogin,Mode=OneWay,Source={x:Static resx:R.Current}}"></TextBlock>
</Button>-->
</StackPanel>
</Grid>
</Panel>
<!--Toast-->
<controls:ToastMessage />
</Panel>
</Window>
@@ -63,7 +63,7 @@
<DockPanel>
<Image Source="/Application/UI/Assets/AppResources/avater.jpg" Width="184" Height="184"/>
<StackPanel Orientation="Vertical" Margin="16,0,0,0">
<Button Content="{ReflectionBinding Path=Res.UploadYourAvatar,Mode=OneWay,Source={x:Static resx:R.Current}}"
<Button Content="{ReflectionBinding Path=Res.RefreshSteamAvatar,Mode=OneWay,Source={x:Static resx:R.Current}}"
Opacity="0"
IsEnabled="False"
Classes="SecondaryMin MariginButton WidthUnify"/>
@@ -71,13 +71,13 @@
Margin="0,0,0,32"
Opacity="0"
FontSize="12"
Text="{ReflectionBinding Path=Res.UploadYourAvatarDesc,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
Text="{ReflectionBinding Path=Res.RefreshSteamAvatarDesc,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<Button Classes="SecondaryMin MariginButton"
IsEnabled="False"
Content="{ReflectionBinding Path=Res.RefreshSteamAvatar,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
Content="{ReflectionBinding Path=Res.UploadYourAvatar,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
<TextBlock FontSize="12"
TextWrapping="Wrap"
Text="{ReflectionBinding Path=Res.RefreshSteamAvatarDesc,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
Text="{ReflectionBinding Path=Res.UploadYourAvatarDesc,Mode=OneWay,Source={x:Static resx:R.Current}}"/>
</StackPanel>
</DockPanel>
<Grid>
@@ -4,6 +4,8 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client.Desktop"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls;assembly=System.Application.SteamTools.Client.Desktop.Avalonia"
xmlns:ms="clr-namespace:System.Application.Models.Settings;assembly=System.Application.SteamTools.Client.Desktop"
FontFamily="{ReflectionBinding Source={x:Static ms:UISettings.FontName},Path=Value, Mode=OneWay,Converter={StaticResource NameToFontFamilyConverter}}"
mc:Ignorable="d"
d:DesignWidth="800" d:DesignHeight="600"
Width="800" Height="600"
@@ -25,7 +27,8 @@
</Image>-->
<ExperimentalAcrylicBorder Opacity="{StaticResource ContentOpacity}">
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}" MaterialOpacity="0.80" TintOpacity="1"/>
<ExperimentalAcrylicMaterial TintColor="{DynamicResource ThemeColorKey}"
MaterialOpacity="{ReflectionBinding Value,Source={x:Static ms:UISettings.AcrylicOpacity},Mode=OneWay}" TintOpacity="1"/>
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
<controls:WebView3 x:Name="webView"/>
@@ -2,10 +2,15 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using CefNet;
using CefNet.JSInterop;
using CefNet.Net;
using CefSharp;
using ReactiveUI;
using System.Application.Services;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Application.UI.Views.Controls;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@@ -50,7 +55,6 @@ namespace System.Application.UI.Views.Windows
}
catch (OperationCanceledException)
{
}
if (isDelayed && vm.IsLoading)
{
@@ -66,54 +70,152 @@ namespace System.Application.UI.Views.Windows
}
bool isFirstWebViewLoading;
private void WebView_LoadingStateChange(object? sender, LoadingStateChangeEventArgs e)
//#if DEBUG
// bool isShowDevTools;
//#endif
private async void WebView_LoadingStateChange(object? sender, LoadingStateChangeEventArgs e)
{
if (!isFirstWebViewLoading)
//#if DEBUG
// if (!isShowDevTools)
// {
// webView.ShowDevTools();
// isShowDevTools = true;
// }
//#endif
if (DataContext is WebView3WindowViewModel vm)
{
isFirstWebViewLoading = true;
if (DataContext is WebView3WindowViewModel vm && !string.IsNullOrWhiteSpace(vm.TimeoutErrorMessage))
if (!isFirstWebViewLoading)
{
FirstWebViewLoadingTimeoutInspect(vm);
isFirstWebViewLoading = true;
if (!string.IsNullOrWhiteSpace(vm.TimeoutErrorMessage))
{
FirstWebViewLoadingTimeoutInspect(vm);
}
}
}
if (!e.Busy)
{
if (webView.Opacity != 1) webView.Opacity = 1;
if (DataContext is WebView3WindowViewModel vm && vm.IsLoading)
if (!e.Busy)
{
vm.IsLoading = false;
if (loginUsingSteamClientState == LoginUsingSteamClientState.Loading)
{
var frame = webView.GetMainFrame();
if (frame == null)
{
LoginUsingSteamClientFinishNavigate(vm);
}
try
{
dynamic scriptable = await frame.GetScriptableObjectAsync(CancellationToken.None).ConfigureAwait(true);
scriptable.window.eval("function V_SetCookie() {} function V_GetCookie() {}");
scriptable.window.LoginUsingSteamClient("https://steamcommunity.com");
loginUsingSteamClientState = LoginUsingSteamClientState.Success;
}
catch (Exception ex)
{
#if DEBUG
Log.Error(nameof(WebView3Window), ex, "JSInterop fail.");
#endif
LoginUsingSteamClientFinishNavigate(vm);
}
}
else if (loginUsingSteamClientState == LoginUsingSteamClientState.Success)
{
LoginUsingSteamClientFinishNavigate(vm);
}
else
{
if (webView.Opacity != 1) webView.Opacity = 1;
if (vm.IsLoading)
{
vm.IsLoading = false;
}
}
}
}
}
void Navigate(string url)
{
if (webView.BrowserObject == null)
{
webView.InitialUrl = url;
}
else
{
webView.Navigate(url);
}
}
void LoginUsingSteamClientFinishNavigate(WebView3WindowViewModel? vm = null)
{
loginUsingSteamClientState = LoginUsingSteamClientState.None;
if (vm == null && DataContext is WebView3WindowViewModel vm2) vm = vm2;
Navigate(vm?.Url ?? WebView3WindowViewModel.AboutBlank);
}
static Task? mGetLoginUsingSteamClientCookiesAsync;
static async Task GetLoginUsingSteamClientCookiesAsync()
{
var value = await ISteamService.Instance.GetLoginUsingSteamClientCookiesAsync(runasInvoker: DI.Platform == Platform.Windows);
if (value != default)
{
var url = value.uri.ToString();
var cookies = value.cookies;
var manager = CefRequestContext.GetGlobalContext().GetCookieManager(null);
foreach (Cookie item in cookies)
{
var cookie = new CefNetCookie(item.Name, item.Value);
var setCookieResult = await manager.SetCookieAsync(url, cookie);
if (item.Name == "steamLoginSecure" && !setCookieResult)
{
return;
}
}
}
}
async void GetLoginUsingSteamClientCookies()
{
if (mGetLoginUsingSteamClientCookiesAsync == null)
mGetLoginUsingSteamClientCookiesAsync = GetLoginUsingSteamClientCookiesAsync();
await mGetLoginUsingSteamClientCookiesAsync;
LoginUsingSteamClientFinishNavigate();
}
LoginUsingSteamClientState loginUsingSteamClientState;
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
if (DataContext is WebView3WindowViewModel vm)
{
vm.Close = Close;
if (!string.IsNullOrWhiteSpace(vm.Title)) webView.DocumentTitleChanged -= WebView_DocumentTitleChanged;
vm.Close += Close;
if (!string.IsNullOrWhiteSpace(vm.Title))
webView.DocumentTitleChanged -= WebView_DocumentTitleChanged;
if (vm.UseLoginUsingSteamClient)
{
loginUsingSteamClientState = LoginUsingSteamClientState.Loading;
Navigate("https://steamcommunity.com/login/home/?goto=my/profile");
}
else if (vm.UseLoginUsingSteamClientV2)
{
loginUsingSteamClientState = LoginUsingSteamClientState.Loading;
GetLoginUsingSteamClientCookies();
}
vm.WhenAnyValue(x => x.Url).WhereNotNull().Subscribe(x =>
{
if (x == WebView3WindowViewModel.AboutBlank)
if (loginUsingSteamClientState == default)
{
webView.Opacity = 0;
}
else if (IsHttpUrl(x))
{
if (x.Contains("steampp.net"))
x = string.Format(
x + "?theme={0}&language={1}",
CefNetApp.GetTheme(),
R.Language);
//if (webView.Opacity != 1) webView.Opacity = 1;
if (webView.BrowserObject == null)
if (x == WebView3WindowViewModel.AboutBlank)
{
webView.InitialUrl = x;
webView.Opacity = 0;
}
else
else if (IsHttpUrl(x))
{
webView.Navigate(x);
if (x.StartsWith("https://steampp.net", StringComparison.OrdinalIgnoreCase))
x = string.Format(
x + "?theme={0}&language={1}",
CefNetApp.GetTheme(),
R.Language);
//if (webView.Opacity != 1) webView.Opacity = 1;
Navigate(x);
}
}
}).AddTo(vm);
@@ -190,5 +292,12 @@ namespace System.Application.UI.Views.Windows
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
enum LoginUsingSteamClientState
{
None,
Loading,
Success,
}
}
}
@@ -0,0 +1,46 @@
// Copyright © 2017 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
// https://github.com/cefsharp/CefSharp/blob/v89.0.170/CefSharp/AsyncExtensions.cs
using CefNet;
using CefNet.Net;
using System;
using System.Threading.Tasks;
namespace CefSharp
{
public static class AsyncExtensions
{
/// <summary>
/// Sets a cookie given a valid URL and explicit user-provided cookie attributes.
/// This function expects each attribute to be well-formed. It will check for disallowed
/// characters (e.g. the ';' character is disallowed within the cookie value attribute) and will return false without setting
/// </summary>
/// <param name="cookieManager">cookie manager</param>
/// <param name="url">The cookie URL. If an empty string is provided, any URL will be matched.</param>
/// <param name="cookie">the cookie to be set</param>
/// <returns>returns false if the cookie cannot be set (e.g. if illegal charecters such as ';' are used);
/// otherwise task that represents the set operation. The value of the TResult parameter contains a bool to indicate success.</returns>
public static Task<bool> SetCookieAsync(this CefCookieManager cookieManager, string url, CefNetCookie cookie)
{
if (cookieManager == null)
{
throw new NullReferenceException("cookieManager");
}
if (cookieManager.IsDisposed)
{
throw new ObjectDisposedException("cookieManager");
}
var callback = new TaskSetCookieCallback();
if (cookieManager.SetCookie(url, cookie, callback))
{
return callback.Task;
}
//There was a problem setting cookies
return Task.FromResult(false);
}
}
}
@@ -0,0 +1,60 @@
// Copyright © 2015 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
// https://github.com/cefsharp/CefSharp/blob/v89.0.170/CefSharp/Callback/TaskSetCookieCallback.cs
using CefNet;
using CefSharp.Internals;
using System.Threading.Tasks;
namespace CefSharp
{
/// <summary>
/// Provides a callback implementation of <see cref="ISetCookieCallback"/>.
/// </summary>
public class TaskSetCookieCallback : CefSetCookieCallback
{
private readonly TaskCompletionSource<bool> taskCompletionSource;
private bool onComplete; //Only ever accessed on the same CEF thread, so no need for thread safety
/// <summary>
/// Default constructor
/// </summary>
public TaskSetCookieCallback()
{
taskCompletionSource = new TaskCompletionSource<bool>();
}
protected override void OnComplete(bool success)
{
onComplete = true;
taskCompletionSource.TrySetResultAsync(success);
}
/// <summary>
/// Task used to await this callback
/// </summary>
public Task<bool> Task
{
get { return taskCompletionSource.Task; }
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
var task = taskCompletionSource.Task;
//If onComplete is false then ISetCookieCallback.OnComplete was never called,
//so we'll set the result to false. Calling TrySetResultAsync multiple times
//can result in the issue outlined in https://github.com/cefsharp/CefSharp/pull/2349
if (onComplete == false && task.IsCompleted == false)
{
taskCompletionSource.TrySetResultAsync(false);
}
}
base.Dispose(disposing);
}
}
}
@@ -0,0 +1,31 @@
// Copyright © 2014 The CefSharp Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
// https://github.com/cefsharp/CefSharp/blob/v89.0.170/CefSharp/Internals/TaskExtensions.cs
using System.Threading;
using System.Threading.Tasks;
namespace CefSharp.Internals
{
/// <summary>
/// TaskExtension based on the following
/// https://github.com/ChadBurggraf/parallel-extensions-extras/blob/master/Extensions/TaskExtrasExtensions.cs
/// https://github.com/ChadBurggraf/parallel-extensions-extras/blob/ec803e58eee28c698e44f55f49c5ad6671b1aa58/Extensions/TaskCompletionSourceExtensions.cs
/// </summary>
internal static class TaskExtensions
{
/// <summary>
/// Set the TaskCompletionSource in an async fashion. This prevents the Task Continuation being executed sync on the same thread
/// This is required otherwise contintinuations will happen on CEF UI threads
/// </summary>
/// <typeparam name="TResult">Generic param</typeparam>
/// <param name="taskCompletionSource">tcs</param>
/// <param name="result">result</param>
public static void TrySetResultAsync<TResult>(this TaskCompletionSource<TResult> taskCompletionSource, TResult result)
{
Task.Factory.StartNew(delegate
{ taskCompletionSource.TrySetResult(result); }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default);
}
}
}
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>System</RootNamespace>
<SignAssembly>false</SignAssembly>
<!--(SignAssembly)对此程序集进行签名会导致编译失败(CompileAvaloniaXamlTask)-->
@@ -41,17 +41,17 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia" Version="0.10.999-cibuild0013745-beta" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.999-cibuild0013745-beta" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.999-cibuild0013745-beta" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.999-cibuild0013745-beta" />
<PackageReference Include="Avalonia" Version="0.10.999-cibuild0013932-beta" />
<PackageReference Include="Avalonia.Desktop" Version="0.10.999-cibuild0013932-beta" />
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.10.999-cibuild0013932-beta" />
<PackageReference Include="Avalonia.ReactiveUI" Version="0.10.999-cibuild0013932-beta" />
<PackageReference Include="Avalonia.Xaml.Behaviors" Version="0.10.0" />
<!--<PackageReference Include="CefNet.Avalonia" Version="88.1.21022.1657" />-->
<PackageReference Include="LibVLCSharp.Avalonia" Version="3.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.999-cibuild0013745-beta" />
<PackageReference Include="Avalonia.Diagnostics" Version="0.10.999-cibuild0013932-beta" />
</ItemGroup>
<ItemGroup>
@@ -0,0 +1,16 @@
using System.Application.Services;
namespace System.Application
{
/// <summary>
/// 使用单元测试进行检查依赖注入关系是否配置正确
/// </summary>
static class DISafeGet
{
public static ISteamService GetLoginUsingSteamClientAuth()
{
Startup.Init(DILevel.HttpClientFactory | DILevel.Steam);
return ISteamService.Instance;
}
}
}
@@ -0,0 +1,46 @@
using NLog;
using System;
using System.Application;
using System.Application.UI;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using static System.Application.Program;
using Process = System.Diagnostics.Process;
var logDirPath = InitLogDir("_console");
logger = LogManager.GetCurrentClassLogger();
if (!args.Any())
{
var mainFilePath = AppHelper.ProgramPath;
var endsWithMark = DI.Platform == Platform.Windows ? ".console.exe" : ".console";
if (mainFilePath.EndsWith(endsWithMark, StringComparison.OrdinalIgnoreCase))
{
mainFilePath = mainFilePath.Substring(0, mainFilePath.Length - endsWithMark.Length);
if (DI.Platform == Platform.Windows) mainFilePath += ".exe";
if (File.Exists(mainFilePath))
{
Process.Start(mainFilePath);
return 0;
}
}
}
var rootCommand = new RootCommand("命令行工具(Command Line Tools/CLT)");
var glusca = new Command("GetLoginUsingSteamClientAuth", "获取 Steam 客户端自动登录数据");
glusca.AddAlias("glusca");
glusca.Handler = CommandHandler.Create(async () =>
{
var s = DISafeGet.GetLoginUsingSteamClientAuth();
var r = await s.GetLoginUsingSteamClientAuthAsync(false);
var r2 = Serializable.SMPB64U(r);
Console.WriteLine(r2);
});
rootCommand.AddCommand(glusca);
var r = rootCommand.InvokeAsync(args).Result;
return r;
@@ -0,0 +1,86 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>Steam++.Console</AssemblyName>
<DefineConstants>CONSOLEAPP;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>WINDOWS;$(DefineConstants)</DefineConstants>
<ApplicationIcon>..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico</ApplicationIcon>
<!--<TargetFramework>net5.0-windows10.0.19041.0</TargetFramework>
<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>-->
<Platforms>AnyCPU;x86</Platforms>
<PlatformTarget>x86</PlatformTarget>
<!-- 注意:RuntimeIdentifier win-x86 会导致亚克力效果会丢失 -->
<RuntimeIdentifier>win7-x86</RuntimeIdentifier>
<!--<UseWindowsForms>false</UseWindowsForms>-->
<!--<UseWPF>false</UseWPF>-->
</PropertyGroup>
<PropertyGroup Condition=" $(RuntimeIdentifier.Contains(`osx`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<DefineConstants>MAC;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" $(DefineConstants.Contains(`PUBLISH`)) ">
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
<!--目前裁剪存在问题,禁用-->
<PublishTrimmed>false</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>
<ItemGroup>
<Compile Include="..\Startup2.cs" />
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
<Compile Include="..\ST\Properties\InternalsVisibleTo.cs">
<Link>Properties\InternalsVisibleTo.cs</Link>
</Compile>
<Compile Include="..\ST.Client.Desktop.Avalonia.App\Program.InitLogDir.cs">
<Link>Program.InitLogDir.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ST.Client.Desktop.Avalonia\ST.Client.Desktop.Avalonia.csproj"/>
<ProjectReference Include="..\ST.Client.Desktop\ST.Client.Desktop.csproj"/>
<ProjectReference Include="..\Common.CoreLib\Common.CoreLib.csproj"/>
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<ProjectReference Include="..\ST.Client.Desktop.Windows\ST.Client.Desktop.Windows.csproj"/>
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`osx`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<ProjectReference Include="..\ST.Client.Desktop.Mac\ST.Client.Desktop.Mac.csproj"/>
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`linux`)) Or ('$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<ProjectReference Include="..\ST.Client.Desktop.Linux\ST.Client.Desktop.Linux.csproj"/>
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
<!--Win8.1/10的开始菜单磁贴配置-->
<None Include="..\..\Resources\AppIcon\visualelementsmanifest.xml">
<Link>Steam++.Console.visualelementsmanifest.xml</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.Desktop.Linux</AssemblyName>
</PropertyGroup>
@@ -27,6 +27,11 @@ namespace System.Application.Services.Implementation
return vi;
}
public void SetSystemSessionEnding(Action action)
{
}
public void SetBootAutoStart(bool isAutoStart, string name)
{
}
@@ -63,5 +68,15 @@ namespace System.Application.Services.Implementation
public void SetLightOrDarkThemeFollowingSystem(bool enable)
{
}
public Process StartAsInvoker(string fileName)
{
return Process.Start(fileName);
}
public Process? StartAsInvoker(ProcessStartInfo startInfo)
{
return Process.Start(startInfo);
}
}
}
@@ -1,9 +1,10 @@
<!--<Project Sdk="Microsoft.NET.Sdk">-->
<Project Sdk="MSBuild.Sdk.Extras">
<Project Sdk="Microsoft.NET.Sdk">
<!--<Project Sdk="MSBuild.Sdk.Extras">-->
<PropertyGroup>
<!--<TargetFramework>net6.0-macos</TargetFramework>-->
<TargetFrameworks>Xamarin.Mac20;netstandard2.1</TargetFrameworks>
<!--<TargetFrameworks>Xamarin.Mac20;net5.0</TargetFrameworks>-->
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.Desktop.Mac</AssemblyName>
</PropertyGroup>
@@ -23,7 +24,7 @@
<DefineConstants>XAMARIN_MAC;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
<PropertyGroup Condition=" $(TargetFramework.StartsWith('netstandard')) OR $(TargetFramework.StartsWith('net5')) OR $(TargetFramework.EndsWith('net6.0')) ">
<DefineConstants>MONO_MAC;$(DefineConstants)</DefineConstants>
</PropertyGroup>
@@ -43,13 +44,13 @@
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac20')) ">
<PackageReference Include="nor0x.AppCenter" Version="4.1.0.1-XMAC"/>
<PackageReference Include="nor0x.AppCenter.Analytics" Version="4.1.0.1-XMAC"/>
<PackageReference Include="nor0x.AppCenter.Crashes" Version="4.1.0.1-XMAC"/>
<PackageReference Include="nor0x.AppCenter" Version="4.1.0.1-XMAC" />
<PackageReference Include="nor0x.AppCenter.Analytics" Version="4.1.0.1-XMAC" />
<PackageReference Include="nor0x.AppCenter.Crashes" Version="4.1.0.1-XMAC" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4"/>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) OR $(TargetFramework.StartsWith('net5')) OR $(TargetFramework.EndsWith('net6.0')) ">
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" />
</ItemGroup>
<!--<ItemGroup Condition=" '$(OS)' == 'Windows_NT' ">
@@ -67,14 +68,14 @@
</ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\ST.Client.Desktop\ST.Client.Desktop.csproj"/>
<ProjectReference Include="..\ST.Client.Desktop\ST.Client.Desktop.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug' And Exists('$(MSBuildProjectDirectory)\..\..\appcenter-secret-mac-debug.pfx')">
<EmbeddedResource Include="..\..\appcenter-secret-mac-debug.pfx" Link="Resources\547E2811"/>
<EmbeddedResource Include="..\..\appcenter-secret-mac-debug.pfx" Link="Resources\547E2811" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Release' And Exists('$(MSBuildProjectDirectory)\..\..\appcenter-secret-mac-release.pfx')">
<EmbeddedResource Include="..\..\appcenter-secret-mac-release.pfx" Link="Resources\93850BFE"/>
<EmbeddedResource Include="..\..\appcenter-secret-mac-release.pfx" Link="Resources\93850BFE" />
</ItemGroup>
</Project>
@@ -31,6 +31,11 @@ namespace System.Application.Services.Implementation
p?.Close();
}
public void SetSystemSessionEnding(Action action)
{
}
public void OpenFolder(string dirPath)
{
@@ -153,5 +158,15 @@ namespace System.Application.Services.Implementation
public void SetLightOrDarkThemeFollowingSystem(bool enable)
{
}
public Process StartAsInvoker(string fileName)
{
return Process.Start(fileName);
}
public Process? StartAsInvoker(ProcessStartInfo startInfo)
{
return Process.Start(startInfo);
}
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
#if MONO_MAC
#if MONO_MAC
using MonoMac.AppKit;
using MonoMac.Foundation;
#elif XAMARIN_MAC
@@ -60,7 +60,7 @@ namespace System.Application.UI
/// <param name="notification"></param>
public override void DidFinishLaunching(NSNotification notification)
{
#if !NETSTANDARD
#if !NETSTANDARD && !NET5_0 && !NET6_0
VisualStudioAppCenterSDK.Init();
#endif
@@ -2,7 +2,7 @@
<PropertyGroup>
<!--<TargetFramework>net5.0-windows10.0.19041.0</TargetFramework>-->
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<!--<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>-->
<RootNamespace>System.Application</RootNamespace>
<!--<UseWindowsForms>false</UseWindowsForms>-->
@@ -135,6 +135,15 @@ namespace System.Application.Services.Implementation
}
}
public void SetSystemSessionEnding(Action action)
{
Microsoft.Win32.SystemEvents.SessionEnding += (sender, e) =>
{
//IDesktopAppService.Instance.CompositeDisposable.Dispose();
action.Invoke();
};
}
static string? GetFullPath(string s)
{
if (!string.IsNullOrWhiteSpace(s))
@@ -164,6 +173,17 @@ namespace System.Application.Services.Implementation
static readonly Lazy<(byte[] key, byte[] iv)> mMachineSecretKey = IDesktopPlatformService.GetMachineSecretKey(GetMachineSecretKey);
public (byte[] key, byte[] iv) MachineSecretKey => mMachineSecretKey.Value;
public Process StartAsInvoker(string fileName)
{
return Process.Start($"/trustlevel:0x20000 \"{fileName}\"");
}
public Process? StartAsInvoker(ProcessStartInfo startInfo)
{
startInfo.FileName = $"/trustlevel:0x20000 \"{startInfo.FileName}\"";
return Process.Start(startInfo);
}
}
}
#pragma warning restore CA1416 // 验证平台兼容性
@@ -1,9 +1,8 @@
using System;
using System.Application.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace System.Application.Models.Settings
{
@@ -50,6 +49,17 @@ namespace System.Application.Models.Settings
public static SerializableProperty<IReadOnlyCollection<string>> SupportProxyServicesStatus { get; }
= new SerializableProperty<IReadOnlyCollection<string>>(GetKey(), Providers.Local, new List<string>());
/// <summary>
/// 系统代理模式端口
/// </summary>
public static SerializableProperty<int> SystemProxyPortId { get; }
= new SerializableProperty<int>(GetKey(), Providers.Local, 26501);
/// <summary>
/// 系统代理模式IP
/// </summary>
public static SerializableProperty<string> SystemProxyIp { get; }
= new SerializableProperty<string>(GetKey(), Providers.Local, IPAddress.Loopback.ToString());
/// <summary>
/// 脚本启用状态
@@ -58,6 +58,12 @@ namespace System.Application.Models.Settings
public static SerializableProperty<int> ThemeAccent { get; }
= new SerializableProperty<int>(GetKey(), Providers.Local, 0) { AutoSave = true };
/// <summary>
/// 窗口毛玻璃背景透明度
/// </summary>
public static SerializableProperty<double> AcrylicOpacity { get; }
= new SerializableProperty<double>(GetKey(), Providers.Local, 0.80) { AutoSave = true };
/// <summary>
/// 库存游戏封面大小
/// </summary>
@@ -69,7 +75,7 @@ namespace System.Application.Models.Settings
/// </summary>
public static SerializableProperty<Dictionary<string, WindowSizePosition>> WindowSizePositions { get; }
= new SerializableProperty<Dictionary<string, WindowSizePosition>>(GetKey(), Providers.Local, new Dictionary<string, WindowSizePosition>()) { AutoSave = true };
private static string GetKey([CallerMemberName] string propertyName = "")
{
return nameof(UISettings) + "." + propertyName;
+12 -3
View File
@@ -70,12 +70,21 @@ namespace System.Application.Properties {
}
/// <summary>
/// 查找类似 echo &quot;{4}&quot;
///taskkill /f /im &quot;{0}&quot;
/// 查找类似 @echo off
///:loop
///ping -n 1 127.0.0.1
///tasklist|find /i &quot;{0}&quot;
///if %errorlevel%==0 (
///taskkill /im &quot;{0}&quot; /f
///)
///else(
///taskkill /im &quot;{0}&quot; /f
///xcopy /y /c /h /r /s &quot;{1}\*.*&quot; &quot;{2}&quot;
///rmdir /s /q &quot;{1}&quot;
///&quot;{3}&quot;
///del %0 的本地化字符串。
///del %0
///)
///goto :loop 的本地化字符串。
/// </summary>
internal static string ProgramUpdateCmd_ {
get {
+14 -5
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
@@ -121,12 +121,21 @@
<value>操作 hosts 错误 {0}</value>
</data>
<data name="ProgramUpdateCmd_" xml:space="preserve">
<value>echo "{4}"
taskkill /f /im "{0}"
<value>@echo off
:loop
ping -n 1 127.0.0.1
tasklist|find /i "{0}"
if %errorlevel%==0 (
taskkill /im "{0}" /f
)
else(
taskkill /im "{0}" /f
xcopy /y /c /h /r /s "{1}\*.*" "{2}"
rmdir /s /q "{1}"
"{3}"
del %0</value>
del %0
)
goto :loop</value>
<comment>升级程序CMD命令行</comment>
</data>
<data name="ProgramUpdateEcho" xml:space="preserve">
@@ -138,4 +147,4 @@ del %0</value>
<data name="UpdateUnpackFail" xml:space="preserve">
<value>更新包解压失败,请打开官网手动更新</value>
</data>
</root>
</root>
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.Desktop</AssemblyName>
</PropertyGroup>
@@ -62,7 +62,7 @@ namespace System.Application.Serialization
lock (_sync)
{
using var stream = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite);
using var stream = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
if (stream.Position > 0)
{
stream.Position = 0;
@@ -77,7 +77,7 @@ namespace System.Application.Serialization
{
if (File.Exists(_path))
{
using var stream = new FileStream(_path, FileMode.Open, FileAccess.Read);
using var stream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
lock (_sync)
{
if (stream.Position > 0)
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;
using System.Application.Services;
using System.Application.Services.Implementation;
@@ -98,7 +98,7 @@ namespace Microsoft.Extensions.DependencyInjection
{
services.AddSingleton<IHttpPlatformHelper, DesktopHttpPlatformHelper>();
return services;
}
}
/// <summary>
/// 添加 Window 窗口viewmodel
/// </summary>
@@ -101,6 +101,11 @@ namespace System.Application.Services
/// <param name="dirPath"></param>
void OpenFolder(string dirPath);
/// <summary>
/// 设置系统关闭时任务
/// </summary>
void SetSystemSessionEnding(Action action);
/// <summary>
/// 获取文本阅读器提供商程序文件路径或文件名(如果提供程序已注册环境变量)
/// </summary>
@@ -182,5 +187,14 @@ namespace System.Application.Services
/// 打开桌面图标设置
/// </summary>
void OpenDesktopIconsSettings();
/// <summary>
/// 已正常权限启动进程
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
Process StartAsInvoker(string fileName);
Process? StartAsInvoker(ProcessStartInfo startInfo);
}
}
@@ -1,6 +1,6 @@
using System.Application.Models;
using System.Application.Models;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace System.Application.Services
@@ -84,5 +84,26 @@ namespace System.Application.Services
Task<string> GetAppImageAsync(SteamApp app, SteamApp.LibCacheType type);
ValueTask LoadAppImageAsync(SteamApp app);
/// <summary>
/// Steam 客户端自动登录
/// </summary>
/// <param name="runasInvoker"></param>
/// <returns></returns>
Task<(string steamid, string encrypted_loginkey, string sessionkey, string digest)> GetLoginUsingSteamClientAuthAsync(bool runasInvoker = false);
/// <summary>
/// 获取 Steam 客户端自动登录 Cookie(用于写入到 WebView3 中免登录)
/// </summary>
/// <param name="auth_data"></param>
/// <returns></returns>
Task<(CookieCollection cookies, Uri uri)> GetLoginUsingSteamClientCookiesAsync((string steamid, string encrypted_loginkey, string sessionkey, string digest) auth_data);
/// <summary>
/// 获取 Steam 客户端自动登录 Cookie(用于写入到 WebView3 中免登录)
/// </summary>
/// <param name="runasInvoker"></param>
/// <returns></returns>
Task<(CookieCollection cookies, Uri uri)> GetLoginUsingSteamClientCookiesAsync(bool runasInvoker = false);
}
}
@@ -58,16 +58,14 @@ namespace System.Application.Services.Implementation
var updateCommandPath = Path.Combine(IOPath.CacheDirectory, "update.cmd");
IOPath.FileIfExistsItDelete(updateCommandPath);
var echo = SR.ProgramUpdateEcho;
if (echo.Contains('"')) echo = "Steam++ is upgrading...";
var updateCommand = string.Format(
SR.ProgramUpdateCmd_,
AppHelper.ProgramName,
dirPath,
dirPath.TrimEnd(Path.DirectorySeparatorChar),
AppContext.BaseDirectory,
AppHelper.ProgramPath,
echo);
AppHelper.ProgramPath);
updateCommand = "chcp" + Environment.NewLine + "chcp 65001" + Environment.NewLine + updateCommand;
File.WriteAllText(updateCommandPath, updateCommand, Encoding.UTF8);
@@ -1,10 +1,25 @@
using System.Application.UI.Resx;
using System.Application.UI.Resx;
using System.Net.Http;
namespace System.Application.Services.Implementation
{
internal sealed class DesktopHttpPlatformHelper : HttpPlatformHelper
{
readonly string mUserAgent;
public DesktopHttpPlatformHelper()
{
mUserAgent = DI.Platform switch
{
Platform.Windows => $"Mozilla/5.0 (Windows NT {Environment.OSVersion.Version.Major}.{Environment.OSVersion.Version.Minor}{(Environment.Is64BitOperatingSystem ? "; WOW64" : null)}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
Platform.Linux => $"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
Platform.Apple =>
$"Mozilla/5.0 (Macintosh; Intel Mac OS X; {Environment.OSVersion.Version.Major}_{Environment.OSVersion.Version.Minor}_{Environment.OSVersion.Version.Build}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.72 Safari/537.36",
_ => DefaultUserAgent,
};
}
public override string AcceptLanguage => R.AcceptLanguage;
public override string UserAgent => mUserAgent;
}
}
@@ -84,42 +84,52 @@ namespace System.Application.Services.Implementation
bool checkReadOnly = false,
bool checkMaxLength = true)
{
message = null;
removeReadOnly = false;
fileInfo = new FileInfo(s.HostsFilePath);
if (!fileInfo.Exists)
try
{
//message = "hosts file was not found";
//return false;
try
message = null;
removeReadOnly = false;
fileInfo = new FileInfo(s.HostsFilePath);
if (!fileInfo.Exists)
{
fileInfo.Create().Dispose();
return true;
//message = "hosts file was not found";
//return false;
try
{
fileInfo.Create().Dispose();
return true;
}
catch (Exception ex)
{
message = ex.GetAllMessage();
return false;
}
}
catch (Exception ex)
if (checkMaxLength)
{
message = ex.GetAllMessage();
return false;
if (fileInfo.Length > MaxFileLength)
{
message = "hosts file is too large";
return false;
}
}
if (checkReadOnly)
{
var attr = fileInfo.Attributes;
if (attr.HasFlag(FileAttributes.ReadOnly))
{
fileInfo.Attributes = attr & ~FileAttributes.ReadOnly;
removeReadOnly = true;
}
}
return true;
}
if (checkMaxLength)
catch (Exception ex)
{
if (fileInfo.Length > MaxFileLength)
{
message = "hosts file is too large";
return false;
}
removeReadOnly = false;
fileInfo = new FileInfo(s.HostsFilePath);
message = ex.Message;
return false;
}
if (checkReadOnly)
{
var attr = fileInfo.Attributes;
if (attr.HasFlag(FileAttributes.ReadOnly))
{
fileInfo.Attributes = attr & ~FileAttributes.ReadOnly;
removeReadOnly = true;
}
}
return true;
}
/// <summary>
@@ -1,9 +1,14 @@
using System.Application.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Application.Models;
using System.Application.Models.Settings;
using System.Application.UI;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
@@ -59,7 +64,7 @@ namespace System.Application.Services.Implementation
{
get
{
return Process.GetProcesses().Any(p => steamProcess.Contains(p.ProcessName, StringComparer.OrdinalIgnoreCase));
return Process.GetProcessesByName(steamProcess[0])?.Length > 0;
}
}
@@ -70,8 +75,11 @@ namespace System.Application.Services.Implementation
{
if (steamProcess.Contains(p.ProcessName, StringComparer.OrdinalIgnoreCase))
{
p.Kill();
p.WaitForExit();
if (p.HasExited == false)
{
p.Kill();
p.WaitForExit();
}
}
}
}
@@ -346,8 +354,9 @@ namespace System.Application.Services.Implementation
return value ?? string.Empty;
}
public async ValueTask LoadAppImageAsync(SteamApp app)
public /*async*/ ValueTask LoadAppImageAsync(SteamApp app)
{
return ValueTask.CompletedTask;
//if (app.LibraryLogoStream == null)
//{
// app.LibraryLogoStream = await GetAppImageAsync(app, SteamApp.LibCacheType.Library_600x900);
@@ -370,6 +379,119 @@ namespace System.Application.Services.Implementation
//}
}
public async Task<(string steamid, string encrypted_loginkey, string sessionkey, string digest)> GetLoginUsingSteamClientAuthAsync(bool runasInvoker = false)
{
if (runasInvoker)
{
if (AppHelper.ProgramPath.EndsWith(FileEx.EXE))
{
var consoleProgramPath = AppHelper.ProgramPath.Substring(0, AppHelper.ProgramPath.Length - FileEx.EXE.Length) + ".Console" + FileEx.EXE;
string? value = null;
if (File.Exists(consoleProgramPath))
{
var startInfo = new ProcessStartInfo
{
FileName = consoleProgramPath + " glusca",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
};
using var p = platformService.StartAsInvoker(startInfo)!;
var reader = p.StandardOutput;
StringBuilder sb = new();
while (!reader.EndOfStream)
{
sb.AppendLine(reader.ReadLine());
}
value = sb.ToString();
p.WaitForExit();
}
if (value != null)
{
try
{
var r = Serializable.DMPB64U<(string steamid, string encrypted_loginkey, string sessionkey, string digest)>(value);
return r;
}
catch
{
}
}
}
}
else
{
const string url_localhost_auth_public = "http://127.0.0.1:27060/auth/?u=public";
try
{
var client = http.Factory.CreateClient();
client.Timeout = TimeSpan.FromSeconds(.85);
var request = new HttpRequestMessage(HttpMethod.Get, url_localhost_auth_public);
request.Headers.Add("Origin", "https://steamcommunity.com");
request.Headers.Add("Accept", MediaTypeNames.JSON);
request.Headers.UserAgent.ParseAdd(http.PlatformHelper.UserAgent);
var response = await client.SendAsync(request);
if (response.IsSuccessStatusCode)
{
using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
using var reader = new StreamReader(stream, Encoding.UTF8);
using var json = new JsonTextReader(reader);
var jsonObj = JObject.Load(json);
var steamid = jsonObj["steamid"]!.ToString();
var encrypted_loginkey = jsonObj["encrypted_loginkey"]!.ToString();
var sessionkey = jsonObj["sessionkey"]!.ToString();
var digest = jsonObj["digest"]!.ToString();
return (steamid, encrypted_loginkey, sessionkey, digest);
}
}
catch (OperationCanceledException)
{
}
}
return default;
}
public async Task<(CookieCollection cookies, Uri uri)> GetLoginUsingSteamClientCookiesAsync((string steamid, string encrypted_loginkey, string sessionkey, string digest) auth_data)
{
if (auth_data == default) return default;
const string url_steamcommunity_checkclientautologin = "https://steamcommunity.com//login/checkclientautologin";
var uri_steamcommunity_checkclientautologin = new Uri(url_steamcommunity_checkclientautologin);
var request = new HttpRequestMessage(HttpMethod.Post, uri_steamcommunity_checkclientautologin)
{
#pragma warning disable CS8620 // 由于引用类型的可为 null 性差异,实参不能用于形参。
Content = new FormUrlEncodedContent(new Dictionary<string, string?>
{
{ "steamid", auth_data.steamid },
{ "encrypted_loginkey", auth_data.encrypted_loginkey },
{ "sessionkey", auth_data.sessionkey },
{ "digest", auth_data.digest },
}),
#pragma warning restore CS8620 // 由于引用类型的可为 null 性差异,实参不能用于形参。
};
var client = http.Factory.CreateClient();
client.Timeout = TimeSpan.FromSeconds(9.75);
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
if (response.IsSuccessStatusCode && response.Headers.TryGetValues("Set-Cookie", out var cookies))
{
CookieContainer container = new();
foreach (var item in cookies)
{
if (string.IsNullOrWhiteSpace(item)) continue;
container.SetCookies(uri_steamcommunity_checkclientautologin, item);
}
var cookies2 = container.GetCookies(uri_steamcommunity_checkclientautologin);
return (cookies2, uri_steamcommunity_checkclientautologin);
}
return default;
}
public async Task<(CookieCollection cookies, Uri uri)> GetLoginUsingSteamClientCookiesAsync(bool runasInvoker = false)
{
var auth_data = await GetLoginUsingSteamClientAuthAsync(runasInvoker);
var r = await GetLoginUsingSteamClientCookiesAsync(auth_data);
return r;
}
}
}
@@ -1,4 +1,4 @@
using ReactiveUI;
using ReactiveUI;
using System;
using System.Application.Mvvm;
using System.Application.UI.ViewModels;
@@ -26,15 +26,22 @@ namespace System.Application.Services.Implementation
public void Init()
{
if (appidUnlockAchievement.HasValue)
try
{
achievementWindow = new AchievementWindowViewModel(appidUnlockAchievement.Value);
MainWindow = achievementWindow;
if (appidUnlockAchievement.HasValue)
{
achievementWindow = new AchievementWindowViewModel(appidUnlockAchievement.Value);
MainWindow = achievementWindow;
}
else
{
mainWindow = new MainWindowViewModel();
MainWindow = mainWindow;
}
}
else
catch (Exception ex)
{
mainWindow = new MainWindowViewModel();
MainWindow = mainWindow;
Log.Error("WindowService", ex, "Init WindowViewModel");
}
}
@@ -1,4 +1,4 @@
using DynamicData;
using DynamicData;
using DynamicData.Binding;
using Newtonsoft.Json.Linq;
using ReactiveUI;
@@ -487,14 +487,10 @@ namespace System.Application.Services
public void SaveEditNameAuthenticators()
{
Task.Run(() =>
{
var auths = Authenticators.Items.Where(x => x.Name != x.OriginName);
foreach (var auth in auths)
AddOrUpdateSaveAuthenticators(auth);
});
var auths = Authenticators.Items.Where(x => x.Name != x.OriginName);
foreach (var auth in auths)
AddOrUpdateSaveAuthenticators(auth);
}
}
}
@@ -276,12 +276,6 @@ namespace System.Application.Services
//}
//new ObservableCollection<ScriptDTO>(response.Content);
var scriptList = await DI.Get<IScriptManagerService>().GetAllScript();
var basicsId = Guid.Parse("00000000-0000-0000-0000-000000000001");
foreach (var item in scriptList)
{
item.IsBasics = item.Id == basicsId;
}
if (ProxySettings.ScriptsStatus.Value.Any_Nullable() && scriptList.Any())
{
foreach (var item in scriptList)
@@ -313,16 +307,16 @@ namespace System.Application.Services
public async void BasicsInfo()
{
var basicsInfo = await ICloudServiceClient.Instance.Script.Basics(AppResources.Script_UpdateError);
if (basicsInfo.Code == ApiResponseCode.OK && basicsInfo.Content != null)
var basicsItem = ProxyScripts.Items.FirstOrDefault(x => x.Id == Guid.Parse("00000000-0000-0000-0000-000000000001"));
if (basicsItem == null)
{
var basicsItem = ProxyScripts.Items.FirstOrDefault(x => x.Id == Guid.Parse("00000000-0000-0000-0000-000000000001"));
if (basicsItem == null)
var basicsInfo = await ICloudServiceClient.Instance.Script.Basics(AppResources.Script_UpdateError);
if (basicsInfo.Code == ApiResponseCode.OK && basicsInfo.Content != null)
{
var jspath = await DI.Get<IScriptManagerService>().DownloadScript(basicsInfo.Content.UpdateLink);
if (jspath.state)
{
var build = await DI.Get<IScriptManagerService>().AddScriptAsync(jspath.path, build: false, order: 1, deleteFile: true, pid: basicsInfo.Content.Id);
var build = await DI.Get<IScriptManagerService>().AddScriptAsync(jspath.path, build: false, order: 1, deleteFile: true, pid: basicsInfo.Content.Id, ignoreCache: true);
if (build.state)
{
if (build.model != null)
@@ -333,30 +327,6 @@ namespace System.Application.Services
}
}
}
//if (basicsItem != null)
//{
// if (basicsItem.Version != basicsInfo.Content.Version)
// {
// var index = ProxyScripts.Items.IndexOf(basicsItem);
// basicsItem.IsUpdate = true;
// basicsItem.UpdateLink = basicsInfo.Content.UpdateLink;
// basicsItem.NewVersion = basicsInfo.Content.Version;
// ProxyScripts.ReplaceAt(index, basicsItem);
// }
//}
//else
//{
// var jspath = await DI.Get<IScriptManagerService>().DownloadScript(basicsInfo.Content.UpdateLink);
// if (jspath.state)
// {
// var build = await DI.Get<IScriptManagerService>().AddScriptAsync(jspath.path, build: false, order: 1, deleteFile: true, pid: basicsInfo.Content.Id);
// if (build.state)
// {
// if (build.model != null)
// ProxyScripts.Insert(0, build.model);
// }
// }
//}
}
}
@@ -376,8 +346,8 @@ namespace System.Application.Services
public void Dispose()
{
IHostsFileService.OnExitRestoreHosts();
httpProxyService.StopProxy();
IHostsFileService.OnExitRestoreHosts();
httpProxyService.Dispose();
}
@@ -419,7 +389,15 @@ namespace System.Application.Services
public async Task AddNewScript(FileInfo fileInfo, ScriptDTO? info, ScriptDTO? oldInfo = null)
{
IsLoading = true;
var item = await DI.Get<IScriptManagerService>().AddScriptAsync(fileInfo, info, oldInfo);
bool isbuild = true;
int order = 10;
if (oldInfo != null)
{
isbuild = oldInfo.IsBuild;
order = oldInfo.Order;
}
var item = await DI.Get<IScriptManagerService>().AddScriptAsync(fileInfo, info, oldInfo, build: isbuild, order: order);
if (item.state)
{
if (item.model != null)
@@ -435,12 +413,10 @@ namespace System.Application.Services
{
var scriptList = await DI.Get<IScriptManagerService>().GetAllScript();
ProxyScripts.Clear();
var basicsId = Guid.Parse("00000000-0000-0000-0000-000000000001");
if (ProxySettings.ScriptsStatus.Value.Any_Nullable() && scriptList.Any())
{
foreach (var item in scriptList)
{
item.IsBasics = item.Id == basicsId;
if (ProxySettings.ScriptsStatus.Value.Contains(item.LocalId))
{
item.Enable = true;
@@ -457,7 +433,7 @@ namespace System.Application.Services
var jspath = await DI.Get<IScriptManagerService>().DownloadScript(model.UpdateLink);
if (jspath.state)
{
var build = await DI.Get<IScriptManagerService>().AddScriptAsync(jspath.path, model, build: model.IsBuild, order: 10, deleteFile: true, pid: model.Id);
var build = await DI.Get<IScriptManagerService>().AddScriptAsync(jspath.path, model, build: model.IsBuild, order: model.Order, deleteFile: true, pid: model.Id);
if (build.state)
{
if (build.model != null)
@@ -475,6 +451,7 @@ namespace System.Application.Services
model.IsUpdate = false;
model.IsExist = true;
model.UpdateLink = build.model.UpdateLink;
model.FilePath = build.model.FilePath;
model.Version = build.model.Version;
model.Name = build.model.Name;
RefreshScript();
@@ -146,13 +146,15 @@ namespace System.Application.Services
#region 初始化需要steam启动才能使用的功能
InitializeGameList();
while (true)
//尝试十次无法获取到就不再尝试
for (var i = 0; i < 10; i++)
{
if (SteamApps.Items.Any())
{
LoadGames(ApiService.OwnsApps(SteamApps.Items));
break;
}
await Task.Delay(2000);
}
//var mainViewModel = (IWindowService.Instance.MainWindow as WindowViewModel);
@@ -168,7 +170,7 @@ namespace System.Application.Services
{
IsConnectToSteam = false;
}
Thread.Sleep(2000);
await Task.Delay(2000);
}
}
catch (Exception ex)
@@ -211,20 +213,20 @@ namespace System.Application.Services
return;
}
#endif
if (SteamApps.Items.Any())
{
Parallel.ForEach(SteamApps.Items, new ParallelOptions
{
MaxDegreeOfParallelism = (Environment.ProcessorCount / 2) + 1
}, async app =>
{
await ISteamService.Instance.LoadAppImageAsync(app);
//app.LibraryLogoStream = await IHttpService.Instance.GetImageAsync(app.LibraryLogoUrl, ImageChannelType.SteamGames);
//app.LibraryHeaderStream = await IHttpService.Instance.GetImageAsync(app.LibraryHeaderUrl, ImageChannelType.SteamGames);
//app.LibraryNameStream = await IHttpService.Instance.GetImageAsync(app.LibraryNameUrl, ImageChannelType.SteamGames);
//app.HeaderLogoStream = await IHttpService.Instance.GetImageAsync(app.HeaderLogoUrl, ImageChannelType.SteamGames);
});
}
//if (SteamApps.Items.Any())
//{
// Parallel.ForEach(SteamApps.Items, new ParallelOptions
// {
// MaxDegreeOfParallelism = (Environment.ProcessorCount / 2) + 1
// }, async app =>
// {
// await ISteamService.Instance.LoadAppImageAsync(app);
// //app.LibraryLogoStream = await IHttpService.Instance.GetImageAsync(app.LibraryLogoUrl, ImageChannelType.SteamGames);
// //app.LibraryHeaderStream = await IHttpService.Instance.GetImageAsync(app.LibraryHeaderUrl, ImageChannelType.SteamGames);
// //app.LibraryNameStream = await IHttpService.Instance.GetImageAsync(app.LibraryNameUrl, ImageChannelType.SteamGames);
// //app.HeaderLogoStream = await IHttpService.Instance.GetImageAsync(app.HeaderLogoUrl, ImageChannelType.SteamGames);
// });
//}
}
private bool _IsRefreshing;
@@ -17,12 +17,16 @@ namespace System.Application.Services
public async void ShowWindow(CustomWindow windowName)
{
switch (windowName)
if (windowName == CustomWindow.LoginOrRegister)
{
case CustomWindow.LoginOrRegister:
var cUser = await userManager.GetCurrentUserAsync();
if (cUser.HasValue()) return;
break;
var cUser = await userManager.GetCurrentUserAsync();
if (cUser.HasValue()) return;
}
else if (windowName == CustomWindow.ChangeBindPhoneNumber)
{
var cUser = await userManager.GetCurrentUserAsync();
if (!cUser.HasValue()) return;
if (string.IsNullOrWhiteSpace(cUser!.PhoneNumber)) return;
}
var vmType = Type.GetType($"System.Application.UI.ViewModels.{windowName}WindowViewModel");
if (vmType != null && typeof(WindowViewModel).IsAssignableFrom(vmType))
@@ -54,12 +58,20 @@ namespace System.Application.Services
set => this.RaiseAndSetIfChanged(ref _User, value);
}
static string GetAvaterPath(UserInfoDTO? user)
SteamUser? _SteamUser;
public SteamUser? CurrentSteamUser
{
string? value = null;
get => _SteamUser;
set => this.RaiseAndSetIfChanged(ref _SteamUser, value);
}
object GetAvaterPath(UserInfoDTO? user)
{
object? value = null;
if (user is UserInfoDTO userInfo && userInfo.SteamAccountId.HasValue)
{
// Steam Avatar
value = CurrentSteamUser?.AvatarStream;
}
if (user is IUserDTO user2 && user2.Avatar.HasValue)
@@ -71,17 +83,18 @@ namespace System.Application.Services
}
const string DefaultAvaterPath = "avares://System.Application.SteamTools.Client.Desktop.Avalonia/Application/UI/Assets/AppResources/avater_default.png";
string _AvaterPath = DefaultAvaterPath;
public string AvaterPath
//string _AvaterPath = DefaultAvaterPath;
public object AvaterPath
{
get => GetAvaterPath(User);
set => this.RaiseAndSetIfChanged(ref _AvaterPath, value);
//set => this.RaiseAndSetIfChanged(ref _AvaterPath, value);
}
public UserService()
{
this.WhenAnyValue(x => x.User)
.Subscribe(x => AvaterPath = GetAvaterPath(x));
.Subscribe(_ => this.RaisePropertyChanged(nameof(AvaterPath)));
userManager.OnSignOut += () =>
{
@@ -100,10 +113,26 @@ namespace System.Application.Services
await RefreshUserAsync();
}
bool _HasPhoneNumber;
public bool HasPhoneNumber
{
get => _HasPhoneNumber;
set => this.RaiseAndSetIfChanged(ref _HasPhoneNumber, value);
}
public async Task RefreshUserAsync()
{
User = await userManager.GetCurrentUserInfoAsync();
AvaterPath = GetAvaterPath(User);
if (User != null && User.SteamAccountId.HasValue)
{
CurrentSteamUser = await ISteamworksWebApiService.Instance.GetUserInfo(User.SteamAccountId.Value);
CurrentSteamUser.AvatarStream = IHttpService.Instance.GetImageAsync(CurrentSteamUser.AvatarFull, ImageChannelType.SteamAvatars);
}
this.RaisePropertyChanged(nameof(AvaterPath));
var userInfo = await userManager.GetCurrentUserAsync();
HasPhoneNumber = !string.IsNullOrWhiteSpace(userInfo?.PhoneNumber);
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ namespace System.Application.UI
var mainModule = Process.GetCurrentProcess().MainModule;
if (mainModule == null)
throw new ArgumentNullException(nameof(mainModule));
ProgramPath = mainModule.FileName;
ProgramPath = mainModule.FileName!;
if (ProgramPath == null)
throw new ArgumentNullException(nameof(ProgramPath));
var programName = Path.GetFileName(ProgramPath);
+61 -7
View File
@@ -558,7 +558,7 @@ namespace System.Application.UI.Resx {
}
/// <summary>
/// 查找类似 Hosts代理模式 的本地化字符串。
/// 查找类似 Hosts代理模式(推荐) 的本地化字符串。
/// </summary>
public static string CommunityFix_ProxyMode_Hosts {
get {
@@ -566,6 +566,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 修改Hosts文件来监听本机请求实现代理,此方式速度更快且只会影响加速的网站,效果最好,但需要本机443端口未被使用。 的本地化字符串。
/// </summary>
public static string CommunityFix_ProxyMode_HostsTip {
get {
return ResourceManager.GetString("CommunityFix_ProxyMode_HostsTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 Windows系统代理模式 的本地化字符串。
/// </summary>
@@ -575,6 +584,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 设置Windows系统代理来监听请求,不需要占用443端口,会全局代理本机所有流量,如果你使用Hosts方式没有问题,那就不需要使用此模式。 的本地化字符串。
/// </summary>
public static string CommunityFix_ProxyMode_WinSystemTip {
get {
return ResourceManager.GetString("CommunityFix_ProxyMode_WinSystemTip", resourceCulture);
}
}
/// <summary>
/// 查找类似 加速模式: 的本地化字符串。
/// </summary>
@@ -1854,6 +1872,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 该文本文件已丢失,是否删除脚本记录。 的本地化字符串。
/// </summary>
public static string Script_NoFileDeleteItem {
get {
return ResourceManager.GetString("Script_NoFileDeleteItem", resourceCulture);
}
}
/// <summary>
/// 查找类似 刷新缓存 的本地化字符串。
/// </summary>
@@ -2097,6 +2124,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 背景透明度 的本地化字符串。
/// </summary>
public static string Settings_UI_AcrylicTransparency {
get {
return ResourceManager.GetString("Settings_UI_AcrylicTransparency", resourceCulture);
}
}
/// <summary>
/// 查找类似 深色 的本地化字符串。
/// </summary>
@@ -2458,6 +2494,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 快速登录 的本地化字符串。
/// </summary>
public static string User_FastLogin {
get {
return ResourceManager.GetString("User_FastLogin", resourceCulture);
}
}
/// <summary>
/// 查找类似 获取验证码 的本地化字符串。
/// </summary>
@@ -2557,6 +2602,15 @@ namespace System.Application.UI.Resx {
}
}
/// <summary>
/// 查找类似 手机号登录 的本地化字符串。
/// </summary>
public static string User_PhoneLogin {
get {
return ResourceManager.GetString("User_PhoneLogin", resourceCulture);
}
}
/// <summary>
/// 查找类似 隐私政策 的本地化字符串。
/// </summary>
@@ -2639,7 +2693,7 @@ namespace System.Application.UI.Resx {
}
/// <summary>
/// 查找类似 按下此按钮将重启Steam并以该账号登录 的本地化字符串。
/// 查找类似 按下此按钮将重启 Steam 并以该账号登录 的本地化字符串。
/// </summary>
public static string UserChange_BtnTootlip {
get {
@@ -2658,7 +2712,7 @@ namespace System.Application.UI.Resx {
/// <summary>
/// 查找类似 确定要删除这条本地记录帐户数据吗?
///这将会删除此账户在本地的Steam缓存数据。 的本地化字符串。
///这将会删除此账户在本地的 Steam 缓存数据。 的本地化字符串。
/// </summary>
public static string UserChange_DeleteUserTip {
get {
@@ -2676,7 +2730,7 @@ namespace System.Application.UI.Resx {
}
/// <summary>
/// 查找类似 登录新Steam账号 的本地化字符串。
/// 查找类似 登录新 Steam 账号 的本地化字符串。
/// </summary>
public static string UserChange_LoginNewAccount {
get {
@@ -2685,8 +2739,8 @@ namespace System.Application.UI.Resx {
}
/// <summary>
/// 查找类似 确定要登录Steam新账户吗?
///此操作会结束正在运行的Steamt跳转到新账号登录窗口。 的本地化字符串。
/// 查找类似 确定要登录 Steam 新账户吗?
///此操作会结束正在运行的 Steam 跳转到新账号登录窗口。 的本地化字符串。
/// </summary>
public static string UserChange_LoginNewAccountTip {
get {
@@ -2695,7 +2749,7 @@ namespace System.Application.UI.Resx {
}
/// <summary>
/// 查找类似 没有在您的电脑上读取到任何Steam帐户数据。 的本地化字符串。
/// 查找类似 没有在您的电脑上读取到任何 Steam 帐户数据。 的本地化字符串。
/// </summary>
public static string UserChange_NoUserTip {
get {
@@ -289,11 +289,17 @@
<value>加速模式:</value>
</data>
<data name="CommunityFix_ProxyMode_Hosts" xml:space="preserve">
<value>Hosts代理模式</value>
<value>Hosts代理模式(推荐)</value>
</data>
<data name="CommunityFix_ProxyMode_HostsTip" xml:space="preserve">
<value>修改Hosts文件来监听本机请求实现代理,此方式速度更快且只会影响加速的网站,效果最好,但需要本机443端口未被使用。</value>
</data>
<data name="CommunityFix_ProxyMode_WinSystem" xml:space="preserve">
<value>Windows系统代理模式</value>
</data>
<data name="CommunityFix_ProxyMode_WinSystemTip" xml:space="preserve">
<value>设置Windows系统代理来监听请求,不需要占用443端口,会全局代理本机所有流量,如果你使用Hosts方式没有问题,那就不需要使用此模式。</value>
</data>
<data name="CommunityFix_ScriptManage" xml:space="preserve">
<value>管理脚本</value>
</data>
@@ -738,6 +744,9 @@
<data name="Script_Installed" xml:space="preserve">
<value>已安装</value>
</data>
<data name="Script_NoFileDeleteItem" xml:space="preserve">
<value>该文本文件已丢失,是否删除脚本记录。</value>
</data>
<data name="Script_Refresh" xml:space="preserve">
<value>刷新缓存</value>
</data>
@@ -802,6 +811,9 @@
<data name="Settings_UI" xml:space="preserve">
<value>界面设置</value>
</data>
<data name="Settings_UI_AcrylicTransparency" xml:space="preserve">
<value>背景透明度</value>
</data>
<data name="Settings_UI_Dark" xml:space="preserve">
<value>深色</value>
</data>
@@ -918,27 +930,27 @@
<value>一键登录Steam</value>
</data>
<data name="UserChange_BtnTootlip" xml:space="preserve">
<value>按下此按钮将重启Steam并以该账号登录</value>
<value>按下此按钮将重启 Steam 并以该账号登录</value>
</data>
<data name="UserChange_DeleteUser" xml:space="preserve">
<value>删除此账号数据</value>
</data>
<data name="UserChange_DeleteUserTip" xml:space="preserve">
<value>确定要删除这条本地记录帐户数据吗?
这将会删除此账户在本地的Steam缓存数据。</value>
这将会删除此账户在本地的 Steam 缓存数据。</value>
</data>
<data name="UserChange_EditRemark" xml:space="preserve">
<value>点此修改备注</value>
</data>
<data name="UserChange_LoginNewAccount" xml:space="preserve">
<value>登录新Steam账号</value>
<value>登录新 Steam 账号</value>
</data>
<data name="UserChange_LoginNewAccountTip" xml:space="preserve">
<value>确定要登录Steam新账户吗?
此操作会结束正在运行的Steamt跳转到新账号登录窗口。</value>
<value>确定要登录 Steam 新账户吗?
此操作会结束正在运行的 Steam 跳转到新账号登录窗口。</value>
</data>
<data name="UserChange_NoUserTip" xml:space="preserve">
<value>没有在您的电脑上读取到任何Steam帐户数据。</value>
<value>没有在您的电脑上读取到任何 Steam 帐户数据。</value>
</data>
<data name="UserChange_OfflineBtn" xml:space="preserve">
<value>离线模式启动</value>
@@ -974,6 +986,9 @@
<data name="User_EditProfile" xml:space="preserve">
<value>编辑资料</value>
</data>
<data name="User_FastLogin" xml:space="preserve">
<value>快速登录</value>
</data>
<data name="User_GetSMSCode" xml:space="preserve">
<value>获取验证码</value>
</data>
@@ -1008,6 +1023,9 @@
<data name="User_Phone" xml:space="preserve">
<value>手机号码</value>
</data>
<data name="User_PhoneLogin" xml:space="preserve">
<value>手机号登录</value>
</data>
<data name="User_Privacy" xml:space="preserve">
<value>隐私政策</value>
</data>
@@ -1038,4 +1056,4 @@
<data name="Welcome" xml:space="preserve">
<value>起始页</value>
</data>
</root>
</root>
+1
View File
@@ -51,6 +51,7 @@ namespace System.Application.UI.Resx
static IReadOnlyCollection<KeyValuePair<string, string>> GetFonts()
{
// https://docs.microsoft.com/zh-cn/typography/font-list
var culture = Culture;
InstalledFontCollection ifc = new();
var list = ifc.Families.Where(x => x.IsStyleAvailable(FontStyle.Regular)).Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList();
@@ -32,7 +32,7 @@ namespace System.Application.UI.ViewModels
public string VersionDisplay => ThisAssembly.VersionDisplay;
public string LabelVersionDisplay => (ThisAssembly.IsBetaRelease ? "Beta " : "Current") + "Version: ";
public string LabelVersionDisplay => ThisAssembly.IsBetaRelease ? "Beta Version: " : "Current Version: ";
public string Copyright
{
@@ -297,7 +297,7 @@ namespace System.Application.UI.ViewModels
if (s.Result == MessageBoxResultCompat.OK)
{
Toast.Show(AppResources.GameList_RuningWait);
app.Process = Process.Start(AppHelper.ProgramName, "-clt app -id " + app.AppId.ToString(CultureInfo.InvariantCulture));
app.Process = Process.Start(AppHelper.ProgramPath, "-clt app -id " + app.AppId.ToString(CultureInfo.InvariantCulture));
SteamConnectService.Current.RuningSteamApps.Add(app);
}
});
@@ -139,26 +139,54 @@ namespace System.Application.UI.ViewModels
}
});
}
public void DeleteNoFileScriptItemButton(ScriptDTO script)
{
var result = MessageBoxCompat.ShowAsync(@AppResources.Script_NoFileDeleteItem, ThisAssembly.AssemblyTrademark, MessageBoxButtonCompat.OKCancel).ContinueWith(async (s) =>
{
if (s.Result == MessageBoxResultCompat.OK)
{
var item = await DI.Get<IScriptManagerService>().DeleteScriptAsync(script);
if (item.state)
{
if (ProxyService.Current.ProxyScripts != null)
ProxyService.Current.ProxyScripts.Remove(script);
}
Toast.Show(item.msg);
}
});
}
public void EditScriptItemButton(ScriptDTO script)
{
var url = Path.Combine(IOPath.AppDataDirectory, script.FilePath);
DI.Get<IDesktopPlatformService>().OpenFileByTextReader(url);
var result = MessageBoxCompat.ShowAsync(@AppResources.Script_EditTxt, ThisAssembly.AssemblyTrademark, MessageBoxButtonCompat.OKCancel).ContinueWith(async (s) =>
var fileInfo = new FileInfo(url);
if (fileInfo.Exists)
{
if (s.Result == MessageBoxResultCompat.OK)
DI.Get<IDesktopPlatformService>().OpenFileByTextReader(url);
var result = MessageBoxCompat.ShowAsync(@AppResources.Script_EditTxt, ThisAssembly.AssemblyTrademark, MessageBoxButtonCompat.OKCancel).ContinueWith(async (s) =>
{
var item = await DI.Get<IScriptManagerService>().AddScriptAsync(url, script,build: script.IsBuild,order:script.Order);
if (item.state)
if (s.Result == MessageBoxResultCompat.OK)
{
if (ProxyService.Current.ProxyScripts.Items.Any() && item.model != null)
var item = await DI.Get<IScriptManagerService>().AddScriptAsync(url, script, build: script.IsBuild, order: script.Order, ignoreCache: true);
if (item.state)
{
ProxyService.Current.ProxyScripts.Replace(script, item.model) ;
if (ProxyService.Current.ProxyScripts.Items.Any() && item.model != null)
{
ProxyService.Current.ProxyScripts.Replace(script, item.model);
Toast.Show(AppResources.Success_.Format(AppResources.Script_Edit));
}
}
}
}
});
});
}
else
{
DeleteNoFileScriptItemButton(script);
}
}
public void OpenHomeScriptItemButton(ScriptDTO script)
@@ -170,11 +198,12 @@ namespace System.Application.UI.ViewModels
{
if (script?.FilePath != null)
{
var item = await DI.Get<IScriptManagerService>().AddScriptAsync(Path.Combine(IOPath.AppDataDirectory, script.FilePath), build: script.IsBuild);
var item = await DI.Get<IScriptManagerService>().AddScriptAsync(Path.Combine(IOPath.AppDataDirectory, script.FilePath), script, order: script.Order, build: script.IsBuild, ignoreCache: true);
if (item.state)
{
if (item.model != null)
{
script = item.model;
ProxyService.Current.ProxyScripts.Replace(script, item.model);
Toast.Show(AppResources.RefreshOK);
}
else
@@ -182,6 +211,11 @@ namespace System.Application.UI.ViewModels
script.Enable = false;
Toast.Show(item.msg);
}
}
else
{
DeleteNoFileScriptItemButton(script);
}
}
}
@@ -13,7 +13,7 @@ namespace System.Application.UI.ViewModels
public class ChangeBindPhoneNumberWindowViewModel : WindowViewModel
{
readonly IReadOnlyDictionary<Step, SendSmsUIHelper.IViewModel> sendSmsUIViewModels;
public ChangeBindPhoneNumberWindowViewModel()
public ChangeBindPhoneNumberWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.User_ChangePhoneNum;
sendSmsUIViewModels = new Dictionary<Step, SendSmsUIHelper.IViewModel>
@@ -86,7 +86,7 @@ namespace System.Application.UI.ViewModels
};
}
public AchievementWindowViewModel(int appid)
public AchievementWindowViewModel(int appid) : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.AchievementManage;
@@ -160,12 +160,12 @@ namespace System.Application.UI.ViewModels
ToastService.Current.Notify(AppResources.Achievement_LoadSucces.Format(_AchievementsSourceList.Count, _StatisticsSourceList.Count));
});
Task.Run(async () =>
Task.Run(() =>
{
while (true)
{
ISteamworksLocalApiService.Instance.RunCallbacks(false);
await Task.Delay(2000);
Threading.Thread.Sleep(2000);
}
}).Forget();
@@ -9,7 +9,7 @@ namespace System.Application.UI.ViewModels
{
private readonly SteamApp? _App;
public EditAppInfoWindowViewModel()
public EditAppInfoWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.GameList_EditAppInfo;
}
@@ -1,4 +1,4 @@
using ReactiveUI;
using ReactiveUI;
using System.Application.Models;
using System.Application.Services;
using System.Application.UI.Resx;
@@ -14,7 +14,7 @@ namespace System.Application.UI.ViewModels
{
readonly IHttpService httpService = DI.Get<IHttpService>();
public AddAuthWindowViewModel()
public AddAuthWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.LocalAuth_AddAuth;
}
@@ -21,7 +21,7 @@ namespace System.Application.UI.ViewModels
private readonly MyAuthenticator MyAuthenticator;
private readonly GAPAuthenticatorValueDTO.SteamAuthenticator _Authenticator;
public AuthTradeWindowViewModel()
public AuthTradeWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.LocalAuth_SteamAuthTrade;
_ConfirmationsSourceList = new SourceList<WinAuthSteamClient.Confirmation>();
@@ -286,7 +286,6 @@ namespace System.Application.UI.ViewModels
ToastService.Current.Notify(steam.Error);
return;
}
return;
}
ToastService.Current.Notify(AppResources.User_LoiginSuccess);
@@ -1,4 +1,4 @@
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Linq;
using System.Application.Models;
using System.Application.UI.Resx;
using System.Properties;
@@ -9,7 +9,7 @@ namespace System.Application.UI.ViewModels
{
private readonly GAPAuthenticatorValueDTO.SteamAuthenticator? _Authenticator;
public ShowAuthWindowViewModel()
public ShowAuthWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.LocalAuth_AuthData;
}
@@ -3,19 +3,23 @@ using System.Application.Models;
using System.Application.Services;
using System.Application.Services.CloudService;
using System.Application.UI.Resx;
using System.IO;
using System.Properties;
using System.Reactive;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using static System.Application.Services.CloudService.Constants;
namespace System.Application.UI.ViewModels
{
public class LoginOrRegisterWindowViewModel : WindowViewModel, SendSmsUIHelper.IViewModel
{
public LoginOrRegisterWindowViewModel()
public LoginOrRegisterWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.LoginAndRegister;
SteamFastLogin = ReactiveCommand.CreateFromTask(async () => await FastLoginOrRegisterAsync(Close));
}
private string? _PhoneNumber;
@@ -94,7 +98,7 @@ namespace System.Application.UI.ViewModels
close?.Invoke();
}
internal static async Task FastLoginOrRegisterAsync()
internal static async Task FastLoginOrRegisterAsync(Action? close = null)
{
var apiBaseUrl = ICloudServiceClient.Instance.ApiBaseUrl;
var urlExternalLoginCallback = apiBaseUrl + "/ExternalLoginCallback";
@@ -111,12 +115,15 @@ namespace System.Application.UI.ViewModels
Title = AppResources.User_SteamFastLogin,
TimeoutErrorMessage = AppResources.User_SteamFastLoginTimeoutErrorMessage,
IsSecurity = true,
//UseLoginUsingSteamClient = true,
UseLoginUsingSteamClientV2 = false,
Close = close,
};
async void _OnStreamResponseFilterResourceLoadComplete(string url, byte[] data)
async void _OnStreamResponseFilterResourceLoadComplete(string url, Stream data)
{
if (url.StartsWith(urlExternalLoginCallback, StringComparison.OrdinalIgnoreCase))
{
var response = ApiResponse.Deserialize<LoginOrRegisterResponse>(data);
var response = await ApiResponse.DeserializeAsync<LoginOrRegisterResponse>(data, default);
if (response.IsSuccess && response.Content == null)
{
response.Code = ApiResponseCode.NoResponseContent;
@@ -125,16 +132,23 @@ namespace System.Application.UI.ViewModels
if (response.IsSuccess)
{
await conn_helper.OnLoginedAsync(null, response.Content!);
await SuccessAsync(response.Content!, vm?.Close);
await MainThreadDesktop.InvokeOnMainThreadAsync(async () =>
{
await SuccessAsync(response.Content!, vm?.Close);
});
}
else
{
conn_helper.ShowResponseErrorMessage(response);
vm?.Close?.Invoke();
MainThreadDesktop.BeginInvokeOnMainThread(() =>
{
conn_helper.ShowResponseErrorMessage(response);
close?.Invoke();
vm?.Close?.Invoke();
});
}
}
}
await IShowWindowService.Instance.Show(CustomWindow.WebView3, vm, resizeMode: ResizeModeCompat.NoResize);
await IShowWindowService.Instance.Show(CustomWindow.WebView3, vm, resizeMode: ResizeModeCompat.CanResize);
}
public Action? Close { private get; set; }
@@ -171,9 +185,7 @@ namespace System.Application.UI.ViewModels
}, resizeMode: ResizeModeCompat.NoResize);
}
public void SteamFastLogin()
{
}
public ICommand SteamFastLogin { get; }
protected override void Dispose(bool disposing)
{
@@ -1,4 +1,4 @@
using DynamicData;
using DynamicData;
using DynamicData.Binding;
using Newtonsoft.Json.Linq;
using ReactiveUI;
@@ -13,8 +13,8 @@ namespace System.Application.UI.ViewModels
{
public class ScriptStoreWindowViewModel : WindowViewModel
{
public ScriptStoreWindowViewModel()
{
public ScriptStoreWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.ScriptStore;
_ScriptsSourceList = new SourceList<ScriptDTO>();
@@ -15,7 +15,7 @@ namespace System.Application.UI.ViewModels
byte[]? userInfoValue;
UserInfoDTO? userInfoSource;
readonly IUserManager userManager;
public UserProfileWindowViewModel()
public UserProfileWindowViewModel() : base()
{
Title = ThisAssembly.AssemblyTrademark + " | " + AppResources.UserProfile;
userManager = DI.Get<IUserManager>();
@@ -1,4 +1,5 @@
using ReactiveUI;
using System.IO;
using System.Net.Http;
namespace System.Application.UI.ViewModels
@@ -21,7 +22,7 @@ namespace System.Application.UI.ViewModels
set => this.RaiseAndSetIfChanged(ref _StreamResponseFilterUrls, value);
}
public Action<string, byte[]>? OnStreamResponseFilterResourceLoadComplete { get; set; }
public Action<string, Stream>? OnStreamResponseFilterResourceLoadComplete { get; set; }
public bool FixedSinglePage { get; set; }
@@ -45,5 +46,13 @@ namespace System.Application.UI.ViewModels
public bool IsSecurity { get; set; }
public Action? Close { get; set; }
/// <summary>
/// 使用 Steam 客户端登录
/// </summary>
[Obsolete]
public bool UseLoginUsingSteamClient { get; set; }
public bool UseLoginUsingSteamClientV2 { get; set; }
}
}
@@ -54,7 +54,7 @@
<AndroidEnableProfiledAot>true</AndroidEnableProfiledAot>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
<MandroidI18n />
<AndroidSupportedAbis>x86_64;arm64-v8a</AndroidSupportedAbis>
<AndroidSupportedAbis>armeabi-v7a;arm64-v8a</AndroidSupportedAbis>
<AndroidKeyStore>false</AndroidKeyStore>
</PropertyGroup>
<ItemGroup>

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