Compare commits

...
Author SHA1 Message Date
Aigio Liu 82814649e3 misc 2022-10-13 14:36:22 +08:00
Aigio Liu 978411b677 restore sms 2022-09-22 19:10:30 +08:00
Aigio Liu 166f8732dc Misc 2022-09-22 11:17:58 +08:00
Aigio Liu 8c2a7068b9 fix Android reverseProxyService.ProxyIp & Misc 2022-08-31 11:16:04 +08:00
Aigio Liu b832f3c927 fix maui-android projects & update AndroidX packages 2022-08-27 20:00:21 +08:00
Aigio Liu c367cac992 fix maui csproj errors 2022-08-27 13:09:06 +08:00
dependabot[bot]andAigio L f78271c2f5 Bump AspNet.Security.OAuth.QQ from 6.0.6 to 6.0.9 (#1943)
Bumps [AspNet.Security.OAuth.QQ](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers) from 6.0.6 to 6.0.9.
- [Release notes](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/releases)
- [Commits](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/compare/6.0.6...6.0.9)

---
updated-dependencies:
- dependency-name: AspNet.Security.OAuth.QQ
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aigio L <24450093+AigioL@users.noreply.github.com>
2022-08-26 15:00:42 +08:00
dependabot[bot] f2bdc19d74 Bump AspNet.Security.OAuth.Apple from 6.0.6 to 6.0.9 (#1942)
Bumps [AspNet.Security.OAuth.Apple](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers) from 6.0.6 to 6.0.9.
- [Release notes](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/releases)
- [Commits](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/compare/6.0.6...6.0.9)

---
updated-dependencies:
- dependency-name: AspNet.Security.OAuth.Apple
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:59:54 +08:00
dependabot[bot] 0fde0eccba Bump Moq from 4.18.1 to 4.18.2 (#1817)
Bumps [Moq](https://github.com/moq/moq4) from 4.18.1 to 4.18.2.
- [Release notes](https://github.com/moq/moq4/releases)
- [Changelog](https://github.com/moq/moq4/blob/main/CHANGELOG.md)
- [Commits](https://github.com/moq/moq4/compare/v4.18.1...v4.18.2)

---
updated-dependencies:
- dependency-name: Moq
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:59:30 +08:00
dependabot[bot]andAigio L 5c55fa97e7 Bump NLog.Web.AspNetCore from 5.1.0 to 5.1.1 (#1927)
Bumps [NLog.Web.AspNetCore](https://github.com/NLog/NLog.Web) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/NLog/NLog.Web/releases)
- [Changelog](https://github.com/NLog/NLog.Web/blob/master/CHANGELOG.MD)
- [Commits](https://github.com/NLog/NLog.Web/compare/v5.1.0...v5.1.1)

---
updated-dependencies:
- dependency-name: NLog.Web.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aigio L <24450093+AigioL@users.noreply.github.com>
2022-08-26 14:59:01 +08:00
dependabot[bot] 323c7eb6c3 Bump DynamicData from 7.9.7 to 7.9.14 (#1925)
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.9.7 to 7.9.14.
- [Release notes](https://github.com/reactiveui/DynamicData/releases)
- [Changelog](https://github.com/reactivemarbles/DynamicData/blob/main/ReleaseNotes.md)
- [Commits](https://github.com/reactiveui/DynamicData/compare/7.9.7...7.9.14)

---
updated-dependencies:
- dependency-name: DynamicData
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:58:22 +08:00
dependabot[bot] 42dea46260 Bump Z.EntityFramework.Plus.EFCore from 6.14.3 to 6.14.4 (#1915)
Bumps [Z.EntityFramework.Plus.EFCore](https://github.com/zzzprojects/EntityFramework-Plus) from 6.14.3 to 6.14.4.
- [Release notes](https://github.com/zzzprojects/EntityFramework-Plus/releases)
- [Commits](https://github.com/zzzprojects/EntityFramework-Plus/compare/6.14.3...6.14.4)

---
updated-dependencies:
- dependency-name: Z.EntityFramework.Plus.EFCore
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:58:08 +08:00
dependabot[bot]andAigio L 1bf65820c0 Bump NLog.Extensions.Logging from 5.0.1 to 5.0.2 (#1894)
Bumps [NLog.Extensions.Logging](https://github.com/NLog/NLog.Extensions.Logging) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/NLog/NLog.Extensions.Logging/releases)
- [Changelog](https://github.com/NLog/NLog.Extensions.Logging/blob/master/CHANGELOG.MD)
- [Commits](https://github.com/NLog/NLog.Extensions.Logging/compare/v5.0.1...v5.0.2)

---
updated-dependencies:
- dependency-name: NLog.Extensions.Logging
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Aigio L <24450093+AigioL@users.noreply.github.com>
2022-08-26 14:57:28 +08:00
dependabot[bot] ba1c5b6c8b Bump Microsoft.NET.Test.Sdk from 17.2.0 to 17.3.0 (#1870)
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.2.0 to 17.3.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Commits](https://github.com/microsoft/vstest/compare/v17.2.0...v17.3.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:56:03 +08:00
dependabot[bot] deb6c4eaa1 Bump Microsoft.Extensions.Logging.AzureAppServices from 6.0.7 to 6.0.8 (#1857)
Bumps [Microsoft.Extensions.Logging.AzureAppServices](https://github.com/dotnet/aspnetcore) from 6.0.7 to 6.0.8.
- [Release notes](https://github.com/dotnet/aspnetcore/releases)
- [Changelog](https://github.com/dotnet/aspnetcore/blob/main/docs/ReleasePlanning.md)
- [Commits](https://github.com/dotnet/aspnetcore/compare/v6.0.7...v6.0.8)

---
updated-dependencies:
- dependency-name: Microsoft.Extensions.Logging.AzureAppServices
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:55:27 +08:00
dependabot[bot] af337a8fbd Bump Octokit from 2.0.0 to 2.0.1 (#1892)
Bumps [Octokit](https://github.com/octokit/octokit.net) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/octokit/octokit.net/releases)
- [Changelog](https://github.com/octokit/octokit.net/blob/main/docs/releases.md)
- [Commits](https://github.com/octokit/octokit.net/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: Octokit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:54:46 +08:00
dependabot[bot] 80d14c6c24 Bump Microsoft.WindowsAppSDK from 1.1.3 to 1.1.4 (#1877)
Bumps [Microsoft.WindowsAppSDK](https://github.com/microsoft/windowsappsdk) from 1.1.3 to 1.1.4.
- [Release notes](https://github.com/microsoft/windowsappsdk/releases)
- [Commits](https://github.com/microsoft/windowsappsdk/commits)

---
updated-dependencies:
- dependency-name: Microsoft.WindowsAppSDK
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:54:24 +08:00
dependabot[bot] 07d82be4c7 Bump NLog from 5.0.1 to 5.0.2 (#1891)
Bumps [NLog](https://github.com/NLog/NLog) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/NLog/NLog/releases)
- [Changelog](https://github.com/NLog/NLog/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/NLog/NLog/compare/v5.0.1...v5.0.2)

---
updated-dependencies:
- dependency-name: NLog
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:53:59 +08:00
dependabot[bot] 1e261f1125 Bump HtmlAgilityPack from 1.11.43 to 1.11.45 (#1940)
Bumps [HtmlAgilityPack](https://github.com/zzzprojects/html-agility-pack) from 1.11.43 to 1.11.45.
- [Release notes](https://github.com/zzzprojects/html-agility-pack/releases)
- [Commits](https://github.com/zzzprojects/html-agility-pack/compare/v1.11.43...v1.11.45)

---
updated-dependencies:
- dependency-name: HtmlAgilityPack
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-08-26 14:52:55 +08:00
Aigio Liu 8a1bde0773 Fix
System.ComponentModel.Win32Exception: An error occurred trying to start process 'C:\WINDOWS\explorer.exe' with working directory 'AppContext.BaseDirectory'. 拒绝访问。
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/180265099u/overview
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/3342720977u/overview
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/799855238u/overview
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/18523660u/overview
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/118999695u/overview

Try Fix
System.IO.IOException: The process cannot access the file 'C:\Users\***\AppData\Local\Packages\4651ED44255E.47979655102CE_k6txddmbb6c52\LocalState\Config.mpo' because it is being used by another process.
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/2552968077u/overview

Try Fix
System.Runtime.InteropServices.COMException: 无法在设置线程模式后对其加以更改。 (0x80010106 (RPC_E_CHANGED_MODE))
https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/1550045210u/overview
2022-08-24 14:28:20 +08:00
Aigio Liu 617b99c39d MSStore 2.8.4 2022-08-18 10:27:41 +08:00
RMBGAME 8b4680fcee ReverseProxyHttpClientHandler in Server fix 2022-08-17 23:14:50 +08:00
RMBGAME e27ae2b202 Update bug-report.md 2022-08-16 20:15:48 +08:00
Aigio Liu 5419530031 Bump v2.8.4 2022-08-16 17:49:12 +08:00
RMBGAME 415fd30cc5 Bump Avalonia to 0.10.18 2022-08-16 12:27:40 +08:00
Aigio Liu ef627692ef v2.8.3 rev.1
fix SettingsHost.Load
2022-08-15 12:32:18 +08:00
Aigio Liu 6f28ce0993 Get_Nullable remove throw 2022-08-15 12:17:07 +08:00
RMBGAME 2dbb13db87 #1888 #1897 2022-08-15 12:12:20 +08:00
Aigio Liu 40d3c0e669 Build Android versionCode="20220814" 2022-08-14 21:58:22 +08:00
RMBGAME 6be424dc5f ReverseProxyHttpClientHandler in Server 2022-08-14 16:57:49 +08:00
Aigio Liu 6babd615cd Use ReverseProxyHttpClientHandler in Server 2022-08-14 16:41:10 +08:00
Aigio Liu d1f266465b v2.8.3 rev.0 2022-08-14 16:01:31 +08:00
RMBGAME fccd8da9f6 添加asynclock尝试修复 asf启动时接收令牌输入卡死问题 2022-08-14 15:30:48 +08:00
Aigio Liu df2f84ff99 Remove ReverseProxyHttpClient userAgent 2022-08-14 15:06:28 +08:00
Aigio Liu d0bfbdbc77 Update ASF v5.2.8.4 2022-08-14 14:27:41 +08:00
RMBGAME 51e19bae95 Update Package 2022-08-14 04:54:54 +08:00
RMBGAME 5673bf2150 config bak 2022-08-14 04:49:57 +08:00
RMBGAME f5c66a353e PNA Support 2022-08-12 19:33:18 +08:00
RMBGAME 09dd6fe47e Misc 2022-08-11 18:43:28 +08:00
Aigio Liu 96471ccf27 #1875 explorer.exe full path 2022-08-11 14:26:22 +08:00
Aigio Liu 7b3f40da3b Update .NET Runtime 6.0.8/SDK 6.0.400 & VS 17.3 | Bump v2.8.3 2022-08-10 10:32:13 +08:00
Aigio Liu e369c6aa10 非简中默认隐藏加速与脚本仅在 Windows 上生效 2022-08-10 00:46:53 +08:00
Aigio Liu 5b4fcc2b8b revoke DBreeze 2022-08-10 00:36:57 +08:00
Aigio Liu 33c6f0d5f9 fix 2022-08-10 00:08:49 +08:00
RMBGAME 6abdb6dc11 Misc 2022-08-10 00:09:27 +08:00
RMBGAME a981d31ec4 修复可能导致内存泄漏的问题 2022-08-07 00:34:15 +08:00
Aigio Liu 8a0dd49e39 改进 查找脚本注入位置 2022-08-06 10:07:46 +08:00
Aigio Liu dc005a1a47 fix Release 2022-08-04 22:09:00 +08:00
Aigio Liu 5d69679073 fix Preferences 2022-08-04 19:20:08 +08:00
Aigio Liu 1030e15d8e 改进 InitTabItems,减少启动时间 2022-08-04 18:19:57 +08:00
Aigio Liu 48083a90d2 Use DBreeze Impl Preferences/SettingsHost
fix StringExtensions.Trim
2022-08-04 14:11:29 +08:00
Aigio Liu aab89668a9 fix nuget.config unix path 2022-08-03 18:50:17 +08:00
Aigio Liu a4a6f0e61d add nupkg 2022-08-03 18:19:19 +08:00
Aigio Liu a103ec141b fix Android Microsoft.Extensions.Primitives 6.X 2022-08-03 17:52:25 +08:00
ff m c23dc29e1c Mac证书安装 同步等待 2022-08-02 19:25:23 +08:00
Aigio Liu ddda4c0273 fix appcenter crashes 2022-08-02 19:17:56 +08:00
ff m cd1c1b91d7 CookieHttpClient.CookieContainer.Add Cookie
UserAgent.ParseAdd(context.Request.Headers.UserAgent)
2022-07-31 14:15:01 +08:00
Aigio Liu ce09385a52 Add CookieHttpClient(HttpLocalRequestMiddleware) 2022-07-31 13:09:20 +08:00
RMBGAME 8d6e83a42b Misc 2022-07-29 15:45:36 +08:00
RMBGAME b0a72ab23a 调整代理模式顺序 2022-07-29 15:44:38 +08:00
Aigio Liu b5f8910e2e fix SettingsHost.Load catch 2022-07-29 15:40:59 +08:00
Aigio Liu 881ff3fba9 Misc 2022-07-29 08:45:23 +08:00
Aigio Liu 8878d183a7 fix #1781 2022-07-29 07:57:20 +08:00
Aigio Liu 46f95574d1 fix Bridge & Release Windows Desktop Bridge v2.8.2 2022-07-28 13:37:48 +08:00
Aigio Liu c9c846ccd6 Release v2.8.2 2022-07-28 10:48:25 +08:00
Aigio Liu 72976110d7 Add ApiConnectionPH Log.Error 2022-07-28 10:07:30 +08:00
RMBGAME 82736e38d8 加速过程中如果出现DNS错误现在会弹出通知提示,便于排查问题 2022-07-28 09:10:03 +08:00
RMBGAME 1ec6199c18 #461 Windows上可以在设置中开关是否以管理员权限运行Steam 2022-07-27 23:17:15 +08:00
RMBGAME e5eaf173b2 Misc 2022-07-27 17:22:25 +08:00
RMBGAME 3227df2afb #1770 2022-07-27 17:19:51 +08:00
Aigio Liu 769398fb56 impl -clt shutdown 2022-07-27 16:52:33 +08:00
RMBGAME 7d8cad6f6a Misc 2022-07-27 16:24:24 +08:00
RMBGAME f82aafba45 Misc 2022-07-27 13:04:21 +08:00
Aigio Liu 1a2b0e5fbc fix CI 2022-07-27 12:53:37 +08:00
Aigio Liu 3afd331ced request.Headers.Add(SecurityKeyHex 2022-07-27 12:06:50 +08:00
Aigio Liu daa43cb0a2 fix GetPaddingByOaepHashAlgorithmName 2022-07-27 12:02:43 +08:00
Aigio Liu e1ff5b17bb fix
2022-07-26 12:53:42.1279||ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request. System.Security.Cryptography.CryptographicException: 'sha256' is not a known hash algorithm.
   at Interop.Crypto.HashAlgorithmToEvp(String hashAlgorithmId)
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(SafeEvpPKeyHandle key, ReadOnlySpan`1 data, Span`1 destination, RSAEncryptionPadding padding)
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(Byte[] data, RSAEncryptionPadding padding)
   at System.Application.Middleware.JwtInUrlMiddleware.<>c__DisplayClass8_0.<<GetSecurityResultAsync>g__GetSecurityResultCoreAsync|0>d.MoveNext()

2022-07-26 08:18:19.9302||ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request. MessagePack.MessagePackSerializationException: Failed to serialize System.Application.Models.ApiRsp`1[[System.Application.Models.AccelerateProjectGroupDTO[], System.Application.SteamTools.Services.CloudService.Models, Version=2.8.2.0, Culture=neutral, PublicKeyToken=null]] value.
 ---> System.OperationCanceledException: The operation was canceled.
   at System.Threading.CancellationToken.ThrowOperationCanceledException()
   at MessagePack.Formatters.ArrayFormatter`1.Serialize(MessagePackWriter& writer, T[] value, MessagePackSerializerOptions options)
   at MessagePack.Formatters.System_Application_Models_ApiRsp`1\[\[System_Application_Models_AccelerateProjectGroupDTO\[\]\, System_Application_SteamTools_Services_CloudService_Models\]\]Formatter2.Serialize(MessagePackWriter& writer, ApiRsp`1 value, MessagePackSerializerOptions options)
   at MessagePack.MessagePackSerializer.Serialize[T](MessagePackWriter& writer, T value, MessagePackSerializerOptions options)
   --- End of inner exception stack trace ---
   at MessagePack.MessagePackSerializer.Serialize[T](MessagePackWriter& writer, T value, MessagePackSerializerOptions options)
   at lambda_method358(Closure , IBufferWriter`1 , Object , MessagePackSerializerOptions , CancellationToken )
   at System.Application.Formatters.GeneralOutputFormatter.WriteAsync(OutputFormatterWriteContext context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeNextResultFilterAsync[TFilter,TFilterAsync]()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at System.Application.Middleware.JwtInUrlMiddleware.Invoke(HttpContext context, IAppVersionInfoRepository repository)
   at System.Application.Middleware.StandardizedExceptionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

2022-07-26 12:53:42.1257||ERROR|JwtInUrlMiddleware|isBind: False, UserAgent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36
CryptographicException: 'sha256' is not a known hash algorithm.
2022-07-26 12:53:42.1279||ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request. System.Security.Cryptography.CryptographicException: 'sha256' is not a known hash algorithm.
   at Interop.Crypto.HashAlgorithmToEvp(String hashAlgorithmId)
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(SafeEvpPKeyHandle key, ReadOnlySpan`1 data, Span`1 destination, RSAEncryptionPadding padding)
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(Byte[] data, RSAEncryptionPadding padding)
   at System.Application.Middleware.JwtInUrlMiddleware.<>c__DisplayClass8_0.<<GetSecurityResultAsync>g__GetSecurityResultCoreAsync|0>d.MoveNext()
--- End of stack trace from previous location ---
   at System.Application.Middleware.JwtInUrlMiddleware.GetSecurityResultAsync(HttpContext context, IAppVersionInfoRepository repository)
   at System.Application.Controllers.AuthenticationController.ExternalLoginCallback()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at System.Application.Middleware.JwtInUrlMiddleware.Invoke(HttpContext context, IAppVersionInfoRepository repository)
   at System.Application.Middleware.StandardizedExceptionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

022-07-26 14:36:47.5345||ERROR|JwtInUrlMiddleware|isBind: False, UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36 Edg/103.0.1264.71
CryptographicException: Padding is invalid and cannot be removed.
2022-07-26 14:36:47.5362||ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request. System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
   at Internal.Cryptography.UniversalCryptoDecryptor.GetPaddingLength(ReadOnlySpan`1 block)
   at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(ReadOnlySpan`1 inputBuffer, Span`1 outputBuffer)
   at Internal.Cryptography.UniversalCryptoDecryptor.UncheckedTransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at Internal.Cryptography.UniversalCryptoTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.AESUtils.Decrypt(Aes aes, Byte[] data)
   at System.Security.Cryptography.AESUtils.Decrypt(Aes aes, String text)
   at System.Application.Middleware.JwtInUrlMiddleware.Invoke(HttpContext context, IAppVersionInfoRepository repository)
   at System.Application.Middleware.StandardizedExceptionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

2022-07-26 14:38:24.7126||ERROR|JwtInUrlMiddleware|isBind: False, UserAgent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
CryptographicException: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
2022-07-26 14:38:24.7126||ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request. Interop+Crypto+OpenSslCryptographicException: error:04099079:rsa routines:RSA_padding_check_PKCS1_OAEP_mgf1:oaep decoding error
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(SafeEvpPKeyHandle key, ReadOnlySpan`1 data, Span`1 destination, RSAEncryptionPadding padding)
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(Byte[] data, RSAEncryptionPadding padding)
   at System.Application.Formatters.GeneralInputFormatter.ReadAsync(InputFormatterContext context)
   at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
   at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at System.Application.Middleware.JwtInUrlMiddleware.Invoke(HttpContext context, IAppVersionInfoRepository repository)
   at System.Application.Middleware.StandardizedExceptionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)

2022-07-26 15:10:15.1974||ERROR|JwtInUrlMiddleware|isBind: False, UserAgent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
CryptographicException: error:04065084:rsa routines:rsa_ossl_private_decrypt:data too large for modulus
2022-07-26 15:10:15.1974||ERROR|Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware|An unhandled exception has occurred while executing the request. Interop+Crypto+OpenSslCryptographicException: error:04065084:rsa routines:rsa_ossl_private_decrypt:data too large for modulus
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(SafeEvpPKeyHandle key, ReadOnlySpan`1 data, Span`1 destination, RSAEncryptionPadding padding)
   at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.Decrypt(Byte[] data, RSAEncryptionPadding padding)
   at System.Application.Formatters.GeneralInputFormatter.ReadAsync(InputFormatterContext context)
   at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)
   at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container)
   at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at System.Application.Middleware.JwtInUrlMiddleware.Invoke(HttpContext context, IAppVersionInfoRepository repository)
   at System.Application.Middleware.StandardizedExceptionMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
2022-07-27 11:58:55 +08:00
RMBGAME c55870379e Notice UI 2022-07-27 00:10:53 +08:00
RMBGAME 48bbc5a530 Misc 2022-07-26 23:59:45 +08:00
RMBGAME 94d26bd874 fix #1758 2022-07-26 23:51:01 +08:00
RMBGAME f3d5c251da packaging 2022-07-26 23:28:51 +08:00
Aigio Liu a8ac5b9901 fix ERR_SSL_VERSION_OR_CIPHER_MISMATCH in Windows 7 2022-07-26 23:21:45 +08:00
RMBGAME 5ba8d727ed Misc 2022-07-26 21:58:24 +08:00
Aigio Liu 570ca3c623 sc stop WinDivert1.4
https://reqrypt.org/windivert-doc-1.4.html#uninstalling
2022-07-26 21:40:54 +08:00
Aigio Liu 295948816b fix Log Init 2022-07-26 19:30:02 +08:00
Aigio Liu 2a196b1ca0 Update Microsoft.AppCenter v4.5.3 2022-07-26 16:53:34 +08:00
RMBGAME 81a70492a7 #1758 2022-07-26 14:12:37 +08:00
RMBGAME 5f374557de Misc 2022-07-26 08:08:58 +08:00
Aigio Liu f0a0a77f0a Translate 2022-07-26 00:49:32 +08:00
Aigio Liu c2a502a6aa Misc & Server 2022-07-26 00:14:20 +08:00
Aigio Liu f6d6ba08a5 fix msstore system boot run silence no work 2022-07-25 18:20:25 +08:00
Aigio Liu 98e4620c0b fix NRE
2022-07-25 13:24:27.6944|Error|Shutdown|compositeDisposable.Dispose() | System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Application.Services.Implementation.YarpReverseProxyServiceImpl.StopProxy()
   at System.Application.Services.ProxyService.Exit()
   at System.TaskExtensions.RunSync(Func`1 func)
   at System.Reactive.Disposables.CompositeDisposable.Dispose() in D:\a\SteamTools\SteamTools\references\reactive\Rx.NET\Source\src\System.Reactive\Disposables\CompositeDisposable.cs:line 244
   at System.Application.UI.App.ApplicationLifetime_Exit(Object sender, ControlledApplicationLifetimeExitEventArgs e)
2022-07-25 13:52:56 +08:00
Aigio Liu ba6405074e Bump 2.8.2 2022-07-25 09:51:21 +08:00
AndromedaMelody 06d67e527f Add Firewall Rules to AppxManifest (#1729)
* Add FireWall Rules to WindowsAppPackaging Project

* Add FireWall Rules to Single-Project MSIX
2022-07-25 09:02:21 +08:00
Aigio Liu b9e4c8a410 Misc 2022-07-24 23:01:56 +08:00
Aigio Liu 1571259321 fix 2022-07-24 17:05:15 +08:00
Aigio Liu a9c11ee72f #1717 2022-07-24 17:04:18 +08:00
RMBGAME 0393e82007 fix Http Proxy 2022-07-24 16:25:40 +08:00
Aigio Liu 3358ee78e7 Add WindowsCryptographicException 2022-07-24 16:23:33 +08:00
Aigio Liu b7e5746d7d Misc 2022-07-24 13:58:41 +08:00
Aigio Liu efae85db2c Add UseWinHttpHandler 2022-07-24 13:41:39 +08:00
RMBGAME 4826939668 Misc 2022-07-24 00:54:36 +08:00
RMBGAME ebe346b3b1 fix #1714 2022-07-24 00:48:07 +08:00
RMBGAME 0652f49b65 修复代理DNS设置无效 2022-07-24 00:35:10 +08:00
Aigio Liu b6729e45ae fix FDELauncher 2022-07-23 23:51:53 +08:00
Aigio Liu a0fe199d20 Add app.manifest 2022-07-23 23:47:01 +08:00
231 changed files with 6761 additions and 4126 deletions
+24 -5
View File
@@ -7,26 +7,45 @@ assignees: ''
---
### 🐛 描述(Description)
<!--
发布前请先尝试在 Issuse 内搜索一下你的问题是否已经被提出过,
发布前请先尝试在 Issues 内搜索一下你的问题是否已经被提出过,
详细地描述 bug,让大家都能理解,请一定确定你所要发布的内容是一个 Bug,如果不确定请发 Question
Before posting, please try searching in Issuse to see if your question has already been asked,
别忘了填写标题,标题要简短的描述问题
Before posting, please try searching in Issues to see if your question has already been asked,
Describe the bug in detail so that everyone can understand it
Don't forget to fill in the title, which should briefly describe the problem
-->
### 🐛 描述(Description)
<!--
详细的描述该问题
Describe the problem in detail
-->
### 📷 复现步骤(Steps to Reproduce)
<!--
清晰描述复现步骤,让别人也能看到问题
确保上述步骤尽可能能够在大多数设备上 100% 复现,以便定位问题原因
Clearly describe the reproduction steps so that others can see the problem
Ensure that the above steps can be reproduced 100% on most devices as far as possible in order to locate the cause of the problem
-->
1.
2.
3.
### 📄 [异常/日志]信息([Exception/Log] Information)
### 📄 日志信息(Log Information)
<!--
在程序内 设置 - 通用设置 - 存储空间 - 打开Logs文件夹 找到当天的日志,将文件上传或将关键部分写在此处,在内容的开始与结束上加上 ``` 单独作为一行,如下所示
Set in the program - General Settings - storage space - open the logs folder to find the log of the day, upload the file or write the key part here, and add ``` to the beginning and end of the content as a separate line, as shown below
```
你的日志内容
Your log content
```
-->
### 🚑 基本信息(Basic Information)
@@ -7,6 +7,13 @@ assignees: ''
---
<!--
发布前请先尝试在 Issuse 内搜索一下你的 Feature 是否已经被提出过,
别忘了填写标题,标题要简短的描述 Feature
Before publishing, please try to search in issue to see if your feature has been proposed,
Don't forget to fill in the title, which should briefly describe the feature
-->
### 🥰 需求描述(Description)
<!--
+9 -2
View File
@@ -7,11 +7,18 @@ assignees: ''
---
<!--
发布前请先尝试在 Issuse 内搜索一下你的 Question 是否已经被提出过,
别忘了填写标题,标题要简短的描述 Question
Before publishing, please try to search in issue to see if your question has been proposed,
Don't forget to fill in the title, which should briefly describe the question
-->
### 🧐 问题描述(Description)
<!--
详细地描述需求,让大家都能理解
Describe the requirements in detail so that everyone can understand them
详细地描述 Question,让大家都能理解
Describe the question in detail so that everyone can understand it
-->
### 🚑 其他信息(Other Information)
+61 -56
View File
@@ -5,18 +5,18 @@
<PackageVersion Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.7" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.7" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.7" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.8" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.8" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcoreapp3.1'))">
<!-- Microsoft.Extensions.* & AspNetCore & EntityFrameworkCore(NETCOREAPP31) -->
@@ -24,7 +24,7 @@
<PackageVersion Include="Microsoft.Extensions.Http" Version="3.1.27" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="3.1.27" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.27" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.27" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="3.1.27" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.27" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="3.1.27" />
@@ -40,12 +40,12 @@
<ItemGroup Condition=" $(TargetFramework.StartsWith('net6.0')) ">
<!-- Entity Framework Plus -->
<!-- A FREE & Open Source library to enhance EF6 and EF Core -->
<PackageVersion Include="Z.EntityFramework.Plus.EFCore" Version="6.14.3" />
<PackageVersion Include="Z.EntityFramework.Plus.EFCore" Version="6.14.4" />
<!-- AspNetCore 6 OpenId/OAuth -->
<PackageVersion Include="AspNet.Security.OpenId.Steam" Version="6.0.0" />
<PackageVersion Include="AspNet.Security.OAuth.QQ" Version="6.0.6" />
<PackageVersion Include="AspNet.Security.OAuth.Apple" Version="6.0.6" />
<PackageVersion Include="AspNet.Security.OAuth.QQ" Version="6.0.9" />
<PackageVersion Include="AspNet.Security.OAuth.Apple" Version="6.0.9" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
@@ -74,24 +74,26 @@
</ItemGroup>
<ItemGroup>
<!-- Microsoft.* -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.3.0" />
<!--<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="1.4.1" />-->
<!--<PackageVersion Include="Microsoft.Windows.SDK.NET.Ref" Version="10.0.19041.22" />-->
<!--<PackageVersion Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />-->
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.1" />
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="6.0.0" />
<PackageVersion Include="Microsoft.Net.Http.Headers" Version="2.2.255.255" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<!--<PackageVersion Include="CommunityToolkit.Mvvm" Version="7.1.2" />-->
<PackageVersion Include="System.Text.Encoding.CodePages" Version="6.0.0" />
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="6.0.1" />
<PackageVersion Include="System.Net.Http.WinHttpHandler" Version="6.0.1" />
<!-- AppCenter.* -->
<PackageVersion Include="Microsoft.AppCenter" Version="4.5.1" />
<PackageVersion Include="Microsoft.AppCenter.Analytics" Version="4.5.1" />
<PackageVersion Include="Microsoft.AppCenter.Crashes" Version="4.5.1" />
<PackageVersion Include="Aigio.Avalonia.AppCenter" Version="4.5.1" />
<PackageVersion Include="Aigio.Avalonia.AppCenter.Analytics" Version="4.5.1" />
<PackageVersion Include="Aigio.Avalonia.AppCenter.Crashes" Version="4.5.1" />
<PackageVersion Include="Microsoft.AppCenter" Version="4.5.3" />
<PackageVersion Include="Microsoft.AppCenter.Analytics" Version="4.5.3" />
<PackageVersion Include="Microsoft.AppCenter.Crashes" Version="4.5.3" />
<PackageVersion Include="Aigio.Avalonia.AppCenter" Version="4.5.3" />
<PackageVersion Include="Aigio.Avalonia.AppCenter.Analytics" Version="4.5.3" />
<PackageVersion Include="Aigio.Avalonia.AppCenter.Crashes" Version="4.5.3" />
<!--<PackageVersion Include="nor0x.AppCenter" Version="4.4.0-XMAC" />
<PackageVersion Include="nor0x.AppCenter.Analytics" Version="4.4.0-XMAC" />
<PackageVersion Include="nor0x.AppCenter.Crashes" Version="4.4.0-XMAC" />-->
@@ -112,18 +114,18 @@
<PackageVersion Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageVersion Include="nunit.xamarin" Version="3.6.1" />
<PackageVersion Include="PCLStorage" Version="1.0.2" />
<PackageVersion Include="Moq" Version="4.18.1" />
<PackageVersion Include="Moq" Version="4.18.2" />
<!-- NLog -->
<PackageVersion Include="NLog" Version="5.0.1" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.0.1" />
<PackageVersion Include="NLog.Web.AspNetCore" Version="5.1.0" />
<PackageVersion Include="NLog" Version="5.0.2" />
<PackageVersion Include="NLog.Extensions.Logging" Version="5.0.2" />
<PackageVersion Include="NLog.Web.AspNetCore" Version="5.1.1" />
<PackageVersion Include="AspNetCore2.NETStandard.NLog.Web.AspNetCore" Version="5.0.0" />
<!-- ReactiveUI -->
<PackageVersion Include="System.Reactive" Version="5.0.0" />
<PackageVersion Include="Splat" Version="14.4.1" />
<PackageVersion Include="DynamicData" Version="7.9.7" />
<PackageVersion Include="DynamicData" Version="7.9.14" />
<PackageVersion Include="ReactiveUI" Version="18.3.1" />
<PackageVersion Include="ReactiveUI.Fody" Version="18.3.1" />
<PackageVersion Include="ReactiveUI.XamForms" Version="18.3.1" />
@@ -131,11 +133,11 @@
<PackageVersion Include="ReactiveUI.Maui" Version="18.3.1" />
<!-- SkiaSharp & HarfBuzzSharp -->
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/HarfBuzzSharp.props -->
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.1-preview.91" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.1-preview.91" />
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2.1-preview.104" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.1-preview.104" />
<!-- https://github.com/AvaloniaUI/Avalonia/blob/master/build/SkiaSharp.props -->
<PackageVersion Include="SkiaSharp" Version="2.88.1-preview.91" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1-preview.91" />
<PackageVersion Include="SkiaSharp" Version="2.88.1-preview.104" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1-preview.104" />
<!-- AutoMapper -->
<PackageVersion Include="AutoMapper" Version="11.0.1" />
@@ -191,7 +193,7 @@
<PackageVersion Include="NPOI" Version="2.5.6" />
<!-- Github API -->
<PackageVersion Include="Octokit" Version="1.0.0" />
<PackageVersion Include="Octokit" Version="2.0.1" />
<!-- ORM -->
<PackageVersion Include="sqlite-net-pcl" Version="1.8.116" />
@@ -209,7 +211,7 @@
<PackageVersion Include="Newtonsoft.Json" Version="13.0.1" />
<!-- Html Parser -->
<PackageVersion Include="HtmlAgilityPack" Version="1.11.43" />
<PackageVersion Include="HtmlAgilityPack" Version="1.11.45" />
<!-- Clipboard -->
<PackageVersion Include="TextCopy" Version="6.1.0" />
@@ -237,31 +239,31 @@
<PackageVersion Include="Polly" Version="7.2.3" />
<!--Avalonia Start-->
<PackageVersion Include="Avalonia" Version="0.10.17" />
<PackageVersion Include="Avalonia.Desktop" Version="0.10.17" />
<PackageVersion Include="Avalonia.Skia" Version="0.10.17" />
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.17" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="0.10.17" />
<PackageVersion Include="Avalonia" Version="0.10.18" />
<PackageVersion Include="Avalonia.Desktop" Version="0.10.18" />
<PackageVersion Include="Avalonia.Skia" Version="0.10.18" />
<PackageVersion Include="Avalonia.Diagnostics" Version="0.10.18" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="0.10.18" />
<!--<PackageVersion Include="Avalonia.Direct2D1" Version="0.10.16" />-->
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.17" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.18" />
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="0.10.17" />
<!--<PackageVersion Include="Avalonia.AvaloniaEdit" Version="0.10.12.2" />-->
<!--<PackageVersion Include="CefNet.Avalonia" Version="93.1.21240.857" />-->
<!--<PackageVersion Include="LibVLCSharp.Avalonia" Version="3.5.1" />-->
<!--<PackageVersion Include="FluentAvaloniaUI" Version="1.4.1" />-->
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-beta.330" />
<PackageVersion Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-beta.350" />
<PackageVersion Include="JumpLists.Win32.Avalonia" Version="1.0.0" />
<PackageVersion Include="Avalonia.Native" Version="0.10.17" />
<PackageVersion Include="Avalonia.Win32" Version="0.10.17" />
<PackageVersion Include="Avalonia.X11" Version="0.10.17" />
<PackageVersion Include="Avalonia.Native" Version="0.10.18" />
<PackageVersion Include="Avalonia.Win32" Version="0.10.18" />
<PackageVersion Include="Avalonia.X11" Version="0.10.18" />
<!--<PackageVersion Include="Avalonia.HtmlRenderer" Version="0.10.0" />-->
<PackageVersion Include="WebView2.Avalonia" Version="1.0.1264.42-preview.220713.10" />
<!--Avalonia End-->
<!-- Xamarin.Android -->
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.2" />
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.40.5" />
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="116.1.2.5" />
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.3" />
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.41.0.2" />
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="117.0.2.2" />
<PackageVersion Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageVersion Include="de.hdodenhof.circleimageview" Version="3.1.0.4" />
<PackageVersion Include="Square.OkHttp3" Version="4.9.3" />
@@ -273,29 +275,29 @@
<!-- V2Ray -->
<PackageVersion Include="XAB.AndroidLibV2rayLite" Version="1.0.0.1" />
<!--<PackageVersion Include="Karamunting.KotlinX.Coroutines.Core" Version="1.4.2" />-->
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.2.1" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.2.1" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.4" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.4" />
<PackageVersion Include="Xamarin.Android.ReactiveX.RxJava3.RxJava" Version="3.1.5.1" />
<!-- Xamarin.AndroidX -->
<PackageVersion Include="Xamarin.AndroidX.Migration" Version="1.0.10" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.4.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Emoji.AppCompat" Version="1.1.0.9" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.4.1.2" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.5.1" />
<PackageVersion Include="Xamarin.AndroidX.RecyclerView" Version="1.2.1.7" />
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.6.1.1" />
<PackageVersion Include="Xamarin.AndroidX.SwipeRefreshLayout" Version="1.1.0.9" />
<PackageVersion Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.4.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.4.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.4.2.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.5.1" />
<PackageVersion Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.16" />
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.4.0.4" />
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Biometric" Version="1.1.0.10" />
<PackageVersion Include="Xamarin.AndroidX.ExifInterface" Version="1.3.3.6" />
<PackageVersion Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.15" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.4.1.2" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.1.0-beta02" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.1.0-beta02" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.5.1" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.1.0" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.1.0" />
<PackageVersion Include="Xamarin.AndroidX.Camera.View" Version="1.1.0-beta02" />
<!--<PackageVersion Include="Xamarin.AndroidX.Window" Version="1.0.0.9" />-->
<PackageVersion Include="Xamarin.AndroidX.WebKit" Version="1.4.0.8" />
@@ -305,7 +307,7 @@
<!-- UWP -->
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.1.3" />
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.1.4" />
<!-- Code Style -->
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.435" />
@@ -321,5 +323,8 @@
<!-- ArchiSteamFarm -->
<PackageVersion Include="ArchiSteamFarm.Library" Version="5.2.6.3-preview.220608" />
<!-- DBreeze(key value store embedded) -->
<PackageVersion Include="DBreeze" Version="1.107.0" />
</ItemGroup>
</Project>
+5
View File
@@ -0,0 +1,5 @@
<configuration>
<packageSources>
<add key="LocalNuGetPackages" value="./references/NuGetPackages" />
</packageSources>
</configuration>
+2 -2
View File
@@ -17,7 +17,7 @@ English | [简体中文](./README.md)
[![C# 10.0](https://img.shields.io/badge/c%23-10.0-green.svg?style=flat-square&color=6da86a)](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10)
[![Desktop UI](https://img.shields.io/badge/ui@desktop-AvaloniaUI-purple.svg?style=flat-square&color=8c45ab)](https://github.com/AvaloniaUI/Avalonia)
[![Mobile GUI](https://img.shields.io/badge/gui@mobile-Xamarin.Forms-blue.svg?style=flat-square&color=3498db)](https://github.com/xamarin/Xamarin.Forms)
[![Mobile UI](https://img.shields.io/badge/ui@mobile-MAUI-blue.svg?style=flat-square&color=512BD4)](https://github.com/dotnet/maui)
[![Official WebSite](https://img.shields.io/badge/website@official-Ant%20Design%20of%20React-blue.svg?style=flat-square&color=61dafb)](https://github.com/ant-design/ant-design)
[![BackManage WebSite](https://img.shields.io/badge/website@back_manage-Ant%20Design%20of%20Blazor-purple.svg?style=flat-square&color=512bd4)](https://github.com/ant-design-blazor/ant-design-blazor)
@@ -183,7 +183,7 @@ Read what we [milestones](https://github.com/BeyondDimension/SteamTools/mileston
- [Avalonia for Visual Studio(Optional)](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
- [NUnit VS Templates(Optional)](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
[OpenJDK 11](https://docs.microsoft.com/java/openjdk/download#openjdk-11)
[OpenJDK 17](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-17)
[Android Studio 2021.1.1 Or Higher](https://developer.android.com/studio/)
[Xcode 13 Or Higher](https://developer.apple.com/xcode/)
+2 -2
View File
@@ -17,7 +17,7 @@
[![C# 10.0](https://img.shields.io/badge/c%23-10.0-brightgreen.svg?style=flat-square&color=6da86a)](https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10)
[![Desktop UI](https://img.shields.io/badge/ui@desktop-AvaloniaUI-purple.svg?style=flat-square&color=8c45ab)](https://github.com/AvaloniaUI/Avalonia)
[![Mobile GUI](https://img.shields.io/badge/gui@mobile-Xamarin.Forms-blue.svg?style=flat-square&color=3498db)](https://github.com/xamarin/Xamarin.Forms)
[![Mobile UI](https://img.shields.io/badge/ui@mobile-MAUI-blue.svg?style=flat-square&color=512BD4)](https://github.com/dotnet/maui)
[![Official WebSite](https://img.shields.io/badge/website@official-Ant%20Design%20of%20React-blue.svg?style=flat-square&color=61dafb)](https://github.com/ant-design/ant-design)
[![BackManage WebSite](https://img.shields.io/badge/website@back_manage-Ant%20Design%20of%20Blazor-purple.svg?style=flat-square&color=512bd4)](https://github.com/ant-design-blazor/ant-design-blazor)
@@ -194,7 +194,7 @@ OS | Version | Architectures |
- [Avalonia for Visual Studio(可选)](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
- [NUnit VS Templates(可选)](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
[OpenJDK 11](https://docs.microsoft.com/zh-cn/java/openjdk/download#openjdk-11)
[OpenJDK 17](https://docs.microsoft.com/zh-cn/java/openjdk/download#openjdk-17)
[Android Studio 2021.1.1 或更高版本](https://developer.android.google.cn/studio/)
[Xcode 13 或更高版本](https://developer.apple.com/xcode/)
+1 -64
View File
@@ -14,6 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Root", "_Root", "{66839CD8
download-guide.md = download-guide.md
global.json = global.json
packaging\Info.plist = packaging\Info.plist
NuGet.Config = NuGet.Config
packaging\package.net472.ps1 = packaging\package.net472.ps1
README.en.md = README.en.md
README.md = README.md
@@ -173,8 +174,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gameloop.Vdf", "references\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.Shadowsocks", "src\ST.Client.Android.Shadowsocks\ST.Client.Android.Shadowsocks.csproj", "{920EF29F-406F-43A9-B002-29DD6B0B4FBF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.App.Modern", "src\ST.Client.Android.App.Modern\ST.Client.Android.App.Modern.csproj", "{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ResSecrets", "ResSecrets", "{17667B53-1A09-45A6-855A-0F07F9AE044F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.ResSecrets", "src\ST.Client.Android.ResSecrets\ST.Client.Android.ResSecrets.csproj", "{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}"
@@ -189,8 +188,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Windows.ResSecret
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Desktop", "src\Avalonia.Desktop\Avalonia.Desktop.csproj", "{FA9F0E89-E410-400A-86F3-C603E51E62A8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Avalonia.App.MsixPackage", "src\ST.Client.Desktop.Avalonia.App.Bridge2\ST.Client.Avalonia.App.MsixPackage.csproj", "{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FDELauncher", "src\FDELauncher\FDELauncher.csproj", "{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Net.Http.Headers", "src\Microsoft.Net.Http.Headers\Microsoft.Net.Http.Headers.csproj", "{C7F109B9-EA88-4B7E-ADB5-D6407686ADE0}"
@@ -1937,36 +1934,6 @@ Global
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x64.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x86.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x86.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|ARM64.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhone.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x64.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x64.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x86.ActiveCfg = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Debug|x86.Build.0 = Debug|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|Any CPU.Deploy.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM64.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|ARM64.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhone.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhone.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x64.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x64.Build.0 = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x86.ActiveCfg = Release|Any CPU
{5E2ABB4A-FDD6-47B0-946D-FAAD31301B82}.Release|x86.Build.0 = Release|Any CPU
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68DD3E9C-A96C-4128-8D95-DCD65D1FA277}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -2135,36 +2102,6 @@ Global
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x64.Build.0 = Release|Any CPU
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x86.ActiveCfg = Release|Any CPU
{FA9F0E89-E410-400A-86F3-C603E51E62A8}.Release|x86.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|Any CPU.ActiveCfg = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|Any CPU.Build.0 = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM.ActiveCfg = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM.Build.0 = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM64.ActiveCfg = Debug|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|ARM64.Build.0 = Debug|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhone.Build.0 = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.ActiveCfg = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.Build.0 = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x64.Deploy.0 = Debug|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x86.ActiveCfg = Debug|x86
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Debug|x86.Build.0 = Debug|x86
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|Any CPU.ActiveCfg = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|Any CPU.Build.0 = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM.ActiveCfg = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM64.ActiveCfg = Release|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|ARM64.Build.0 = Release|arm64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhone.ActiveCfg = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhone.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.ActiveCfg = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.Build.0 = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x64.Deploy.0 = Release|x64
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x86.ActiveCfg = Release|x86
{7E7C34F0-1391-473C-8A1C-CE3EAF5D66DB}.Release|x86.Build.0 = Release|x86
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AAA8A01-A4FE-49AD-9664-AC53C4C8EAC6}.Debug|ARM.ActiveCfg = Debug|Any CPU
+2 -2
View File
@@ -7,9 +7,9 @@
<key>CFBundleIdentifier</key>
<string>net.steampp.app</string>
<key>CFBundleShortVersionString</key>
<string>2.8.1</string>
<string>2.8.3</string>
<key>CFBundleVersion</key>
<string>2.8.1.0</string>
<string>2.8.3.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
<key>CFBundleDevelopmentRegion</key>
+1
View File
@@ -0,0 +1 @@
dotnet publish "..\src\ST.Client.Desktop.Avalonia.App\ST.Client.Avalonia.App.csproj" -c Release -p:PublishProfile=win-x64 -p:DeployOnBuild=true -p:ExtraDefineConstants=win-x64 --nologo
Binary file not shown.
+33 -46
View File
@@ -3,44 +3,31 @@
2. 因经济状况原因,现已停止短信服务节约开销,后续会推出邮箱注册登录,对于仅使用手机号登录的用户请绑定第三方快速登录,否则注销后将无法再次登录,需要等待至邮箱服务推出后支持会暂时在开放短信服务提供换绑邮箱。
3. 自动更新目前仅 Windows 端可用,且由于下载渠道限速可能导致无法更新成功,推荐在官网链接的网盘或群文件中下载压缩包解压覆盖更新(应用商店版由商店更新不受此影响)
4. 在 Android 上因系统限制,目前的加速功能无法正常使用,所以此功能已放弃继续开发,如仍想使用需要自行导入证书到系统目录,使用 adb 工具或 Magisk 之类的软件操作,未来会使用不需要证书的加速功能替换此功能
5. fde 版本需要安装 [ASP.NET Core 运行时 6.0.7 (x64) 与 .NET Core 运行时 6.0.7 (x64)](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)
5. fde 版本需要安装 [ASP.NET Core 运行时 6.0.8 (x64) 与 .NET Core 运行时 6.0.8 (x64)](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)
6. Windows x86 与 x64 版本令牌本机加密互不兼容,使用两者版本时注意令牌加密后的文件不能共用。
7. 由于新版本加速功能重构,调整了部分加速项目,这会影响旧版本程序使用加速功能
8. 为了能继续维持开发,从此版本开始将会添加程序内广告,赞助用户可以在设置中关闭所有广告
### 版本亮点
1. 新增 Steam 云存档管理功能,可自行上传或删除 Steam 云存档
2. 库存游戏支持筛选支持 Steam 云存档的游戏
3. ASF 升级至 V5.2.7.7
4. .NET 运行时升级至 6.0.7,使用 fde 版本需要升级运行时
5. 库存游戏中解锁成就与挂时长支持 macOS 与 Linux 系统
6. 在设置中可关闭托盘,关闭托盘后关闭主窗口即退出程序
7. 使用 Yarp.ReverseProxy 重写了反代加速和脚本功能,大幅提升稳定性与性能
8. Windows 新增 DNS 驱动拦截模式进行本地加速
9. 令牌交易现在支持查看交易详情,可以确认交易方的Steam注册时间等信息
10. 恢复 Windows x86(32 位) 版本发布
1. .NET 运行时升级至 6.0.8,使用 fde 版本需要升级运行时
2. ASF 升级至 V5.2.8.4
### 修复问题
1. 修复 窗口在某些情况下最大化或最小化恢复时窗口大小会变化的问题
2. 修复 库存游戏 编辑 Steam 游戏封面时选择自定义图片失败的问题
3. 修复 程序内在显示某些图片时会出现错乱马赛克的问题
4. 修复 Linux 上点击关于页面可能因字体引发闪退
5. 修复 MIUI Android 11 ~ 12 中绑定或换绑手机号页面闪退
6. 修复 Android 本地加速中已知问题弹窗显示时不应同时跳转引导证书页
7. 修复 令牌交易确认要求输本地令牌密钥时点击取消也能进行交易确认的问题
8. 修复 令牌加载输入密码解密时点击取消或输入错误密码没有移除此前的数据问题
9. 修复 2.8.1 中出现因脚本导致的启动加速服务失败
10. 修复 网络加速中图标在跟随系统的浅色模式下字体颜色不应为白色
11. 修复 系统代理模式与 PAC 代理模式中监听地址为 0.0.0.0 时出现的错误
12. 修复 切换页面 UI 布局错乱
1. 修复 2.8.0 ~ 2.8.2 中 AppData/Config.mpo 文件大小为 0 时导致的程序无法正常启动
2. 修复 Windows 上版本更新在 2.8.0 ~ 2.8.2 中非 FDE 版本识别为 FDE 版
3. 改进 调整代理模式顺序,Hosts 模式置顶
4. 修复 划词翻译等一些 JS 脚本
5. 改进 macOS 上的证书安装
6. 尝试修复 网络加速中能导致内存泄露的问题
7. 改进 非简中默认隐藏加速与脚本仅在 Windows 上生效
8. 改进 减少 Android 上的启动时间
9. 修复 退出程序时可能引发的闪退
10. 修复 macOS/Linux 上设置页面打不开的问题
11. 修复 网络加速中网页上出现 Because https://... actually points to WattToolkit itself...
12. 尝试修复 ASF 控制台中输入时卡死
<!--
TODO:
Android 第三方快速登录回调改为 URL Scheme
修复 Android 检查更新检测不到最新版本的问题
### 已知问题
- 除 Windows 之外的平台此软件自动更新尚不可用
- Desktop
@@ -74,7 +61,7 @@ Android 第三方快速登录回调改为 URL Scheme
[![WebSite steampp.net](https://img.shields.io/badge/WebSite-steampp.net-brightgreen.svg?style=flat-square&color=61dafb)](https://steampp.net)
[![Steam++ v2.8.1](https://img.shields.io/badge/Steam++-v2.8.1-brightgreen.svg?style=flat-square&color=512bd4)]()
[![Steam++ v2.8.3](https://img.shields.io/badge/Steam++-v2.8.3-brightgreen.svg?style=flat-square&color=512bd4)]()
##### [不知道该下载哪个文件?](./download-guide.md)
@@ -83,28 +70,28 @@ Android 第三方快速登录回调改为 URL Scheme
### 文件校验
| File | Checksum (SHA256) |
| ---- | ---- |
| Steam++_win_x64_v2.8.1.7z | SHA256 |
| Steam++_win_x64_fde_v2.8.1.7z | SHA256 |
| Steam++_win_x64_v2.8.3.7z | SHA256 |
| Steam++_win_x64_fde_v2.8.3.7z | SHA256 |
| | |
| Steam++_win_x64_v2.8.1.exe | SHA256 |
| Steam++_win_x64_fde_v2.8.1.exe | SHA256 |
| Steam++_win_x64_v2.8.3.exe | SHA256 |
| Steam++_win_x64_fde_v2.8.3.exe | SHA256 |
| | |
| Steam++_win_x86_v2.8.1.7z | SHA256 |
| Steam++_win_x86_fde_v2.8.1.7z | SHA256 |
| Steam++_win_x86_v2.8.3.7z | SHA256 |
| Steam++_win_x86_fde_v2.8.3.7z | SHA256 |
| | |
| Steam++_win_x86_v2.8.1.exe | SHA256 |
| Steam++_win_x86_fde_v2.8.1.exe | SHA256 |
| Steam++_win_x86_v2.8.3.exe | SHA256 |
| Steam++_win_x86_fde_v2.8.3.exe | SHA256 |
| | |
| Steam++_linux_x64_v2.8.1.7z | SHA256 |
| Steam++_linux_arm64_v2.8.1.7z | SHA256 |
| Steam++_linux_x64_v2.8.3.7z | SHA256 |
| Steam++_linux_arm64_v2.8.3.7z | SHA256 |
| | |
| Steam++_linux_x64_v2.8.1.deb | SHA256 |
| Steam++_linux_arm64_v2.8.1.deb | SHA256 |
| Steam++_linux_x64_v2.8.3.deb | SHA256 |
| Steam++_linux_arm64_v2.8.3.deb | SHA256 |
| | |
| Steam++_linux_x64_v2.8.1.rpm | SHA256 |
| Steam++_linux_arm64_v2.8.1.rpm | SHA256 |
| Steam++_linux_x64_v2.8.3.rpm | SHA256 |
| Steam++_linux_arm64_v2.8.3.rpm | SHA256 |
| | |
| Steam++_macos_x64_v2.8.1.dmg | SHA256 |
| Steam++_macos_arm64_v2.8.1.dmg | SHA256 |
| Steam++_macos_x64_v2.8.3.dmg | SHA256 |
| Steam++_macos_arm64_v2.8.3.dmg | SHA256 |
| | |
| Steam++_android_v2.8.1.apk | SHA256 |
| Steam++_android_v2.8.3.apk | SHA256 |
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+5 -1
View File
@@ -5,7 +5,11 @@ using Android.OS;
using Android.Webkit;
using Android.Util;
using Android.Opengl;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using Process = System.Diagnostics.Process;
using AndroidApplication = Android.App.Application;
#endif
@@ -543,7 +547,7 @@ namespace System.Application.UI
b.Append(Essentials.IsSupported.ToLowerString());
b.AppendLine();
#if __ANDROID__
#if __ANDROID__ && !NET6_0_MAUI_LIB
b.Append("[startup.track] ");
b.AppendLine();
b.Append(MainApplication.StartupTrack);
@@ -0,0 +1,219 @@
// https://github.com/AvaloniaUI/Avalonia/blob/0.10.17/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Interactivity;
using Avalonia.Platform;
using Avalonia.Threading;
namespace Avalonia.Controls.ApplicationLifetimes
{
sealed class ClassicDesktopStyleApplicationLifetime2 : IClassicDesktopStyleApplicationLifetime, IDisposable
{
private int _exitCode;
private CancellationTokenSource? _cts;
private bool _isShuttingDown;
private HashSet<Window> _windows = new();
private static ClassicDesktopStyleApplicationLifetime2? _activeLifetime;
static ClassicDesktopStyleApplicationLifetime2()
{
Window.WindowOpenedEvent.AddClassHandler(typeof(Window), OnWindowOpened);
Window.WindowClosedEvent.AddClassHandler(typeof(Window), WindowClosedEvent);
}
private static void WindowClosedEvent(object sender, RoutedEventArgs e)
{
_activeLifetime?._windows.Remove((Window)sender);
_activeLifetime?.HandleWindowClosed((Window)sender);
}
private static void OnWindowOpened(object sender, RoutedEventArgs e)
{
_activeLifetime?._windows.Add((Window)sender);
}
public ClassicDesktopStyleApplicationLifetime2()
{
if (_activeLifetime != null)
throw new InvalidOperationException(
"Can not have multiple active ClassicDesktopStyleApplicationLifetime instances and the previously created one was not disposed");
_activeLifetime = this;
}
/// <inheritdoc/>
public event EventHandler<ControlledApplicationLifetimeStartupEventArgs>? Startup;
/// <inheritdoc/>
public event EventHandler<ShutdownRequestedEventArgs>? ShutdownRequested;
/// <inheritdoc/>
public event EventHandler<ControlledApplicationLifetimeExitEventArgs>? Exit;
/// <summary>
/// Gets the arguments passed to the AppBuilder Start method.
/// </summary>
public string[]? Args { get; set; }
/// <inheritdoc/>
public ShutdownMode ShutdownMode { get; set; }
/// <inheritdoc/>
public Window? MainWindow { get; set; }
public IReadOnlyList<Window> Windows => _windows.ToList();
private void HandleWindowClosed(Window window)
{
if (window == null)
return;
if (_isShuttingDown)
return;
if (ShutdownMode == ShutdownMode.OnLastWindowClose && _windows.Count == 0)
TryShutdown();
else if (ShutdownMode == ShutdownMode.OnMainWindowClose && ReferenceEquals(window, MainWindow))
TryShutdown();
}
public void Shutdown(int exitCode = 0)
{
DoShutdown(new ShutdownRequestedEventArgs(), true, exitCode);
}
public bool TryShutdown(int exitCode = 0)
{
return DoShutdown(new ShutdownRequestedEventArgs(), false, exitCode);
}
public int Start(string[] args)
{
Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args));
var options = AvaloniaLocator.Current.GetService<ClassicDesktopStyleApplicationLifetimeOptions>();
if (options != null && options.ProcessUrlActivationCommandLine && args.Length > 0)
{
if (Application.Current is IApplicationPlatformEvents events)
{
events.RaiseUrlsOpened(args);
}
}
var lifetimeEvents = AvaloniaLocator.Current.GetService<IPlatformLifetimeEventsImpl>();
if (lifetimeEvents != null)
lifetimeEvents.ShutdownRequested += OnShutdownRequested;
_cts = new CancellationTokenSource();
// Note due to a bug in the JIT we wrap this in a method, otherwise MainWindow
// gets stuffed into a local var and can not be GCed until after the program stops.
// this method never exits until program end.
ShowMainWindow();
Dispatcher.UIThread.MainLoop(_cts.Token);
Environment.ExitCode = _exitCode;
return _exitCode;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private void ShowMainWindow()
{
MainWindow?.Show();
}
public void Dispose()
{
if (_activeLifetime == this)
_activeLifetime = null;
}
private bool DoShutdown(ShutdownRequestedEventArgs e, bool force = false, int exitCode = 0)
{
if (!force)
{
ShutdownRequested?.Invoke(this, e);
if (e.Cancel)
return false;
// https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/3780037517u/overview
// ClassicDesktopStyleApplicationLifetime.DoShutdown (ShutdownRequestedEventArgs e, Boolean force, Int32 exitCode) /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs, line 147
// System.InvalidOperationException: Application is already shutting down.
// v2.8.2 | 73 users | 76 reports
// Exception Stack:
// System.InvalidOperationException: Application is already shutting down.
// at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.DoShutdown(ShutdownRequestedEventArgs e, Boolean force, Int32 exitCode) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 147
// at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.OnShutdownRequested(Object sender, ShutdownRequestedEventArgs e) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 186
// at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam) in /_/src/Windows/Avalonia.Win32/Win32Platform.cs:line 283
if (_isShuttingDown)
// throw new InvalidOperationException("Application is already shutting down.");
return true;
}
_exitCode = exitCode;
_isShuttingDown = true;
try
{
// When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel
// shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their
// owners.
foreach (var w in Windows)
{
if (w.Owner is null)
{
w.Close();
}
}
if (!force && Windows.Count > 0)
{
e.Cancel = true;
return false;
}
var args = new ControlledApplicationLifetimeExitEventArgs(exitCode);
Exit?.Invoke(this, args);
_exitCode = args.ApplicationExitCode;
}
finally
{
_cts?.Cancel();
_cts = null;
_isShuttingDown = false;
}
return true;
}
private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e);
}
}
namespace Avalonia
{
public static class ClassicDesktopStyleApplicationLifetimeExtensions
{
public static int StartWithClassicDesktopLifetime2<T>(
this T builder, string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
where T : AppBuilderBase<T>, new()
{
var lifetime = new ClassicDesktopStyleApplicationLifetime2()
{
Args = args,
ShutdownMode = shutdownMode,
};
builder.SetupWithLifetime(lifetime);
return lifetime.Start(args);
}
}
}
@@ -3,7 +3,11 @@ using Microsoft.Extensions.DependencyInjection;
using AndroidToast = Android.Widget.Toast;
using AndroidToastLength = Android.Widget.ToastLength;
using JException = Java.Lang.Exception;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -7,7 +7,11 @@ using AndroidX.AppCompat.App;
using AndroidX.Fragment.App;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using Fragment = AndroidX.Fragment.App.Fragment;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
@@ -3,9 +3,17 @@ using Android.OS;
using Android.Provider;
using Android.Webkit;
using System.IO;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using AndroidUri = Android.Net.Uri;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
// ReSharper disable once CheckNamespace
namespace System
@@ -11,11 +11,22 @@ namespace System.Application;
/// </summary>
public static class MainThread2
{
static IMainThreadPlatformService? mInterface;
static IMainThreadPlatformService Interface
{
get
{
if (mInterface == null) mInterface = IMainThreadPlatformService.Instance;
return mInterface;
}
}
/// <summary>
/// 获取当前是否为主线程。
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsMainThread() => IMainThreadPlatformService.Instance.PlatformIsMainThread;
public static bool IsMainThread() => Interface.PlatformIsMainThread;
/// <summary>
/// 调用应用程序主线程上的操作。
@@ -33,7 +44,7 @@ public static class MainThread2
{
try
{
IMainThreadPlatformService.Instance.PlatformBeginInvokeOnMainThread(action, priority);
Interface.PlatformBeginInvokeOnMainThread(action, priority);
}
catch (InvalidOperationException)
{
@@ -1,6 +1,7 @@
using SQLite;
using System.Application.Entities;
using System.Application.Repositories;
using System.Application.Settings;
using System.Diagnostics;
using System.Globalization;
using SQLiteNotNull = SQLite.NotNullAttribute;
@@ -8,8 +9,13 @@ using SQLiteTable = SQLite.TableAttribute;
namespace System.Application.Services.Implementation;
internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatformService
#if DBREEZE
partial class PreferencesPlatformServiceImplV2
#else
sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatformService
#endif
{
#if !DBREEZE
readonly SQLiteConnection conn;
public PreferencesPlatformServiceImpl()
@@ -17,9 +23,9 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
conn = Repository.GetDbConnectionSync<Entity>();
}
static string GetId(string key) => $"{key}_K";
internal static string GetId(string key) => $"{key}_K";
static string GetId(string key, string? sharedName)
internal static string GetId(string key, string? sharedName)
{
if (sharedName == null) return GetId(key);
return $"{key}_{sharedName}_S";
@@ -75,12 +81,14 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
});
}
}
#endif
const string TableName = "1984415E";
const string ColumnName_Id = "0F5E4BAA";
const string ColumnName_Value = "4FC331D7";
const string ColumnName_SharedName = "F6A739AA";
#if !DBREEZE
const string Sql_Delete_Where_SharedName_Equals =
$"DELETE FROM \"{TableName}\" WHERE \"{ColumnName_SharedName}\" = ?";
@@ -101,12 +109,12 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
//const string Sql_Select_Value_Where_Key_Equals_And_SharedName_Equals =
// $"SELECT \"{ColumnName_Value}\" FROM \"{TableName}\" WHERE \"{ColumnName_Id}\" = ? AND \"{ColumnName_SharedName}\" = ?";
#endif
[SQLiteTable(TableName)]
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public sealed class Entity : IEntity<string>
{
#pragma warning disable CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
[Column(ColumnName_Id)]
[PrimaryKey]
[SQLiteNotNull]
@@ -115,7 +123,6 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
[Column(ColumnName_Value)]
[SQLiteNotNull]
public string Value { get; set; } = string.Empty;
#pragma warning restore CS8618 // 在退出构造函数时,不可为 null 的字段必须包含非 null 值。请考虑声明为可以为 null。
[Column(ColumnName_SharedName)]
[SQLiteNotNull]
@@ -124,3 +131,121 @@ internal sealed class PreferencesPlatformServiceImpl : IPreferencesGenericPlatfo
string DebuggerDisplay() => SharedName == string.Empty ? $"{Id}, {Value}" : $"{Id}, {Value}, {SharedName}";
}
}
#if DBREEZE
public sealed partial class PreferencesPlatformServiceImplV2 : IPreferencesGenericPlatformService
{
static string GetTableName(string? sharedName) => $"Preferences.{sharedName}";
public void PlatformSet<T>(string key, T? value, string? sharedName) where T : notnull, IConvertible
{
if (value == null)
{
PlatformRemove(key, sharedName);
}
else
{
using var t = SettingsProviderV3.Provider.GetTransaction();
t.Insert(GetTableName(sharedName), key, value.ToString(CultureInfo.InvariantCulture));
t.Commit();
}
}
public void PlatformClear(string? sharedName)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
t.RemoveAllKeys(GetTableName(sharedName), true);
t.Commit();
}
public bool PlatformContainsKey(string key, string? sharedName)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
var row = t.Select<string, string>(GetTableName(sharedName), key);
if (row == null) return false;
return row.Exists;
}
public T? PlatformGet<T>(string key, T? defaultValue, string? sharedName) where T : notnull, IConvertible
{
using var t = SettingsProviderV3.Provider.GetTransaction();
var row = t.Select<string, string>(GetTableName(sharedName), key);
if (row == null || !row.Exists) return defaultValue;
var value = ConvertibleHelper.Convert<T>(row.Value);
return value;
}
public void PlatformRemove(string key, string? sharedName)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
t.RemoveKey(GetTableName(sharedName), key);
t.Commit();
}
/// <summary>
/// 将数据从
/// <para>使用 SQLiteConnection 的 PreferencesPlatformServiceImpl</para>
/// <para>迁移到</para>
/// <para>使用 DBreeze 的 PreferencesPlatformServiceImplV2</para>
/// </summary>
public static void Migrate()
{
var dbPath = Repository.DataBaseDirectory;
bool isOK = false;
bool exists = false;
try
{
var dbFilePath = Path.Combine(dbPath, "application2.dbf");
try
{
exists = File.Exists(dbFilePath);
}
catch
{
}
if (!exists) return;
var conn = new SQLiteConnection(dbPath, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.SharedCache);
var items = conn.Table<Entity>().ToArray();
if (items.Any())
{
var itemGroups = items.GroupBy(x => x.SharedName).ToArray();
foreach (var itemGroup in itemGroups)
{
using var t = SettingsProviderV3.Provider.GetTransaction();
foreach (var item in itemGroup)
{
if (item.Value != null)
{
string key;
if (string.IsNullOrEmpty(item.SharedName)) key = item.Id.TrimEnd("_K");
else key = item.Id.TrimEnd($"_{item.SharedName}_S");
var tableName = GetTableName(item.SharedName);
t.Insert(tableName, key, item.Value.ToString(CultureInfo.InvariantCulture));
}
}
t.Commit();
}
}
conn.Close();
conn.Dispose();
isOK = true;
}
catch
{
}
finally
{
if (isOK)
{
var files = Directory.GetFiles(dbPath, "application2*");
foreach (var item in files)
{
IOPath.FileTryDelete(item);
}
}
}
}
}
#endif
@@ -62,7 +62,11 @@ public static class ServiceCollectionExtensions
/// <returns></returns>
public static IServiceCollection AddRepositoryPreferences(this IServiceCollection services)
{
#if DBREEZE
services.AddSingleton<IPreferencesPlatformService, PreferencesPlatformServiceImplV2>();
#else
services.AddSingleton<IPreferencesPlatformService, PreferencesPlatformServiceImpl>();
#endif
return services;
}
}
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.Diagnostics.CodeAnalysis;
namespace System.Application.Settings;
@@ -60,7 +61,7 @@ public sealed class FileSettingsProvider : ISerializationProvider
lock (_sync)
{
using var stream = new FileStream(_path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
using var stream = OpenReadWrite(_path);
if (stream.Position > 0)
{
stream.Position = 0;
@@ -71,6 +72,28 @@ public sealed class FileSettingsProvider : ISerializationProvider
}
}
static FileStream OpenReadWrite(string path)
{
try
{
return OpenReadWrite();
}
catch (Exception)
{
if (File.Exists(path))
{
if (IOPath.FileTryDelete(path))
{
// 直接打开文件流失败,尝试删除后再打开一次
return OpenReadWrite();
}
}
throw;
}
FileStream OpenReadWrite() => new(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
}
public void Load()
{
if (File.Exists(_path))
@@ -82,7 +105,7 @@ public sealed class FileSettingsProvider : ISerializationProvider
{
stream.Position = 0;
}
var source = Serializable.DMP<IDictionary<string, object?>>(stream);
var source = stream.Length == 0 ? null : Serializable.DMP<IDictionary<string, object?>>(stream);
//var source = XamlServices.Load(stream) as IDictionary<string, object>;
_settings = source == null
? new SortedDictionary<string, object?>()
@@ -107,4 +130,5 @@ public sealed class FileSettingsProvider : ISerializationProvider
add { }
remove { }
}
}
}
#endif
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.Diagnostics.CodeAnalysis;
namespace System.Application.Settings;
@@ -22,4 +23,5 @@ public interface ISerializationProvider
bool RemoveValue(string key);
string ToJsonString();
}
}
#endif
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.ComponentModel;
using System.Diagnostics;
@@ -194,4 +195,5 @@ public class SerializableProperty<T> : INotifyPropertyChanged
}
#endregion
}
}
#endif
@@ -1,3 +1,4 @@
#if !DBREEZE
using System.Runtime.CompilerServices;
namespace System.Application.Settings;
@@ -43,23 +44,96 @@ public static class SettingsHost
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), "Config Save", ex);
Log.Error(nameof(SettingsHost), ex, "Config Save");
throw;
}
}
/// <summary>
/// 尝试备份配置
/// </summary>
/// <param name="bakLocalFilePath"></param>
static void TryBackup(string bakLocalFilePath)
{
try
{
var localFilePath = SettingsHostBase.LocalFilePath;
if (File.Exists(localFilePath))
{
File.Copy(localFilePath, bakLocalFilePath, true);
}
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryBackUp");
}
}
/// <summary>
/// 尝试还原备份配置,返回是否有备份文件
/// </summary>
/// <param name="bakLocalFilePath"></param>
/// <returns></returns>
static bool TryRestoreBackup(string bakLocalFilePath)
{
try
{
var exists = File.Exists(bakLocalFilePath);
if (exists)
{
var localFilePath = SettingsHostBase.LocalFilePath;
File.Copy(bakLocalFilePath, localFilePath, true);
}
return exists;
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryRestoreBackup");
}
return false;
}
/// <summary>
/// 尝试删除配置
/// </summary>
static void TryDelete()
{
try
{
var localFilePath = SettingsHostBase.LocalFilePath;
if (File.Exists(localFilePath))
{
File.Delete(localFilePath);
}
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), ex, "Config TryDelete");
}
}
public static void Load()
{
var isLoad = false;
var bakLocalFilePath = $"{SettingsHostBase.LocalFilePath}.bak";
try
{
SettingsHostBase.Local.Load();
isLoad = true;
TryBackup(bakLocalFilePath);
}
catch (Exception ex)
{
Log.Error(nameof(SettingsHost), "Config Load", ex);
if (!TryRestoreBackup(bakLocalFilePath))
{
// 还原备份文件失败,删除当前配置
TryDelete();
}
File.Delete(SettingsHostBase.LocalFilePath);
SettingsHostBase.Local.Load();
Log.Error(nameof(SettingsHost), ex, $"Config Load, isLoad: {isLoad}");
if (!isLoad) SettingsHostBase.Local.Load();
}
}
}
@@ -85,5 +159,6 @@ public abstract class SettingsHost2<TSettings> : SettingsHostBase where TSetting
static string GetKey(string propertyName) => $"{CategoryName}.{propertyName}";
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave, [CallerMemberName] string propertyName = "") => GetProperty(GetKey, Local, defaultValue, autoSave, propertyName);
}
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave = true, [CallerMemberName] string propertyName = "") => GetProperty(GetKey, Local, defaultValue, autoSave, propertyName);
}
#endif
@@ -0,0 +1,168 @@
#if DBREEZE
using DBreeze;
using System.ComponentModel;
using System.Diagnostics;
using static System.Application.Settings.ISerializableProperty;
namespace System.Application.Settings;
public interface ISerializableProperty : INotifyPropertyChanged
{
public const string tableName = "SerializableProperty";
}
[DebuggerDisplay("Value={Value}, Key={Key}, Default={Default}")]
public sealed class SerializableProperty<T> : ISerializableProperty, INotifyPropertyChanged
{
T? _value;
bool _cached;
DBreezeEngine? _Provider;
public string Key { get; }
public DBreezeEngine Provider { get => _Provider ?? throw new ArgumentNullException(nameof(_Provider)); set => _Provider = value; }
public T? Default { get; }
public T? Value
{
get
{
if (!_cached)
{
{
using var t = Provider.GetTransaction();
var row = t.Select<string, byte[]>(tableName, Key);
if (row?.Value == null)
{
_value = Default;
}
else
{
try
{
_value = Serializable.DMP<T>(row.Value);
}
catch
{
_value = Default;
}
}
}
_cached = true;
}
return _value;
}
set
{
var comparer = EqualityComparer<T?>.Default;
if (_cached && comparer.Equals(_value, value)) return;
var old = _value;
_value = value;
_cached = true;
SetValue(comparer, old, value);
}
}
void SetValue(EqualityComparer<T?> comparer, T? oldValue, T? newValue)
{
{
using var t = Provider.GetTransaction();
if (comparer.Equals(newValue, Default))
t.RemoveKey(tableName, Key);
else
t.Insert(tableName, Key, Serializable.SMP(newValue));
t.Commit();
}
OnValueChanged(oldValue, newValue);
}
public override string ToString() => Value?.ToString() ?? string.Empty;
public void RaiseValueChanged()
{
var comparer = EqualityComparer<T?>.Default;
SetValue(comparer, _value, _value);
}
public SerializableProperty(string key, DBreezeEngine provider) : this(key, provider, default)
{
}
public SerializableProperty(string key, DBreezeEngine provider, T? defaultValue)
{
Key = key;
Provider = provider;
Default = defaultValue;
}
public IDisposable Subscribe(Action<T?> listener, bool notifyOnInitialValue = true)
{
if (notifyOnInitialValue)
listener(Value);
return new ValueChangedEventListener(this, listener);
}
public void Reset()
{
var comparer = EqualityComparer<T?>.Default;
SetValue(comparer, _value, Default);
}
sealed class ValueChangedEventListener : IDisposable
{
private readonly Action<T?> _listener;
private readonly SerializableProperty<T> _source;
public ValueChangedEventListener(SerializableProperty<T> property, Action<T?> listener)
{
_listener = listener;
_source = property;
_source.ValueChanged += HandleValueChanged;
}
private void HandleValueChanged(object? sender, ValueChangedEventArgs<T?> args)
{
_listener(args.NewValue);
}
public void Dispose()
{
_source.ValueChanged -= HandleValueChanged;
}
}
public static implicit operator T?(SerializableProperty<T> property) => property.Value;
#region events
public event EventHandler<ValueChangedEventArgs<T?>>? ValueChanged;
void OnValueChanged(T? oldValue, T? newValue) => ValueChanged?.Invoke(this, new ValueChangedEventArgs<T?>(oldValue, newValue));
readonly Dictionary<PropertyChangedEventHandler, EventHandler<ValueChangedEventArgs<T>>> _handlers = new();
event PropertyChangedEventHandler? INotifyPropertyChanged.PropertyChanged
{
add
{
if (value == null) return;
ValueChanged += _handlers[value] = (sender, args) => value(sender, new PropertyChangedEventArgs(nameof(Value)));
}
remove
{
if (value == null) return;
if (_handlers.TryGetValue(value, out var handler))
{
ValueChanged -= handler;
_handlers.Remove(value);
}
}
}
#endregion
}
#endif
@@ -0,0 +1,28 @@
#if DBREEZE
using System.Runtime.CompilerServices;
namespace System.Application.Settings;
public static class SettingsHost
{
public static void Load() => SettingsProviderV3.Load();
[Obsolete]
public static void Save()
{
}
}
public abstract class SettingsHost2<TSettings> where TSettings : SettingsHost2<TSettings>, new()
{
static readonly string CategoryName = typeof(TSettings).Name;
static string GetKey(string propertyName) => $"{CategoryName}.{propertyName}";
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, [CallerMemberName] string propertyName = "") => new(GetKey(propertyName), SettingsProviderV3.Provider, defaultValue);
[Obsolete("autoSave N/A")]
public static SerializableProperty<T> GetProperty<T>(T? defaultValue, bool autoSave, [CallerMemberName] string propertyName = "") => new(GetKey(propertyName), SettingsProviderV3.Provider, defaultValue);
}
#endif
@@ -0,0 +1,90 @@
#if DBREEZE
using DBreeze;
using DBreeze.Utils;
namespace System.Application.Settings;
public static class SettingsProviderV3
{
static DBreezeEngine? _Provider;
static readonly object lock_load = new();
public static DBreezeEngine Provider
{
get
{
if (_Provider == null) Load();
return _Provider ?? throw new ArgumentNullException(nameof(_Provider));
}
set => _Provider = value;
}
public static void Load()
{
lock (lock_load)
{
if (_Provider == null)
{
_Provider = new(Path.Combine(IOPath.AppDataDirectory, "Config"));
//Setting up NetJSON serializer (from NuGet) to be used by DBreeze
CustomSerializator.ByteArraySerializator = value => Serializable.SMP(value == null ? typeof(object) : value.GetType(), value!);
CustomSerializator.ByteArrayDeSerializator = (buffer, type) => Serializable.DMP(type, buffer);
}
}
}
/// <summary>
/// 将数据从
/// <para>使用 <see cref="IDictionary{TKey, TValue}"/> + <see cref="MessagePack"/> 单文件 的 FileSettingsProvider</para>
/// <para>迁移到</para>
/// <para>使用 DBreeze 的 SettingsProviderV3</para>
/// </summary>
public static void Migrate()
{
var filePath = Path.Combine(IOPath.AppDataDirectory, "Config" + FileEx.MPO);
bool exists = false;
try
{
exists = File.Exists(filePath);
}
catch
{
}
if (exists)
{
try
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
if (stream.Position > 0)
{
stream.Position = 0;
}
var source = stream.Length == 0 ? null : Serializable.DMP<IDictionary<string, object?>>(stream);
if (source.Any_Nullable())
{
if (_Provider == null) Load();
using var t = Provider.GetTransaction();
foreach (var item in source)
{
if (item.Value == null) continue;
var valueType = item.Value.GetType();
var value = Serializable.SMP(valueType, item.Value);
t.Insert(ISerializableProperty.tableName, item.Key, value);
}
t.Commit();
}
}
catch
{
}
finally
{
IOPath.FileTryDelete(filePath);
}
}
}
}
#endif
@@ -1,6 +1,6 @@
namespace System.Application.Settings;
public sealed class ValueChangedEventArgs<T> : EventArgs where T : notnull
public sealed class ValueChangedEventArgs<T> : EventArgs
{
public T? OldValue { get; }
+1
View File
@@ -20,6 +20,7 @@
<PackageReference Include="gfoidl.Base64" />
<PackageReference Include="MessagePack" />
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="DBreeze" Condition=" $(DefineConstants.Contains('DBREEZE')) " />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) ">
+29
View File
@@ -0,0 +1,29 @@
using System.Runtime.CompilerServices;
namespace System;
public static class Convert2
{
/// <summary>
/// Converts the specified string, which encodes binary data as hex characters, to an equivalent 8-bit unsigned integer array.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <returns>An array of 8-bit unsigned integers that is equivalent to s.</returns>
#if HEXMATE || NET5_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
public static byte[] FromHexString(string s)
#if HEXMATE
=> HexMate.Convert.FromHexString(s);
#elif NET5_0_OR_GREATER
=> Convert.FromHexString(s);
#else
{
var bytes = new byte[s.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(s.Substring(i * 2, 2), 16);
}
}
#endif
}
+2 -8
View File
@@ -77,10 +77,7 @@ public static partial class DI
/// <inheritdoc cref="Get{T}"/>
public static T? Get_Nullable<T>() where T : notnull
{
if (value == null)
{
throw GetDIGetFailException(typeof(T));
}
if (value == null) return default;
return value.GetService<T>();
}
@@ -97,10 +94,7 @@ public static partial class DI
/// <inheritdoc cref="Get_Nullable{T}"/>
public static object? Get_Nullable(Type serviceType)
{
if (value == null)
{
throw GetDIGetFailException(serviceType);
}
if (value == null) return default;
return value.GetService(serviceType);
}
@@ -34,4 +34,23 @@ public static class ProcessExtensions
process.Kill();
#endif
}
/// <summary>
/// 尝试 Process 组件在指定的毫秒数内等待关联进程退出。
/// </summary>
/// <param name="process"></param>
/// <param name="milliseconds"></param>
/// <returns></returns>
public static bool TryWaitForExit(this Process process, int milliseconds = 9000)
{
try
{
return process.WaitForExit(milliseconds);
}
catch
{
}
return false;
}
}
@@ -3,11 +3,11 @@ namespace System;
public static partial class StringExtensions
{
public static string TrimStart(this string s, string trimString)
public static string TrimStart(this string s, string value)
{
if (trimString.StartsWith(trimString))
if (s.StartsWith(value))
{
return s[trimString.Length..];
return s[value.Length..];
}
else
{
@@ -15,11 +15,11 @@ public static partial class StringExtensions
}
}
public static string TrimEnd(this string s, string trimString)
public static string TrimEnd(this string s, string value)
{
if (trimString.EndsWith(trimString))
if (s.EndsWith(value))
{
return s[..^trimString.Length];
return s[..^value.Length];
}
else
{
@@ -27,11 +27,11 @@ public static partial class StringExtensions
}
}
public static string TrimStart(this string s, string trimString, StringComparison comparisonType)
public static string TrimStart(this string s, string value, StringComparison comparisonType)
{
if (trimString.StartsWith(trimString, comparisonType))
if (s.StartsWith(value, comparisonType))
{
return s[trimString.Length..];
return s[value.Length..];
}
else
{
@@ -39,11 +39,11 @@ public static partial class StringExtensions
}
}
public static string TrimEnd(this string s, string trimString, StringComparison comparisonType)
public static string TrimEnd(this string s, string value, StringComparison comparisonType)
{
if (trimString.EndsWith(trimString, comparisonType))
if (s.EndsWith(value, comparisonType))
{
return s[..^trimString.Length];
return s[..^value.Length];
}
else
{
+5
View File
@@ -132,6 +132,11 @@ public static class FileEx
public const string Qt = ".qt";
public const string Wmv = ".wmv";
/// <summary>
/// 导入注册条目 (.reg) 文件是 Regedit.exe 的功能,Regedt32.exe 不支持。您可以使用 Regedit.exe 对基于 Windows NT 4.0 或基于 Windows 2000 的计算机上注册表进行一些更改,但某些更改需要 Regedt32.exe。
/// </summary>
public const string Reg = ".reg";
public static readonly string[] ImageFileExtensions = new string[]
{
PNG,
+126 -126
View File
@@ -10,43 +10,43 @@ namespace HexMate;
static class Convert
{
// /// <summary>
// /// Converts the specified string, which encodes binary data as hex characters, to an equivalent 8-bit unsigned integer array.
// /// </summary>
// /// <param name="s">The string to convert.</param>
// /// <returns>An array of 8-bit unsigned integers that is equivalent to <paramref name="s"/>.</returns>
// /// <exception cref="ArgumentNullException"><paramref name="s"/> is <code>null</code>.</exception>
// /// <exception cref="FormatException">The length of <paramref name="s"/>, ignoring white-space characters, is not zero or a multiple of 2.</exception>
// /// <exception cref="FormatException">The format of <paramref name="s"/> is invalid. <paramref name="s"/> contains a non-hex character.</exception>
// public static byte[] FromHexString(string s)
// {
// if (s == null)
// throw new ArgumentNullException(nameof(s));
// if (s.Length == 0)
// return Array.Empty<byte>();
/// <summary>
/// Converts the specified string, which encodes binary data as hex characters, to an equivalent 8-bit unsigned integer array.
/// </summary>
/// <param name="s">The string to convert.</param>
/// <returns>An array of 8-bit unsigned integers that is equivalent to <paramref name="s"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="s"/> is <code>null</code>.</exception>
/// <exception cref="FormatException">The length of <paramref name="s"/>, ignoring white-space characters, is not zero or a multiple of 2.</exception>
/// <exception cref="FormatException">The format of <paramref name="s"/> is invalid. <paramref name="s"/> contains a non-hex character.</exception>
public static byte[] FromHexString(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
if (s.Length == 0)
return Array.Empty<byte>();
// unsafe
// {
// fixed (char* inPtr = s)
// {
// var resultLength = FromHex_ComputeResultLength(inPtr, s.Length);
//#if NET5_0_OR_GREATER
// var result = GC.AllocateUninitializedArray<byte>(resultLength);
//#else
// var result = new byte[resultLength];
//#endif
// fixed (byte* outPtr = result)
// {
// var res = ConvertFromHexArray(outPtr, result.Length, inPtr, s.Length);
// if (res < 0)
// throw new FormatException(SR.Format_BadHexChar);
// Debug.Assert(res == result.Length);
// }
unsafe
{
fixed (char* inPtr = s)
{
var resultLength = FromHex_ComputeResultLength(inPtr, s.Length);
#if NET5_0_OR_GREATER
var result = GC.AllocateUninitializedArray<byte>(resultLength);
#else
var result = new byte[resultLength];
#endif
fixed (byte* outPtr = result)
{
var res = ConvertFromHexArray(outPtr, result.Length, inPtr, s.Length);
if (res < 0)
throw new FormatException(SR.Format_BadHexChar);
Debug.Assert(res == result.Length);
}
// return result;
// }
// }
// }
return result;
}
}
}
/// <summary>
/// Converts an array of 8-bit unsigned integers to its equivalent string representation that is encoded with hex characters.
@@ -251,108 +251,108 @@ static class Convert
return false;
}
// private static unsafe int FromHex_ComputeResultLength(char* inputPtr, int inputLength)
// => CharHelper.CountUsefulCharacters(inputPtr, inputLength) / 2;
private static unsafe int FromHex_ComputeResultLength(char* inputPtr, int inputLength)
=> CharHelper.CountUsefulCharacters(inputPtr, inputLength) / 2;
// private static unsafe int ConvertFromHexArray(byte* outData, int outLength, char* inChars, int inLength)
// {
// Debug.Assert(inLength != 0);
// if (inLength == 1)
// {
// return errInvalidData;
// }
private static unsafe int ConvertFromHexArray(byte* outData, int outLength, char* inChars, int inLength)
{
Debug.Assert(inLength != 0);
if (inLength == 1)
{
return errInvalidData;
}
// var charsToRead = inLength;
// var remainingIn = charsToRead;
// var bytesToWrite = outLength;
// var remainingOut = bytesToWrite;
// var src = inChars;
// var last = src;
// var srcEnd = src + inLength;
// var dest = outData;
var charsToRead = inLength;
var remainingIn = charsToRead;
var bytesToWrite = outLength;
var remainingOut = bytesToWrite;
var src = inChars;
var last = src;
var srcEnd = src + inLength;
var dest = outData;
// while (remainingOut > 0)
// {
//#if NETCOREAPP3_0_OR_GREATER
// // Ignore errors in the SIMD part, and handle them in scalar part below
// if (Avx2.IsSupported && remainingIn >= 64 && remainingOut >= 32)
// {
// Utf16HexParser.Avx2.TryParse(ref src, ref dest, remainingOut);
// remainingIn = charsToRead - (int)(src - inChars);
// remainingOut = bytesToWrite - (int)(dest - outData);
// }
while (remainingOut > 0)
{
#if NETCOREAPP3_0_OR_GREATER
// Ignore errors in the SIMD part, and handle them in scalar part below
if (Avx2.IsSupported && remainingIn >= 64 && remainingOut >= 32)
{
Utf16HexParser.Avx2.TryParse(ref src, ref dest, remainingOut);
remainingIn = charsToRead - (int)(src - inChars);
remainingOut = bytesToWrite - (int)(dest - outData);
}
// if (remainingIn >= 32 && remainingOut >= 16)
// {
// if (Ssse3.IsSupported)
// {
// Utf16HexParser.Ssse3.TryParse(ref src, ref dest, remainingOut);
// remainingIn = charsToRead - (int)(src - inChars);
// remainingOut = bytesToWrite - (int)(dest - outData);
// }
// else if (Sse2.IsSupported)
// {
// Utf16HexParser.Sse2.TryParse(ref src, ref dest, remainingOut);
// remainingIn = charsToRead - (int)(src - inChars);
// remainingOut = bytesToWrite - (int)(dest - outData);
// }
// }
//#endif
//#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
// if (!Utf16HexParser.Span.TryParse(ref src, remainingIn, ref dest, remainingOut))
//#else
// if (!Utf16HexParser.Fixed.TryParse(ref src, remainingIn, ref dest, remainingOut))
//#endif
// {
// goto InvalidData;
// }
// remainingIn = charsToRead - (int)(src - inChars);
// remainingOut = bytesToWrite - (int)(dest - outData);
if (remainingIn >= 32 && remainingOut >= 16)
{
if (Ssse3.IsSupported)
{
Utf16HexParser.Ssse3.TryParse(ref src, ref dest, remainingOut);
remainingIn = charsToRead - (int)(src - inChars);
remainingOut = bytesToWrite - (int)(dest - outData);
}
else if (Sse2.IsSupported)
{
Utf16HexParser.Sse2.TryParse(ref src, ref dest, remainingOut);
remainingIn = charsToRead - (int)(src - inChars);
remainingOut = bytesToWrite - (int)(dest - outData);
}
}
#endif
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
if (!Utf16HexParser.Span.TryParse(ref src, remainingIn, ref dest, remainingOut))
#else
if (!Utf16HexParser.Fixed.TryParse(ref src, remainingIn, ref dest, remainingOut))
#endif
{
goto InvalidData;
}
remainingIn = charsToRead - (int)(src - inChars);
remainingOut = bytesToWrite - (int)(dest - outData);
// if (src >= srcEnd)
// {
// goto Ok;
// }
if (src >= srcEnd)
{
goto Ok;
}
// if (src == last)
// {
// // No progress == invalid data
// goto InvalidData;
// }
if (src == last)
{
// No progress == invalid data
goto InvalidData;
}
// last = src;
// }
last = src;
}
// // No more space in destination
// No more space in destination
// if (src < srcEnd)
// {
// while (IsWhitespace(*src))
// {
// // Skip past any consecutive trailing white-space in the input
// if (++src >= srcEnd)
// {
// goto Ok;
// }
// }
if (src < srcEnd)
{
while (IsWhitespace(*src))
{
// Skip past any consecutive trailing white-space in the input
if (++src >= srcEnd)
{
goto Ok;
}
}
// if (IsValid(*src))
// {
// goto OutLenTooShort;
// }
// else
// {
// goto InvalidData;
// }
// }
if (IsValid(*src))
{
goto OutLenTooShort;
}
else
{
goto InvalidData;
}
}
// Ok:
// return (int)(dest - outData);
Ok:
return (int)(dest - outData);
// InvalidData:
// return errInvalidData;
InvalidData:
return errInvalidData;
// OutLenTooShort:
// return errDestTooShort;
// }
OutLenTooShort:
return errDestTooShort;
}
}
+61 -61
View File
@@ -1,76 +1,76 @@
//using System.Diagnostics;
//#if NETCOREAPP3_0_OR_GREATER
//using System.Numerics;
//using System.Runtime.Intrinsics;
//using System.Runtime.Intrinsics.X86;
//#endif
using System.Diagnostics;
#if NETCOREAPP3_0_OR_GREATER
using System.Numerics;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
#endif
//namespace HexMate;
namespace HexMate;
//internal static unsafe class CharHelper
//{
// internal static int CountUsefulCharacters(char* inputPtr, int inputLength)
// {
// Debug.Assert(inputLength > 0);
internal static unsafe class CharHelper
{
internal static int CountUsefulCharacters(char* inputPtr, int inputLength)
{
Debug.Assert(inputLength > 0);
// // All characters above ' ' (space) are considered useful, as it is good enough, if this method
// // returns an upper bound on the number of bytes encoded in the given input.
// var byteLength = inputLength * 2;
// var usefulCharacters = 0;
//#if NETCOREAPP3_0_OR_GREATER
// var byteSrc = (byte*)inputPtr;
// All characters above ' ' (space) are considered useful, as it is good enough, if this method
// returns an upper bound on the number of bytes encoded in the given input.
var byteLength = inputLength * 2;
var usefulCharacters = 0;
#if NETCOREAPP3_0_OR_GREATER
var byteSrc = (byte*)inputPtr;
// if (Avx2.IsSupported && byteLength >= 32)
// {
// var space = Vector256.Create(' ').AsInt16();
// var bytesToProcess = FastMath.RoundDownTo32(byteLength);
// var end = byteSrc + bytesToProcess;
// while (byteSrc != end)
// {
// var input = Avx.LoadVector256(byteSrc).AsInt16();
if (Avx2.IsSupported && byteLength >= 32)
{
var space = Vector256.Create(' ').AsInt16();
var bytesToProcess = FastMath.RoundDownTo32(byteLength);
var end = byteSrc + bytesToProcess;
while (byteSrc != end)
{
var input = Avx.LoadVector256(byteSrc).AsInt16();
// var cnt = Avx2.CompareGreaterThan(input, space);
// var mask = (uint)Avx2.MoveMask(cnt.AsByte());
// usefulCharacters += BitOperations.PopCount(mask) >> 1;
var cnt = Avx2.CompareGreaterThan(input, space);
var mask = (uint)Avx2.MoveMask(cnt.AsByte());
usefulCharacters += BitOperations.PopCount(mask) >> 1;
// byteSrc += 32;
// }
byteSrc += 32;
}
// byteLength -= bytesToProcess;
// }
byteLength -= bytesToProcess;
}
// if (Sse2.IsSupported && byteLength >= 16)
// {
// var space = Vector128.Create(' ').AsInt16();
// var bytesToProcess = FastMath.RoundDownTo16(byteLength);
// var end = byteSrc + bytesToProcess;
// while (byteSrc != end)
// {
// var input = Sse2.LoadVector128(byteSrc).AsInt16();
if (Sse2.IsSupported && byteLength >= 16)
{
var space = Vector128.Create(' ').AsInt16();
var bytesToProcess = FastMath.RoundDownTo16(byteLength);
var end = byteSrc + bytesToProcess;
while (byteSrc != end)
{
var input = Sse2.LoadVector128(byteSrc).AsInt16();
// var cnt = Sse2.CompareGreaterThan(input, space);
// var mask = (uint)Sse2.MoveMask(cnt.AsByte());
// usefulCharacters += BitOperations.PopCount(mask) >> 1;
var cnt = Sse2.CompareGreaterThan(input, space);
var mask = (uint)Sse2.MoveMask(cnt.AsByte());
usefulCharacters += BitOperations.PopCount(mask) >> 1;
// byteSrc += 16;
// }
byteSrc += 16;
}
// byteLength -= bytesToProcess;
// }
byteLength -= bytesToProcess;
}
// inputPtr = (char*)byteSrc;
//#endif
// const uint intSpace = ' ';
inputPtr = (char*)byteSrc;
#endif
const uint intSpace = ' ';
// var charEnd = inputPtr + (byteLength / 2);
// while (inputPtr < charEnd)
// {
// uint c = *inputPtr++;
var charEnd = inputPtr + (byteLength / 2);
while (inputPtr < charEnd)
{
uint c = *inputPtr++;
// if (c > intSpace)
// usefulCharacters++;
// }
if (c > intSpace)
usefulCharacters++;
}
// return usefulCharacters;
// }
//}
return usefulCharacters;
}
}
@@ -1,130 +1,130 @@
//#if NETCOREAPP3_0_OR_GREATER
#if NETCOREAPP3_0_OR_GREATER
//using System.Diagnostics;
//using System.Runtime.CompilerServices;
//using System.Runtime.Intrinsics;
//using static HexMate.VectorConstants;
//using static HexMate.VectorUtils;
//using static System.Runtime.Intrinsics.X86.Avx;
//using static System.Runtime.Intrinsics.X86.Avx2;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using static HexMate.VectorConstants;
using static HexMate.VectorUtils;
using static System.Runtime.Intrinsics.X86.Avx;
using static System.Runtime.Intrinsics.X86.Avx2;
//namespace HexMate;
namespace HexMate;
//internal static partial class Utf16HexParser
//{
// internal static unsafe class Avx2
// {
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// internal static bool TryParse(ref char* srcBytes, ref byte* destBytes, int destLength)
// {
// Debug.Assert(System.Runtime.Intrinsics.X86.Avx2.IsSupported);
internal static partial class Utf16HexParser
{
internal static unsafe class Avx2
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryParse(ref char* srcBytes, ref byte* destBytes, int destLength)
{
Debug.Assert(System.Runtime.Intrinsics.X86.Avx2.IsSupported);
// var x0F = Vector256.Create((byte)0x0F);
// var xF0 = Vector256.Create((byte)0xF0);
// var digHexSelector = ReadVector256(s_upperLowerDigHexSelector);
// var digits = ReadVector256(s_digits);
// var hexs = ReadVector256(s_hexs);
// var evenBytes = ReadVector256(s_evenBytes);
// var oddBytes = ReadVector256(s_oddBytes);
// var src = (byte*)srcBytes;
// var dest = destBytes;
var x0F = Vector256.Create((byte)0x0F);
var xF0 = Vector256.Create((byte)0xF0);
var digHexSelector = ReadVector256(s_upperLowerDigHexSelector);
var digits = ReadVector256(s_digits);
var hexs = ReadVector256(s_hexs);
var evenBytes = ReadVector256(s_evenBytes);
var oddBytes = ReadVector256(s_oddBytes);
var src = (byte*)srcBytes;
var dest = destBytes;
// var target = dest + FastMath.RoundDownTo32(destLength);
// int leftOk, rightOk;
// while (dest != target)
// {
// var a = LoadVector256(src).AsInt16();
// src += 32;
// var b = LoadVector256(src).AsInt16();
// src += 32;
// var c = LoadVector256(src).AsInt16();
// src += 32;
// var d = LoadVector256(src).AsInt16();
// src += 32;
var target = dest + FastMath.RoundDownTo32(destLength);
int leftOk, rightOk;
while (dest != target)
{
var a = LoadVector256(src).AsInt16();
src += 32;
var b = LoadVector256(src).AsInt16();
src += 32;
var c = LoadVector256(src).AsInt16();
src += 32;
var d = LoadVector256(src).AsInt16();
src += 32;
// var ab = PackUnsignedSaturate(a, b);
// var cd = PackUnsignedSaturate(c, d);
var ab = PackUnsignedSaturate(a, b);
var cd = PackUnsignedSaturate(c, d);
// var inputLeft = Permute4x64(ab.AsUInt64(), 0b11_01_10_00).AsByte();
// var inputRight = Permute4x64(cd.AsUInt64(), 0b11_01_10_00).AsByte();
var inputLeft = Permute4x64(ab.AsUInt64(), 0b11_01_10_00).AsByte();
var inputRight = Permute4x64(cd.AsUInt64(), 0b11_01_10_00).AsByte();
// var loNibbleLeft = And(inputLeft, x0F);
// var loNibbleRight = And(inputRight, x0F);
var loNibbleLeft = And(inputLeft, x0F);
var loNibbleRight = And(inputRight, x0F);
// var hiNibbleLeft = And(inputLeft, xF0);
// var hiNibbleRight = And(inputRight, xF0);
var hiNibbleLeft = And(inputLeft, xF0);
var hiNibbleRight = And(inputRight, xF0);
// var leftDigits = Shuffle(digits, loNibbleLeft);
// var leftHex = Shuffle(hexs, loNibbleLeft);
var leftDigits = Shuffle(digits, loNibbleLeft);
var leftHex = Shuffle(hexs, loNibbleLeft);
// var hiNibbleShLeft = ShiftRightLogical(hiNibbleLeft.AsInt16(), 4).AsByte();
// var hiNibbleShRight = ShiftRightLogical(hiNibbleRight.AsInt16(), 4).AsByte();
var hiNibbleShLeft = ShiftRightLogical(hiNibbleLeft.AsInt16(), 4).AsByte();
var hiNibbleShRight = ShiftRightLogical(hiNibbleRight.AsInt16(), 4).AsByte();
// var rightDigits = Shuffle(digits, loNibbleRight);
// var rightHex = Shuffle(hexs, loNibbleRight);
var rightDigits = Shuffle(digits, loNibbleRight);
var rightHex = Shuffle(hexs, loNibbleRight);
// var magicLeft = Shuffle(digHexSelector, hiNibbleShLeft);
// var magicRight = Shuffle(digHexSelector, hiNibbleShRight);
var magicLeft = Shuffle(digHexSelector, hiNibbleShLeft);
var magicRight = Shuffle(digHexSelector, hiNibbleShRight);
// var valueLeft = BlendVariable(leftDigits, leftHex, magicLeft);
// var valueRight = BlendVariable(rightDigits, rightHex, magicRight);
var valueLeft = BlendVariable(leftDigits, leftHex, magicLeft);
var valueRight = BlendVariable(rightDigits, rightHex, magicRight);
// var errLeft = ShiftLeftLogical(magicLeft.AsInt16(), 7).AsByte();
// var errRight = ShiftLeftLogical(magicRight.AsInt16(), 7).AsByte();
var errLeft = ShiftLeftLogical(magicLeft.AsInt16(), 7).AsByte();
var errRight = ShiftLeftLogical(magicRight.AsInt16(), 7).AsByte();
// var evenBytesLeft = Shuffle(valueLeft, evenBytes);
// var oddBytesLeft = Shuffle(valueLeft, oddBytes);
// var evenBytesRight = Shuffle(valueRight, evenBytes);
// var oddBytesRight = Shuffle(valueRight, oddBytes);
var evenBytesLeft = Shuffle(valueLeft, evenBytes);
var oddBytesLeft = Shuffle(valueLeft, oddBytes);
var evenBytesRight = Shuffle(valueRight, evenBytes);
var oddBytesRight = Shuffle(valueRight, oddBytes);
// evenBytesLeft = ShiftLeftLogical(evenBytesLeft.AsUInt16(), 4).AsByte();
// evenBytesRight = ShiftLeftLogical(evenBytesRight.AsUInt16(), 4).AsByte();
evenBytesLeft = ShiftLeftLogical(evenBytesLeft.AsUInt16(), 4).AsByte();
evenBytesRight = ShiftLeftLogical(evenBytesRight.AsUInt16(), 4).AsByte();
// evenBytesLeft = Or(evenBytesLeft, oddBytesLeft);
// evenBytesRight = Or(evenBytesRight, oddBytesRight);
evenBytesLeft = Or(evenBytesLeft, oddBytesLeft);
evenBytesRight = Or(evenBytesRight, oddBytesRight);
// var result = Merge(evenBytesLeft, evenBytesRight);
var result = Merge(evenBytesLeft, evenBytesRight);
// var validationResultLeft = Or(errLeft, valueLeft);
// var validationResultRight = Or(errRight, valueRight);
var validationResultLeft = Or(errLeft, valueLeft);
var validationResultRight = Or(errRight, valueRight);
// leftOk = MoveMask(validationResultLeft);
// rightOk = MoveMask(validationResultRight);
leftOk = MoveMask(validationResultLeft);
rightOk = MoveMask(validationResultRight);
// if ((leftOk | rightOk) != 0) goto Err;
if ((leftOk | rightOk) != 0) goto Err;
// Store(dest, result);
// dest += 32;
// }
Store(dest, result);
dest += 32;
}
// srcBytes = (char*)src;
// destBytes = dest;
// return true;
srcBytes = (char*)src;
destBytes = dest;
return true;
// Err:
// if (leftOk != 0)
// {
// srcBytes = (char*)(src - 128);
// destBytes = dest;
// return false;
// }
// else
// {
// Debug.Assert(rightOk != 0);
// srcBytes = (char*)(src - 64);
// destBytes = dest;
// return false;
// }
// }
Err:
if (leftOk != 0)
{
srcBytes = (char*)(src - 128);
destBytes = dest;
return false;
}
else
{
Debug.Assert(rightOk != 0);
srcBytes = (char*)(src - 64);
destBytes = dest;
return false;
}
}
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// private static Vector256<byte> Merge(Vector256<byte> a, Vector256<byte> b)
// {
// var a1 = Permute4x64(a.AsUInt64(), 0b11_10_10_00);
// var b1 = Permute4x64(b.AsUInt64(), 0b11_00_01_00);
// return Blend(a1.AsUInt32(), b1.AsUInt32(), 0b1111_0000).AsByte();
// }
// }
//}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vector256<byte> Merge(Vector256<byte> a, Vector256<byte> b)
{
var a1 = Permute4x64(a.AsUInt64(), 0b11_10_10_00);
var b1 = Permute4x64(b.AsUInt64(), 0b11_00_01_00);
return Blend(a1.AsUInt32(), b1.AsUInt32(), 0b1111_0000).AsByte();
}
}
}
//#endif
#endif
@@ -1,60 +1,60 @@
//using System.Runtime.CompilerServices;
//using static HexMate.ScalarConstants;
using System.Runtime.CompilerServices;
using static HexMate.ScalarConstants;
//namespace HexMate;
namespace HexMate;
//internal static partial class Utf16HexParser
//{
// internal static unsafe class Fixed
// {
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// internal static bool TryParse(ref char* srcBytes, int srcLength, ref byte* destBytes, int destLength)
// {
// var src = srcBytes;
// var dest = destBytes;
internal static partial class Utf16HexParser
{
internal static unsafe class Fixed
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryParse(ref char* srcBytes, int srcLength, ref byte* destBytes, int destLength)
{
var src = srcBytes;
var dest = destBytes;
// var srcTarget = src + srcLength;
// var destTarget = dest + destLength;
var srcTarget = src + srcLength;
var destTarget = dest + destLength;
// fixed (byte* lut = LookupUpperLower)
// {
// int hi, lo;
// while (srcTarget > src && destTarget > dest)
// {
// ReadHi:
// int valHi = *src++;
// if (valHi > 0xFF) { goto Err; }
// hi = lut[valHi];
// if (hi >= 0xFE)
// {
// if (hi == 0xFF) goto Err;
// if (srcTarget > src) goto ReadHi; // skip whitespace
// }
// *dest |= (byte)(hi << 4);
fixed (byte* lut = LookupUpperLower)
{
int hi, lo;
while (srcTarget > src && destTarget > dest)
{
ReadHi:
int valHi = *src++;
if (valHi > 0xFF) { goto Err; }
hi = lut[valHi];
if (hi >= 0xFE)
{
if (hi == 0xFF) goto Err;
if (srcTarget > src) goto ReadHi; // skip whitespace
}
*dest |= (byte)(hi << 4);
// ReadLo:
// int valLo = *src++;
// if (valLo > 0xFF) goto Err;
// lo = lut[valLo];
// if (lo >= 0xFE)
// {
// if (lo == 0xFF) goto Err;
// if (srcTarget > src) goto ReadLo; // skip whitespace
// }
// *dest |= (byte)lo;
ReadLo:
int valLo = *src++;
if (valLo > 0xFF) goto Err;
lo = lut[valLo];
if (lo >= 0xFE)
{
if (lo == 0xFF) goto Err;
if (srcTarget > src) goto ReadLo; // skip whitespace
}
*dest |= (byte)lo;
// dest++;
// }
// }
dest++;
}
}
// srcBytes = src;
// destBytes = dest;
// return true;
srcBytes = src;
destBytes = dest;
return true;
// Err:
// srcBytes = src - 1;
// destBytes = dest;
// return false;
// }
// }
//}
Err:
srcBytes = src - 1;
destBytes = dest;
return false;
}
}
}
@@ -1,61 +1,61 @@
//#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1_OR_GREATER
//using System.Runtime.CompilerServices;
//using static HexMate.ScalarConstants;
using System.Runtime.CompilerServices;
using static HexMate.ScalarConstants;
//namespace HexMate;
namespace HexMate;
//internal static partial class Utf16HexParser
//{
// internal static unsafe class Span
// {
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// internal static bool TryParse(ref char* srcBytes, int srcLength, ref byte* destBytes, int destLength)
// {
// var src = srcBytes;
// var dest = destBytes;
internal static partial class Utf16HexParser
{
internal static unsafe class Span
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryParse(ref char* srcBytes, int srcLength, ref byte* destBytes, int destLength)
{
var src = srcBytes;
var dest = destBytes;
// var srcTarget = src + srcLength;
// var destTarget = dest + destLength;
var srcTarget = src + srcLength;
var destTarget = dest + destLength;
// int hi, lo;
// while (srcTarget > src && destTarget > dest)
// {
// ReadHi:
// int valHi = *src++;
// if (valHi > 0xFF) { goto Err; }
// hi = LookupUpperLower[valHi];
// if (hi >= 0xFE)
// {
// if (hi == 0xFF) goto Err;
// if (srcTarget > src) goto ReadHi;
// }
// *dest |= (byte)(hi << 4);
int hi, lo;
while (srcTarget > src && destTarget > dest)
{
ReadHi:
int valHi = *src++;
if (valHi > 0xFF) { goto Err; }
hi = LookupUpperLower[valHi];
if (hi >= 0xFE)
{
if (hi == 0xFF) goto Err;
if (srcTarget > src) goto ReadHi;
}
*dest |= (byte)(hi << 4);
// ReadLo:
// int valLo = *src++;
// if (valLo > 0xFF) goto Err;
// lo = LookupUpperLower[valLo];
// if (lo >= 0xFE)
// {
// if (lo == 0xFF) goto Err;
// if (srcTarget > src) goto ReadLo;
// }
// *dest |= (byte)lo;
ReadLo:
int valLo = *src++;
if (valLo > 0xFF) goto Err;
lo = LookupUpperLower[valLo];
if (lo >= 0xFE)
{
if (lo == 0xFF) goto Err;
if (srcTarget > src) goto ReadLo;
}
*dest |= (byte)lo;
// dest++;
// }
dest++;
}
// srcBytes = src;
// destBytes = dest;
// return true;
srcBytes = src;
destBytes = dest;
return true;
// Err:
// srcBytes = src - 1;
// destBytes = dest;
// return false;
// }
// }
//}
Err:
srcBytes = src - 1;
destBytes = dest;
return false;
}
}
}
//#endif
#endif
@@ -1,142 +1,142 @@
//#if NETCOREAPP3_0_OR_GREATER
#if NETCOREAPP3_0_OR_GREATER
//using System.Diagnostics;
//using System.Runtime.CompilerServices;
//using System.Runtime.Intrinsics;
//using static System.Runtime.Intrinsics.X86.Sse2;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using static System.Runtime.Intrinsics.X86.Sse2;
//namespace HexMate;
namespace HexMate;
//internal static partial class Utf16HexParser
//{
// internal static unsafe class Sse2
// {
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// internal static bool TryParse(ref char* srcBytes, ref byte* destBytes, int destLength)
// {
// Debug.Assert(System.Runtime.Intrinsics.X86.Sse2.IsSupported);
internal static partial class Utf16HexParser
{
internal static unsafe class Sse2
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryParse(ref char* srcBytes, ref byte* destBytes, int destLength)
{
Debug.Assert(System.Runtime.Intrinsics.X86.Sse2.IsSupported);
// var x05 = Vector128.Create((byte)0x05);
// var x09 = Vector128.Create((byte)0x09);
// var x0A = Vector128.Create((byte)0x0A);
// var x20 = Vector128.Create((byte)0x20);
// var x30 = Vector128.Create((byte)0x30);
// var x40 = Vector128.Create((byte)0x40);
// var x41 = Vector128.Create((byte)0x41);
// var x60 = Vector128.Create((byte)0x60);
// var xFF = Vector128.Create((byte)0xFF);
// var src = (byte*)srcBytes;
// var dest = destBytes;
var x05 = Vector128.Create((byte)0x05);
var x09 = Vector128.Create((byte)0x09);
var x0A = Vector128.Create((byte)0x0A);
var x20 = Vector128.Create((byte)0x20);
var x30 = Vector128.Create((byte)0x30);
var x40 = Vector128.Create((byte)0x40);
var x41 = Vector128.Create((byte)0x41);
var x60 = Vector128.Create((byte)0x60);
var xFF = Vector128.Create((byte)0xFF);
var src = (byte*)srcBytes;
var dest = destBytes;
// var target = dest + FastMath.RoundDownTo16(destLength);
// int leftOk, rightOk;
// while (dest != target)
// {
// var a = LoadVector128(src).AsInt16();
// src += 16;
// var b = LoadVector128(src).AsInt16();
// src += 16;
// var c = LoadVector128(src).AsInt16();
// src += 16;
// var d = LoadVector128(src).AsInt16();
// src += 16;
var target = dest + FastMath.RoundDownTo16(destLength);
int leftOk, rightOk;
while (dest != target)
{
var a = LoadVector128(src).AsInt16();
src += 16;
var b = LoadVector128(src).AsInt16();
src += 16;
var c = LoadVector128(src).AsInt16();
src += 16;
var d = LoadVector128(src).AsInt16();
src += 16;
// var inputLeft = PackUnsignedSaturate(a, b);
// var inputRight = PackUnsignedSaturate(c, d);
var inputLeft = PackUnsignedSaturate(a, b);
var inputRight = PackUnsignedSaturate(c, d);
// var g40Left = CompareGreaterThan(inputLeft.AsSByte(), x40.AsSByte()).AsByte();
// var g60Left = CompareGreaterThan(inputLeft.AsSByte(), x60.AsSByte()).AsByte();
// var g40Right = CompareGreaterThan(inputRight.AsSByte(), x40.AsSByte()).AsByte();
// var g60Right = CompareGreaterThan(inputRight.AsSByte(), x60.AsSByte()).AsByte();
var g40Left = CompareGreaterThan(inputLeft.AsSByte(), x40.AsSByte()).AsByte();
var g60Left = CompareGreaterThan(inputLeft.AsSByte(), x60.AsSByte()).AsByte();
var g40Right = CompareGreaterThan(inputRight.AsSByte(), x40.AsSByte()).AsByte();
var g60Right = CompareGreaterThan(inputRight.AsSByte(), x60.AsSByte()).AsByte();
// var corr40Left = And(x41, g40Left);
// var corr60Left = And(x20, g60Left);
var corr40Left = And(x41, g40Left);
var corr60Left = And(x20, g60Left);
// var corr40Right = And(x41, g40Right);
// var corr60Right = And(x20, g60Right);
var corr40Right = And(x41, g40Right);
var corr60Right = And(x20, g60Right);
// var sub30Left = Subtract(inputLeft, x30);
// var sub40Left = Subtract(inputLeft, corr40Left);
var sub30Left = Subtract(inputLeft, x30);
var sub40Left = Subtract(inputLeft, corr40Left);
// var sub30Right = Subtract(inputRight, x30);
// var sub40Right = Subtract(inputRight, corr40Right);
var sub30Right = Subtract(inputRight, x30);
var sub40Right = Subtract(inputRight, corr40Right);
// var sub60Left = Subtract(sub40Left, corr60Left);
// var sub60Right = Subtract(sub40Right, corr60Right);
var sub60Left = Subtract(sub40Left, corr60Left);
var sub60Right = Subtract(sub40Right, corr60Right);
// var maskAfLeft = Or(g60Left, g40Left);
// var maskAfRight = Or(g60Right, g40Right);
var maskAfLeft = Or(g60Left, g40Left);
var maskAfRight = Or(g60Right, g40Right);
// var maskDigLeft = Xor(maskAfLeft, xFF);
// var maskDigRight = Xor(maskAfRight, xFF);
var maskDigLeft = Xor(maskAfLeft, xFF);
var maskDigRight = Xor(maskAfRight, xFF);
// var afLeft = And(sub60Left, maskAfLeft);
// var corrAfLeft = And(maskAfLeft, x0A);
var afLeft = And(sub60Left, maskAfLeft);
var corrAfLeft = And(maskAfLeft, x0A);
// var afRight = And(sub60Right, maskAfRight);
// var corrAfRight = And(maskAfRight, x0A);
var afRight = And(sub60Right, maskAfRight);
var corrAfRight = And(maskAfRight, x0A);
// var digLeft = And(sub30Left, maskDigLeft);
// var corrLeft = Add(afLeft, corrAfLeft);
var digLeft = And(sub30Left, maskDigLeft);
var corrLeft = Add(afLeft, corrAfLeft);
// var digRight = And(sub30Right, maskDigRight);
// var corrRight = Add(afRight, corrAfRight);
var digRight = And(sub30Right, maskDigRight);
var corrRight = Add(afRight, corrAfRight);
// var resultAfLeft = CompareGreaterThan(afLeft.AsSByte(), x05.AsSByte()).AsByte();
// var resultDigLeft = CompareGreaterThan(digLeft.AsSByte(), x09.AsSByte()).AsByte();
var resultAfLeft = CompareGreaterThan(afLeft.AsSByte(), x05.AsSByte()).AsByte();
var resultDigLeft = CompareGreaterThan(digLeft.AsSByte(), x09.AsSByte()).AsByte();
// var resultAfRight = CompareGreaterThan(afRight.AsSByte(), x05.AsSByte()).AsByte();
// var resultDigRight = CompareGreaterThan(digRight.AsSByte(), x09.AsSByte()).AsByte();
var resultAfRight = CompareGreaterThan(afRight.AsSByte(), x05.AsSByte()).AsByte();
var resultDigRight = CompareGreaterThan(digRight.AsSByte(), x09.AsSByte()).AsByte();
// var valueLeft = Or(corrLeft, digLeft);
// var valueRight = Or(corrRight, digRight);
var valueLeft = Or(corrLeft, digLeft);
var valueRight = Or(corrRight, digRight);
// var digAfLeft = Or(digLeft, afLeft);
// var digAfRight = Or(digRight, afRight);
var digAfLeft = Or(digLeft, afLeft);
var digAfRight = Or(digRight, afRight);
// var digAfOutOfRangeLeft = Or(resultAfLeft, resultDigLeft);
// var digAfOutOfRangeRight = Or(resultAfRight, resultDigRight);
var digAfOutOfRangeLeft = Or(resultAfLeft, resultDigLeft);
var digAfOutOfRangeRight = Or(resultAfRight, resultDigRight);
// var resLeft = Or(digAfLeft, digAfOutOfRangeLeft);
// var resRight = Or(digAfRight, digAfOutOfRangeRight);
var resLeft = Or(digAfLeft, digAfOutOfRangeLeft);
var resRight = Or(digAfRight, digAfOutOfRangeRight);
// var sh12Left = ShiftLeftLogical(valueLeft.AsUInt16(), 12).AsByte();
// var sh12Right = ShiftLeftLogical(valueRight.AsUInt16(), 12).AsByte();
var sh12Left = ShiftLeftLogical(valueLeft.AsUInt16(), 12).AsByte();
var sh12Right = ShiftLeftLogical(valueRight.AsUInt16(), 12).AsByte();
// var unp1 = ShiftRightLogical(Or(valueLeft, sh12Left).AsUInt16(), 8).AsByte();
// var unp2 = ShiftRightLogical(Or(valueRight, sh12Right).AsUInt16(), 8).AsByte();
var unp1 = ShiftRightLogical(Or(valueLeft, sh12Left).AsUInt16(), 8).AsByte();
var unp2 = ShiftRightLogical(Or(valueRight, sh12Right).AsUInt16(), 8).AsByte();
// var result = PackUnsignedSaturate(unp1.AsInt16(), unp2.AsInt16()).AsByte();
var result = PackUnsignedSaturate(unp1.AsInt16(), unp2.AsInt16()).AsByte();
// leftOk = MoveMask(resLeft);
// rightOk = MoveMask(resRight);
leftOk = MoveMask(resLeft);
rightOk = MoveMask(resRight);
// if ((leftOk | rightOk) != 0) goto Err;
if ((leftOk | rightOk) != 0) goto Err;
// Store(dest, result);
// dest += 16;
// }
Store(dest, result);
dest += 16;
}
// srcBytes = (char*)src;
// destBytes = dest;
// return true;
srcBytes = (char*)src;
destBytes = dest;
return true;
// Err:
// if (leftOk != 0)
// {
// srcBytes = (char*)(src - 64);
// destBytes = dest;
// return false;
// }
// else
// {
// Debug.Assert(rightOk != 0);
// srcBytes = (char*)(src - 32);
// destBytes = dest;
// return false;
// }
// }
// }
//}
Err:
if (leftOk != 0)
{
srcBytes = (char*)(src - 64);
destBytes = dest;
return false;
}
else
{
Debug.Assert(rightOk != 0);
srcBytes = (char*)(src - 32);
destBytes = dest;
return false;
}
}
}
}
//#endif
#endif
@@ -1,129 +1,129 @@
//#if NETCOREAPP3_0_OR_GREATER
#if NETCOREAPP3_0_OR_GREATER
//using System.Diagnostics;
//using System.Runtime.CompilerServices;
//using System.Runtime.Intrinsics;
//using static HexMate.VectorConstants;
//using static HexMate.VectorUtils;
//using static System.Runtime.Intrinsics.X86.Sse2;
//using static System.Runtime.Intrinsics.X86.Ssse3;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using static HexMate.VectorConstants;
using static HexMate.VectorUtils;
using static System.Runtime.Intrinsics.X86.Sse2;
using static System.Runtime.Intrinsics.X86.Ssse3;
//namespace HexMate;
namespace HexMate;
//internal static partial class Utf16HexParser
//{
// internal static unsafe class Ssse3
// {
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// internal static bool TryParse(ref char* srcBytes, ref byte* destBytes, int destLength)
// {
// Debug.Assert(System.Runtime.Intrinsics.X86.Ssse3.IsSupported);
internal static partial class Utf16HexParser
{
internal static unsafe class Ssse3
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TryParse(ref char* srcBytes, ref byte* destBytes, int destLength)
{
Debug.Assert(System.Runtime.Intrinsics.X86.Ssse3.IsSupported);
// var x0F = Vector128.Create((byte)0x0F);
// var x30 = Vector128.Create((byte)0x30);
// var x40 = Vector128.Create((byte)0x40);
// var x60 = Vector128.Create((byte)0x60);
// var xF0 = Vector128.Create((byte)0xF0);
// var validDig = ReadVector128(s_validDig);
// var validHex = ReadVector128(s_validHex);
// var evenBytes = ReadVector128(s_evenBytes);
// var oddBytes = ReadVector128(s_oddBytes);
// var src = (byte*)srcBytes;
// var dest = destBytes;
var x0F = Vector128.Create((byte)0x0F);
var x30 = Vector128.Create((byte)0x30);
var x40 = Vector128.Create((byte)0x40);
var x60 = Vector128.Create((byte)0x60);
var xF0 = Vector128.Create((byte)0xF0);
var validDig = ReadVector128(s_validDig);
var validHex = ReadVector128(s_validHex);
var evenBytes = ReadVector128(s_evenBytes);
var oddBytes = ReadVector128(s_oddBytes);
var src = (byte*)srcBytes;
var dest = destBytes;
// var target = dest + FastMath.RoundDownTo16(destLength);
// int leftOk, rightOk;
// while (dest != target)
// {
// var a = LoadVector128(src).AsInt16();
// src += 16;
// var b = LoadVector128(src).AsInt16();
// src += 16;
// var c = LoadVector128(src).AsInt16();
// src += 16;
// var d = LoadVector128(src).AsInt16();
// src += 16;
var target = dest + FastMath.RoundDownTo16(destLength);
int leftOk, rightOk;
while (dest != target)
{
var a = LoadVector128(src).AsInt16();
src += 16;
var b = LoadVector128(src).AsInt16();
src += 16;
var c = LoadVector128(src).AsInt16();
src += 16;
var d = LoadVector128(src).AsInt16();
src += 16;
// var inputLeft = PackUnsignedSaturate(a, b);
// var inputRight = PackUnsignedSaturate(c, d);
var inputLeft = PackUnsignedSaturate(a, b);
var inputRight = PackUnsignedSaturate(c, d);
// var hiNibbleLeft = And(inputLeft, xF0);
// var hiNibbleRight = And(inputRight, xF0);
var hiNibbleLeft = And(inputLeft, xF0);
var hiNibbleRight = And(inputRight, xF0);
// var upperHexMaskLeft = CompareEqual(hiNibbleLeft, x40);
// var lowerHexMaskLeft = CompareEqual(hiNibbleLeft, x60);
// var digitMaskLeft = CompareEqual(hiNibbleLeft, x30);
// var upperHexMaskRight = CompareEqual(hiNibbleRight, x40);
// var lowerHexMaskRight = CompareEqual(hiNibbleRight, x60);
// var digitMaskRight = CompareEqual(hiNibbleRight, x30);
var upperHexMaskLeft = CompareEqual(hiNibbleLeft, x40);
var lowerHexMaskLeft = CompareEqual(hiNibbleLeft, x60);
var digitMaskLeft = CompareEqual(hiNibbleLeft, x30);
var upperHexMaskRight = CompareEqual(hiNibbleRight, x40);
var lowerHexMaskRight = CompareEqual(hiNibbleRight, x60);
var digitMaskRight = CompareEqual(hiNibbleRight, x30);
// var hexMaskLeft = Or(upperHexMaskLeft, lowerHexMaskLeft);
// var hexMaskRight = Or(upperHexMaskRight, lowerHexMaskRight);
var hexMaskLeft = Or(upperHexMaskLeft, lowerHexMaskLeft);
var hexMaskRight = Or(upperHexMaskRight, lowerHexMaskRight);
// var hiNibbleValidLeft = Or(digitMaskLeft, hexMaskLeft);
// var hiNibbleValidRight = Or(digitMaskRight, hexMaskRight);
var hiNibbleValidLeft = Or(digitMaskLeft, hexMaskLeft);
var hiNibbleValidRight = Or(digitMaskRight, hexMaskRight);
// var digitsAndFLeft = Or(inputLeft, hexMaskLeft);
// var hexAndFLeft = Or(inputLeft, digitMaskLeft);
// var digitsAndFRight = Or(inputRight, hexMaskRight);
// var hexAndFRight = Or(inputRight, digitMaskRight);
var digitsAndFLeft = Or(inputLeft, hexMaskLeft);
var hexAndFLeft = Or(inputLeft, digitMaskLeft);
var digitsAndFRight = Or(inputRight, hexMaskRight);
var hexAndFRight = Or(inputRight, digitMaskRight);
// var okDig1 = Shuffle(validDig, digitsAndFLeft);
// var okHex1 = Shuffle(validHex, hexAndFLeft);
// var okDig2 = Shuffle(validDig, digitsAndFRight);
// var okHex2 = Shuffle(validHex, hexAndFRight);
var okDig1 = Shuffle(validDig, digitsAndFLeft);
var okHex1 = Shuffle(validHex, hexAndFLeft);
var okDig2 = Shuffle(validDig, digitsAndFRight);
var okHex2 = Shuffle(validHex, hexAndFRight);
// var loNibbleValidLeft = Or(okDig1, okHex1);
// var loNibbleValidRight = Or(okDig2, okHex2);
var loNibbleValidLeft = Or(okDig1, okHex1);
var loNibbleValidRight = Or(okDig2, okHex2);
// var validLeft = And(loNibbleValidLeft, hiNibbleValidLeft);
// var validRight = And(loNibbleValidRight, hiNibbleValidRight);
var validLeft = And(loNibbleValidLeft, hiNibbleValidLeft);
var validRight = And(loNibbleValidRight, hiNibbleValidRight);
// loNibbleValidLeft = And(loNibbleValidLeft, x0F);
// loNibbleValidRight = And(loNibbleValidRight, x0F);
loNibbleValidLeft = And(loNibbleValidLeft, x0F);
loNibbleValidRight = And(loNibbleValidRight, x0F);
// var evenBytesLeft = Shuffle(loNibbleValidLeft, evenBytes);
// var oddBytesLeft = Shuffle(loNibbleValidLeft, oddBytes);
// var evenBytesRight = Shuffle(loNibbleValidRight, evenBytes);
// var oddBytesRight = Shuffle(loNibbleValidRight, oddBytes);
var evenBytesLeft = Shuffle(loNibbleValidLeft, evenBytes);
var oddBytesLeft = Shuffle(loNibbleValidLeft, oddBytes);
var evenBytesRight = Shuffle(loNibbleValidRight, evenBytes);
var oddBytesRight = Shuffle(loNibbleValidRight, oddBytes);
// evenBytesLeft = ShiftLeftLogical(evenBytesLeft.AsUInt16(), 4).AsByte();
// evenBytesRight = ShiftLeftLogical(evenBytesRight.AsUInt16(), 4).AsByte();
evenBytesLeft = ShiftLeftLogical(evenBytesLeft.AsUInt16(), 4).AsByte();
evenBytesRight = ShiftLeftLogical(evenBytesRight.AsUInt16(), 4).AsByte();
// evenBytesLeft = Or(evenBytesLeft, oddBytesLeft);
// evenBytesRight = Or(evenBytesRight, oddBytesRight);
evenBytesLeft = Or(evenBytesLeft, oddBytesLeft);
evenBytesRight = Or(evenBytesRight, oddBytesRight);
// var result = UnpackLow(evenBytesLeft.AsInt64(), evenBytesRight.AsInt64()).AsByte();
var result = UnpackLow(evenBytesLeft.AsInt64(), evenBytesRight.AsInt64()).AsByte();
// leftOk = MoveMask(validLeft);
// rightOk = MoveMask(validRight);
leftOk = MoveMask(validLeft);
rightOk = MoveMask(validRight);
// if ((leftOk & rightOk) != 0xFFFF) goto Err;
if ((leftOk & rightOk) != 0xFFFF) goto Err;
// Store(dest, result);
// dest += 16;
// }
Store(dest, result);
dest += 16;
}
// srcBytes = (char*)src;
// destBytes = dest;
// return true;
srcBytes = (char*)src;
destBytes = dest;
return true;
// Err:
// if (leftOk != 0xFFFF)
// {
// srcBytes = (char*)(src - 64);
// destBytes = dest;
// return false;
// }
// else
// {
// Debug.Assert(rightOk != 0xFFFF);
// srcBytes = (char*)(src - 32);
// destBytes = dest;
// return false;
// }
// }
// }
//}
Err:
if (leftOk != 0xFFFF)
{
srcBytes = (char*)(src - 64);
destBytes = dest;
return false;
}
else
{
Debug.Assert(rightOk != 0xFFFF);
srcBytes = (char*)(src - 32);
destBytes = dest;
return false;
}
}
}
}
//#endif
#endif
+87
View File
@@ -153,6 +153,89 @@ public static class IOPath
}
}
static readonly object lock_GetCacheFilePath = new();
/// <summary>
/// 根据缓存子文件夹名称与文件扩展名获取一个缓存文件路径
/// </summary>
/// <param name="dirName">缓存子文件夹名称</param>
/// <param name="fileNamePrefix">文件名前缀</param>
/// <param name="fileEx">文件扩展名</param>
public static string GetCacheFilePath(string dirName, string fileNamePrefix, string fileEx)
{
lock (lock_GetCacheFilePath)
{
var cacheDirPath = Path.Combine(CacheDirectory, dirName);
if (!Directory.Exists(cacheDirPath))
{
Directory.CreateDirectory(cacheDirPath);
return GetCacheFilePath();
}
else
{
string cacheFilePath;
do
{
cacheFilePath = GetCacheFilePath();
} while (File.Exists(cacheFilePath));
return cacheFilePath;
}
string GetCacheFilePath() => Path.Combine(cacheDirPath, GetCacheFileName());
string GetCacheFileName() => $"{fileNamePrefix}_{DateTimeOffset.Now.Ticks}{Random2.GenerateRandomString(4)}{fileEx}";
}
}
/// <summary>
/// 尝试延时一段时间后删除文件
/// </summary>
/// <param name="filePath">要删除的文件路径</param>
/// <param name="millisecondsDelay">延时等待的毫秒数</param>
public static async void TryDeleteInDelay(string filePath, int millisecondsDelay = 9000)
{
await Task.Delay(millisecondsDelay);
FileTryDelete(filePath);
}
/// <summary>
/// 启动进程后尝试延时一段时间后删除文件
/// </summary>
/// <param name="process">启动的进程</param>
/// <param name="filePath">要删除的文件路径</param>
/// <param name="millisecondsDelay">延时等待的毫秒数</param>
/// <param name="processWaitMillisecondsDelay">启动的进程等待退出的毫秒数</param>
public static void TryDeleteInDelay(Process? process, string filePath, int millisecondsDelay = 9000, int processWaitMillisecondsDelay = 9000)
{
if (process != null)
{
var waitForExitResult = process.TryWaitForExit(processWaitMillisecondsDelay);
if (!waitForExitResult)
{
try
{
process.KillEntireProcessTree();
}
catch
{
}
TryDeleteInDelay(filePath, millisecondsDelay);
return;
}
}
FileTryDelete(filePath);
}
/// <summary>
/// 尝试根据缓存子文件夹名称删除整个缓存子文件夹
/// </summary>
/// <param name="dirName">缓存子文件夹名称</param>
public static void TryDeleteCacheSubDir(string dirName)
{
var cacheDirPath = Path.Combine(CacheDirectory, dirName);
DirTryDelete(cacheDirPath);
}
public abstract class FileSystemBase
{
protected FileSystemBase()
@@ -291,6 +374,10 @@ public static class IOPath
{
paths[i] = item;
}
else
{
DirCreateByNotExists(paths[i]);
}
}
InitFileSystem(GetAppDataDirectory, GetCacheDirectory);
+17 -13
View File
@@ -11,7 +11,11 @@ namespace System;
/// </summary>
public static class Log
{
internal static ILoggerFactory Factory => DI.Get<ILoggerFactory>();
public static Func<ILoggerFactory>? LoggerFactory { private get; set; }
static ILoggerFactory? factory;
public static ILoggerFactory Factory => factory ??= (DI.IsConfigured ? DI.Get<ILoggerFactory>() : null) ?? LoggerFactory?.Invoke() ?? throw new ArgumentNullException(nameof(LoggerFactory));
public static ILogger CreateLogger(string tag) => Factory.CreateLogger(tag);
@@ -32,21 +36,21 @@ public static class Log
}
[Conditional("DEBUG")]
public static void Debug(string tag, Exception exception, string msg)
public static void Debug(string tag, Exception? exception, string msg)
{
var logger = CreateLogger(tag);
logger.LogDebug(exception, msg);
}
[Conditional("DEBUG")]
public static void Debug(string tag, Exception exception, string msg, params object?[] args)
public static void Debug(string tag, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogDebug(exception, msg, args);
}
[Conditional("DEBUG")]
public static void Debug(string tag, EventId eventId, Exception exception, string msg, params object?[] args)
public static void Debug(string tag, EventId eventId, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogDebug(eventId, exception, msg, args);
@@ -75,19 +79,19 @@ public static class Log
logger.LogError(msg, args);
}
public static void Error(string tag, Exception exception, string msg)
public static void Error(string tag, Exception? exception, string msg)
{
var logger = CreateLogger(tag);
logger.LogError(exception, msg);
}
public static void Error(string tag, Exception exception, string msg, params object?[] args)
public static void Error(string tag, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogError(exception, msg, args);
}
public static void Error(string tag, EventId eventId, Exception exception, string msg, params object?[] args)
public static void Error(string tag, EventId eventId, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogError(eventId, exception, msg, args);
@@ -115,19 +119,19 @@ public static class Log
logger.LogInformation(msg, args);
}
public static void Info(string tag, Exception exception, string msg)
public static void Info(string tag, Exception? exception, string msg)
{
var logger = CreateLogger(tag);
logger.LogInformation(exception, msg);
}
public static void Info(string tag, Exception exception, string msg, params object?[] args)
public static void Info(string tag, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogInformation(exception, msg, args);
}
public static void Info(string tag, EventId eventId, Exception exception, string msg, params object?[] args)
public static void Info(string tag, EventId eventId, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogInformation(eventId, exception, msg, args);
@@ -155,19 +159,19 @@ public static class Log
logger.LogWarning(msg, args);
}
public static void Warn(string tag, Exception exception, string msg)
public static void Warn(string tag, Exception? exception, string msg)
{
var logger = CreateLogger(tag);
logger.LogWarning(exception, msg);
}
public static void Warn(string tag, Exception exception, string msg, params object?[] args)
public static void Warn(string tag, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogWarning(exception, msg, args);
}
public static void Warn(string tag, EventId eventId, Exception exception, string msg, params object?[] args)
public static void Warn(string tag, EventId eventId, Exception? exception, string msg, params object?[] args)
{
var logger = CreateLogger(tag);
logger.LogWarning(eventId, exception, msg, args);
@@ -0,0 +1,21 @@
#if !NETSTANDARD
using System.Security.Authentication;
namespace System.Net.Http;
partial class GeneralHttpClientFactory
{
public static SocketsHttpHandler CreateSocketsHttpHandler(SocketsHttpHandler? handler = null)
{
handler ??= new();
if (OperatingSystem2.IsWindows7())
{
// https://github.com/dotnet/runtime/issues/25722
handler.SslOptions.EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
}
return handler;
}
}
#endif
@@ -58,7 +58,7 @@ partial class GeneralHttpClientFactory
/// <summary>
/// https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpNoProxy.cs
/// </summary>
sealed class HttpNoProxy : IWebProxy
public sealed class HttpNoProxy : IWebProxy
{
public static readonly HttpNoProxy Instance = new();
@@ -12,7 +12,7 @@ namespace System.Properties
/// <item> macOS:\packaging\build-osx-app.sh &lt;CFBundleVersion&gt; &lt;CFBundleShortVersionString&gt; </item>
/// </list>
/// </summary>
public const string Version = "2.8.1";
public const string Version = "2.8.4";
//public const string InfoVersion = Version + "-beta";
}
@@ -163,6 +163,18 @@ public static class AESUtils
return result.Base64UrlEncode();
}
/// <summary>
/// AES加密(String → String)
/// </summary>
/// <param name="aes"></param>
/// <param name="text"></param>
/// <returns></returns>
public static string EncryptHex(this Aes aes, string text)
{
var result = EncryptToByteArray(aes, text);
return result.ToHexString(true);
}
/// <summary>
/// AES加密(String → String)
/// </summary>
@@ -239,6 +251,18 @@ public static class AESUtils
return Decrypt(aes, data);
}
/// <summary>
/// (解密) String → ByteArray
/// </summary>
/// <param name="aes"></param>
/// <param name="text"></param>
/// <returns></returns>
public static byte[] DecryptHexToByteArray(this Aes aes, string text)
{
var data = Convert2.FromHexString(text);
return Decrypt(aes, data);
}
/// <summary>
/// (解密) String → ByteArray
/// </summary>
@@ -263,6 +287,18 @@ public static class AESUtils
return Encoding.UTF8.GetString(result);
}
/// <summary>
/// (解密) String → String
/// </summary>
/// <param name="aes"></param>
/// <param name="text"></param>
/// <returns></returns>
public static string DecryptHex(this Aes aes, string text)
{
var result = DecryptHexToByteArray(aes, text);
return Encoding.UTF8.GetString(result);
}
/// <summary>
/// (解密) String → String
/// </summary>
@@ -149,16 +149,16 @@ public static partial class RSAUtils
{
if (!string.IsNullOrWhiteSpace(oaepHashAlgorithmName))
{
try
{
var hashAlgorithm = new HashAlgorithmName(oaepHashAlgorithmName);
return RSAEncryptionPadding.CreateOaep(hashAlgorithm);
}
catch
{
}
if (oaepHashAlgorithmName.Equals(nameof(HashAlgorithmName.SHA1), StringComparison.OrdinalIgnoreCase))
return RSAEncryptionPadding.OaepSHA1;
if (oaepHashAlgorithmName.Equals(nameof(HashAlgorithmName.SHA256), StringComparison.OrdinalIgnoreCase))
return RSAEncryptionPadding.OaepSHA256;
if (oaepHashAlgorithmName.Equals(nameof(HashAlgorithmName.SHA384), StringComparison.OrdinalIgnoreCase))
return RSAEncryptionPadding.OaepSHA384;
if (oaepHashAlgorithmName.Equals(nameof(HashAlgorithmName.SHA512), StringComparison.OrdinalIgnoreCase))
return RSAEncryptionPadding.OaepSHA512;
}
return Padding;
return RSAEncryptionPadding.OaepSHA256;
}
public static RSAEncryptionPadding DefaultPadding
@@ -176,7 +176,7 @@ public static partial class RSAUtils
/// <param name="rsa"></param>
/// <param name="data"></param>
/// <returns></returns>
[Obsolete()]
[Obsolete("", true)]
public static byte[] Encrypt(this RSA rsa, byte[] data) => rsa.Encrypt(data, Padding);
/// <summary>
@@ -260,6 +260,20 @@ public static partial class RSAUtils
return bytes.Base64UrlEncode();
}
/// <summary>
/// RSA加密(ByteArray → String)
/// </summary>
/// <param name="rsa"></param>
/// <param name="data"></param>
/// <param name="padding"></param>
/// <returns></returns>
public static string EncryptToHexString(this RSA rsa, byte[] data, RSAEncryptionPadding? padding = null)
{
padding ??= DefaultPadding;
var bytes = rsa.Encrypt(data, padding);
return bytes.ToHexString();
}
/// <summary>
/// RSA加密(ByteArray → String)
/// </summary>
@@ -283,7 +297,7 @@ public static partial class RSAUtils
/// <param name="rsa"></param>
/// <param name="data"></param>
/// <returns></returns>
[Obsolete]
[Obsolete("", true)]
public static byte[] Decrypt(this RSA rsa, byte[] data) => rsa.Decrypt(data, Padding);
/// <summary>
@@ -314,6 +328,20 @@ public static partial class RSAUtils
return rsa.Decrypt(bytes, padding);
}
/// <summary>
/// RSA解密(String → ByteArray)
/// </summary>
/// <param name="rsa"></param>
/// <param name="text"></param>
/// <param name="padding"></param>
/// <returns></returns>
public static byte[] DecryptToByteArrayHex(this RSA rsa, string text, RSAEncryptionPadding? padding = null)
{
var bytes = Convert2.FromHexString(text);
padding ??= DefaultPadding;
return rsa.Decrypt(bytes, padding);
}
/// <summary>
/// RSA解密(String → ByteArray)
/// </summary>
+1 -1
View File
@@ -87,7 +87,7 @@ public struct ShortGuid
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is ShortGuid shortGuid)
{
@@ -0,0 +1,77 @@
using System.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace System.Application.Middleware;
// https://github.com/dotnet/efcore/issues/19526#issuecomment-989036617
/* 2022-07-25 13:09:15.3924||ERROR|Microsoft.EntityFrameworkCore.Query|An exception occurred while iterating over the results of a query for context type 'System.Application.Data.ApplicationDbContext'.
System.Threading.Tasks.TaskCanceledException: A task was canceled.
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync() System.Threading.Tasks.TaskCanceledException: A task was canceled.
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()|url: https://api.steampp.net/ExternalLoginCallback|action: ExternalLoginCallback
*/
public sealed class StandardizedExceptionMiddleware
{
readonly RequestDelegate _next;
//readonly ILogger<StandardizedExceptionMiddleware> _logger;
public StandardizedExceptionMiddleware(RequestDelegate next/*, ILogger<StandardizedExceptionMiddleware> logger*/)
{
_next = next;
//_logger = logger;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context).ConfigureAwait(false);
}
catch (Exception ex)
{
if (IsCancellationException(ex))
{
if (context.RequestAborted.IsCancellationRequested)
{
// Try to ensure cancelled requests don't get reported as 5xx errors
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
return;
}
// This exception wasn't handled so let it bubble up
throw;
}
}
static bool IsCancellationException(Exception ex)
{
if (ex == null) return false;
if (ex is OperationCanceledException)
return true;
if (ex is IOException && ex.Message == "The client reset the request stream.")
return true;
if (ex is Microsoft.AspNetCore.Connections.ConnectionResetException)
return true;
// .NET SQL has a number of different exceptions thrown when operations are cancelled
if (ex.Source == "Microsoft.Data.SqlClient" && ex.Message == "Operation cancelled by user.")
return true;
if ((ex is Microsoft.Data.SqlClient.SqlException /*|| ex is System.Data.SqlClient.SqlException*/) &&
ex.Message.Contains("Operation cancelled by user"))
return true;
if (ex.InnerException is not null) return IsCancellationException(ex.InnerException);
return false;
}
}
@@ -0,0 +1,105 @@
using System.Net.Security;
using System.Net.Sockets;
namespace System.Net.Http;
public sealed class ReverseProxyHttpClientHandler : DelegatingHandler
{
readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(10d);
public ReverseProxyHttpClientHandler()
{
InnerHandler = new SocketsHttpHandler()
{
Proxy = GeneralHttpClientFactory.HttpNoProxy.Instance,
UseProxy = false,
UseCookies = false,
AllowAutoRedirect = false,
AutomaticDecompression = DecompressionMethods.None,
ConnectCallback = ConnectCallback,
};
}
/// <summary>
/// 发送请求
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var uri = request.RequestUri;
if (uri == null)
{
throw new ApplicationException("The requested URI must be specified.");
}
// 设置请求头 host,修改协议为 http
request.Headers.Host = uri.Host;
request.RequestUri = new UriBuilder(uri) { Scheme = Uri.UriSchemeHttp }.Uri;
return await base.SendAsync(request, cancellationToken);
}
/// <summary>
/// 连接回调
/// </summary>
/// <param name="context"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
async ValueTask<Stream> ConnectCallback(SocketsHttpConnectionContext context, CancellationToken cancellationToken)
{
var innerExceptions = new List<Exception>();
var ipEndPoints = (await Dns.GetHostAddressesAsync("steamcommunity.rmbgame.net", cancellationToken)).Select(s => new IPEndPoint(s, context.DnsEndPoint.Port));
foreach (var ipEndPoint in ipEndPoints)
{
try
{
using var timeoutTokenSource = new CancellationTokenSource(connectTimeout);
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutTokenSource.Token, cancellationToken);
return await ConnectAsync(context, ipEndPoint, linkedTokenSource.Token);
}
catch (OperationCanceledException)
{
cancellationToken.ThrowIfCancellationRequested();
innerExceptions.Add(new TimeoutException(
$"HTTP connection to {ipEndPoint.Address} timed out."));
}
catch (Exception ex)
{
innerExceptions.Add(ex);
}
}
throw new AggregateException("Could not find any IP that can be successfully connected.", innerExceptions);
}
/// <summary>
/// 建立连接
/// </summary>
/// <param name="context"></param>
/// <param name="ipEndPoint"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
static async ValueTask<Stream> ConnectAsync(SocketsHttpConnectionContext context, IPEndPoint ipEndPoint, CancellationToken cancellationToken)
{
var socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
await socket.ConnectAsync(ipEndPoint, cancellationToken);
var stream = new NetworkStream(socket, ownsSocket: true);
if (context.DnsEndPoint.Port != 443)
{
return stream;
}
var sslStream = new SslStream(stream, leaveInnerStreamOpen: false);
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
{
TargetHost = string.Empty,
RemoteCertificateValidationCallback = (_, _, _, _) => true,
}, cancellationToken);
return sslStream;
}
}
+3
View File
@@ -2,6 +2,7 @@
#if NET35
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace System
{
@@ -54,6 +55,8 @@ namespace System
public static bool Is64BitOperatingSystem => Is64BitProcess || (IntPtr.Size == 4 && Is32BitProcessOn64BitProcessor());
public static bool Is64BitProcess => IntPtr.Size == 8;
public static string ProcessPath => Application.ExecutablePath;
}
}
#endif
+1 -1
View File
@@ -4,7 +4,7 @@
<OutputType>WinExe</OutputType>
<PlatformTarget>AnyCPU</PlatformTarget>
<TargetFramework>net35</TargetFramework>
<ApplicationManifest>..\ST.Client.Desktop.Avalonia.App\Properties\app.manifest</ApplicationManifest>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
<AssemblyName>Steam++.Launcher</AssemblyName>
<ApplicationIcon>..\ST.Client.Desktop.Avalonia\Application\UI\Assets\Icon.ico</ApplicationIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+42 -5
View File
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using NuGet.Versioning;
using Microsoft.Win32;
using Microsoft.DotNet.Tools.Uninstall.Windows;
using Microsoft.DotNet.Tools.Uninstall.Shared.BundleInfo;
using FDELauncher.Properties;
@@ -16,8 +17,10 @@ internal static class Program
{
const string ExecutiveName = "Steam++";
static BundleArch matchArch;
static readonly SemanticVersion runtimeVersion = new(6, 0, 7);
static readonly SemanticVersion sdkVersion = new(6, 0, 107);
static readonly SemanticVersion runtimeVersion = new(6, 0, 8);
static readonly SemanticVersion sdkVersion1 = new(6, 0, 108);
static readonly SemanticVersion sdkVersion3 = new(6, 0, 303);
static readonly SemanticVersion sdkVersion4 = new(6, 0, 400);
/// <summary>
/// 应用程序的主入口点。
@@ -27,6 +30,11 @@ internal static class Program
{
try
{
if (IsProgramInCompatibilityMode())
{
MessageBox.Show(R.ProgramInCompatibilityModeError, R.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
return 0;
}
if (args.Length == 1 && args[0] == "--query")
{
var installed = RegistryQuery.GetAllInstalledBundles().ToArray();
@@ -50,7 +58,7 @@ internal static class Program
if (RuntimeInformation2.OSArchitecture != Architecture.Arm64) throw new PlatformNotSupportedException();
break;
}
if (IsRuntimeInstalled(matchArch, runtimeVersion, sdkVersion))
if (IsRuntimeInstalled(matchArch, runtimeVersion, sdkVersion1, sdkVersion3, sdkVersion4))
{
Run();
}
@@ -187,7 +195,7 @@ internal static class Program
/// 是否已安装运行时或 SDK
/// </summary>
/// <returns></returns>
static bool IsRuntimeInstalled(BundleArch matchArch, SemanticVersion runtimeVersion, SemanticVersion sdkVersion)
static bool IsRuntimeInstalled(BundleArch matchArch, SemanticVersion runtimeVersion, SemanticVersion sdkVersion1, SemanticVersion sdkVersion3, SemanticVersion sdkVersion4)
{
// ArchiSteamFarm 依赖 ASP.NET Core
// ASP.NET Core 运行时安装程序除 Hosting Bundle 不包含 .NET 运行时 缺少文件 C:\Program Files\dotnet\host\fxr\{version}\hostfxr.dll
@@ -196,7 +204,12 @@ internal static class Program
// https://github.com/dotnet/runtime/blob/v6.0.5/src/native/corehost/apphost/apphost.windows.cpp#L106-L113
var installed = RegistryQuery.GetAllInstalledBundles().Where(m => m.Arch.HasFlags(matchArch)).ToArray();
var query_sdk = installed.Where(m => m.Version.Type == BundleType.Sdk && m.Version.SemVer >= sdkVersion);
var query_sdk = installed.Where(m => m.Version.Type == BundleType.Sdk &&
(
(m.Version.SemVer >= sdkVersion1 && m.Version.SemVer < new SemanticVersion(sdkVersion1.Major, sdkVersion1.Minor, 199)) ||
(m.Version.SemVer >= sdkVersion3 && m.Version.SemVer < new SemanticVersion(sdkVersion3.Major, sdkVersion3.Minor, 399)) ||
(m.Version.SemVer >= sdkVersion4 && m.Version.SemVer < new SemanticVersion(sdkVersion4.Major, sdkVersion4.Minor, 499))
));
if (query_sdk.Any()) return true;
var query_runtime = installed.Where(m => (m.Version.Type == BundleType.Runtime || m.Version.Type == BundleType.WindowsDesktopRuntime) && m.Version.SemVer >= runtimeVersion);
@@ -259,4 +272,28 @@ internal static class Program
UseShellExecute = false,
});
}
static bool IsProgramInCompatibilityMode()
{
try
{
foreach (var item in new[] { Registry.CurrentUser, Registry.LocalMachine })
{
using var layers = item.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers");
var value = layers?.GetValue(Environment2.ProcessPath)?.ToString();
if (value != null)
{
value = value.ToUpperInvariant();
if (value.Contains("WIN8")) return true;
if (value.Contains("WIN7")) return true;
if (value.Contains("VISTA")) return true;
if (value.Contains("WINXP")) return true;
}
}
}
catch
{
}
return false;
}
}
+23
View File
@@ -149,6 +149,29 @@ static class Resources
Language.Russian => "Это приложение поддерживает только 64-битные операционные системы",
_ => "This application only supports 64-bit operating systems",
});
public static string Error => GetString(l => l switch
{
Language.ChineseSimplified => "错误",
Language.ChineseTraditional => "錯誤",
Language.Italian => "errore",
Language.Japanese => "エラー",
Language.Korean => "잘못",
Language.Russian => "ошибка",
_ => "Error",
});
public static string ProgramInCompatibilityModeError => GetString(l => l switch
{
Language.ChineseSimplified => "不能在 Windows 兼容模式中运行,请关闭后重试",
Language.ChineseTraditional => "不能在 Windows 相容模式中運行,請關閉後重試",
Language.Spanish => "El modo de compatibilidad de programas de Windows está activado. Desactívelo y vuelva a intentarlo",
Language.Italian => "La modalità di compatibilità dei programmi di Windows è attiva. Disattivarla e riprovare",
Language.Japanese => "Windowsプログラムの互換性モードがオンになっています。これをオフにしてから、もう一度試してください。",
Language.Korean => "Windows 프로그램 호환 모드가 열렸습니다. 닫고 다시 시도하십시오.",
Language.Russian => "режим совместимости Windows был открыт. пожалуйста, выключите его и попробуйте снова",
_ => "Windows Program Compatibility mode is on. Turn it off and then try again",
});
}
enum Language
@@ -5,6 +5,6 @@ namespace System.Properties
/// <summary>
/// 版本号
/// </summary>
public const string Version = "1.0.1";
public const string Version = "1.1.0";
}
}
+79
View File
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC 清单选项
如果想要更改 Windows 用户帐户控制级别,请使用
以下节点之一替换 requestedExecutionLevel 节点。
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
指定 requestedExecutionLevel 元素将禁用文件和注册表虚拟化。
如果你的应用程序需要此虚拟化来实现向后兼容性,则移除此
元素。
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- 设计此应用程序与其一起工作且已针对此应用程序进行测试的
Windows 版本的列表。取消评论适当的元素,
Windows 将自动选择最兼容的环境。 -->
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<!--
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
-->
<!-- 启用 Windows 公共控件和对话框的主题(Windows XP 和更高版本) -->
<!--
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
-->
</assembly>
@@ -1,15 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SignAssembly>true</SignAssembly>
<DelaySign>false</DelaySign>
<AssemblyOriginatorKeyFile>$(MSBuildProjectDirectory)\..\..\avalonia.snk</AssemblyOriginatorKeyFile>
<Version>2.2.255.255</Version>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\AssemblyInfo.Version.Max.cs">
<LinkBase>Properties</LinkBase>
</Compile>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Primitives" />
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220514" android:versionName="2.8.0" package="net.steampp.app" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220803" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
@@ -19,7 +19,8 @@
<AotAssemblies>false</AotAssemblies>
<EnableLLVM>false</EnableLLVM>
<AndroidEnableProfiledAot>false</AndroidEnableProfiledAot>
<AndroidLinkMode>None</AndroidLinkMode>
<AndroidLinkMode>Full</AndroidLinkMode>
<AndroidLinkTool>r8</AndroidLinkTool>
<PublishTrimmed>false</PublishTrimmed>
<AndroidFragmentType>AndroidX.Fragment.App.Fragment</AndroidFragmentType>
</PropertyGroup>
@@ -187,7 +188,7 @@
<PackageReference Include="Xamarin.Build.Download" />
<!--<PackageReference Include="Xamarin.AndroidX.Window" />-->
</ItemGroup>
<ItemGroup>
<AndroidAsset Include="..\..\references\Android Assets\cncity.txt" Link="Assets\cncity.txt" />
</ItemGroup>
@@ -553,6 +554,9 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_toolbar_tablayout_viewpager2.xml">
<Link>Resources\layout\activity_toolbar_tablayout_viewpager2.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_toolbar_webview.xml">
<Link>Resources\layout\activity_toolbar_webview.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_about.xml">
<Link>Resources\layout\fragment_about.xml</Link>
</AndroidResource>
@@ -0,0 +1,15 @@
#if NET6_0_OR_GREATER
using System.Drawing;
using AndroidColor = Android.Graphics.Color;
namespace System;
public static partial class ColorExtensions
{
public static Color ToSystemColor(this AndroidColor color) =>
Color.FromArgb(color.A, color.R, color.G, color.B);
public static AndroidColor ToPlatformColor(this Color color) =>
new(color.R, color.G, color.B, color.A);
}
#endif
@@ -4,28 +4,29 @@ using Android.OS;
using NativeService = System.Application.Services.Native.IServiceBase;
// ReSharper disable once CheckNamespace
namespace System
namespace System;
partial class ContextExtensions
{
partial class ContextExtensions
/// <summary>
/// 启动或关闭前台服务
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="context"></param>
/// <param name="startOrStop"></param>
public static void StartOrStopForegroundService<TService>(this Context context, bool startOrStop) where TService : Service, NativeService
{
/// <summary>
/// 启动或关闭前台服务
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="context"></param>
/// <param name="startOrStop"></param>
public static void StartOrStopForegroundService<TService>(this Context context, bool startOrStop) where TService : Service, NativeService
Intent intent = new(context, typeof(TService));
intent.SetAction(startOrStop ? NativeService.START : NativeService.STOP);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
Intent intent = new(context, typeof(TService));
intent.SetAction(startOrStop ? NativeService.START : NativeService.STOP);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
context.StartForegroundService(intent);
}
else
{
context.StartService(intent);
}
#pragma warning disable CA1416 // 验证平台兼容性
context.StartForegroundService(intent);
#pragma warning restore CA1416 // 验证平台兼容性
}
else
{
context.StartService(intent);
}
}
}
@@ -1,6 +1,10 @@
using System.Threading.Tasks;
using Android.Telephony;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application;
+11 -4
View File
@@ -1,7 +1,7 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>MonoAndroid12.0</TargetFrameworks>
<TargetFrameworks>MonoAndroid12.0;net6.0-android</TargetFrameworks>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>Xamarin.Forms.Platform.Android.UnitTests</AssemblyName>
<DefineConstants>SHADOWSOCKS;$(DefineConstants)</DefineConstants>
@@ -9,6 +9,11 @@
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-android'))">21.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition=" !($(TargetFramework.StartsWith('MonoAndroid'))) ">
<UseMaui>true</UseMaui>
<DefineConstants>NET6_0_MAUI_LIB;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!--当前包是否为应用商店渠道包(IS_STORE_PACKAGE)-->
<!--<PropertyGroup>
<DefineConstants>IS_STORE_PACKAGE;$(DefineConstants)</DefineConstants>
@@ -25,7 +30,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="..\Startup.cs" Link="UI\MainApplication.Startup.cs" />
<Compile Condition="!$(TargetFramework.Contains('-android'))" Include="..\Startup.cs" Link="UI\MainApplication.Startup.cs" />
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
@@ -106,7 +111,7 @@
<LinkBase>UI\Adapters</LinkBase>
</Compile>
<Compile Include="..\Common.ClientLib.Droid\Application\DarkModeUtil.cs" />
<Compile Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddWindowManager.cs" />
<Compile Condition="!$(TargetFramework.Contains('-android'))" Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddWindowManager.cs" />
<Compile Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddApplicationUpdateService.cs" />
<AndroidResource Include="Resources\**\*" />
<Compile Remove="Services\V2Ray\**" />
@@ -149,6 +154,7 @@
<PackageReference Include="Xamarin.Google.MLKit.BarcodeScanning" />
<PackageReference Include="Xamarin.Build.Download" />
<!--<PackageReference Include="Xamarin.AndroidX.Window" />-->
<PackageReference Include="Microsoft.Net.Http.Headers" />
</ItemGroup>
<!--<ItemGroup Condition="'$(Configuration)'=='Debug'">
@@ -157,7 +163,8 @@
<ItemGroup>
<ProjectReference Include="..\Common.CoreLib\Common.CoreLib.csproj" />
<ProjectReference Include="..\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj" />
<ProjectReference Condition=" ($(TargetFramework.StartsWith('MonoAndroid'))) " Include="..\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj" />
<ProjectReference Condition=" !($(TargetFramework.StartsWith('MonoAndroid'))) " Include="..\Common.Essentials.Maui\Common.Essentials.Maui.csproj" />
<ProjectReference Condition=" $(DefineConstants.Contains(`V2RAY`)) " Include="..\ST.Client.Android.V2Ray\ST.Client.Android.V2Ray.csproj" />
<ProjectReference Condition=" $(DefineConstants.Contains(`SHADOWSOCKS`)) " Include="..\ST.Client.Android.Shadowsocks\ST.Client.Android.Shadowsocks.csproj" />
<ProjectReference Include="..\ST.Client.AppCenter\ST.Client.AppCenter.csproj" />
@@ -1,7 +1,15 @@
using Android.OS;
using System.IO;
#if NET6_0_OR_GREATER
using Microsoft.Maui.Devices;
#else
using Xamarin.Essentials;
#endif
#if NET6_0_OR_GREATER
using XEDeviceType = Microsoft.Maui.Devices.DeviceType;
#else
using XEDeviceType = Xamarin.Essentials.DeviceType;
#endif
namespace System.Application.Services.Implementation
{
@@ -2,7 +2,11 @@ using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using ASF_FS = System.Application.Services.Native.ArchiSteamFarmForegroundService;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using Android.App;
using System.Application.Services.Native;
@@ -4,7 +4,11 @@ using System.Net;
using AndroidX.AppCompat.App;
using System.Application.UI.Activities;
using AndroidApplication = Android.App.Application;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -12,288 +12,305 @@ using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using System.Collections.Generic;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
using static Microsoft.Maui.ApplicationModel.Platform;
#else
using Xamarin.Essentials;
using static Xamarin.Essentials.Platform;
#endif
using AlertDialog = AndroidX.AppCompat.App.AlertDialog;
namespace System.Application.Services.Implementation
namespace System.Application.Services.Implementation;
/// <inheritdoc cref="IWindowManager"/>
public class AndroidWindowManagerImpl : IWindowManagerImpl
{
/// <inheritdoc cref="IWindowManager"/>
public class AndroidWindowManagerImpl : IWindowManagerImpl
/* AlertDialog
* =======================================
* = Title =
* = Message(Content) =
* = Neutral Negative Positive =
* =======================================
*/
protected static string PositiveButtonText => AppResources.Confirm;
protected static string NegativeButtonText => AppResources.Cancel;
protected static string NeutralButtonText => AppResources.RememberChooseNotToAskAgain;
protected async Task<bool> PlatformShowWindow(CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
{
/* AlertDialog
* =======================================
* = Title =
* = Message(Content) =
* = Neutral Negative Positive =
* =======================================
*/
protected static string PositiveButtonText => AppResources.Confirm;
protected static string NegativeButtonText => AppResources.Cancel;
protected static string NeutralButtonText => AppResources.RememberChooseNotToAskAgain;
protected async Task<bool> PlatformShowWindow(CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
Activity currentActivity;
do
{
Activity currentActivity;
do
{
currentActivity = await WaitForActivityAsync();
await Task.Delay(100);
} while (!currentActivity.HasValue());
return await MainThread.InvokeOnMainThreadAsync(async () =>
{
return await PlatformShowWindowCore(currentActivity, customWindow, viewModel, title);
});
currentActivity = await WaitForActivityAsync();
await Task.Delay(100);
} while (!currentActivity.HasValue());
return await MainThread.InvokeOnMainThreadAsync(async () =>
{
return await PlatformShowWindowCore(currentActivity, customWindow, viewModel, title);
});
}
bool IWindowManager.UseMyAuthenticatorWrapper => true;
protected Task<bool> PlatformShowWindowCore(Activity currentActivity, CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
case CustomWindow.AuthTrade:
if (viewModel is IMyAuthenticatorWrapper viewModel_auth_w && viewModel_auth_w.MyAuthenticator != null)
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
// Android Activity 传参需要序列化后再反序列化,不能直接传递
// 所以此处传递 Id,在 Activity 中从关联的集合中根据 Id 取值
SteamAuthDataActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
case CustomWindow.AuthTrade:
SteamAuthTradeActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
}
}
return Task.FromResult(false);
}
bool IWindowManager.UseMyAuthenticatorWrapper => true;
protected Task<bool> PlatformShowWindowCore(Activity currentActivity, CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
var activityType = customWindow switch
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
case CustomWindow.AuthTrade:
if (viewModel is IMyAuthenticatorWrapper viewModel_auth_w && viewModel_auth_w.MyAuthenticator != null)
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
// Android Activity 传参需要序列化后再反序列化,不能直接传递
// 所以此处传递 Id,在 Activity 中从关联的集合中根据 Id 取值
SteamAuthDataActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
case CustomWindow.AuthTrade:
SteamAuthTradeActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
}
}
return Task.FromResult(false);
}
CustomWindow.AddAuth => typeof(AddAuthActivity),
CustomWindow.ExportAuth => typeof(ExportAuthActivity),
CustomWindow.EncryptionAuth => typeof(EncryptionAuthActivity),
CustomWindow.ProxySettings => typeof(ProxySettingsActivity),
_ => null,
};
if (activityType != null)
{
currentActivity.StartActivity(activityType);
return Task.FromResult(false);
}
var activityType = customWindow switch
{
CustomWindow.AddAuth => typeof(AddAuthActivity),
CustomWindow.ExportAuth => typeof(ExportAuthActivity),
CustomWindow.EncryptionAuth => typeof(EncryptionAuthActivity),
CustomWindow.ProxySettings => typeof(ProxySettingsActivity),
_ => null,
};
if (activityType != null)
{
currentActivity.StartActivity(activityType);
return Task.FromResult(false);
}
TaskCompletionSource<bool> tcs = new();
try
{
AlertDialog? dialog = null;
TaskCompletionSource<bool> tcs = new();
try
void SetConfirmButton(MaterialAlertDialogBuilder b)
{
AlertDialog? dialog = null;
void SetConfirmButton(MaterialAlertDialogBuilder b)
b.SetPositiveButton(PositiveButtonText, (_, e) =>
{
b.SetPositiveButton(PositiveButtonText, (_, e) =>
{
tcs.TrySetResult(true);
});
}
void SetCancelButton(MaterialAlertDialogBuilder b)
{
b.SetNegativeButton(NegativeButtonText, (_, e) =>
{
tcs.TrySetResult(false);
});
}
void SetNeutralButton(MaterialAlertDialogBuilder b, MessageBoxWindowViewModel vm)
{
b.SetNeutralButton(NeutralButtonText, (_, e) =>
{
vm.RememberChoose = true;
tcs.TrySetResult(true);
});
}
Action<AlertDialog>? CreateMessageBoxDialogWindow(MaterialAlertDialogBuilder b)
{
SetConfirmButton(b);
var isCancelcBtn = false;
if (viewModel is MessageBoxWindowViewModel viewModel_mb)
{
b.SetMessage(viewModel_mb.Content);
isCancelcBtn = viewModel_mb.IsCancelcBtn;
if (viewModel_mb.IsShowRememberChoose) SetNeutralButton(b, viewModel_mb);
}
if (isCancelcBtn) SetCancelButton(b);
return null;
}
Action<AlertDialog>? CreateTextBoxDialogWindowCore(MaterialAlertDialogBuilder b, Action<textbox_password, TextBoxWindowViewModel>? action = null)
{
if (viewModel is not TextBoxWindowViewModel viewModel_tb) throw new NotSupportedException();
// https://material.io/components/text-fields/android
// https://material.io/components/dialogs#specs
IDialogInterfaceOnClickListener? listener = null;
b.SetPositiveButton(PositiveButtonText, listener);
SetCancelButton(b);
var view = LayoutInflater.From(b.Context)!.Inflate(Resource.Layout.textbox_password, null, false)!;
var binding = new textbox_password(view);
var selectionIndex = 0;
if (!string.IsNullOrEmpty(viewModel_tb.Value))
{
binding.tbPassword.Text = viewModel_tb.Value;
selectionIndex = viewModel_tb.Value!.Length;
}
binding.layoutPassword.Hint = viewModel_tb.Placeholder;
if (viewModel_tb.MaxLength > 0)
binding.tbPassword.SetMaxLength(viewModel_tb.MaxLength);
action?.Invoke(binding, viewModel_tb);
b.SetView(view);
return d =>
{
if (binding.tbPassword.KeyListener != null)
{
currentActivity.ShowSoftInput(binding.tbPassword, inOnCreate: true);
if (selectionIndex > 0)
{
binding.tbPassword.SetSelection(selectionIndex);
}
}
d.GetButton((int)DialogButtonType.Positive).Click += (_, _) =>
{
if (viewModel is ITextBoxWindowViewModel viewModel_tb)
{
viewModel_tb.Value = binding.tbPassword.Text;
if (viewModel_tb.InputValidator())
{
d.Dismiss();
tcs.TrySetResult(true);
}
}
};
};
}
Action<AlertDialog>? CreateTextBoxDialogWindow(MaterialAlertDialogBuilder b) => CreateTextBoxDialogWindowCore(b, static (binding, viewModel) =>
{
switch (viewModel.InputType)
{
case TextBoxWindowViewModel.TextBoxInputType.TextBox:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconClearText;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
break;
case TextBoxWindowViewModel.TextBoxInputType.ReadOnlyText:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconNone;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
binding.tbPassword.SetReadOnly();
break;
}
tcs.TrySetResult(true);
});
Func<MaterialAlertDialogBuilder, Action<AlertDialog>?> @delegate = customWindow switch
{
CustomWindow.MessageBox => CreateMessageBoxDialogWindow,
CustomWindow.TextBox => CreateTextBoxDialogWindow,
_ => throw new NotImplementedException(),
};
if (!string.IsNullOrEmpty(title) && viewModel != null)
{
viewModel.Title = title;
}
var builder = new MaterialAlertDialogBuilder(currentActivity);
if (!string.IsNullOrWhiteSpace(viewModel?.Title))
{
builder.SetTitle(viewModel!.Title);
}
var dialog_delegate = @delegate(builder);
dialog = builder.Create();
dialog.SetCanceledOnTouchOutside(false);
dialog.CancelEvent += (_, _) =>
}
void SetCancelButton(MaterialAlertDialogBuilder b)
{
b.SetNegativeButton(NegativeButtonText, (_, e) =>
{
tcs.TrySetResult(false);
};
if (dialog_delegate != null)
});
}
void SetNeutralButton(MaterialAlertDialogBuilder b, MessageBoxWindowViewModel vm)
{
b.SetNeutralButton(NeutralButtonText, (_, e) =>
{
dialog.ShowEvent += (_, _) =>
vm.RememberChoose = true;
tcs.TrySetResult(true);
});
}
Action<AlertDialog>? CreateMessageBoxDialogWindow(MaterialAlertDialogBuilder b)
{
SetConfirmButton(b);
var isCancelcBtn = false;
if (viewModel is MessageBoxWindowViewModel viewModel_mb)
{
b.SetMessage(viewModel_mb.Content);
isCancelcBtn = viewModel_mb.IsCancelcBtn;
if (viewModel_mb.IsShowRememberChoose) SetNeutralButton(b, viewModel_mb);
}
if (isCancelcBtn) SetCancelButton(b);
return null;
}
Action<AlertDialog>? CreateTextBoxDialogWindowCore(MaterialAlertDialogBuilder b, Action<textbox_password, TextBoxWindowViewModel>? action = null)
{
if (viewModel is not TextBoxWindowViewModel viewModel_tb) throw new NotSupportedException();
// https://material.io/components/text-fields/android
// https://material.io/components/dialogs#specs
IDialogInterfaceOnClickListener? listener = null;
b.SetPositiveButton(PositiveButtonText, listener);
SetCancelButton(b);
var view = LayoutInflater.From(b.Context)!.Inflate(Resource.Layout.textbox_password, null, false)!;
var binding = new textbox_password(view);
var selectionIndex = 0;
if (!string.IsNullOrEmpty(viewModel_tb.Value))
{
binding.tbPassword.Text = viewModel_tb.Value;
selectionIndex = viewModel_tb.Value!.Length;
}
binding.layoutPassword.Hint = viewModel_tb.Placeholder;
if (viewModel_tb.MaxLength > 0)
binding.tbPassword.SetMaxLength(viewModel_tb.MaxLength);
action?.Invoke(binding, viewModel_tb);
b.SetView(view);
return d =>
{
if (binding.tbPassword.KeyListener != null)
{
dialog_delegate?.Invoke(dialog);
currentActivity.ShowSoftInput(binding.tbPassword, inOnCreate: true);
if (selectionIndex > 0)
{
binding.tbPassword.SetSelection(selectionIndex);
}
}
d.GetButton((int)DialogButtonType.Positive).Click += (_, _) =>
{
if (viewModel is ITextBoxWindowViewModel viewModel_tb)
{
viewModel_tb.Value = binding.tbPassword.Text;
if (viewModel_tb.InputValidator())
{
d.Dismiss();
tcs.TrySetResult(true);
}
}
};
}
dialog.Show();
};
}
catch (Exception e)
Action<AlertDialog>? CreateTextBoxDialogWindow(MaterialAlertDialogBuilder b) => CreateTextBoxDialogWindowCore(b, static (binding, viewModel) =>
{
tcs.TrySetException(e);
}
return tcs.Task;
}
public virtual Type? WindowType => typeof(Activity);
public virtual Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
protected bool IsMatchCurrentActivityViewModel(object vm, [NotNullWhen(true)] out Activity? activity)
{
foreach (var item in MainApplication.Activities)
{
if (item is IViewFor vf && vf.ViewModel == vm)
switch (viewModel.InputType)
{
activity = item;
return true;
case TextBoxWindowViewModel.TextBoxInputType.TextBox:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconClearText;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
break;
case TextBoxWindowViewModel.TextBoxInputType.ReadOnlyText:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconNone;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
binding.tbPassword.SetReadOnly();
break;
}
}
activity = null;
return false;
}
});
public virtual void CloseWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
Func<MaterialAlertDialogBuilder, Action<AlertDialog>?> @delegate = customWindow switch
{
activity.OnBackPressed();
}
}
public virtual bool IsVisibleWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
CustomWindow.MessageBox => CreateMessageBoxDialogWindow,
CustomWindow.TextBox => CreateTextBoxDialogWindow,
_ => throw new NotImplementedException(),
};
if (!string.IsNullOrEmpty(title) && viewModel != null)
{
return activity.HasValue();
viewModel.Title = title;
}
return default;
var builder = new MaterialAlertDialogBuilder(currentActivity);
if (!string.IsNullOrWhiteSpace(viewModel?.Title))
{
builder.SetTitle(viewModel!.Title);
}
var dialog_delegate = @delegate(builder);
dialog = builder.Create();
dialog.SetCanceledOnTouchOutside(false);
dialog.CancelEvent += (_, _) =>
{
tcs.TrySetResult(false);
};
if (dialog_delegate != null)
{
dialog.ShowEvent += (_, _) =>
{
dialog_delegate?.Invoke(dialog);
};
}
dialog.Show();
}
public virtual void HideWindow(WindowViewModel vm)
catch (Exception e)
{
CloseWindow(vm);
tcs.TrySetException(e);
}
return tcs.Task;
}
public virtual Type? WindowType => typeof(Activity);
public virtual Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
protected virtual IEnumerable<Activity> Activities
{
get
{
#if NET6_0_MAUI_LIB
throw new NotImplementedException();
#else
return MainApplication.Activities;
#endif
}
}
protected bool IsMatchCurrentActivityViewModel(object vm, [NotNullWhen(true)] out Activity? activity)
{
foreach (var item in Activities)
{
if (item is IViewFor vf && vf.ViewModel == vm)
{
activity = item;
return true;
}
}
activity = null;
return false;
}
public virtual void CloseWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
{
activity.OnBackPressed();
}
}
public virtual bool IsVisibleWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
{
return activity.HasValue();
}
return default;
}
public virtual void HideWindow(WindowViewModel vm)
{
CloseWindow(vm);
}
}
@@ -3,7 +3,11 @@ using Android.OS;
#endif
using Microsoft.Extensions.Options;
using System.Application.Models;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using System.Application.UI;
namespace System.Application.Services.Implementation
@@ -1,11 +1,17 @@
#if ANDROID || __ANDROID__
using Android.Content;
using Android.Net;
#endif
using System.Application.Services;
using System.Application.Services.Implementation;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -3,7 +3,11 @@ using System.Linq;
using System.IO;
using System.Threading.Tasks;
using static AndroidX.Activity.Result.ActivityResultTask;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -1,5 +1,9 @@
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using XEPermissions = Microsoft.Maui.ApplicationModel.Permissions;
#else
using XEPermissions = Xamarin.Essentials.Permissions;
#endif
namespace System.Application.Services.Implementation.Permissions;
@@ -1,6 +1,10 @@
using AndroidX.Biometric;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -14,10 +14,10 @@ namespace System.Application.Services.Implementation
#endif
}
public static AndroidClientHandler CreateAndroidClientHandler()
public static AndroidClientHandler CreateAndroidClientHandler(AndroidClientHandler? handler = null)
{
// https://docs.microsoft.com/zh-cn/xamarin/android/app-fundamentals/http-stack?context=xamarin%2Fcross-platform&tabs=macos
var handler = new AndroidClientHandler();
handler ??= new AndroidClientHandler();
AddFiddlerRootCertificate(handler);
GeneralHttpClientFactory.SetProxyToHandler(GeneralHttpClientFactory.DefaultProxy, handler);
return handler;
@@ -16,15 +16,22 @@ using System.Application.Services;
using System.Application.UI.Resx;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Essentials;
using Xamarin.Google.MLKit.Vision.BarCode;
using Xamarin.Google.MLKit.Vision.Common;
using Xamarin.Google.MLKit.Vision.Barcode.Common;
using AUri = Android.Net.Uri;
using Fragment = AndroidX.Fragment.App.Fragment;
using GmsTask = Android.Gms.Tasks.Task;
using JException = Java.Lang.Exception;
using JObject = Java.Lang.Object;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Media;
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using Xamarin.Essentials;
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.UI.Activities
{
@@ -20,7 +20,13 @@ using System.Threading.Tasks;
using static AndroidX.Activity.Result.ActivityResultTask;
using _ThisAssembly = System.Properties.ThisAssembly;
using ASettings = Android.Provider.Settings;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using Xamarin.Essentials;
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.UI.Activities
{
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using Android.App;
using Android.Content;
using Android.Content.PM;
@@ -15,155 +16,155 @@ using Fragment = AndroidX.Fragment.App.Fragment;
using Google.Android.Material.Navigation;
using AndroidX.ViewPager2.Widget;
namespace System.Application.UI.Activities
namespace System.Application.UI.Activities;
/// <summary>
/// 使用 ViewPager2 + BottomNavigationView 实现的 MainActivity
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(MainActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_NoActionBar,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
internal sealed partial class MainActivity : BaseActivity<activity_main_3>, ViewPagerAdapter.IHost, BottomNavigationView.IOnItemSelectedListener
{
/// <summary>
/// 使用 ViewPager2 + BottomNavigationView 实现的 MainActivity
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(MainActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_NoActionBar,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
internal sealed partial class MainActivity : BaseActivity<activity_main_3>, ViewPagerAdapter.IHost, BottomNavigationView.IOnItemSelectedListener
protected override int? LayoutResource => Resource.Layout.activity_main_3;
protected override bool BackToHome => true;
void SetBottomNavigationMenuTitle(int resId, CharSequence value)
{
protected override int? LayoutResource => Resource.Layout.activity_main_3;
if (binding == null) return;
var menu = binding.nav_view.Menu;
var menuItem = menu.FindItem(resId);
if (menuItem == null) return;
menuItem.SetTitle(value);
}
protected override bool BackToHome => true;
void SetSubPageTitle(int resId, string value)
{
var value_ = value.ToJavaString();
SetBottomNavigationMenuTitle(resId, value_);
this.SetNavigationGraphTitle(resId, value_);
}
void SetBottomNavigationMenuTitle(int resId, CharSequence value)
static MainActivity? mainActivity;
public static MainActivity Instance => mainActivity ?? throw new ArgumentNullException(nameof(mainActivity));
(Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]? fragments;
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
mainActivity = this;
fragments = new (Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]
{
(typeof(LocalAuthFragment), () => LocalAuthPageViewModel.DisplayName, Resource.Id.navigation_local_auth, TabItemViewModel.TabItemId.LocalAuth),
(typeof(ASFPlusFragment), () => ArchiSteamFarmPlusPageViewModel.DisplayName, Resource.Id.navigation_asf_plus, TabItemViewModel.TabItemId.ArchiSteamFarmPlus),
(typeof(CommunityFixFragment), () => AppResources.CommunityFix, Resource.Id.navigation_community_fix, TabItemViewModel.TabItemId.CommunityProxy),
(typeof(MyFragment), () => MyPageViewModel.DisplayName, Resource.Id.navigation_my, default),
};
SetSupportActionBar(binding!.toolbar);
R.Subscribe(() =>
{
if (binding == null) return;
var menu = binding.nav_view.Menu;
var menuItem = menu.FindItem(resId);
if (menuItem == null) return;
menuItem.SetTitle(value);
}
void SetSubPageTitle(int resId, string value)
{
var value_ = value.ToJavaString();
SetBottomNavigationMenuTitle(resId, value_);
this.SetNavigationGraphTitle(resId, value_);
}
static MainActivity? mainActivity;
public static MainActivity Instance => mainActivity ?? throw new ArgumentNullException(nameof(mainActivity));
(Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]? fragments;
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
mainActivity = this;
fragments = new (Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]
foreach (var (_, getTitle, menuId, _) in fragments)
{
(typeof(LocalAuthFragment), () => LocalAuthPageViewModel.DisplayName, Resource.Id.navigation_local_auth, TabItemViewModel.TabItemId.LocalAuth),
(typeof(ASFPlusFragment), () => ArchiSteamFarmPlusPageViewModel.DisplayName, Resource.Id.navigation_asf_plus, TabItemViewModel.TabItemId.ArchiSteamFarmPlus),
(typeof(CommunityFixFragment), () => AppResources.CommunityFix, Resource.Id.navigation_community_fix, TabItemViewModel.TabItemId.CommunityProxy),
(typeof(MyFragment), () => MyPageViewModel.DisplayName, Resource.Id.navigation_my, default),
};
SetSupportActionBar(binding!.toolbar);
R.Subscribe(() =>
{
if (binding == null) return;
foreach (var (_, getTitle, menuId, _) in fragments)
{
var title = getTitle();
SetSubPageTitle(menuId, title);
}
SetTitleByPosition(binding.viewPager2.CurrentItem);
}).AddTo(this);
var adapter = new ViewPagerAdapter(this, this);
binding.viewPager2.Adapter = adapter;
binding.viewPager2.RegisterOnPageChangeCallback(new OnPageChangeCallback(this));
binding.nav_view.SetOnItemSelectedListener(this);
}
sealed class OnPageChangeCallback : ViewPager2.OnPageChangeCallback
{
readonly MainActivity thiz;
public OnPageChangeCallback(MainActivity thiz)
{
this.thiz = thiz;
var title = getTitle();
SetSubPageTitle(menuId, title);
}
SetTitleByPosition(binding.viewPager2.CurrentItem);
}).AddTo(this);
public override void OnPageSelected(int position)
{
thiz.OnPageSelected(position);
}
var adapter = new ViewPagerAdapter(this, this);
binding.viewPager2.Adapter = adapter;
binding.viewPager2.RegisterOnPageChangeCallback(new OnPageChangeCallback(this));
binding.nav_view.SetOnItemSelectedListener(this);
}
sealed class OnPageChangeCallback : ViewPager2.OnPageChangeCallback
{
readonly MainActivity thiz;
public OnPageChangeCallback(MainActivity thiz)
{
this.thiz = thiz;
}
protected override void OnNewIntent(Intent? intent)
public override void OnPageSelected(int position)
{
base.OnNewIntent(intent);
thiz.OnPageSelected(position);
}
}
if (binding == null || fragments == null) return;
var action = intent?.Action;
if (!string.IsNullOrWhiteSpace(action))
protected override void OnNewIntent(Intent? intent)
{
base.OnNewIntent(intent);
if (binding == null || fragments == null) return;
var action = intent?.Action;
if (!string.IsNullOrWhiteSpace(action))
{
if (Enum.TryParse<TabItemViewModel.TabItemId>(action, out var tabItem))
{
if (Enum.TryParse<TabItemViewModel.TabItemId>(action, out var tabItem))
for (int i = 0; i < fragments!.Length; i++)
{
for (int i = 0; i < fragments!.Length; i++)
if (fragments[i].tabItemId == tabItem)
{
if (fragments[i].tabItemId == tabItem)
{
Navigate(i);
}
Navigate(i);
}
}
}
}
}
int ViewPagerAdapter.IHost.ItemCount => fragments!.Length;
int ViewPagerAdapter.IHost.ItemCount => fragments!.Length;
Fragment ViewPagerAdapter.IHost.CreateFragment(int position) => (Fragment)Activator.CreateInstance(fragments![position].fragmentType);
Fragment ViewPagerAdapter.IHost.CreateFragment(int position) => (Fragment)Activator.CreateInstance(fragments![position].fragmentType);
bool NavigationBarView.IOnItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
bool NavigationBarView.IOnItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
if (binding == null || fragments == null) return false;
var itemId = item.ItemId;
for (int i = 0; i < fragments!.Length; i++)
{
if (binding == null || fragments == null) return false;
var itemId = item.ItemId;
for (int i = 0; i < fragments!.Length; i++)
if (fragments[i].menuId == itemId)
{
if (fragments[i].menuId == itemId)
{
Navigate(i);
return true;
}
Navigate(i);
return true;
}
return false;
}
return false;
}
void Navigate(int position)
{
binding!.viewPager2.SetCurrentItem(position, false);
SetTitleByPosition(position);
SetChecked(position);
}
void Navigate(int position)
{
binding!.viewPager2.SetCurrentItem(position, false);
SetTitleByPosition(position);
SetChecked(position);
}
void SetTitleByPosition(int position)
{
var title = fragments![position].getTitle();
Title = title;
}
void SetTitleByPosition(int position)
{
var title = fragments![position].getTitle();
Title = title;
}
void OnPageSelected(int position)
{
if (binding == null) return;
SetTitleByPosition(position);
SetChecked(position);
}
void OnPageSelected(int position)
{
if (binding == null) return;
SetTitleByPosition(position);
SetChecked(position);
}
void SetChecked(int position)
{
var menuItem = binding!.nav_view.Menu.FindItem(fragments![position].menuId);
if (menuItem != null && !menuItem.IsChecked) menuItem.SetChecked(true);
}
void SetChecked(int position)
{
var menuItem = binding!.nav_view.Menu.FindItem(fragments![position].menuId);
if (menuItem != null && !menuItem.IsChecked) menuItem.SetChecked(true);
}
}
#endif
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using Android.App;
using Android.Content.PM;
using Android.OS;
@@ -5,31 +6,31 @@ using Android.Runtime;
using Android.Views;
using System.Application.Security;
namespace System.Application.UI.Activities
{
/// <summary>
/// 页面 - 启动屏幕
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(SplashActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_Splash,
MainLauncher = true,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges,
NoHistory = true)]
internal sealed class SplashActivity : Activity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
//if (!DeviceSecurityCheckUtil.IsAllowStart(this)) return;
StartActivity(IAndroidApplication.Instance.MainActivityType);
OverridePendingTransition(Resource.Animation.abc_fade_in, Resource.Animation.abc_fade_out);
}
namespace System.Application.UI.Activities;
public override void OnBackPressed()
{
GoToPlatformPages.MockHomePressed(this);
return;
}
/// <summary>
/// 页面 - 启动屏幕
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(SplashActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_Splash,
MainLauncher = true,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges,
NoHistory = true)]
internal sealed class SplashActivity : Activity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
//if (!DeviceSecurityCheckUtil.IsAllowStart(this)) return;
StartActivity(IAndroidApplication.Instance.MainActivityType);
OverridePendingTransition(Resource.Animation.abc_fade_in, Resource.Animation.abc_fade_out);
}
}
public override void OnBackPressed()
{
GoToPlatformPages.MockHomePressed(this);
return;
}
}
#endif
@@ -2,7 +2,11 @@ using Android.Views;
using Binding;
using ReactiveUI;
using System.Application.UI.ViewModels;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using TViewHolder = System.Application.UI.Adapters.FastLoginChannelViewHolder;
using TViewModel = System.Application.UI.ViewModels.LoginOrRegisterWindowViewModel.FastLoginChannelViewModel;
@@ -1,14 +1,18 @@
using Android.Views;
using Binding;
using ReactiveUI;
using System.Threading.Tasks;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Application.UI.Activities;
using static System.Application.UI.Resx.AppResources;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using TViewHolder = System.Application.UI.Adapters.SteamAuthTradeConfirmationViewHolder;
using TViewModel = WinAuth.WinAuthSteamClient.Confirmation;
using static System.Application.UI.Resx.AppResources;
using System.Application.UI.Activities;
using XEPlatform = Xamarin.Essentials.Platform;
using System.Threading.Tasks;
namespace System.Application.UI.Adapters
{
@@ -13,7 +13,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reflection;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
// ReSharper disable once CheckNamespace
namespace System.Application.UI.Activities
@@ -13,7 +13,11 @@ using System.Application.UI.Adapters;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Text;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using static System.Application.UI.ViewModels.AboutPageViewModel;
using M = System.Application.UI.ViewModels.AboutPageViewModel;
using V = Binding.fragment_about;
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
#if !NET6_0_MAUI_LIB
using AndroidApplication = Android.App.Application;
namespace System.Application.UI
@@ -10,3 +8,4 @@ namespace System.Application.UI
}
}
#endif
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using System.Application.Services;
using System.Application.UI.Activities;
using System.Collections.Generic;
@@ -25,10 +26,11 @@ namespace System.Application.UI
VisualStudioAppCenterSDK.Init();
}
void IApplication.IProgramHost.ConfigureServices(DILevel level) => ConfigureServices(this, level);
void IApplication.IProgramHost.ConfigureServices(DILevel level, bool isTrace) => ConfigureServices(this, level, isTrace: isTrace);
void IApplication.IProgramHost.OnStartup() => OnStartup(this);
IApplication IApplication.IProgramHost.Application => this;
}
}
#endif
+4 -6
View File
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using Android.App;
using Android.Runtime;
using System.Application.UI.Resx;
@@ -102,7 +103,7 @@ namespace System.Application.UI
var level = DILevel.Min;
if (IsMainProcess) level = DILevel.MainProcess;
IApplication.IProgramHost host = this;
host.ConfigureServices(level);
host.ConfigureServices(level, isTrace);
if (isTrace) StartWatchTrace.Record("Startup");
if (IsMainProcess)
@@ -125,8 +126,6 @@ namespace System.Application.UI
if (IsMainProcess)
{
var vmService = IViewModelManager.Instance;
#if __XAMARIN_FORMS__
Forms.Init(this, null);
FormsMaterial.Init(this, null);
@@ -136,8 +135,6 @@ namespace System.Application.UI
_Current = new(RealTheme);
if (isTrace) StartWatchTrace.Record("XFApp");
#endif
vmService.MainWindow!.Initialize();
if (isTrace) StartWatchTrace.Record("MainVM.Init");
}
StartupTrack = StartWatchTrace.ToString();
@@ -290,4 +287,5 @@ namespace System.Application.UI
void IApplication.PlatformInitSettingSubscribe() => PlatformInitSettingSubscribe();
}
}
}
#endif
+16 -13
View File
@@ -1,24 +1,27 @@
using Android.Util;
using AndroidX.SwipeRefreshLayout.Widget;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.UI
namespace System.Application.UI;
public static class StylesEx
{
public static class Styles
public static void InitDefaultStyles(this SwipeRefreshLayout swipeRefreshLayout)
{
public static void InitDefaultStyles(this SwipeRefreshLayout swipeRefreshLayout)
{
swipeRefreshLayout.SetColorSchemeColors(new[] { ColorPrimary });
}
swipeRefreshLayout.SetColorSchemeColors(new[] { ColorPrimary });
}
public static int ColorPrimary
public static int ColorPrimary
{
get
{
get
{
using TypedValue typedValue = new();
XEPlatform.CurrentActivity.Theme!.ResolveAttribute(Resource.Attribute.colorPrimary, typedValue, true);
return typedValue.Data;
}
using TypedValue typedValue = new();
XEPlatform.CurrentActivity.Theme!.ResolveAttribute(Resource.Attribute.colorPrimary, typedValue, true);
return typedValue.Data;
}
}
}
@@ -6,7 +6,11 @@ using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using AndroidAppActivity = Android.App.Activity;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using AndroidAppResult = Android.App.Result;
// 将 onActivityResult() 转换为 System.Threading.Tasks.Task
@@ -1,14 +1,29 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<!--<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-android;net6.0-windows</TargetFrameworks>-->
<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-windows</TargetFrameworks>
<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-android;net6.0-windows;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<RootNamespace>System.Application.AppCenter</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.AppCenter</AssemblyName>
<ImplicitUsings>enable</ImplicitUsings>
<AndroidUseIntermediateDesignerFile>false</AndroidUseIntermediateDesignerFile>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<SupportedOSPlatformVersion>21.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<TargetPlatformMinVersion>7.0</TargetPlatformMinVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
@@ -23,17 +38,17 @@
<Link>Properties\AssemblyInfo.OS.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AppCenter" />
<PackageReference Include="Microsoft.AppCenter.Analytics" />
<PackageReference Include="Microsoft.AppCenter.Crashes" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ST.Client.Android.ResSecrets\ST.Client.Android.ResSecrets.csproj" Condition=" $(TargetFramework.StartsWith('MonoAndroid')) OR $(TargetFramework.Contains('-android')) " />
<ProjectReference Include="..\ST.Client.iOS.ResSecrets\ST.Client.iOS.ResSecrets.csproj" Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) OR $(TargetFramework.Contains('-ios')) " />
+175 -71
View File
@@ -1,12 +1,13 @@
using System.Application.UI;
using System.Application.Services;
using System.CommandLine;
using System.CommandLine.NamingConventionBinder;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Application.Settings;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.CommandLine;
using System.CommandLine.NamingConventionBinder;
using System.Application.UI;
using System.Application.Services;
using System.Application.Settings;
using System.Application.UI.ViewModels;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
@@ -22,7 +23,7 @@ public abstract class CommandLineHost : IDisposable
protected abstract IApplication.IDesktopProgramHost Host { get; }
protected abstract void ConfigureServices(DILevel level);
protected abstract void ConfigureServices(DILevel level, bool isTrace = false);
#if StartWatchTrace
protected abstract void StartWatchTraceRecord(string? mark = null, bool dispose = false);
@@ -34,6 +35,26 @@ public abstract class CommandLineHost : IDisposable
public abstract IApplication? Application { get; }
Task<IApplication>? _WaitForApplication;
public Task<IApplication> WaitForApplicationAsync()
{
if (Application != null) return Task.FromResult(Application);
lock (this)
{
if (_WaitForApplication == null)
_WaitForApplication = Task.Run(async () =>
{
while (Application == null)
{
await Task.Delay(500);
}
return Application;
});
return _WaitForApplication;
}
}
protected abstract void SetIsMainProcess(bool value);
protected abstract void SetIsCLTProcess(bool value);
@@ -45,6 +66,34 @@ public abstract class CommandLineHost : IDisposable
// https://docs.microsoft.com/zh-cn/archive/msdn-magazine/2019/march/net-parse-the-command-line-with-system-commandline
var rootCommand = new RootCommand("命令行工具(Command Line Tools/CLT)");
bool InitAppInstance(Func<string>? sendMessage = null)
{
var isInitAppInstanceReset = false;
initAppInstance: AppInstance = new();
if (!AppInstance.IsFirst)
{
//Console.WriteLine("ApplicationInstance.SendMessage(string.Empty);");
if (IApplication.SingletonInstance.SendMessage(sendMessage?.Invoke() ?? ""))
{
return false;
}
else
{
if (!isInitAppInstanceReset &&
IApplication.SingletonInstance.TryKillCurrentAllProcess())
{
isInitAppInstanceReset = true;
AppInstance.Dispose();
goto initAppInstance;
}
else
{
return false;
}
}
}
return true;
}
void MainHandler() => MainHandler_(null);
void MainHandler_(Action? onInitStartuped, Func<string>? sendMessage = null)
{
@@ -58,68 +107,67 @@ public abstract class CommandLineHost : IDisposable
onInitStartuped?.Invoke();
if (Host.IsMainProcess)
{
var isInitAppInstanceReset = false;
initAppInstance: AppInstance = new();
if (!AppInstance.IsFirst)
if (!InitAppInstance(sendMessage))
{
//Console.WriteLine("ApplicationInstance.SendMessage(string.Empty);");
if (IApplication.SingletonInstance.SendMessage(sendMessage?.Invoke() ?? ""))
{
return;
}
else
{
if (!isInitAppInstanceReset &&
IApplication.SingletonInstance.TryKillCurrentAllProcess())
{
isInitAppInstanceReset = true;
AppInstance.Dispose();
goto initAppInstance;
}
else
{
return;
}
}
return;
}
AppInstance.MessageReceived += value =>
AppInstance!.MessageReceived += async value =>
{
if (!string.IsNullOrEmpty(value))
{
var args = value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (args.Length >= 1)
switch (value)
{
switch (args[0])
{
case key_proxy:
if (args.Length >= 2)
case key_shutdown:
(await WaitForApplicationAsync()).Shutdown();
return;
default:
var args = value.Split(' ', StringSplitOptions.RemoveEmptyEntries);
if (args.Length >= 1)
{
switch (args[0])
{
ProxyMessageReceived();
return;
}
void ProxyMessageReceived()
{
var value = Enum.TryParse<EOnOff>(args[1], out var value_) ? value_ : default;
MainThread2.BeginInvokeOnMainThread(() =>
{
ProxyService.Current.ProxyStatus = value switch
case key_proxy:
if (args.Length >= 2)
{
EOnOff.On => true,
EOnOff.Off => false,
_ => !ProxyService.Current.ProxyStatus,
};
});
ProxyMessageReceived();
return;
}
void ProxyMessageReceived()
{
var value = Enum.TryParse<EOnOff>(args[1], out var value_) ? value_ : default;
try
{
MainThread2.BeginInvokeOnMainThread(() =>
{
ProxyService.Current.ProxyStatus = value switch
{
EOnOff.On => true,
EOnOff.Off => false,
_ => !ProxyService.Current.ProxyStatus,
};
});
}
catch
{
}
}
break;
}
break;
}
}
break;
}
}
var app = Application;
if (app != null)
try
{
var app = await WaitForApplicationAsync();
MainThread2.BeginInvokeOnMainThread(app.RestoreMainWindow);
}
catch
{
}
};
}
//#if StartWatchTrace
@@ -263,27 +311,27 @@ public abstract class CommandLineHost : IDisposable
// -clt show -config -cert
var show = new Command("show", "显示信息");
show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
//show.AddOption(new Option<bool>("-config", "显示 Config.mpo 值"));
show.AddOption(new Option<bool>("-cert", "显示当前根证书信息"));
show.Handler = CommandHandler.Create((bool config, bool cert) =>
show.Handler = CommandHandler.Create((/*bool config,*/ bool cert) =>
{
if (OperatingSystem.IsWindows()) if (!AttachConsole()) AllocConsole();
if (config)
{
Console.WriteLine("Config: ");
try
{
SettingsHost.Load();
var configValue = SettingsHostBase.Local.ToJsonString();
Console.WriteLine(configValue);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine();
}
//if (config)
//{
// Console.WriteLine("Config: ");
// try
// {
// SettingsHost.Load();
// var configValue = SettingsHostBase.Local.ToJsonString();
// Console.WriteLine(configValue);
// }
// catch (Exception e)
// {
// Console.WriteLine(e.ToString());
// }
// Console.WriteLine();
//}
if (cert)
{
@@ -337,11 +385,66 @@ public abstract class CommandLineHost : IDisposable
});
rootCommand.AddCommand(proxy);
// -clt ayaneo -path
var ayaneo = new Command("ayaneo", "生成 ayaneo 数据在指定位置");
ayaneo.AddOption(new Option<string>("-path", "json 生成路径"));
ayaneo.Handler = CommandHandler.Create((string path) =>
{
ConfigureServices(DILevel.Steam);
var steamService = ISteamService.Instance;
var users = steamService.GetRememberUserList();
#pragma warning disable CA1416 // 验证平台兼容性
IReadOnlyDictionary<long, string?>? accountRemarks = SteamAccountSettings.AccountRemarks.Value;
#pragma warning restore CA1416 // 验证平台兼容性
var sUsers = users.Select(s =>
{
if (accountRemarks?.TryGetValue(s.SteamId64, out var remark) == true &&
!string.IsNullOrEmpty(remark))
s.Remark = remark;
var title = s.SteamNickName ?? s.SteamId64.ToString(CultureInfo.InvariantCulture);
if (!string.IsNullOrEmpty(s.Remark))
title = s.SteamNickName + "(" + s.Remark + ")";
#pragma warning disable CS8619 // 值中的引用类型的为 Null 性与目标类型不匹配。
return new
{
Name = title,
Account = s.AccountName,
};
#pragma warning restore CS8619 // 值中的引用类型的为 Null 性与目标类型不匹配。
});
var content = new
{
steamppPath = Path.Combine(IOPath.BaseDirectory, System.Application.Constants.HARDCODED_APP_NAME + ".exe"),
steamUsers = sUsers,
};
if (string.IsNullOrWhiteSpace(path))
{
path = Path.Combine(IOPath.BaseDirectory, "steampp.json");
}
File.WriteAllText(path, Serializable.SJSON(content));
});
rootCommand.AddCommand(ayaneo);
// -clt shutdown
var shutdown = new Command(key_shutdown, "安全结束正在运行的程序")
{
Handler = CommandHandler.Create(() =>
{
InitAppInstance(() => key_shutdown);
}),
};
rootCommand.AddCommand(shutdown);
var r = rootCommand.InvokeAsync(args).GetAwaiter().GetResult();
return r;
}
const string key_proxy = "proxy";
const string key_shutdown = "shutdown";
protected virtual void Dispose(bool disposing)
{
@@ -350,6 +453,7 @@ public abstract class CommandLineHost : IDisposable
if (disposing)
{
// TODO: 释放托管状态(托管对象)
_WaitForApplication = null;
AppInstance?.Dispose();
Application?.Dispose();
}
@@ -5,12 +5,13 @@
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap rescap">
xmlns:desktop2="http://schemas.microsoft.com/appx/manifest/desktop/windows10/2"
IgnorableNamespaces="uap rescap desktop desktop2">
<Identity
Name="4651ED44255E.47979655102CE"
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
Version="2.8.1.0" />
Version="2.8.4.0" />
<Properties>
<DisplayName>Watt Toolkit</DisplayName>
@@ -59,6 +60,15 @@
</Application>
</Applications>
<Extensions>
<desktop2:Extension Category="windows.firewallRules">
<desktop2:FirewallRules Executable="Steam++\Steam++.exe">
<desktop2:Rule Direction="in" IPProtocol="TCP" Profile="all" />
<desktop2:Rule Direction="in" IPProtocol="UDP" Profile="all" />
</desktop2:FirewallRules>
</desktop2:Extension>
</Extensions>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
@@ -18,6 +18,7 @@
<WindowsSdkPackageVersion>10.0.19041.24</WindowsSdkPackageVersion>
<UseWindowsForms Condition="'$(Configuration)'=='Debug'">true</UseWindowsForms>
<UseWPF>false</UseWPF>
<DefineConstants>AVALONIA;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
@@ -44,7 +45,7 @@
.allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>
@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
IgnorableNamespaces="uap rescap">
xmlns:desktop2="http://schemas.microsoft.com/appx/manifest/desktop/windows10/2"
IgnorableNamespaces="uap rescap desktop desktop2">
<Identity
Name="4651ED44255E.47979655102CE"
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
Version="2.8.1.0" />
Version="2.8.2.0" />
<Properties>
<DisplayName>Watt Toolkit</DisplayName>
@@ -59,6 +60,15 @@
</Application>
</Applications>
<Extensions>
<desktop2:Extension Category="windows.firewallRules">
<desktop2:FirewallRules Executable="Steam++.exe">
<desktop2:Rule Direction="in" IPProtocol="TCP" Profile="all" />
<desktop2:Rule Direction="in" IPProtocol="UDP" Profile="all" />
</desktop2:FirewallRules>
</desktop2:Extension>
</Extensions>
<Capabilities>
<Capability Name="internetClient" />
<rescap:Capability Name="runFullTrust" />
+44 -10
View File
@@ -1,14 +1,22 @@
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Runtime.Versioning;
using System.Application.Settings;
using System.Application.CommandLine;
using System.Application.UI.Resx;
using NLog;
using Avalonia;
using Avalonia.ReactiveUI;
using Avalonia.Controls;
#if WINDOWS || WINDOWS_DESKTOP_BRIDGE
using WPFMessageBox = System.Windows.MessageBox;
using WPFMessageBoxButton = System.Windows.MessageBoxButton;
using WPFMessageBoxImage = System.Windows.MessageBoxImage;
#endif
#if MAC
[assembly: SupportedOSPlatform("macOS")]
#elif LINUX
@@ -39,17 +47,42 @@ namespace System.Application.UI
// fix The request was aborted: Could not create SSL/TLS secure channel
TrySetSecurityProtocol();
var host = ProgramHost.Instance;
host.IsMainProcess = args.Length == 0;
host.IsCLTProcess = !host.IsMainProcess && args.FirstOrDefault() == "-clt";
#if WINDOWS_DESKTOP_BRIDGE
if (!DesktopBridgeHelper.Init()) return 0;
InitWithUWP(args);
InitWithUWP(ref args);
#elif WINDOWS
//#if NET7_0_OR_GREATER
// if (/*Environment.Version >= new Version(7, 0) && */!OperatingSystem2.IsWindows10AtLeast())
// {
// // [TBD] .NET 7 中考虑弃用对 Windows 7/2008 R2/8.1/2012 R2 的支持
// WPFMessageBox.Show("TBD", AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
// return 0;
// }
//#endif
if (OperatingSystem2.IsWindows10AtLeast() &&
!OperatingSystem.IsWindowsVersionAtLeast(10, 0, 14393))
{
// Win10 最低需要 1607,低于此版本则弹窗错误中止运行
// appcenter.ms 上有 10240,10586 的 crash 报告
WPFMessageBox.Show(AppResources.Error_Lower_Than_Windows10_1607, AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
return 0;
}
if (AppContext.BaseDirectory.StartsWith(Path.GetTempPath(), StringComparison.OrdinalIgnoreCase))
{
// 检测当前目录 Temp\Rar$ 这类目录,可能是在压缩包中直接启动程序导致的,还有一堆 文件找不到/加载失败的异常
// System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\USER\AppData\Local\Temp\Rar$EXa15528.13350\Cache\switchproxy.reg'.
// System.IO.FileLoadException ...
// System.IO.FileNotFoundException: Could not load file or assembly ...
WPFMessageBox.Show(AppResources.Error_BaseDir_StartsWith_Temp, AppResources.Error, WPFMessageBoxButton.OK, WPFMessageBoxImage.Error);
return 0;
}
#elif MAC
InitWithMAC(args);
#endif
var host = ProgramHost.Instance;
host.IsMainProcess = args.Length == 0;
host.IsCLTProcess = !host.IsMainProcess && args.FirstOrDefault() == "-clt";
OnCreateAppExecuting();
// InitCefNetApp(args);
@@ -77,16 +110,17 @@ namespace System.Application.UI
// Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
PlatformApp?.Dispose();
DI.Dispose();
LogManager.Shutdown();
}
}
static void TrySetSecurityProtocol(SecurityProtocolType type = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13)
static void TrySetSecurityProtocol(SecurityProtocolType type = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13)
{
try
{
ServicePointManager.SecurityProtocol = type;
}
catch (NotSupportedException)
catch
{
}
@@ -97,7 +131,7 @@ namespace System.Application.UI
static void ShowArgs(string[] args) => WinFormsMessageBox.Show(string.Join(' ', args), "Main(string[] args)");
#endif
static void InitWithUWP(string[] args)
static void InitWithUWP(ref string[] args)
{
#if DEBUG && !MSIX_SINGLE_PROJECT
ShowArgs(args);
@@ -204,7 +238,7 @@ namespace System.Application.UI
static void StartAvaloniaApp(string[] args, ShutdownMode shutdownMode = ShutdownMode.OnLastWindowClose)
{
var builder = BuildAvaloniaApp();
builder.StartWithClassicDesktopLifetime(args, shutdownMode);
builder.StartWithClassicDesktopLifetime2(args, shutdownMode);
}
}
}
@@ -4,6 +4,7 @@ using System.Application.Services;
using Program = System.Application.UI.MauiProgram;
#endif
// ReSharper disable once CheckNamespace
namespace System.Application.UI;
static partial class
@@ -37,7 +38,7 @@ static partial class
public EOnOff ProxyStatus { get; set; }
void IApplication.IProgramHost.ConfigureServices(DILevel level) => ConfigureServices(level);
void IApplication.IProgramHost.ConfigureServices(DILevel level, bool isTrace) => ConfigureServices(level, isTrace);
public void InitVisualStudioAppCenterSDK()
{
@@ -55,6 +56,14 @@ static partial class
IApplication IApplication.IProgramHost.Application => App.Instance;
void IApplication.IDesktopProgramHost.OnCreateAppExecuted(Action<IViewModelManager>? handlerViewModelManager, bool isTrace) => Program.OnCreateAppExecuted(this, handlerViewModelManager, isTrace);
DeploymentMode IApplication.IDesktopProgramHost.DeploymentMode => DeploymentMode.
#if FRAMEWORK_DEPENDENT || !PUBLISH
FDE
#else
SCD
#endif
;
}
partial class ProgramHost : CommandLineHost
@@ -63,7 +72,7 @@ static partial class
public Action<DILevel>? ConfigureServicesDelegate { get; set; }
protected override void ConfigureServices(DILevel level)
protected override void ConfigureServices(DILevel level, bool isTrace = false)
{
if (ConfigureServicesDelegate != null)
{
@@ -71,7 +80,7 @@ static partial class
}
else
{
Program.ConfigureServices(this, level);
Program.ConfigureServices(this, level, isTrace: isTrace);
}
}
@@ -9,6 +9,7 @@
<RootNamespace>System.Application.UI</RootNamespace>
<AssemblyName>Steam++</AssemblyName>
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
<DefineConstants>AVALONIA;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
@@ -0,0 +1,57 @@
using System.Application.Services;
using System.Application.Settings;
using System.Application.UI.ViewModels;
using System.Application.UI.Views;
#if !MAUI
using System.Application.UI.Views.Windows;
#endif
namespace System.Application.UI;
partial class App
{
void HandlerViewModelManager(IViewModelManager vmService)
{
switch (vmService.MainWindow)
{
case CloudArchiveWindowViewModel:
ProgramHost.IsMinimize = false;
#if !MAUI
MainWindow = new CloudArchiveWindow();
#endif
break;
case AchievementWindowViewModel:
ProgramHost.IsMinimize = false;
#if !MAUI
MainWindow = new AchievementWindow();
#endif
break;
default:
#region 主窗口启动时加载的资源
#if !UI_DEMO
compositeDisposable.Add(SettingsHost.Save);
compositeDisposable.Add(ProxyService.Current.Exit);
if (IApplication.IsDesktopPlatform)
{
compositeDisposable.Add(SteamConnectService.Current.Dispose);
if (GeneralSettings.IsStartupAppMinimized.Value)
ProgramHost.IsMinimize = true;
}
compositeDisposable.Add(ASFService.Current.StopASF);
#endif
#endregion
#if !MAUI
MainWindow = new MainWindow();
#endif
break;
}
#if !MAUI
MainWindow.DataContext = vmService.MainWindow;
#else
var mainWindowVM = (MainWindowViewModel?)vmService.MainWindow;
MainPage = new AppShell(mainWindowVM.ThrowIsNull());
#endif
}
}

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