Compare commits

...
110 Commits
Author SHA1 Message Date
Aigio Liu b21972db50 fix Resx Values 2022-04-01 11:11:17 +08:00
Aigio Liu 7a12b50ba4 Add ProxyMode Resx String 2022-04-01 11:04:57 +08:00
RMBGAME cfb5796cb6 fix #1186 2022-03-31 16:59:29 +08:00
RMBGAME faecc2b4d8 SteamApp Edit Save 2022-03-31 16:51:01 +08:00
Aigio Liu c3c7c889d4 ProxySettings.ProxyMode replace ProxySettings.IsVpnMode 2022-03-28 22:31:38 +08:00
RMBGAME e29e7a8f0e Update FluentAvalonia 2022-03-26 00:15:46 +08:00
Aigio Liu 3723e0866f #1167 当使用 IPC.config 时,程序内打开网页端口号值不正确 2022-03-25 22:45:02 +08:00
Mossimo bf5ca108e0 DeleteCer security delete-certificate -Z Sha-1 2022-03-25 17:37:51 +08:00
Aigio Liu 69e60440e1 fix Android Guide Pages Test API 21 🆗 2022-03-25 10:22:01 +08:00
RMBGAME 76e75abbc2 Merge pull request #1166 from BeyondDimension/dependabot/nuget/Avalonia.Xaml.Behaviors-0.10.13.2
Bump Avalonia.Xaml.Behaviors from 0.10.13 to 0.10.13.2
2022-03-25 07:45:52 +08:00
dependabot[bot] df7c1d62fb Bump Avalonia.Xaml.Behaviors from 0.10.13 to 0.10.13.2
Bumps [Avalonia.Xaml.Behaviors](https://github.com/wieslawsoltes/AvaloniaBehaviors) from 0.10.13 to 0.10.13.2.
- [Release notes](https://github.com/wieslawsoltes/AvaloniaBehaviors/releases)
- [Commits](https://github.com/wieslawsoltes/AvaloniaBehaviors/compare/0.10.13...0.10.13.2)

---
updated-dependencies:
- dependency-name: Avalonia.Xaml.Behaviors
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-24 23:21:38 +00:00
Aigio Liu ceabdaaa64 fix Android Guide Pages Test API 31 🆗 2022-03-25 00:17:47 +08:00
Aigio Liu 170dc355b7 use NextRequestCode() 2022-03-24 19:29:28 +08:00
Aigio Liu 0b9bccf1e3 Android Guide Pages 2022-03-24 19:21:54 +08:00
dependabot[bot] 91ce45feda Bump Avalonia.Xaml.Behaviors from 0.10.12.2 to 0.10.13
Bumps [Avalonia.Xaml.Behaviors](https://github.com/wieslawsoltes/AvaloniaBehaviors) from 0.10.12.2 to 0.10.13.
- [Release notes](https://github.com/wieslawsoltes/AvaloniaBehaviors/releases)
- [Commits](https://github.com/wieslawsoltes/AvaloniaBehaviors/compare/0.10.12.2...0.10.13)

---
updated-dependencies:
- dependency-name: Avalonia.Xaml.Behaviors
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-24 13:35:57 +08:00
RMBGAME 61722994b1 起始页UI更新 2022-03-24 08:47:00 +08:00
RMBGAME 15557ecd74 改进部分UI问题 2022-03-24 07:49:58 +08:00
RMBGAME 53b2c514a5 新增库存游戏类型筛选状态保存 2022-03-24 06:23:32 +08:00
RMBGAME f7a5646836 Merge pull request #794 from BeyondDimension/feature/edit-game-info
v2.7.0 累计改动提交
2022-03-23 15:02:03 +08:00
Aigio Liu 29820061e1 fix slnf 2022-03-23 14:57:21 +08:00
RMBGAME 281332be71 fix https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/1089197758u/overview
修复菜单切换社区加速UI错位问题 fix #915
修复菜单切换时会错误的重置当前页面的一些状态,例如ASF滚动条无法置底问题
2022-03-23 14:37:23 +08:00
RMBGAME 92f1eb9585 Merge branch 'develop' into feature/edit-game-info 2022-03-23 10:29:19 +08:00
RMBGAME 0b9fdcc0b6 StartPage 2022-03-23 10:27:11 +08:00
Aigio Liu d83c0536c9 Add System.Runtime.CompilerServices.IsExternalInit 2022-03-23 10:24:26 +08:00
RMBGAME d95559e36a Add StartPage & Update New Icon 2022-03-23 08:06:54 +08:00
RMBGAME 185532c79a 修正高DPI下主菜单图标模糊问题 2022-03-23 05:20:26 +08:00
dependabot[bot] c6710ddf2c Bump Z.EntityFramework.Plus.EFCore from 6.13.14 to 6.13.15
Bumps [Z.EntityFramework.Plus.EFCore](https://github.com/zzzprojects/EntityFramework-Plus) from 6.13.14 to 6.13.15.
- [Release notes](https://github.com/zzzprojects/EntityFramework-Plus/releases)
- [Commits](https://github.com/zzzprojects/EntityFramework-Plus/compare/6.13.14...6.13.15)

---
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>
2022-03-22 11:10:00 +08:00
dependabot[bot] 537fc51d49 Bump NUnit from 3.13.2 to 3.13.3
Bumps [NUnit](https://github.com/nunit/nunit) from 3.13.2 to 3.13.3.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/v3.13.3/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/v3.13.2...v3.13.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-22 11:07:47 +08:00
Aigio Liu ed3cf8d36e Update README & Update Android About UI 2022-03-21 21:13:02 +08:00
RMBGAME 09ab684548 Merge branch 'develop' into feature/edit-game-info 2022-03-21 08:49:44 +08:00
RMBGAME fbe0d85d12 UI 样式优化调整 2022-03-21 08:44:19 +08:00
RMBGAME 5887602e31 fix ex 2022-03-21 07:42:02 +08:00
RMBGAME e0bbb58c1a Merge branch 'develop' into feature/edit-game-info 2022-03-21 06:40:30 +08:00
RMBGAME 3b3bcc856a rename FilePicker 2022-03-21 06:38:49 +08:00
Aigio Liu 846c9feac1 fix IsAdministrator 2022-03-19 16:18:25 +08:00
Aigio Liu 8f7930450f v2.7.0 in progress 2022-03-19 14:02:29 +08:00
Aigio Liu c913f623e9 finish Android VpnService 2022-03-19 13:28:05 +08:00
Aigio Liu 21a2dc8d31 add arrays.xml 2022-03-19 13:28:04 +08:00
Aigio Liu eef90d9aaf IsAdministrator Impl => ASF IsRunningAsRoot
Add OnMainOpenTryShowNewVersionWindow
2022-03-17 19:11:14 +08:00
RMBGAME 7e1b4bd820 fix https://appcenter.ms/orgs/BeyondDimension/apps/Steam/crashes/errors/1887110022u 2022-03-17 18:47:03 +08:00
Mossimo 2af95b4491 Linux 可以监听443端口配置 2022-03-17 17:48:31 +08:00
Mossimo 5167c6cbfe fix build osxapp 2022-03-17 15:14:25 +08:00
RMBGAME c551cd278e Merge branch 'develop' into feature/edit-game-info 2022-03-17 15:07:20 +08:00
RMBGAME 258aa518a9 hosts加速模式下不能使用仅启用脚本功能 2022-03-17 14:41:51 +08:00
Mossimo 6158b30364 tryfix 2022-03-17 14:11:11 +08:00
Mossimo f721c6695f try build 2022-03-17 13:54:53 +08:00
Mossimo a8c7a6fe02 try fix 2022-03-17 13:37:46 +08:00
Mossimo 8969f7008c tryFixOsxBuild SH 2022-03-17 13:12:24 +08:00
Aigio Liu f0e6a4fb8f fix OSXBuild 2022-03-17 12:45:35 +08:00
Aigio Liu e647d195fa fix OSXBuild 2022-03-17 10:48:09 +08:00
Aigio Liu 229e9644de fix Publish Tool OSXBuild & Add Debug Command 2022-03-17 10:45:23 +08:00
Aigio Liu ea59d32c93 add x86 Native Library README 2022-03-17 10:44:51 +08:00
Aigio Liu d794fb6a22 Add Native Library README.md
fix Android Java.Lang.NoSuchMethodError: no non-static method "Landroid/widget/CompoundButton;.getButtonDrawable()Landroid/graphics/drawable/Drawable;"
https://developer.android.google.cn/reference/kotlin/android/widget/CompoundButton?hl=en#getbuttondrawable
try fix AuthService.ImportSteamGuard NullReferenceException
2022-03-17 10:16:34 +08:00
Mossimo 62ad711dbd try build osx 2022-03-16 13:35:31 +08:00
RMBGAME 2f472a55ad 完成 FilePicker UI 2022-03-16 12:47:28 +08:00
Aigio Liu 588d663216 fix osx-arm64.pubxml 2022-03-16 11:53:46 +08:00
Aigio Liu 5510b4915c add libe_sqlite3.dylib 2022-03-16 11:53:20 +08:00
Aigio Liu f3649d3246 fix macos-arm64 pubxml 2022-03-16 11:33:08 +08:00
RMBGAME fe45b39c8f Merge branch 'develop' into feature/edit-game-info 2022-03-16 09:47:10 +08:00
RMBGAME c59fb1076c Merge pull request #1109 from BeyondDimension/dependabot/submodules/references/AvaloniaGif-7b41651
Bump references/AvaloniaGif from `016cf27` to `7b41651`
2022-03-16 09:46:13 +08:00
RMBGAME 7717188152 Update FluentAvalonia 2022-03-16 09:45:27 +08:00
RMBGAME 8e78557f16 50% 2022-03-16 09:38:19 +08:00
Aigio Liu 835083b899 Remove Microsoft Store 2022-03-15 08:53:42 +08:00
RMBGAME 1588749280 SteamGridDB API Added 2022-03-15 07:07:06 +08:00
RMBGAME 69c6baf39e FilePicker Control 2022-03-14 03:39:15 +08:00
RMBGAME 36bff3751d only installed load launch items 2022-03-12 03:53:37 +08:00
Mossimo 86df7af88d fix 2022-03-12 03:22:22 +08:00
RMBGAME 09edd5dc3d Merge branch 'develop' into feature/edit-game-info 2022-03-12 03:16:14 +08:00
RMBGAME cd599de46a async 2022-03-12 03:14:48 +08:00
RMBGAME 3d8001dc75 async EnableProxyScripts 2022-03-12 03:11:11 +08:00
Mossimo da3a1e9d9d fix 2022-03-12 03:02:16 +08:00
RMBGAME 49aff6e7dc UI 2022-03-12 02:49:03 +08:00
Mossimo bf34c219a1 fix 2022-03-12 02:41:31 +08:00
RMBGAME efbc17d15f Merge branch 'develop' into feature/edit-game-info 2022-03-12 02:32:16 +08:00
RMBGAME 682165d90e Bump references/AvaloniaGif from 016cf27 to 7b41651 2022-03-12 02:30:00 +08:00
RMBGAME 046d60112c 编辑游戏支持启动项获取 2022-03-12 02:25:00 +08:00
Mossimo 927439c80d 优化脚本占用 不启动加速不占用内存
this.WhenAnyValue(v => v.ProxyScripts) add   if (httpProxyService.ProxyRunning)
2022-03-11 23:37:18 +08:00
Aigio Liu a28f8fa1e1 Add Shadowsocks.VpnService Impl & Store App Rename 2022-03-11 23:12:01 +08:00
dependabot[bot] 29cc793628 Bump Square.OkHttp3 from 4.9.2 to 4.9.3
Bumps [Square.OkHttp3](https://github.com/xamarin/XamarinComponents) from 4.9.2 to 4.9.3.
- [Release notes](https://github.com/xamarin/XamarinComponents/releases)
- [Commits](https://github.com/xamarin/XamarinComponents/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-11 12:58:47 +08:00
dependabot[bot] 42f8971bd7 Bump DynamicData from 7.6.2 to 7.6.5
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.6.2 to 7.6.5.
- [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.6.2...7.6.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-11 12:58:17 +08:00
Aigio Liu f98473246c Add Shadowsocks Kotlin Code 2022-03-09 20:57:53 +08:00
dependabot[bot] e9bbbd8a32 Bump DynamicData from 7.5.4 to 7.6.2
Bumps [DynamicData](https://github.com/reactiveui/DynamicData) from 7.5.4 to 7.6.2.
- [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.5.4...7.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-09 11:01:55 +08:00
dependabot[bot] 9a6c52b88f Bump Swashbuckle.AspNetCore from 6.2.3 to 6.3.0
Bumps [Swashbuckle.AspNetCore](https://github.com/domaindrivendev/Swashbuckle.AspNetCore) from 6.2.3 to 6.3.0.
- [Release notes](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases)
- [Commits](https://github.com/domaindrivendev/Swashbuckle.AspNetCore/compare/v6.2.3...v6.3.0)

---
updated-dependencies:
- dependency-name: Swashbuckle.AspNetCore
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-09 11:01:07 +08:00
Aigio Liu a603fdd834 Update .NET 6.0.3
https://devblogs.microsoft.com/dotnet/march-2022-updates
2022-03-09 09:50:14 +08:00
dependabot[bot] a5343bb2b2 Bump references/AvaloniaGif from 016cf27 to 7b41651
Bumps [references/AvaloniaGif](https://github.com/SteamTools-Team/AvaloniaGif) from `016cf27` to `7b41651`.
- [Release notes](https://github.com/SteamTools-Team/AvaloniaGif/releases)
- [Commits](https://github.com/SteamTools-Team/AvaloniaGif/compare/016cf27b57504bece57657ed6707e1ea3ffab02f...7b4165159df6948f9e8b35632cb42d626a1454f9)

---
updated-dependencies:
- dependency-name: references/AvaloniaGif
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-08 23:25:44 +00:00
RMBGAME e14eec48e9 改进库存游戏信息读取优化内存占用 2022-03-09 07:12:38 +08:00
RMBGAME 2f2923fdb8 Merge branch 'develop' into feature/edit-game-info 2022-03-09 02:20:58 +08:00
Aigio Liu f41fd35d78 Update ProxySettings.DefaultProxyMode 2022-03-09 00:31:23 +08:00
Aigio Liu 32e90b672f Add ProxyMode 2022-03-09 00:29:12 +08:00
RMBGAME ad98879d5c Update FluentAvalonia 2022-03-09 00:14:07 +08:00
Aigio Liu 61a4f05480 fix Android VpnService 2022-03-08 23:52:56 +08:00
Aigio Liu 3a8a232f98 fix V2RayVpnService AddDisallowedApplication this 2022-03-08 20:30:25 +08:00
Aigio Liu 52897064dd fix 2022-03-08 16:43:26 +08:00
Aigio Liu e202f4ae5e fix 2022-03-08 14:09:36 +08:00
Aigio Liu f51ce974de New MS Store Id 2022-03-08 11:06:18 +08:00
dependabot[bot] 4806dbcf27 Bump System.CommandLine from 2.0.0-beta1.21308.1 to 2.0.0-beta3.22114.1
Bumps [System.CommandLine](https://github.com/dotnet/command-line-api) from 2.0.0-beta1.21308.1 to 2.0.0-beta3.22114.1.
- [Release notes](https://github.com/dotnet/command-line-api/releases)
- [Changelog](https://github.com/dotnet/command-line-api/blob/main/docs/History.md)
- [Commits](https://github.com/dotnet/command-line-api/commits)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-08 10:23:18 +08:00
dependabot[bot] e1db44af68 Bump Moq from 4.17.1 to 4.17.2
Bumps [Moq](https://github.com/moq/moq4) from 4.17.1 to 4.17.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.17.1...v4.17.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-08 10:22:48 +08:00
Aigio Liu d6031c8acd API RefreshUserInfo 2022-03-07 10:25:32 +08:00
vanja-san 2852c630e9 Update SR.ru.resx 2022-03-06 10:51:15 +08:00
vanja-san 8a06b7d09f Update SR.ru.resx 2022-03-06 10:51:08 +08:00
vanja-san c14e548b0f Update SR.ru.resx 2022-03-06 10:51:03 +08:00
vanja-san 0820c880ac Update SR.ru.resx 2022-03-06 10:45:59 +08:00
vanja-san 84e3752f88 Update AppResources.ru.resx 2022-03-06 10:45:45 +08:00
Aigio Liu 1f62313978 Remove Resx Key [Script_Installed] & fix ru lost Resx Key [Settings_General_LogSize] 2022-03-05 21:44:49 +08:00
Aigio Liu ffcf0f0ff0 New translator author(Russian: vanja-san) 2022-03-05 21:30:18 +08:00
vanja-san c01a9157e2 Update AppResources.ru.resx 2022-03-05 20:56:55 +08:00
Aigio Liu 13db16b07c Update Android Packages
fix 空令牌刷新时提示密码错误
fix 令牌列表第一条与最后一条的内填充上下
2022-03-04 22:33:49 +08:00
Aigio Liu 33b76c6622 Android Change/BindPhoneNum Impl 2022-03-04 19:40:26 +08:00
RMBGAME 6480d258bf Merge branch 'develop' into feature/edit-game-info 2022-02-22 00:46:42 +08:00
RMBGAME 3fd32b3196 show editgameapp menu 2021-12-14 00:43:58 +08:00
294 changed files with 8857 additions and 12476 deletions
+2 -2
View File
@@ -152,7 +152,7 @@ jobs:
uses: actions/upload-artifact@v2
with:
name: '[${{ matrix.configuration }}]${{ env.ProjectName }}_linux_x64_${{ env.GITHUB_SHA_SHORT }}'
path: src\ST.Client.Desktop.Avalonia.App\bin\${{ matrix.configuration }}\Publish\${{ env.ProjectName }}_linux_x64_${{ env.GITHUB_SHA_SHORT }}.tar.zst
path: src\ST.Client.Desktop.Avalonia.App\bin\${{ matrix.configuration }}\Publish\${{ env.ProjectName }}_linux_x64_${{ env.GITHUB_SHA_SHORT }}.7z
- name: Upload linux-arm64 App ${{ matrix.configuration }}
continue-on-error: true
@@ -160,4 +160,4 @@ jobs:
uses: actions/upload-artifact@v2
with:
name: '[${{ matrix.configuration }}]${{ env.ProjectName }}_linux_arm64_${{ env.GITHUB_SHA_SHORT }}'
path: src\ST.Client.Desktop.Avalonia.App\bin\${{ matrix.configuration }}\Publish\${{ env.ProjectName }}_linux_arm64_${{ env.GITHUB_SHA_SHORT }}.tar.zst
path: src\ST.Client.Desktop.Avalonia.App\bin\${{ matrix.configuration }}\Publish\${{ env.ProjectName }}_linux_arm64_${{ env.GITHUB_SHA_SHORT }}.7z
+63 -60
View File
@@ -5,58 +5,58 @@
<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.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.2" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.2" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="6.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="6.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.3" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="6.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.3" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="6.0.3" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('net5.0')) ">
<!-- Microsoft.Extensions.* & AspNetCore & EntityFrameworkCore(NET50) -->
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="5.0.12" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="5.0.12" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="5.0.12" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.12" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.14" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="5.0.2" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="5.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="5.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="5.0.15" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.15" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="5.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="5.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.14" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.14" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.15" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="5.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="5.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="5.0.15" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.15" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) Or $(TargetFramework.StartsWith('netcoreapp3.1'))">
<!-- Microsoft.Extensions.* & AspNetCore & EntityFrameworkCore(NETCOREAPP31) -->
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="3.1.22" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="3.1.22" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="3.1.22" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.22" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.22" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.22" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="3.1.22" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.22" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.22" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.22" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.22" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.22" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="3.1.22" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.22" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.22" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="3.1.23" />
<PackageVersion Include="Microsoft.Extensions.Http" Version="3.1.23" />
<PackageVersion Include="Microsoft.Extensions.Logging" Version="3.1.23" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.23" />
<PackageVersion Include="Microsoft.Extensions.Logging.AzureAppServices" Version="3.1.23" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.23" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="3.1.23" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.23" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.23" />
<PackageVersion Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.23" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.23" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.23" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="3.1.23" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="3.1.23" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.23" />
</ItemGroup>
<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.13.12" />
<PackageVersion Include="Z.EntityFramework.Plus.EFCore" Version="6.13.15" />
<!-- AspNetCore 6 OpenId/OAuth -->
<PackageVersion Include="AspNet.Security.OpenId.Steam" Version="6.0.0" />
@@ -118,11 +118,11 @@
<PackageVersion Include="Xam.Plugins.Forms.ImageCircle" Version="3.1.1.1-beta" />
<!-- NUnit & NUnit.Xamarin & Moq -->
<PackageVersion Include="NUnit" Version="3.13.2" />
<PackageVersion Include="NUnit" Version="3.13.3" />
<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.17.1" />
<PackageVersion Include="Moq" Version="4.17.2" />
<!-- NLog -->
<PackageVersion Include="NLog" Version="4.7.14" />
@@ -132,17 +132,17 @@
<!-- ReactiveUI -->
<PackageVersion Include="System.Reactive" Version="5.0.0" />
<PackageVersion Include="Splat" Version="14.1.45" />
<PackageVersion Include="DynamicData" Version="7.5.4" />
<PackageVersion Include="DynamicData" Version="7.6.5" />
<PackageVersion Include="ReactiveUI" Version="17.1.50" />
<!--<PackageVersion Include="ReactiveUI.Fody" Version="17.1.50" /> -->
<PackageVersion Include="ReactiveUI.XamForms" Version="17.1.50" />
<PackageVersion Include="ReactiveUI.AndroidX" Version="17.1.50" />
<!-- SkiaSharp & HarfBuzzSharp -->
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2-preview.187" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2-preview.187" />
<PackageVersion Include="SkiaSharp" Version="2.88.0-preview.187" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.0-preview.187" />
<PackageVersion Include="HarfBuzzSharp" Version="2.8.2-preview.232" />
<PackageVersion Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2-preview.232" />
<PackageVersion Include="SkiaSharp" Version="2.88.0-preview.232" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.0-preview.232" />
<!-- AutoMapper -->
<PackageVersion Include="AutoMapper" Version="10.1.1" />
@@ -172,7 +172,8 @@
<PackageVersion Include="gfoidl.Base64" Version="1.1.1" />
<!--Command Line Tools-->
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta1.21308.1" />
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta3.22114.1" />
<PackageVersion Include="System.CommandLine.NamingConventionBinder" Version="2.0.0-beta3.22114.1" />
<!-- Pinyin -->
<PackageVersion Include="TinyPinyin.Net" Version="1.0.2" />
@@ -181,7 +182,7 @@
<PackageVersion Include="TaskScheduler" Version="2.10.1" />
<!-- Swagger -->
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.3.0" />
<!-- Pay -->
<!--<PackageVersion Include="AlipaySDKNet.Standard" Version="4.6.109" />-->
@@ -242,7 +243,7 @@
<PackageVersion Include="Avalonia.ReactiveUI" Version="0.10.13" />
<!--<PackageVersion Include="Avalonia.Direct2D1" Version="0.10.13" />-->
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="0.10.13" />
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="0.10.12.2" />
<PackageVersion Include="Avalonia.Xaml.Behaviors" Version="0.10.13.2" />
<!--<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" />-->
@@ -255,7 +256,7 @@
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="116.1.2.3" />
<PackageVersion Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageVersion Include="de.hdodenhof.circleimageview" Version="3.1.0.1" />
<PackageVersion Include="Square.OkHttp3" Version="4.9.2" />
<PackageVersion Include="Square.OkHttp3" Version="4.9.3" />
<PackageVersion Include="Square.Picasso" Version="2.71828.0" />
<!--<PackageVersion Include="LeakCanaryBinding" Version="1.5.1.1" />-->
<!--<PackageVersion Include="TencentOpenApiSDK.Android" Version="3.5.4.11" />-->
@@ -263,26 +264,28 @@
<!-- V2Ray -->
<PackageVersion Include="XAB.AndroidLibV2rayLite" Version="1.0.0.1" />
<PackageVersion Include="Karamunting.KotlinX.Coroutines.Core" Version="1.4.2" />
<PackageVersion Include="Naxam.RxJava.Droid" Version="1.3.8-pre1" />
<!--<PackageVersion Include="Karamunting.KotlinX.Coroutines.Core" Version="1.4.2" />-->
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Core" Version="1.6.0" />
<PackageVersion Include="Xamarin.KotlinX.Coroutines.Android" Version="1.6.0" />
<PackageVersion Include="Xamarin.Android.ReactiveX.RxJava3.RxJava" Version="3.1.3.2" />
<!-- Xamarin.AndroidX -->
<PackageVersion Include="Xamarin.AndroidX.Migration" Version="1.0.8" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.3.1.5" />
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.4.1" />
<PackageVersion Include="Xamarin.AndroidX.Emoji.AppCompat" Version="1.1.0.7" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.3.6.5" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.3.5.5" />
<PackageVersion Include="Xamarin.AndroidX.Fragment" Version="1.4.1" />
<PackageVersion Include="Xamarin.AndroidX.RecyclerView" Version="1.2.1.5" />
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.4.0.6" />
<PackageVersion Include="Xamarin.Google.Android.Material" Version="1.5.0.1" />
<PackageVersion Include="Xamarin.AndroidX.SwipeRefreshLayout" Version="1.1.0.7" />
<PackageVersion Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.2.2" />
<PackageVersion Include="Xamarin.AndroidX.ConstraintLayout" Version="2.1.3" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.UI" Version="2.3.5.5" />
<PackageVersion Include="Xamarin.AndroidX.Navigation.Fragment" Version="2.3.5.5" />
<PackageVersion Include="Xamarin.AndroidX.ViewPager2" Version="1.0.0.14" />
<PackageVersion Include="Xamarin.AndroidX.Activity" Version="1.4.0.1" />
<PackageVersion Include="Xamarin.AndroidX.Biometric" Version="1.1.0.8" />
<PackageVersion Include="Xamarin.AndroidX.ExifInterface" Version="1.3.3.4" />
<PackageVersion Include="Xamarin.AndroidX.Legacy.Support.Core.UI" Version="1.0.0.13" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.4.0.2" />
<PackageVersion Include="Xamarin.AndroidX.Lifecycle.LiveData" Version="2.4.1" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Camera2" Version="1.0.2.3" />
<PackageVersion Include="Xamarin.AndroidX.Camera.Lifecycle" Version="1.0.2.3" />
<PackageVersion Include="Xamarin.AndroidX.Camera.View" Version="1.0.0.5-alpha20" />
+17 -12
View File
@@ -4,7 +4,7 @@
English | [简体中文](./README.md)
「Steam++」is a toolkit that contains a variety of Steam tools, most of which require you to download and install Steam in order to use them.
"Steam++" is an open source cross-platform multi-purpose game toolkit, most of its features require you to download and install Steam to use it.
![Release Download](https://img.shields.io/github/downloads/rmbadmin/SteamTools/total?style=flat-square)
[![Release Version](https://img.shields.io/github/v/release/rmbadmin/SteamTools?style=flat-square)](https://github.com/rmbadmin/SteamTools/releases/latest)
@@ -32,19 +32,24 @@ English | [简体中文](./README.md)
- [GitHub Releases](https://github.com/BeyondDimension/SteamTools/releases)
- [Gitee Releases](https://gitee.com/rmbgame/SteamTools/releases)
- [Official WebSite](https://steampp.net)
- [![Microsoft Store](./resources/MSStore_English.png)](https://www.microsoft.com/store/apps/9MTCFHS560NG)
- [Arch Linux Package](https://aur.archlinux.org/packages/steam%2B%2B-bin)(By [zhanghua000](https://github.com/zhanghua000))
## ✨ Functions
1. Local reverse proxy for Steam's community webpage to enable normal access in **the Chinese Mainland, Mainland of China**
2. Quickly switch the Steam account that the current PC has remembered to log into
- This feature is to read the local user login records stored under the Steam path to directly display the operation, you can switch between multiple accounts without re-entering passwords and tokens.
3. Achievement stat modifications for Steam games
- Function reference SteamAchievementManager for secondary development, modified the game list loading and operation ease of use.
4. Steam Local Two-Step Authenticator
- The function reference [WinAuth](https://github.com/winauth/winauth) is developed to enable you to view your token without launching the mobile version of Steam App, similar function software are [WinAuth](https://github.com/winauth/winauth), [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator).
5. Some game tools
- Currently there is a forced game borderless windowing.
1. Network Acceleration (Support Windows / Linux / macOS / Android)
- Make the Steam community, Github, Google reCAPTCHA, Pixiv, Discord, Twitch and other domestic hard-to-access pages accessible properly.
- Functions similar to [Steamcommunity 302](https://www.dogfight360.com/blog/686/), using [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy) open source project for local anti-generation.
2. Script Configuration (Windows / Linux / macOS Only)
- Some JS scripts are injected into web pages through an acceleration service that intercepts web requests, providing functionality similar to that of a web plugin.
3. Account Switch (Windows / Linux / macOS Only)
- Switch between Steam accounts that are already logged in on the current PC with one click, and manage features such as sorting your home shared library.
4. Inventory Management (Windows / Linux / macOS Only)
- Lets you manage your Steam game inventory directly, not only by downloading older Steam games, but also by managing Steam game achievements directly, supporting unlocked achievements and unlocked achievements.
5. Local Authentication (Support Windows / Linux / macOS / Android)
- Let your cell phone token unified save in the computer, currently only support Steam token, later will develop support more token types with cloud synchronization token.
6. ArchiSteamFarm (Support Windows / Linux / macOS / Android)
- Integration with [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm) provides functions such as hanging and dropping Steam Collectible Cards within the app.
7. Game Tools (Windows Only)
- Force game windows to use borderless windowing
<!--Prerequisites Microsoft Visual C++ 2015-2019 Redistributable [64 bit](https://aka.ms/vs/16/release/vc_redist.x64.exe) / [32 bit](https://aka.ms/vs/16/release/vc_redist.x86.exe)-->
## 🖥 Supported Operating Systems
@@ -57,7 +62,7 @@ OS | Version | Architectures
[Windows Server][Windows-Server] | 2012+ | x64 | [Windows Server][Windows-Server-lifecycle]
**\*** Windows 7 SP1 is supported with [Extended Security Updates](https://docs.microsoft.com/troubleshoot/windows-client/windows-7-eos-faq/windows-7-extended-security-updates-faq) installed.
**\*** Microsoft Store/Desktop Bridge Version 1809+
**\*** Microsoft Store(Desktop Bridge) Version 1809+
[Windows-client]: https://www.microsoft.com/windows/
[Windows-lifecycle]: https://support.microsoft.com/help/13853/windows-lifecycle-fact-sheet
+17 -19
View File
@@ -4,7 +4,7 @@
[English](./README.en.md) | 简体中文
「Steam++」是一个包含多种Steam工具功能的工具箱,此工具的大部分功能都是需要您下载安装Steam才能使用。
「Steam++」是一个开源跨平台的多功能游戏工具箱,此工具的大部分功能都是需要您下载安装 Steam 才能使用。
![Release Download](https://img.shields.io/github/downloads/BeyondDimension/SteamTools/total?style=flat-square)
[![Release Version](https://img.shields.io/github/v/release/BeyondDimension/SteamTools?style=flat-square)](https://github.com/BeyondDimension/SteamTools/releases/latest)
@@ -33,26 +33,24 @@
- [GitHub Releases](https://github.com/BeyondDimension/SteamTools/releases)
- [Gitee Releases](https://gitee.com/rmbgame/SteamTools/releases)
- [Official WebSite](https://steampp.net)
- [![Microsoft Store](./resources/MSStore_English.png)](https://www.microsoft.com/store/apps/9MTCFHS560NG)
- [Arch Linux Package](https://aur.archlinux.org/packages/steam%2B%2B-bin)(By [zhanghua000](https://github.com/zhanghua000))
## ✨ 功能
1. 反代 Steam 的社区网页使其能正常访问
- 功能类似羽翼城大佬的 [steamcommunity_302](https://www.dogfight360.com/blog/686/)
- 使用 [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy) 开源项目进行本地反代,使国内用户可以正常访问 Steam 社区页
- 相比 **302工具** 具有更快的启动速度,以及支持简单的脚本注入(还顺便支持了Pixiv、Discord、Twitch等网站的反代支持)
2. 快速切换当前设备已记住登陆的 Steam 账号
- 该功能是读取 Steam 路径下存储的本地用户登录记录直接展示操作,可以多账号切换无需重新输入密码和令牌
3. Steam游戏的成就统计管理功能
- 功能参考 [SteamAchievementManager](https://github.com/gibbed/SteamAchievementManager) 进行二次开发,修改了游戏列表的加载和操作易用性
4. Steam本地两步身份验证器
- 功能参考 [WinAuth](https://github.com/winauth/winauth) 开发,可以使您不用启动移动版 Steam App 也能查看您的令牌
- 本地令牌交易市场报价确认
- 功能类似的软件例如:
- [WinAuth](https://github.com/winauth/winauth)
- [SteamDesktopAuthenticator](https://github.com/Jessecar96/SteamDesktopAuthenticator)
5. 其他游戏工具
- 目前已有强制游戏无边框窗口化
1. 网络加速 (Support Windows / Linux / macOS / Android)
- 使 Steam 社区、Github、谷歌验证码、Pixiv、Discord、Twitch 等国内难以访问的网页正常访问。
- 功能类似 [Steamcommunity 302](https://www.dogfight360.com/blog/686/) ,使用 [Titanium-Web-Proxy](https://github.com/justcoding121/Titanium-Web-Proxy) 开源项目进行本地反代。
2. 脚本配置 (Windows / Linux / macOS Only)
- 通过加速服务拦截网络请求将一些 JS 脚本注入在网页中,提供类似网页插件的功能。
3. 账号切换 (Windows / Linux / macOS Only)
- 一键切换已在当前 PC 上登录过的 Steam 账号,与管理家庭共享库排序等功能。
4. 库存管理 (Windows / Linux / macOS Only)
- 让您直接管理到 Steam 游戏库存,不仅能够下载老版本的 Steam 游戏,也能够对 Steam 游戏成就进行直接管理,支持解锁成就以及反解锁成就。
5. 本地令牌 (Support Windows / Linux / macOS / Android)
- 让您的手机令牌统一保存在电脑中,目前仅支持 Steam 令牌,后续会开发支持更多的令牌种类与云同步令牌。
6. 自动挂卡 (Support Windows / Linux / macOS / Android)
- 集成 [ArchiSteamFarm](https://github.com/JustArchiNET/ArchiSteamFarm) 在应用内提供 挂机掉落 Steam 集换式卡牌 等功能。
7. 游戏工具 (Windows Only)
- 强制游戏窗口使用无边框窗口化
<!--发布配置SelfContained=true时会自动打包VC++相关程序集-->
<!--先决条件 Microsoft Visual C++ 2015-2019 Redistributable [64 位](https://aka.ms/vs/16/release/vc_redist.x64.exe) / [32 位](https://aka.ms/vs/16/release/vc_redist.x86.exe)-->
@@ -66,7 +64,7 @@ OS | Version | Architectures
[Windows Server][Windows-Server] | 2012+ | x64 | [Windows Server][Windows-Server-lifecycle]
**\*** Windows 7 SP1 is supported with [Extended Security Updates](https://docs.microsoft.com/troubleshoot/windows-client/windows-7-eos-faq/windows-7-extended-security-updates-faq) installed.
**\*** Microsoft Store/Desktop Bridge Version 1809+
**\*** Microsoft Store(Desktop Bridge) Version 1809+
[Windows-client]: https://www.microsoft.com/windows/
[Windows-lifecycle]: https://support.microsoft.com/help/13853/windows-lifecycle-fact-sheet
-1
View File
@@ -16,7 +16,6 @@
"src\\Avalonia.Win32\\Avalonia.Win32.csproj",
"src\\Avalonia.X11\\Avalonia.X11.csproj",
"src\\Common.AreaLib\\Common.AreaLib.csproj",
"src\\Common.ClientLib.Droid\\Common.ClientLib.Droid.csproj",
"src\\Common.ClientLib.iOS\\Common.ClientLib.iOS.csproj",
"src\\Common.ClientLib\\Common.ClientLib.csproj",
"src\\Common.CoreLib\\Common.CoreLib.csproj",
-1
View File
@@ -16,7 +16,6 @@
"src\\Avalonia.Win32\\Avalonia.Win32.csproj",
"src\\Avalonia.X11\\Avalonia.X11.csproj",
"src\\Common.AreaLib\\Common.AreaLib.csproj",
"src\\Common.ClientLib.Droid\\Common.ClientLib.Droid.csproj",
"src\\Common.ClientLib.iOS\\Common.ClientLib.iOS.csproj",
"src\\Common.ClientLib\\Common.ClientLib.csproj",
"src\\Common.CoreLib\\Common.CoreLib.csproj",
+31 -31
View File
@@ -152,8 +152,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_Github", "_Github", "{B114
.github\workflows\xamarin.yml = .github\workflows\xamarin.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.ClientLib.Droid", "src\Common.ClientLib.Droid\Common.ClientLib.Droid.csproj", "{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Common.ClientLib.iOS", "src\Common.ClientLib.iOS\Common.ClientLib.iOS.csproj", "{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.UnitTest.Droid", "tests\Common.UnitTest.Droid\ST.Client.UnitTest.Droid.csproj", "{80E6762E-AB43-41E2-BDB4-7A3E24713977}"
@@ -174,6 +172,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ST.Client.Android.V2Ray", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gameloop.Vdf", "references\Gameloop.Vdf\Gameloop.Vdf\Gameloop.Vdf.csproj", "{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}"
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -1592,34 +1592,6 @@ Global
{29DE5086-0690-4AE7-9BA9-840F54B249DC}.Release|x64.Build.0 = Release|Any CPU
{29DE5086-0690-4AE7-9BA9-840F54B249DC}.Release|x86.ActiveCfg = Release|Any CPU
{29DE5086-0690-4AE7-9BA9-840F54B249DC}.Release|x86.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|ARM.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|ARM64.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|iPhone.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|x64.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|x64.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|x86.ActiveCfg = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Debug|x86.Build.0 = Debug|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|Any CPU.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|ARM.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|ARM.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|ARM64.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|ARM64.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|iPhone.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|iPhone.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|x64.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|x64.Build.0 = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|x86.ActiveCfg = Release|Any CPU
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C}.Release|x86.Build.0 = Release|Any CPU
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0}.Debug|ARM.ActiveCfg = Debug|Any CPU
@@ -1886,6 +1858,34 @@ Global
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Release|x64.Build.0 = Release|Any CPU
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Release|x86.ActiveCfg = Release|Any CPU
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE}.Release|x86.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|ARM64.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhone.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x64.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x64.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x86.ActiveCfg = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Debug|x86.Build.0 = Debug|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|Any CPU.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM64.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|ARM64.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhone.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhone.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{920EF29F-406F-43A9-B002-29DD6B0B4FBF}.Release|x64.ActiveCfg = Release|Any CPU
{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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1942,7 +1942,6 @@ Global
{E85E92BA-202F-42D3-8C5E-96DA452501B7} = {910D6A0F-42AB-4B65-B532-852E864EC006}
{21C392C5-AE41-421A-A127-1A03C4ACA2AD} = {673FF8CD-9E85-4FA1-ABFC-D1149675E138}
{29DE5086-0690-4AE7-9BA9-840F54B249DC} = {E448F863-4C9D-47A4-BC4A-4A1381B54DA4}
{3C7200C7-8C2D-46F0-BD7D-0A59D915B83C} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{4658B02A-CB1A-4561-AD9C-3B3FF969D7F0} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{80E6762E-AB43-41E2-BDB4-7A3E24713977} = {CC46B486-00D7-49E6-ABA3-FDF8F4868D2B}
{AD7B78B0-AE51-4FB7-9B11-4E22A2B538CA} = {CC46B486-00D7-49E6-ABA3-FDF8F4868D2B}
@@ -1953,6 +1952,7 @@ Global
{80EBD601-28AC-4840-B9B8-E6064816A443} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
{4A79264D-5BF5-4F89-8066-44E154BF557F} = {80EBD601-28AC-4840-B9B8-E6064816A443}
{DFC341E8-5290-428C-8D2B-6DE2AA163FFE} = {673FF8CD-9E85-4FA1-ABFC-D1149675E138}
{920EF29F-406F-43A9-B002-29DD6B0B4FBF} = {80EBD601-28AC-4840-B9B8-E6064816A443}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
RESX_NeutralResourcesLanguage = zh-Hans
+14 -10
View File
@@ -1,23 +1,27 @@
# 下载指南
- Desktop(桌面端)
- Windows
- 如果你使用 Intel、AMD 的 x64 芯片的 PC(较为**普遍**),则下载文件名中带有 **win_x64** 的文件
- 如果你已安装了 [ASP.NET Core Runtime 6.0.1](https://dotnet.microsoft.com/download/dotnet/6.0) 则下载文件名中带有 **fde** 的文件,可减少磁盘占用空间
- [在 Windows 上安装 .NET](https://docs.microsoft.com/en-us/dotnet/core/install/windows)
- 在 Windows 上不需要 Hosting Bundle 和 IIS support
- [下载安装程序并手动安装(aspnetcore-runtime-6.0.1-win-x64.exe)](https://dotnet.microsoft.com/download/dotnet/thank-you/runtime-aspnetcore-6.0.1-windows-x64-installer)
- [使用 PowerShell 自动化安装](https://docs.microsoft.com/en-us/dotnet/core/install/windows?tabs=net60#install-with-powershell-automation)
- 如果你使用 Intel、AMD 的 x64(x86-64) 芯片的 PC,则下载文件名中带有 **win_x64** 的文件
- 如果你 **已安装** 了 [ASP.NET Core 运行时 6.0.3](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0) 则下载文件名中带有 **fde(框架依赖)** 的文件
- 注意:是 《ASP.NET Core 运行时》 而不是 《.NET 桌面运行时》
- [在 Windows 上安装 .NET](https://docs.microsoft.com/zh-cn/dotnet/core/install/windows)
- 本程序在 Windows 上不需要 Hosting Bundle 和 IIS support
- [下载安装程序并手动安装(aspnetcore-runtime-6.0.3-win-x64.exe)](https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-aspnetcore-6.0.3-windows-x64-installer)
- [使用 PowerShell 自动化安装](https://docs.microsoft.com/zh-cn/dotnet/core/install/windows?tabs=net60#install-with-powershell-automation)
- macOS
- 如果你使用 Intel、AMD 的 x64 芯片的 Mac(较为**普遍**),则下载文件名中带有 **macos_x64** 的文件
- 如果你使用 ARM64 芯片的 Mac(较为**稀有**),例如 **M1**,则下载文件名中带有 **macos_arm64** 的文件
- 如果你使用 Intel 的 x64(x86-64) 芯片的 Mac,则下载文件名中带有 **macos_x64** 的文件
- 如果你使用 ARM64(Apple Silicon) 芯片的 Mac,例如 **Apple M1**,则下载文件名中带有 **macos_arm64** 的文件
- Linux
- 如果你使用 Intel、AMD 的 x64 芯片的 PC(较为**普遍**)则下载文件名中带有 **linux_x64** 的文件
- 如果你使用 ARM64 芯片的 PC(较为**稀有**)例如 **Raspberry Pi Model 3+**,则下载文件名中带有 **linux_arm64** 的文件
- 如果你使用 Intel、AMD 的 x64(x86-64) 芯片的 PC 则下载文件名中带有 **linux_x64** 的文件
- 如果你使用 ARM64 芯片的 PC 例如 **Raspberry Pi Model 3+**,则下载文件名中带有 **linux_arm64** 的文件
<!--
- Mobile(移动端)
- Android
- 如果你使用 ARM64 芯片的设备(较为**普遍**)则下载文件名中带有 **android_arm64_v8a** 的文件
- 如果你使用 ARM32 芯片的设备(较为**稀有**)通常为 **14** 年下半年之前生产的设备,则下载文件名中带有 **android_armeabi_v7a** 的文件
- 如果你使用 Intel、AMD 的 x64 芯片的设备(较为**稀有**)则下载文件名中带有 **android_x64** 的文件
-->
<!--
- 如果你使用 ARM64 芯片的 PC(极为**稀有**),例如 **Surface Pro X**,则下载文件名中带有 **win_x64** 的文件可通过 Win11 x86 模拟运行
+1 -1
View File
@@ -3,6 +3,6 @@
"MSBuild.Sdk.Extras": "3.0.44"
},
"sdk": {
"version": "6.0.200"
"version": "6.0.201"
}
}
+12 -18
View File
@@ -1,7 +1,7 @@
create_app_structure() {
APPNAME=$1
APPDIR="$APPNAME.app/Contents"
APPICONS="/Users/mossimo/bin/logo.icns"
APPICONS="${{ Steam++_IcnsFile }}"
if [ ! -d "$APPDIR" ]; then
echo "creating app structure $APPDIR"
@@ -33,19 +33,19 @@ emit_plist() {
<key>CFBundleIdentifier</key>
<string>net.steampp.app</string>
<key>CFBundleShortVersionString</key>
<string>2.6.9</string>
<string>${{ Steam++_ShortVersion }}</string>
<key>CFBundleVersion</key>
<string>2.6.9.0</string>
<string>${{ Steam++_Version }}</string>
<key>LSMinimumSystemVersion</key>
<string>10.14</string>
<string>11.0</string>
<key>CFBundleDevelopmentRegion</key>
<string>zh_CN</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleExecutable</key>
<string>$PLIST_APPNAME</string>
<string>${{ Steam++_RunName }}</string>
<key>CFBundleGetInfoString</key>
<string>$PLIST_APPNAME</string>
<string>${{ Steam++_RunName }}</string>
<key>CFBundleIconFile</key>
<string>$PLIST_APPNAME</string>
<key>CFBundlePackageType</key>
@@ -64,10 +64,10 @@ EOF
fi
}
cd "/Users/mossimo/bin"
cd "${{ Steam++_OutPutFilePath }}"
BINARYNAME="Steam++"
BINARYNAME="${{ Steam++_AppName }}"
echo "Building Avalonia demo..."
@@ -80,14 +80,8 @@ rm -rf "$APPDIR"
create_app_structure "$APPNAME"
emit_plist "$APPNAME" "$APPDIR" true
cd "$APPDIR/Frameworks"
mv -f "${{ Steam++_APPDIR }}" "$APPDIR/MacOS"
chmod +x "$APPDIR/MacOS/Steam++"
APPNAME="$BINARYNAME Helper"
APPDIR="$APPNAME.app/Contents"
create_app_structure "$APPNAME"
emit_plist "$APPNAME" "$APPDIR"
cp -R "../../../steampp/" "../MacOS"
ln -s "../../MacOS" "Frameworks/$APPDIR/MacOS"
chmod +x "../MacOS/$BINARYNAME"
cp "../MacOS/$BINARYNAME" "../MacOS/$APPNAME"
chmod +x "../MacOS/$APPNAME"
mkdir "${{ Steam++_APPDIR }}"
mv -f "${{ Steam++_OutPutFilePath }}/$BINARYNAME.app" "${{ Steam++_APPDIR }}/$BINARYNAME.app"
+7
View File
@@ -0,0 +1,7 @@
# ARM64(Windows/macOS/Linux) Native Library
## 7z.dll
21.07 (2021-12-26) by https://www.7-zip.org
## libe_sqlite3.dylib
sqlitepclraw.lib.e_sqlite3.2.0.7.nupkg
Binary file not shown.
@@ -0,0 +1,8 @@
# Android Native Library
[Xamarin.Android 支持通过标准 PInvoke 机制使用本机库。 你还可以将不属于 OS 的其他本机库绑定到你的 .apk。](https://docs.microsoft.com/zh-cn/xamarin/android/platform/native-libraries)
## libgojni.so & libtun2socks.so
Source code compilation by https://github.com/2dust/v2rayNG
## shadowsocks-android\libtun2socks.so
Apk extraction by https://github.com/shadowsocks/shadowsocks-android/releases/tag/v5.2.6
+7
View File
@@ -0,0 +1,7 @@
# Windows/macOS/Linux x64 Native Library & General C# Source Code & Third Party Projects
## 7z.dll
21.07 (2021-12-26) by https://www.7-zip.org
## libzstd.dll
https://github.com/facebook/zstd/releases/tag/v1.5.2
+4
View File
@@ -0,0 +1,4 @@
# Windows/macOS/Linux x86(32 bit) Native Library
## 7z.dll
21.07 (2021-12-26) by https://www.7-zip.org
+27 -35
View File
@@ -1,27 +1,19 @@
### 版本亮点
1. ASF 升级至 **V5.2.3.5**
2. ASF 配置 中新增 设置自定义密钥(ASF_CRYPTKEY) 与 导入 Bot 文件
3. Linux 发行压缩包由 7z 格式更改为 tar.zst
4. 网络加速 支持 IPv6 网络访问 Steam 讨论/留言相关功能
6. 网络加速 支持 Steam 商店 访问被限制的游戏页面
7. 网络加速 新增了部分被限制的 CDN 加速,支持访问 stackoverflow
8. 账号切换 家庭库共享管理新增暂时禁用启用指定账号的功能 可在排序失效时使用
1. macOS 支持 Arm64(Apple Silicon)
2. Android 支持 VPN 模式(推荐) 进行本地加速
3. ~~Windows 支持 DNS 驱动拦截模式(推荐) 进行本地加速~~
4. ASF 升级至 V5.x.x.x
### 修复问题
1. 修复 Android 端 程序启动时自动运行 网络加速 与 ASF 服务
2. 修复 Android 端 网络加速 VPN 模式
3. 修复 Android 端 切换系统语言时可能导致的闪退
4. 修复 Android 端 拒绝授予存储权限导致的闪退
5. 改进 网络加速 中的代理证书生成
6. 改进 账号切换 中读取 Vdf 配置操作
7. 修复 Desktop 端 家庭共享库管理 在 Steam Beta 版上不能正常使用
8. 修复 网络加速 Twitch 聊天服务链接不上的问题
9. 修复 网络加速 github.io 加速影响部分仓库访问 404 的问题
10. 修复 网络加速 Steam 社区加速后会出现【请重新输入下方验证码中的字符来验证此为人工操作】的问题
11. 暂时移除了网络加速中部分失效的加速项目
12. 修复 令牌交易 登录状态失效时刷新应该回到登录界面
13. 改进 本地令牌 移除令牌时的提示
14. 修复 网络加速 滚动条错误滚动的问题
1. 修复 本地令牌 无令牌刷新时提示密码错误
2. 改进 Android 端 本地令牌 列表样式第一条与最后一条的上下外边距
3. 改进 俄语翻译,由 vanja-san 提供
4. 改进 .NET 运行时升级至 6.0.3(仅 Desktop 端)
5. 改进 脚本配置 未启动时的内存占用,以及减少总体内存占用率
6. 修复 Hosts 加速模式下使用仅启用脚本功能导致死循环
7. 改进 Linux 端 可监听 443 端口配置
8. 修复 Windows 端,动态桌面背景窗口显示时一些可能导致闪退的潜在问题
9. 修复 Android 端,因 CheckBox 导致在低于 6.0 Marshmallow 系统上引发的闪退
### 已知问题
- 除 Windows 之外的平台此软件自动更新尚不可用
@@ -29,7 +21,6 @@
- macOS
- [尚未公证](https://support.apple.com/zh-cn/guide/mac-help/mh40616/10.15/mac/10.15),这会影响 macOS Catalina(版本 10.15)以上版本
- Linux
- **Hosts 代理模式**可能无法配置成功,推荐使用**系统代理模式**
- 窗口弹出位置不正确
- 鼠标指针浮动样式不正确
- Windows
@@ -54,7 +45,7 @@
- .nupkg 文件可使用解压工具打开或解压,找到此文件复制即可
[![steampp.net](https://img.shields.io/badge/WebSite-steampp.net-brightgreen.svg?style=flat-square&color=61dafb)](https://steampp.net)
[![Steam++ v2.6.9](https://img.shields.io/badge/Steam++-v2.6.9-brightgreen.svg?style=flat-square&color=512bd4)]()
[![Steam++ v2.7.0](https://img.shields.io/badge/Steam++-v2.7.0-brightgreen.svg?style=flat-square&color=512bd4)]()
##### [不知道该下载哪个文件?](./download-guide.md)
@@ -63,21 +54,22 @@
### 文件校验
| File | Checksum (SHA256) |
| ---- | ---- |
| Steam++_win_x64_v2.6.9.7z | SHA256 |
| Steam++_win_x64_fde_v2.6.9.7z | SHA256 |
| Steam++_win_x64_v2.7.0.7z | SHA256 |
| Steam++_win_x64_fde_v2.7.0.7z | SHA256 |
| | |
| Steam++_win_x64_v2.6.9.exe | SHA256 |
| Steam++_win_x64_fde_v2.6.9.exe | SHA256 |
| Steam++_win_x64_v2.7.0.exe | SHA256 |
| Steam++_win_x64_fde_v2.7.0.exe | SHA256 |
| | |
| Steam++_linux_x64_v2.6.9.7z | SHA256 |
| Steam++_linux_arm64_v2.6.9.7z | SHA256 |
| Steam++_linux_x64_v2.7.0.7z | SHA256 |
| Steam++_linux_arm64_v2.7.0.7z | SHA256 |
| | |
| Steam++_linux_x64_v2.6.9.deb | SHA256 |
| Steam++_linux_arm64_v2.6.9.deb | SHA256 |
| Steam++_linux_x64_v2.7.0.deb | SHA256 |
| Steam++_linux_arm64_v2.7.0.deb | SHA256 |
| | |
| Steam++_linux_x64_v2.6.9.rpm | SHA256 |
| Steam++_linux_arm64_v2.6.9.rpm | SHA256 |
| Steam++_linux_x64_v2.7.0.rpm | SHA256 |
| Steam++_linux_arm64_v2.7.0.rpm | SHA256 |
| | |
| Steam++_macos_x64_v2.6.9.dmg | SHA256 |
| Steam++_macos_x64_v2.7.0.dmg | SHA256 |
| Steam++_macos_arm64_v2.7.0.dmg | SHA256 |
| | |
| Steam++_android_v2.6.9.apk | SHA256 |
| Steam++_android_v2.7.0.apk | SHA256 |
+3
View File
@@ -46,6 +46,9 @@ namespace System
public const string DirPublishWinX64_ =
@"\src\" + ProjectDir_AvaloniaApp + @"\bin\{0}\Publish\win-x64";
public const string DirPublishOsx =
@"\src\" + ProjectDir_AvaloniaApp + @"\bin\Release\Publish\{0}";
public const string DirPublishWinX64_FDE_ =
@"\src\" + ProjectDir_AvaloniaApp + @"\bin\{0}\Publish\FrameworkDependent\win-x64";
+6
View File
@@ -197,6 +197,12 @@ namespace System.Application.UI
#if __ANDROID__
#if V2RAY
b.Append("[v2ray.ver] ");
b.Append(Libv2ray.Libv2ray.CheckVersionX());
b.AppendLine();
#endif
//if (_ThisAssembly.Debuggable)
//{
// b.Append("[app.multi] ");
@@ -118,19 +118,19 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ExitCode_IsEmulator" xml:space="preserve">
<value>Это приложение не поддерживает запуск в эмуляторе</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Это приложение невозможно запустить через эмулятор</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="ExitCode_IsRoot" xml:space="preserve">
<value>Это приложение не поддерживается для запуска на устройствах с привилегиями ROOT</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Это приложение невозможно запустить на устройствах с root правами</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="ExitCode_IsVirtualApk" xml:space="preserve">
<value>Это приложение не поддерживает мультиоткрытие</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Это приложение не поддерживает несколько окон</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="ExitCode_IsXposedExists" xml:space="preserve">
<value>Это приложение не поддерживает запуск на устройствах с установленной платформой Xposed</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Это приложение невозможно запустить на устройствах с установленным Xposed Framework</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
</root>
@@ -2,33 +2,62 @@ using Android.Runtime;
using Java.Security.Cert;
using System.IO;
using Xamarin.Android.Net;
using X509Certificate2 = System.Security.Cryptography.X509Certificates.X509Certificate2;
// ReSharper disable once CheckNamespace
namespace System
{
public static partial class HttpClientExtensions
{
const string certificateFileType = "X.509";
static readonly Lazy<CertificateFactory?> certificateFactory = new(() =>
{
var certificateFactory = CertificateFactory.GetInstance(certificateFileType);
return certificateFactory;
});
internal static CertificateFactory CertificateFactory
{
get
{
var certificateFactory = HttpClientExtensions.certificateFactory.Value;
if (certificateFactory == null)
throw new NullReferenceException(
$"CertificateFactory.GetInstance Fail, Type: {certificateFileType}");
return certificateFactory;
}
}
/// <summary>
/// 添加可信任证书,可用于调试时HTTPS抓包
/// 添加可信任证书,可用于调试时 HTTPS 抓包
/// </summary>
/// <param name="handler"></param>
/// <param name="certificateFileData">证书文件数据(文件流,内嵌资源流)</param>
/// <param name="certificateFileType">证书文件类型,默认使用X.509</param>
public static void AddTrustedCert(
this AndroidClientHandler handler,
Stream certificateFileData,
string certificateFileType = "X.509")
Stream certificateFileData)
{
var certificateFactory = CertificateFactory.GetInstance(certificateFileType);
if (certificateFactory == null)
throw new NullReferenceException(
$"CertificateFactory.GetInstance Fail, Type: {certificateFileType}");
var certificate = certificateFactory.GenerateCertificate(certificateFileData);
var certificate = CertificateFactory.GenerateCertificate(certificateFileData);
if (certificate == null)
throw new NullReferenceException("GenerateCertificate Fail");
if (handler.TrustedCerts == null)
handler.TrustedCerts = new JavaList<Certificate>();
handler.TrustedCerts.Add(certificate);
}
/// <summary>
/// 将 .NET 中的 X509 证书对象 转换为 JVM 中的 X509 证书对象
/// <para>Java.Security.Cert.X509Certificate</para>
/// <para>=></para>
/// <para>System.Security.Cryptography.X509Certificates.X509Certificate2</para>
/// </summary>
/// <param name="certificate2"></param>
/// <returns></returns>
public static X509Certificate Convert(this X509Certificate2 certificate2)
{
using var stream = new MemoryStream(certificate2.RawData);
return CertificateFactory.GenerateCertificate(stream)!.JavaCast<X509Certificate>();
}
}
}
@@ -29,7 +29,7 @@ namespace System.Application.Services
if ((!string.IsNullOrWhiteSpace(value)) &&
(string.IsNullOrWhiteSpace(textBoxText) ||
(textBoxText.Length < value.Length &&
value.Substring(0, textBoxText.Length) == textBoxText)))
value[..textBoxText.Length] == textBoxText)))
{
return value;
}
+119 -4
View File
@@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
#if !NET35 && !NOT_XE
using System.Threading.Tasks;
@@ -172,27 +173,108 @@ namespace System
string destAppDataPath, string destCachePath,
string sourceAppDataPath, string sourceCachePath)
{
bool ExistsNotEmptyDir(string path)
{
var exists = Directory.Exists(path);
if (DesktopBridge.IsRunningAsUwp)
{
if (path == destCachePath || path == sourceCachePath)
{
return false;
}
}
return exists && Directory.EnumerateFileSystemEntries(path).Any();
}
var paths = new[] { destAppDataPath, destCachePath, };
var dict_paths = paths.ToDictionary(x => x, x => Directory.Exists(x) && Directory.EnumerateFileSystemEntries(x).Any());
var dict_paths = paths.ToDictionary(x => x, x => ExistsNotEmptyDir(x));
if (dict_paths.Values.All(x => !x))
{
var old_paths = new[] { sourceAppDataPath, sourceCachePath, };
if (old_paths.All(x => Directory.Exists(x) && Directory.EnumerateFileSystemEntries(x).Any())) // 迁移之前根目录上的文件夹
{
var isNotFirst = false;
for (int i = 0; i < old_paths.Length; i++)
{
var path = paths[i];
var old_path = old_paths[i];
try
{
Directory.Move(old_path, path);
if (!isNotFirst)
{
try
{
// 尝试搜索之前版本的进程将其结束
var currentProcess = Process.GetCurrentProcess();
var query = from x in Process.GetProcessesByName(currentProcess.ProcessName)
where x != currentProcess
let m = x.TryGetMainModule()
where m != null && m.FileName != currentProcess.TryGetMainModule()?.FileName
select x;
var process = query.ToArray();
foreach (var proces in process)
{
try
{
#if NETCOREAPP3_0_OR_GREATER
proces.Kill(true);
#else
proces.Kill();
#endif
}
catch
{
}
}
}
catch
{
}
isNotFirst = true;
}
try
{
Directory.Move(old_path, path);
}
catch
{
try
{
CopyDirectory(old_path, path);
}
catch
{
if (OperatingSystem2.IsWindows)
{
var psi = new ProcessStartInfo
{
FileName = "cmd.exe",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
};
var p = Process.Start(psi);
p.Start();
p.StandardInput.WriteLine($"xcopy \"{old_path}\" \"{path}\" /y &exit");
p.WaitForExit(10000);
p.Kill();
}
else
{
throw;
}
}
}
dict_paths[path] = true;
}
catch
{
// 跨卷移动失败或其他原因失败,使用旧的目录,并尝试删除创建的空文件夹
DirTryDelete(path);
if (!DesktopBridge.IsRunningAsUwp)
{
// 跨卷移动失败或其他原因失败,使用旧的目录,并尝试删除创建的空文件夹
DirTryDelete(path);
}
paths[i] = old_path;
}
}
@@ -460,5 +542,38 @@ namespace System
public const char UnixDirectorySeparatorChar = '/';
public const char WinDirectorySeparatorChar = '\\';
public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive = true)
{
// Get information about the source directory
var dir = new DirectoryInfo(sourceDir);
// Check if the source directory exists
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
// Cache directories before we start copying
DirectoryInfo[] dirs = dir.GetDirectories();
// Create the destination directory
Directory.CreateDirectory(destinationDir);
// Get the files in the source directory and copy to the destination directory
foreach (FileInfo file in dir.GetFiles())
{
string targetFilePath = Path.Combine(destinationDir, file.Name);
file.CopyTo(targetFilePath);
}
// If recursive and copying subdirectories, recursively call this method
if (recursive)
{
foreach (DirectoryInfo subDir in dirs)
{
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
CopyDirectory(subDir.FullName, newDestinationDir, true);
}
}
}
}
}
+32 -32
View File
@@ -118,95 +118,95 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Age_" xml:space="preserve">
<value>{0} лет</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Возраст: {0}</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L0" xml:space="preserve">
<value>Воскресенье</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L1" xml:space="preserve">
<value>Понедельник</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L2" xml:space="preserve">
<value>Вторник</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L3" xml:space="preserve">
<value>Среда</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L4" xml:space="preserve">
<value>Четверг</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L5" xml:space="preserve">
<value>Пятница</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_L6" xml:space="preserve">
<value>Суббота</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S0" xml:space="preserve">
<value>Воскресенье</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S1" xml:space="preserve">
<value>Понедельник</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S2" xml:space="preserve">
<value>Вторник</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S3" xml:space="preserve">
<value>Среда</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S4" xml:space="preserve">
<value>Четверг</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S5" xml:space="preserve">
<value>Пятница</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="DayOfWeek_S6" xml:space="preserve">
<value>Суббота</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="Female" xml:space="preserve">
<value>женщина</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Женщина</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="He" xml:space="preserve">
<value>он</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Он</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="Male" xml:space="preserve">
<value>мужчина</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Мужчина</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="NotSupported_FixedSizeCollection" xml:space="preserve">
<value>Коллекция была фиксированного размера.</value>
<comment>Comment=https://github.com/dotnet/runtime/blob/v5.0.0-rc.1.20451.14/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx#L2893;Author=MicrosoftTranslator</comment>
<value>Коллекция имела фиксированный размер.</value>
<comment>Comment=https://github.com/dotnet/runtime/blob/v5.0.0-rc.1.20451.14/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx#L2893;Author=vanja-san</comment>
</data>
<data name="She" xml:space="preserve">
<value>она</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Она</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="Unknown" xml:space="preserve">
<value>Неизвестный</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Неизвестно</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="UnsupportedPhoneNumberSegment_" xml:space="preserve">
<value>Сегмент неподдерживаемых номеров мобильных телефонов ({0})</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Неподдерживаемые номера телефонов ({0})</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
<data name="OpenCoreByProcess_Win32Exception_" xml:space="preserve">
<value>Открыть веб-ссылку не удалось 0x{0}, пожалуйста, установите системный браузер по умолчанию перед попыткой</value>
<comment>Comment=;Author=MicrosoftTranslator</comment>
<value>Невозможно открыть ссылку 0x{0}, повторите снова, после установки браузер по умолчанию.</value>
<comment>Comment=;Author=vanja-san</comment>
</data>
</root>
@@ -0,0 +1,7 @@
namespace System.Properties
{
partial class ThisAssembly
{
public static string DisplayTrademark => /*DesktopBridge.IsRunningAsUwp ? $"蒸汽++" :*/ AssemblyTrademark;
}
}
@@ -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.6.9";
public const string Version = "2.7.0";
//public const string InfoVersion = Version + "-beta";
}
@@ -15,7 +15,7 @@ namespace System.Properties
/// <summary>
/// 提供程序集的文本说明
/// </summary>
public const string AssemblyDescription = "「Steam++」是一个包含多种Steam工具功能的工具箱。";
public const string AssemblyDescription = "「Steam++ 工具箱」是一个开源跨平台的多功能游戏工具箱。";
/// <summary>
/// 定义程序集清单的版权自定义属性
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/IsExternalInit.cs
// https://stackoverflow.com/questions/64749385/predefined-type-system-runtime-compilerservices-isexternalinit-is-not-defined
// https://stackoverflow.com/questions/62648189/testing-c-sharp-9-0-in-vs2019-cs0518-isexternalinit-is-not-defined-or-imported
// https://github.com/dotnet/roslyn/issues/45510
// https://docs.microsoft.com/zh-cn/dotnet/api/system.runtime.compilerservices.isexternalinit?view=net-6.0
#if NETSTANDARD2_1
using System.ComponentModel;
namespace System.Runtime.CompilerServices
{
[EditorBrowsable(EditorBrowsableState.Never)]
public class IsExternalInit
{
}
}
#endif
@@ -0,0 +1,44 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFramework>MonoAndroid12.0</TargetFramework>
<IsBindingProject>true</IsBindingProject>
<!--<GeneratePackageOnBuild>true</GeneratePackageOnBuild>-->
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
<Version>1.0.0</Version>
<RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/AigioL/xamarin-bindings</PackageProjectUrl>
<RepositoryUrl>https://github.com/AigioL/xamarin-bindings.git</RepositoryUrl>
<PackageTags>Shadowsocks Shadowsocks-Android Xamarin Plugin Binding Xamarin.Android</PackageTags>
<Product>Shadowsocks</Product>
<Company />
<PackageId>XAB.Shadowsocks</PackageId>
<Title>Xamarin Android Binding Library - Shadowsocks</Title>
<Authors>https://github.com/AigioL</Authors>
<Description>
Shadowsocks Binding for Xamarin Android. https://github.com/shadowsocks/shadowsocks-android
Commonly Used Types:
com.github.shadowsocks -&gt; Shadowsocks
</Description>
<!--<GenerateDocumentationFile>true</GenerateDocumentationFile>-->
<!--<AllowUnsafeBlocks>true</AllowUnsafeBlocks>-->
<!--<PublishRepositoryUrl>true</PublishRepositoryUrl>-->
<!--<EmbedUntrackedSources>true</EmbedUntrackedSources>-->
<!--<IncludeSymbols>true</IncludeSymbols>-->
<!--<SymbolPackageFormat>snupkg</SymbolPackageFormat>-->
</PropertyGroup>
<ItemGroup>
<LibraryProjectZip Include="Jars\*.aar" />
<TransformFile Include="Transforms\*.xml" />
<None Remove="Transforms\*.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.AppCompat" />
<PackageReference Include="Xamarin.KotlinX.Coroutines.Core" />
<PackageReference Include="Xamarin.KotlinX.Coroutines.Android" />
<!--<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />-->
</ItemGroup>
</Project>
@@ -0,0 +1,17 @@
<metadata>
<!--
This sample removes the class: android.support.v4.content.AsyncTaskLoader.LoadTask:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='AsyncTaskLoader.LoadTask']" />
This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground:
<remove-node path="/api/package[@name='android.support.v4.content']/class[@name='CursorLoader']/method[@name='loadInBackground']" />
-->
<remove-node path="/api/package[@name='net.steampp.app.shadowsocks.bg']/class[@name='Executable']" />
<remove-node path="/api/package[@name='net.steampp.app.shadowsocks.bg']/class[@name='GuardedProcessPool']" />
<remove-node path="/api/package[@name='net.steampp.app.shadowsocks.utils']" />
<remove-node path="/api/package[@name='net.steampp.app.shadowsocks']/class[@name='BuildConfig']" />
<attr path="/api/package[@name='net.steampp.app.shadowsocks.bg']"
name="managedName">Shadowsocks</attr>
<attr path="/api/package[@name='net.steampp.app.shadowsocks']"
name="managedName">Shadowsocks</attr>
</metadata>
Binary file not shown.
@@ -38,8 +38,9 @@
<ItemGroup>
<PackageReference Include="XAB.AndroidLibV2rayLite" />
<PackageReference Include="Xamarin.AndroidX.AppCompat" />
<PackageReference Include="Karamunting.KotlinX.Coroutines.Core" />
<PackageReference Include="Naxam.RxJava.Droid" />
<PackageReference Include="Xamarin.KotlinX.Coroutines.Core" />
<PackageReference Include="Xamarin.KotlinX.Coroutines.Android" />
<PackageReference Include="Xamarin.Android.ReactiveX.RxJava3.RxJava" />
<!--<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />-->
</ItemGroup>
</Project>
@@ -18,13 +18,13 @@ namespace System
if (value.HasValue)
{
checkBox.Checked = value.Value;
if (checkBox.GetTag(R.Id.checkbox_indeterminate_state) is Drawable d && checkBox.ButtonDrawable != d) drawable = d;
if (checkBox.GetTag(R.Id.checkbox_indeterminate_state) is Drawable d && checkBox.GetButtonDrawableCompat() != d) drawable = d;
checkBox.SetTag(R.Id.checkbox_indeterminate_state, null);
}
else
{
if (checkBox.GetTag(R.Id.checkbox_indeterminate_state) == null)
checkBox.SetTag(R.Id.checkbox_indeterminate_state, checkBox.ButtonDrawable);
checkBox.SetTag(R.Id.checkbox_indeterminate_state, checkBox.GetButtonDrawableCompat());
drawable = checkBox.Context!.GetDrawableCompat(R.Drawable.bg_checkbox_indeterminate);
}
if (drawable != null) checkBox.SetButtonDrawable(drawable);
@@ -0,0 +1,15 @@
using Android.Graphics.Drawables;
using Android.Widget;
using AndroidX.Core.Widget;
// ReSharper disable once CheckNamespace
namespace System
{
/// <summary>
/// <see cref="CompoundButton"/> 扩展
/// </summary>
public static partial class CompoundButtonExtensions
{
public static Drawable? GetButtonDrawableCompat(this CompoundButton button) => CompoundButtonCompat.GetButtonDrawable(button);
}
}
+51 -27
View File
@@ -84,34 +84,38 @@ namespace System.Application
return default;
}
public static void StartActivity(Activity activity, Type activityType, object viewModel, Type? viewModelType = null)
{
viewModelType ??= viewModel.GetType();
var viewModel_ = Serializable.SMP(viewModelType, viewModel);
#if DEBUG
var t = Serializable.DMP(viewModelType, viewModel_);
#endif
StartActivity(activity, activityType, viewModel_);
}
// [Obsolete]
// public static void StartActivity(Activity activity, Type activityType, object viewModel, Type? viewModelType = null)
// {
// viewModelType ??= viewModel.GetType();
// var viewModel_ = Serializable.SMP(viewModelType, viewModel);
//#if DEBUG
// var t = Serializable.DMP(viewModelType, viewModel_);
//#endif
// StartActivity(activity, activityType, viewModel_);
// }
public static void StartActivity(Fragment fragment, Type activityType, object viewModel, Type? viewModelType = null)
{
var activity = fragment.Activity;
if (activity == null) return;
StartActivity(activity, activityType, viewModel, viewModelType);
}
// [Obsolete]
// public static void StartActivity(Fragment fragment, Type activityType, object viewModel, Type? viewModelType = null)
// {
// var activity = fragment.Activity;
// if (activity == null) return;
// StartActivity(activity, activityType, viewModel, viewModelType);
// }
public static void StartActivity<TActivity>(Activity activity, object viewModel, Type? viewModelType = null)
{
StartActivity(activity, typeof(TActivity), viewModel, viewModelType);
}
// [Obsolete]
// public static void StartActivity<TActivity>(Activity activity, object viewModel, Type? viewModelType = null)
// {
// StartActivity(activity, typeof(TActivity), viewModel, viewModelType);
// }
public static void StartActivity<TActivity>(Fragment fragment, object viewModel, Type? viewModelType = null)
{
var activity = fragment.Activity;
if (activity == null) return;
StartActivity<TActivity>(activity, viewModel, viewModelType);
}
// [Obsolete]
// public static void StartActivity<TActivity>(Fragment fragment, object viewModel, Type? viewModelType = null)
// {
// var activity = fragment.Activity;
// if (activity == null) return;
// StartActivity<TActivity>(activity, viewModel, viewModelType);
// }
public static void StartActivity<TViewModel>(Activity activity, Type activityType, TViewModel viewModel)
{
@@ -180,7 +184,7 @@ namespace System.Application
return InstallApk(context, apkFile);
}
public static bool InstallCertificate(Context context, string filePath, string name)
public static Intent? GetInstallCertificateIntent(string filePath, string name)
{
try
{
@@ -189,6 +193,20 @@ namespace System.Application
intent.PutExtra("name", name);
intent.PutExtra("CERT", File.ReadAllBytes(filePath));
intent.AddFlags(ActivityFlags.NewTask);
return intent;
}
catch
{
return null;
}
}
public static bool InstallCertificate(Context context, string filePath, string name)
{
try
{
var intent = GetInstallCertificateIntent(filePath, name);
if (intent == null) return false;
context.StartActivity(intent);
return true;
}
@@ -198,10 +216,16 @@ namespace System.Application
}
}
static void StartNewTaskActivity(Context context, string action)
public static Intent GetNewTaskIntent(string action)
{
var intent = new Intent(action);
intent.AddFlags(ActivityFlags.NewTask);
return intent;
}
static void StartNewTaskActivity(Context context, string action)
{
var intent = GetNewTaskIntent(action);
context.StartActivity(intent);
}
@@ -15,6 +15,13 @@ namespace System.Application
ConfigChanges.LayoutDirection |
ConfigChanges.SmallestScreenSize;
public const ConfigChanges ConfigurationChangesWithOutOrientationLocale =
ConfigChanges.ScreenSize |
ConfigChanges.Keyboard |
ConfigChanges.KeyboardHidden |
ConfigChanges.ScreenLayout |
ConfigChanges.SmallestScreenSize;
public const string MainTheme2 = "@style/MainTheme2";
public const string MainTheme2_NoActionBar = "@style/MainTheme2.NoActionBar";
public const string MainTheme2_Splash = "@style/MainTheme2.Splash";
-101
View File
@@ -1,101 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 此代码由工具生成。
// 运行时版本:4.0.30319.42000
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
namespace System.Application.Properties {
using System;
/// <summary>
/// 一个强类型的资源类,用于查找本地化的字符串等。
/// </summary>
// 此类是由 StronglyTypedResourceBuilder
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
// 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
// (以 /str 作为命令选项),或重新生成 VS 项目。
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SR {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SR() {
}
/// <summary>
/// 返回此类使用的缓存的 ResourceManager 实例。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("System.Application.Properties.SR", typeof(SR).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写。
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// 查找类似 {
/// &quot;dns&quot;: {
/// &quot;hosts&quot;: {
/// &quot;domain:googleapis.cn&quot;: &quot;googleapis.com&quot;
/// },
/// &quot;servers&quot;: [
/// &quot;1.1.1.1&quot;
/// ]
/// },
/// &quot;inbounds&quot;: [
/// {
/// &quot;listen&quot;: &quot;127.0.0.1&quot;,
/// &quot;port&quot;: 10808,
/// &quot;protocol&quot;: &quot;socks&quot;,
/// &quot;settings&quot;: {
/// &quot;auth&quot;: &quot;noauth&quot;,
/// &quot;udp&quot;: true,
/// &quot;userLevel&quot;: 8
/// },
/// &quot;sniffing&quot;: {
/// &quot;destOverride&quot;: [
/// &quot;http&quot;,
/// &quot;tls&quot;
/// ],
/// &quot;enabled&quot;: true
/// },
/// &quot;tag&quot;: &quot;socks&quot;
/// },
/// {
/// [字符串的其余部分被截断]&quot;; 的本地化字符串。
/// </summary>
internal static string v2rayPoint_configure {
get {
return ResourceManager.GetString("v2rayPoint_configure", resourceCulture);
}
}
}
}
-124
View File
@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="v2rayPoint_configure" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\v2rayPoint.configure.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;gb2312</value>
</data>
</root>
@@ -1,107 +0,0 @@
{
"dns": {
"hosts": {
"domain:googleapis.cn": "googleapis.com"
},
"servers": [
"1.1.1.1"
]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true,
"userLevel": 8
},
"sniffing": {
"destOverride": [
"http",
"tls"
],
"enabled": true
},
"tag": "socks"
},
{
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {
"userLevel": 8
},
"tag": "http"
}
],
"log": {
"loglevel": "warning"
},
"outbounds": [
{
"mux": {
"concurrency": 8,
"enabled": false
},
"protocol": "socks",
"settings": {
"servers": [
{
"address": "${ProxyIp}",
"level": 8,
"method": "chacha20-poly1305",
"ota": false,
"password": "",
"port": ${ProxyPort}
}
]
},
"streamSettings": {
"network": "tcp",
"security": "",
"tcpSettings": {
"header": {
"type": "none"
}
}
},
"tag": "proxy"
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
},
"tag": "block"
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"ip": [
"1.1.1.1"
],
"outboundTag": "proxy",
"port": "53",
"type": "field"
},
{
"ip": [
"geoip:private"
],
"outboundTag": "direct",
"type": "field"
}
]
}
}
+76 -8
View File
@@ -4,7 +4,8 @@
<TargetFrameworks>MonoAndroid12.0</TargetFrameworks>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>Xamarin.Forms.Platform.Android.UnitTests</AssemblyName>
<DefineConstants>__HAVE_ANDROIDX__;$(DefineConstants)</DefineConstants>
<DefineConstants>SHADOWSOCKS;__HAVE_ANDROIDX__;$(DefineConstants)</DefineConstants>
<!--<DefineConstants>SHADOWSOCKS;V2RAY;__HAVE_ANDROIDX__;$(DefineConstants)</DefineConstants>-->
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-android'))">21.0</SupportedOSPlatformVersion>
</PropertyGroup>
@@ -115,7 +116,6 @@
<Compile Remove="Services\V2Ray\**" />
<EmbeddedResource Remove="Services\V2Ray\**" />
<None Remove="Services\V2Ray\**" />
<AndroidResource Remove="Resources\v2rayPoint.configure.txt" />
<Compile Remove="Services\Native\ProxyForegroundService.JNI.tun2http.cs" />
<None Remove="Resources\layout\controls_btntext.xml" />
<Compile Include="..\AboutAppInfoPopup.cs">
@@ -161,7 +161,8 @@
</ItemGroup>-->
<ItemGroup>
<ProjectReference Include="..\ST.Client.Android.V2Ray\ST.Client.Android.V2Ray.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.XamarinForms\ST.Client.XamarinForms.csproj" Condition=" $(DefineConstants.Contains(`__XAMARIN_FORMS__`)) " />
<ProjectReference Include="..\ST.Client\ST.Client.csproj" />
</ItemGroup>
@@ -322,6 +323,9 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\bg_textbox.xml">
<Link>Resources\drawable\bg_textbox.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\bg_vpn_shape_gradient.xml">
<Link>Resources\drawable\bg_vpn_shape_gradient.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\icon_apple_24.xml">
<Link>Resources\drawable\icon_apple_24.xml</Link>
</AndroidResource>
@@ -376,6 +380,12 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\ic_baseline_stop_24.xml">
<Link>Resources\drawable\ic_baseline_stop_24.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\ic_baseline_vpn_key_24.xml">
<Link>Resources\drawable\ic_baseline_vpn_key_24.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\ic_fluent_certificate_24_regular.xml">
<Link>Resources\drawable\ic_fluent_certificate_24_regular.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable\mdi_rocket_black_24.xml">
<Link>Resources\drawable\mdi_rocket_black_24.xml</Link>
</AndroidResource>
@@ -442,6 +452,12 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable-xxhdpi\logo.png">
<Link>Resources\drawable-xxhdpi\logo.png</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable-xxhdpi\logo_kotlin_20.png">
<Link>Resources\drawable-xxhdpi\logo_kotlin_20.png</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable-xxhdpi\logo_xamarin_20.png">
<Link>Resources\drawable-xxhdpi\logo_xamarin_20.png</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\drawable-xxhdpi\splash_logo.png">
<Link>Resources\drawable-xxhdpi\splash_logo.png</Link>
</AndroidResource>
@@ -478,6 +494,15 @@
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_export_auth.xml">
<Link>Resources\layout\activity_export_auth.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_guide_ca_cert.xml">
<Link>Resources\layout\activity_guide_ca_cert.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_guide_vpn.xml">
<Link>Resources\layout\activity_guide_vpn.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_guide_vpn_content.xml">
<Link>Resources\layout\activity_guide_vpn_content.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_login_or_register.xml">
<Link>Resources\layout\activity_login_or_register.xml</Link>
</AndroidBoundLayout>
@@ -529,6 +554,18 @@
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_basic_profile_content.xml">
<Link>Resources\layout\fragment_basic_profile_content.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_bind_phone_number.xml">
<Link>Resources\layout\fragment_bind_phone_number.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_bind_phone_number_content.xml">
<Link>Resources\layout\fragment_bind_phone_number_content.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_change_bind_phone_number.xml">
<Link>Resources\layout\fragment_change_bind_phone_number.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_change_bind_phone_number_content.xml">
<Link>Resources\layout\fragment_change_bind_phone_number_content.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_community_fix.xml">
<Link>Resources\layout\fragment_community_fix.xml</Link>
</AndroidBoundLayout>
@@ -541,6 +578,18 @@
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_game_list.xml">
<Link>Resources\layout\fragment_game_list.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_guide_export_ca_cert.xml">
<Link>Resources\layout\fragment_guide_export_ca_cert.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_guide_export_ca_cert_content.xml">
<Link>Resources\layout\fragment_guide_export_ca_cert_content.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_guide_how_install_ca_cert.xml">
<Link>Resources\layout\fragment_guide_how_install_ca_cert.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_guide_how_install_ca_cert_content.xml">
<Link>Resources\layout\fragment_guide_how_install_ca_cert_content.xml</Link>
</AndroidBoundLayout>
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_local_auth.xml">
<Link>Resources\layout\fragment_local_auth.xml</Link>
</AndroidBoundLayout>
@@ -703,6 +752,9 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\navigation\mobile_navigation.xml">
<Link>Resources\navigation\mobile_navigation.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\navigation\nav_graph_guide_ca_cert.xml">
<Link>Resources\navigation\nav_graph_guide_ca_cert.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\navigation\nav_graph_login_or_register.xml">
<Link>Resources\navigation\nav_graph_login_or_register.xml</Link>
</AndroidResource>
@@ -727,6 +779,21 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values\themes.xml">
<Link>Resources\values\themes.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-en\strings.xml">
<Link>Resources\values-en\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-es\strings.xml">
<Link>Resources\values-es\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-it\strings.xml">
<Link>Resources\values-it\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-ja\strings.xml">
<Link>Resources\values-ja\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-ko\strings.xml">
<Link>Resources\values-ko\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-land\dimens_fixed_width.xml">
<Link>Resources\values-land\dimens_fixed_width.xml</Link>
</AndroidResource>
@@ -736,19 +803,20 @@
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-night\themes.xml">
<Link>Resources\values-night\themes.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-ru\strings.xml">
<Link>Resources\values-ru\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-v23\themes.xml">
<Link>Resources\values-v23\themes.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-v28\themes.xml">
<Link>Resources\values-v28\themes.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\values-zh-rHK\strings.xml">
<Link>Resources\values-zh-rHK\strings.xml</Link>
</AndroidResource>
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\xml\local_auth_appwidget_info.xml">
<Link>Resources\xml\local_auth_appwidget_info.xml</Link>
</AndroidResource>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\SR.Designer.cs">
<DesignTime>True</DesignTime>
</Compile>
</ItemGroup>
</Project>
@@ -0,0 +1,67 @@
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Java.Security;
using Javax.Net.Ssl;
namespace System.Application.Services.Implementation
{
partial class AndroidPlatformServiceImpl
{
static IX509TrustManager? X509TrustManager
{
get
{
var instance = KeyStore.GetInstance("AndroidCAStore");
if (instance == null) return null;
instance.Load(null);
var instance2 = TrustManagerFactory.GetInstance(TrustManagerFactory.DefaultAlgorithm);
if (instance2 == null) return null;
instance2.Init(instance);
var trustManager = instance2.GetTrustManagers()?
.Select(Convert)
.FirstOrDefault(x => x != null);
return trustManager;
}
}
static IX509TrustManager? Convert(ITrustManager? trustManager)
{
if (trustManager == null) return null;
if (trustManager is IX509TrustManager x509TrustManager) return x509TrustManager;
try
{
return Android.Runtime.Extensions.JavaCast<IX509TrustManager>(trustManager);
}
catch
{
return null;
}
}
internal static bool IsCertificateInstalled(X509Certificate2 certificate2)
{
var x509TrustManager = X509TrustManager;
if (x509TrustManager == null) return false;
using var certificate = certificate2.Convert();
var authType = certificate.SigAlgName;
try
{
x509TrustManager.CheckServerTrusted(new[] { certificate }, authType);
return true;
}
#if DEBUG
catch (Exception e)
#else
catch
#endif
{
#if DEBUG
//Toast.Show($"[DEBUG] {e}");
#endif
return false;
}
}
bool IPlatformService.IsCertificateInstalled(X509Certificate2 certificate2) => IsCertificateInstalled(certificate2);
}
}
@@ -23,7 +23,7 @@ namespace System.Application.Services.Native
{
public static async void StartOrStop(Activity activity, bool startOrStop)
{
if (ProxySettings.IsVpnMode.Value)
if (ProxySettings.ProxyModeValue == ProxyMode.VPN)
{
if (startOrStop)
{
@@ -33,8 +33,15 @@ namespace System.Application.Services.Native
{
void OnResult(Intent intent)
=> activity.StartOrStopForegroundService<VpnService>(true);
await IntermediateActivity.StartAsync(intent,
requestCodeVpnService, onResult: OnResult);
try
{
await IntermediateActivity.StartAsync(intent,
requestCodeVpnService, onResult: OnResult);
}
catch (OperationCanceledException)
{
}
return;
}
}
@@ -0,0 +1,162 @@
#if SHADOWSOCKS
using Android.App;
using Android.Content;
using Android.Runtime;
using System.Application.Services.Implementation;
using static System.Application.Services.Native.IServiceBase;
using AndroidX.Core.App;
using static System.Properties.ThisAssembly;
using System.Collections.Generic;
namespace System.Application.Services.Native
{
partial class ProxyForegroundService
{
partial class VpnService : Shadowsocks.VpnService
{
bool isStart;
int notifyId;
NotificationCompat.Builder? builder;
NotificationManagerCompat? mNotificationManager;
NotificationManagerCompat NotificationManager
{
get
{
if (mNotificationManager == null)
{
mNotificationManager = NotificationManagerCompat.From(this);
}
return mNotificationManager;
}
}
public override void OnStart()
{
if (isStart) return;
isStart = true;
// 先显示通知 UI
IForegroundService f = this;
(builder, mNotificationManager, notifyId) = AndroidNotificationServiceImpl.Instance.StartForeground(this, f.NotificationType, f.NotificationText, f.NotificationEntranceAction);
// 启动本地代理服务
ProxyService.Current.ProxyStatus = true;
// 启动 VPN tun2socks
base.OnStart();
}
public override void OnStop()
{
if (!isStart) return;
isStart = false;
// 停止通知栏 UI
StopForeground(true);
// 停止 VPN tun2socks
base.OnStop();
// 停止本地代理服务
ProxyService.Current.ProxyStatus = false;
}
public override void OnRevoke()
{
OnStop();
base.OnRevoke();
}
[return: GeneratedEnum]
public override StartCommandResult OnStartCommand(Intent? intent, [GeneratedEnum] StartCommandFlags flags, int startId)
{
if (intent != null)
{
var action = intent.Action;
switch (action)
{
case START:
OnStart();
return StartCommandResult.RedeliverIntent;
case STOP:
default:
OnStop();
StopSelf();
break;
}
}
return StartCommandResult.NotSticky;
}
public override string SocksServerAddress
{
get
{
var s = ProxyService.Current;
return $"{s.ProxyIp}:{s.Socks5ProxyPortId}";
}
}
const int VPN_MTU = 1500;
const string VPN_MTU_STR = "1500";
public override void OnConfigure(Builder builder)
{
builder.SetSession(AssemblyTrademark);
//builder.AddDnsServer(IDnsAnalysisService.PrimaryDNS_Ali);
// https://github.com/2dust/v2rayNG/blob/master/AndroidLibV2rayLite/CoreI/Status.go#L56
builder.SetMtu(VPN_MTU);
builder.AddAddress("26.26.26.1", 30);
AddRouteByPassPrivateIPAddress(builder);
builder.AddAddress("da26:2626::1", 126);
builder.AddRoute("2000::", 3);
builder.AddDisallowedApplication(PackageName!);
}
public override IList<string> Tun2socksArgs
{
get
{
// https://github.com/2dust/v2rayNG/blob/master/AndroidLibV2rayLite/CoreI/Status.go#L28
return new JavaList<string>
{
Tun2socksExecutablePath,
"--netif-ipaddr",
"26.26.26.2",
"--netif-netmask",
"255.255.255.252",
"--socks-server-addr",
SocksServerAddress,
"--tunmtu",
VPN_MTU_STR,
"--loglevel",
"notice",
"--enable-udprelay",
"--sock-path",
"sock_path",
"--netif-ip6addr",
"da26:2626::2"
};
}
}
#if DEBUG
public override void OnError(string msg, Java.Lang.Throwable tr)
{
base.OnError(msg, tr);
}
public override string SockPath
{
get
{
var value = base.SockPath;
Log.Info(nameof(VpnService), $"SockPath: {value}");
return value;
}
}
#endif
}
}
}
#endif
@@ -1,3 +1,4 @@
#if V2RAY
using V2RayNG;
using Android.App;
using Android.Content;
@@ -92,6 +93,7 @@ namespace System.Application.Services.Native
var s = ProxyService.Current;
text = text.Replace("${ProxyIp}", s.ProxyIp.ToString());
text = text.Replace("${ProxyPort}", s.Socks5ProxyPortId.ToString());
text = text.Replace("${VpnDns}", IDnsAnalysisService.PrimaryDNS_Ali);
return text;
}
}
@@ -105,7 +107,7 @@ namespace System.Application.Services.Native
}
}
bool IV2RayServiceManager.ForwardIpv6 => false;
bool IV2RayServiceManager.ForwardIpv6 => true;
void IV2RayServiceManager.UpdateNotification(string? contentText, long proxyTraffic, long directTraffic)
{
@@ -121,6 +123,14 @@ namespace System.Application.Services.Native
builder.SetContentText(contentText);
NotificationManager.Notify(notifyId, builder.Build());
}
public override void OnConfigure(Builder builder)
{
builder.AddDisallowedApplication(PackageName!);
}
public override string RoutingMode => "3";
}
}
}
#endif
@@ -90,7 +90,7 @@ namespace System.Application.UI.Activities
}
else if (view.Id == Resource.Id.clickDate)
{
this.ShowBirthDatePicker(ViewModel!.DonateFliterDate.Date);
this.ShowBirthDatePicker(ViewModel!.DonateFliterDate.Date, title: AppResources.PleaseSelect);
return;
}
else if (view.Id == Resource.Id.btn_afdian)
@@ -0,0 +1,171 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Text;
using Android.Text.Style;
using AndroidX.Navigation.Fragment;
using AndroidX.Navigation.UI;
using Binding;
using ReactiveUI;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Collections.Generic;
using System.Application.UI.Fragments;
using System.Text;
using Android.Views;
using System.Application.Services;
using ASettings = Android.Provider.Settings;
using static AndroidX.Activity.Result.ActivityResultTask;
using System.Threading.Tasks;
using XEPlatform = Xamarin.Essentials.Platform;
namespace System.Application.UI.Activities
{
/// <summary>
/// 引导导入证书页面
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(GuideCACertActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_NoActionBar,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChangesWithOutOrientationLocale)]
internal sealed class GuideCACertActivity : BaseActivity<activity_guide_ca_cert>
{
protected override int? LayoutResource => Resource.Layout.activity_guide_ca_cert;
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
this.SetSupportActionBarWithNavigationClick(binding!.toolbar, true);
Title = string.Empty;
var appBarConfiguration = new AppBarConfiguration.Builder(Resource.Id.navigation_guide_export_ca_cert).Build();
navController = ((NavHostFragment)SupportFragmentManager.FindFragmentById(Resource.Id.nav_host_fragment)).NavController;
NavigationUI.SetupActionBarWithNavController(this, navController, appBarConfiguration);
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
}
[Register(JavaPackageConstants.Fragments + nameof(GuideExportCACertFragment))]
internal sealed class GuideExportCACertFragment : BaseFragment<fragment_guide_export_ca_cert, CommunityProxyPageViewModel>
{
protected override int? LayoutResource => Resource.Layout.fragment_guide_export_ca_cert;
protected override CommunityProxyPageViewModel? OnCreateViewModel()
{
return IViewModelManager.Instance.GetMainPageViewModel<CommunityProxyPageViewModel>();
}
bool canInstalledCACert;
public override void OnCreateView(View view)
{
base.OnCreateView(view);
var sdkInt = (int)Build.VERSION.SdkInt;
canInstalledCACert = !(sdkInt > 29 || (sdkInt == 29 && Build.VERSION.PreviewSdkInt > 0));
// com.adguard.kit.compatibility.h()
// com.adguard.android.ui.fragments.https_ca_installation.b()
// return com.adguard.kit.compatibility.a.h() ? super.b() : R.l.https_ca_installation_guide_install_ca;
// Android 10+ 只能通过系统设置从存储区导入 CA 证书
if (canInstalledCACert)
{
binding!.tvDesc3.Visibility = ViewStates.Gone;
binding!.btnDone.Text = GetString(Resource.String.guide_export_ca_cert_btn_install);
}
SetOnClickListener(binding!.btnDone);
}
public override void OnResume()
{
base.OnResume();
if (IHttpProxyService.Instance.IsCurrentCertificateInstalled)
{
var intent = IntermediateActivity.SetResult(new(), Result.Ok);
var a = RequireActivity();
a.SetResult(Result.Ok, intent);
a.Finish();
}
}
protected override bool OnClick(View view)
{
if (view.Id == Resource.Id.btnDone)
{
if (canInstalledCACert)
{
CommunityFixFragment.InstallCertificate(RequireContext(), ViewModel!);
}
else
{
ExportCertificateFile();
}
return true;
}
return base.OnClick(view);
}
async void ExportCertificateFile()
{
var isOK = await ViewModel!.ExportCertificateFileAsync();
if (isOK)
{
await GoToGuideHowInstallCACertPageAsync();
}
}
async Task GoToGuideHowInstallCACertPageAsync()
{
int count = 0;
while (XEPlatform.CurrentActivity != RequireActivity() && count < 10)
{
await Task.Delay(200);
count++;
}
var navController = this.GetNavController();
navController?.Navigate(Resource.Id.action_navigation_guide_export_ca_cert_to_navigation_guide_how_install_ca_cert);
}
}
[Register(JavaPackageConstants.Fragments + nameof(GuideHowInstallCACertFragment))]
internal sealed class GuideHowInstallCACertFragment : BaseFragment<fragment_guide_how_install_ca_cert>
{
protected override int? LayoutResource => Resource.Layout.fragment_guide_how_install_ca_cert;
public override void OnCreateView(View view)
{
base.OnCreateView(view);
SetOnClickListener(binding!.btnDone);
}
public override void OnResume()
{
base.OnResume();
if (IHttpProxyService.Instance.IsCurrentCertificateInstalled)
{
var intent = IntermediateActivity.SetResult(new(), Result.Ok);
var a = RequireActivity();
a.SetResult(Result.Ok, intent);
a.Finish();
}
}
protected override bool OnClick(View view)
{
if (view.Id == Resource.Id.btnDone)
{
GoToPlatformPages.SystemSettingsSecurity(RequireActivity());
return true;
}
return base.OnClick(view);
}
}
}
}
@@ -0,0 +1,80 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
using Android.Text;
using Android.Text.Style;
using AndroidX.Navigation.Fragment;
using AndroidX.Navigation.UI;
using Binding;
using ReactiveUI;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Collections.Generic;
using System.Application.UI.Fragments;
using System.Text;
using Android.Views;
using Android.Net;
using static AndroidX.Activity.Result.ActivityResultTask;
namespace System.Application.UI.Activities
{
/// <summary>
/// 引导开启 VPN 页面
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(GuideVPNActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_NoActionBar,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChangesWithOutOrientationLocale)]
internal sealed class GuideVPNActivity : BaseActivity<activity_guide_vpn>
{
protected override int? LayoutResource => Resource.Layout.activity_guide_vpn;
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
this.SetSupportActionBarWithNavigationClick(binding!.toolbar, true);
Title = string.Empty;
SetOnClickListener(binding.btnDone);
}
async void Prepare()
{
var intent = VpnService.Prepare(this);
if (intent != null)
{
void OnResult(Intent intent)
{
intent = IntermediateActivity.SetResult(intent, Result.Ok);
SetResult(Result.Ok, intent);
Finish();
}
try
{
await IntermediateActivity.StartAsync(intent,
NextRequestCode(), onResult: OnResult);
}
catch (OperationCanceledException)
{
}
}
else
{
Finish();
}
}
protected override void OnClick(View view)
{
if (view.Id == Resource.Id.btnDone)
{
Prepare();
}
}
}
}
@@ -176,7 +176,7 @@ namespace System.Application.UI.Activities
}
else if (view.Id == Resource.Id.layoutRootIsVpnMode)
{
IsVpnMode.Value = !IsVpnMode.Value;
ProxyModeValue = ProxyModeValue == ProxyMode.VPN ? ProxyMode.ProxyOnly : ProxyMode.VPN;
SetIsVpnMode();
return;
}
@@ -188,6 +188,6 @@ namespace System.Application.UI.Activities
void SetOnlyEnableProxyScript() => binding!.swOnlyEnableProxyScript.Checked = OnlyEnableProxyScript.Value;
void SetProxySettingsSocks5() => binding!.swProxySettingsSocks5.Checked = Socks5ProxyEnable.Value;
void SetProxySettingsTwoLevelAgent() => binding!.swProxySettingsTwoLevelAgent.Checked = TwoLevelAgentEnable.Value;
void SetIsVpnMode() => binding!.swIsVpnMode.Checked = IsVpnMode.Value;
void SetIsVpnMode() => binding!.swIsVpnMode.Checked = ProxyModeValue == ProxyMode.VPN;
}
}
@@ -1,22 +0,0 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
namespace System.Application.UI.Activities
{
[Authorize]
[Register(JavaPackageConstants.Activities + nameof(BindPhoneNumberActivity))]
[Activity(Theme = ManifestConstants.MainTheme2,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
internal sealed class BindPhoneNumberActivity : BaseActivity
{
protected override int? LayoutResource => throw new NotImplementedException();
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
}
}
}
@@ -1,22 +0,0 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
using Android.Runtime;
namespace System.Application.UI.Activities
{
[Authorize]
[Register(JavaPackageConstants.Activities + nameof(ChangePhoneNumberActivity))]
[Activity(Theme = ManifestConstants.MainTheme2,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
internal sealed class ChangePhoneNumberActivity : BaseActivity
{
protected override int? LayoutResource => throw new NotImplementedException();
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
}
}
}
@@ -8,6 +8,8 @@ using System.Application.UI.Fragments;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using Fragment = AndroidX.Fragment.App.Fragment;
using NUserService = System.Application.Services.UserService;
using static System.Application.UI.ViewModels.UserProfileWindowViewModel;
namespace System.Application.UI.Activities
{
@@ -33,14 +35,18 @@ namespace System.Application.UI.Activities
var adapter = new ViewPagerWithTabLayoutAdapter(this, this);
binding!.pager.SetupWithTabLayout(binding!.tab_layout, adapter);
var position = this.GetViewModel<SubPageType>();
GoToSubPage(position);
}
int ViewPagerAdapter.IHost.ItemCount => 2;
int ViewPagerAdapter.IHost.ItemCount => pageCount;
Fragment ViewPagerAdapter.IHost.CreateFragment(int position) => position switch
{
0 => new UserBasicInfoFragment(),
1 => new UserAccountBindFragment(),
2 => NUserService.Current.HasPhoneNumber ? new ChangePhoneNumberFragment() : new BindPhoneNumberFragment(),
_ => throw new ArgumentOutOfRangeException(nameof(position), position.ToString()),
};
@@ -48,6 +54,7 @@ namespace System.Application.UI.Activities
{
0 => AppResources.User_BasicInfo,
1 => AppResources.User_AccountBind,
2 => NUserService.Current.HasPhoneNumber ? AppResources.User_ChangePhoneNum : AppResources.User_BindPhoneNum,
_ => throw new ArgumentOutOfRangeException(nameof(position), position.ToString()),
};
@@ -64,5 +71,26 @@ namespace System.Application.UI.Activities
base.OnBackPressed();
}
const int pageCount = 3;
public static void StartActivity(Activity activity, SubPageType position = 0)
{
if (position.IsDefined())
{
GoToPlatformPages.StartActivity<UserProfileActivity, SubPageType>(activity, position);
}
else
{
activity.StartActivity<UserProfileActivity>();
}
}
public void GoToSubPage(SubPageType position)
{
if (position.IsDefined())
{
binding!.pager.SetCurrentItem((int)position, false);
}
}
}
}
@@ -130,7 +130,7 @@ namespace System.Application.UI.Controllers
binding.rvPreferenceButtons.AddItemDecoration(new PreferenceButtonItemDecoration(Context, Resource.Dimension.preference_buttons_space_min));
binding.rvPreferenceButtons.SetAdapter(adapter);
SetOnClickListener(binding.ivLogo, binding.tvTitle);
SetOnClickListener(binding.ivLogo, binding.tvTitle, binding.chip_xamarin, binding.chip_kotlin);
}
public override bool OnClick(View view)
@@ -140,6 +140,27 @@ namespace System.Application.UI.Controllers
AboutAppInfoPopup.OnClick();
return true;
}
else if (view.Id == Resource.Id.chip_xamarin)
{
string lang;
if (R.IsChineseSimplified)
{
lang = "zh-cn";
}
else if (R.Culture.Name.StartsWith("ja", StringComparison.OrdinalIgnoreCase))
{
lang = "ja-jp";
}
else
{
lang = "en-us";
}
Browser2.Open($"https://dotnet.microsoft.com/{lang}/learn/xamarin/what-is-xamarin");
}
else if (view.Id == Resource.Id.chip_kotlin)
{
Browser2.Open("https://kotlinlang.org");
}
return base.OnClick(view);
}
+6 -6
View File
@@ -67,15 +67,15 @@ namespace System.Application.UI
return dialogFragment;
}
static MaterialDatePicker GetBirthDatePicker(object listener, DateTime selected = default)
static MaterialDatePicker GetBirthDatePicker(object listener, string? title = null, DateTime selected = default)
=> GetDatePicker(listener,
AppResources.UserProfile_BirthDate,
title ?? AppResources.UserProfile_BirthDate,
selected == default ? IBirthDate.DefaultSelected : selected,
IBirthDate.SelectionRange);
static void ShowBirthDatePicker(this FragmentManager fragmentManager, object listener, DateTime selected = default)
static void ShowBirthDatePicker(this FragmentManager fragmentManager, object listener, string? title = null, DateTime selected = default)
{
var dialogFragment = GetBirthDatePicker(listener, selected);
var dialogFragment = GetBirthDatePicker(listener, title, selected);
dialogFragment.Show(fragmentManager, dialogFragment.ToString());
}
@@ -94,8 +94,8 @@ namespace System.Application.UI
/// <param name="activity"></param>
/// <param name="selected"></param>
/// <param name="listener"></param>
public static void ShowBirthDatePicker(this FragmentActivity activity, DateTime selected = default, object? listener = null)
=> ShowBirthDatePicker(activity.SupportFragmentManager, listener ?? activity, selected);
public static void ShowBirthDatePicker(this FragmentActivity activity, DateTime selected = default, object? listener = null, string? title = null)
=> ShowBirthDatePicker(activity.SupportFragmentManager, listener ?? activity, title, selected);
/// <summary>
/// 日期选择确定按钮点击时监听
@@ -19,6 +19,11 @@ using System.Net.Http;
using System.Text;
using static System.Application.UI.ViewModels.CommunityProxyPageViewModel;
using System.Application.Services.Implementation;
using Android.Net;
using static AndroidX.Activity.Result.ActivityResultTask;
using Android.Content;
using System.Application.UI.Activities;
using Android.App;
namespace System.Application.UI.Fragments
{
@@ -36,18 +41,28 @@ namespace System.Application.UI.Fragments
{
base.OnCreateView(view);
var proxyS = ProxyService.Current;
void SetProxyModeText()
{
var proxyMode = ProxySettings.ProxyModeValue;
binding!.tvProxyMode.Text = proxyMode switch
{
ProxyMode.ProxyOnly => $"{AppResources.CommunityFix_ProxyModeTip}{ProxySettings.ToStringByProxyMode(proxyMode)}{Environment.NewLine}IPEndPoint: {proxyS.ProxyIp}:{proxyS.ProxyPort}",
_ => $"{AppResources.CommunityFix_ProxyModeTip}{ProxySettings.ToStringByProxyMode(proxyMode)}",
};
}
R.Subscribe(() =>
{
if (binding == null) return;
binding.btnStartProxyService.Text = AppResources.CommunityFix_StartProxy;
binding.btnStopProxyService.Text = AppResources.CommunityFix_StopProxy;
//binding.tvProxyMode.Text = AppResources.CommunityFix_ProxyModeTip + AppResources.CommunityFix_ProxyMode_WinSystem;
SetProxyModeText();
binding.tvAccelerationsEnable.Text = AppResources.CommunityFix_AccelerationsEnable;
binding.tvScriptsEnable.Text = AppResources.CommunityFix_ScriptsEnable;
SetMenuTitle();
}).AddTo(this);
var proxyS = ProxyService.Current;
proxyS.WhenAnyValue(x => x.AccelerateTime).SubscribeInMainThread(value =>
{
if (binding == null) return;
@@ -60,7 +75,7 @@ namespace System.Application.UI.Fragments
binding.layoutRootCommunityFixContentStarting.Visibility = value ? ViewStates.Visible : ViewStates.Gone;
if (value)
{
binding.tvProxyMode.Text = $"IPEndPoint: {proxyS.ProxyIp}:{proxyS.ProxyPort}";
SetProxyModeText();
StringBuilder s = new();
var enableProxyDomains = proxyS.GetEnableProxyDomains();
if (enableProxyDomains != null)
@@ -140,14 +155,61 @@ namespace System.Application.UI.Fragments
ProxyService.IsChangeSupportProxyServicesStatus = false;
SettingsHost.Save();
#if DEBUG
Toast.Show("已保存勾选状态");
Toast.Show("[DEBUG] 已保存勾选状态");
#endif
}
}
void StartProxyButton_Click(bool start)
=> AndroidPlatformServiceImpl.StartOrStopForegroundService(
RequireActivity(), nameof(ProxyService), start);
async void StartProxyButton_Click(bool start/*, bool ignoreVPNCheck = false*/)
{
var a = RequireActivity();
if (start)
{
Intent? intent = null;
if (/*!ignoreVPNCheck &&*/ ProxySettings.ProxyModeValue == ProxyMode.VPN) // 当启用 VPN 模式时
{
intent = VpnService.Prepare(a);
if (intent != null)
{
// 需要授予 VPN 权限
intent = new Intent(a, typeof(GuideVPNActivity));
try
{
intent = await IntermediateActivity.StartAsync(intent, NextRequestCode());
}
catch (OperationCanceledException)
{
return;
}
}
}
if (!IHttpProxyService.Instance.IsCurrentCertificateInstalled) // 检查 CA 证书是否已安装
{
// 当未安装证书时
intent = new Intent(a, typeof(GuideCACertActivity));
try
{
intent = await IntermediateActivity.StartAsync(intent, NextRequestCode());
}
catch (OperationCanceledException)
{
return;
}
}
if (intent != null)
{
var result = IntermediateActivity.GetResult(intent);
if (result != Result.Ok)
{
// 从引导页面返回结果不为 Ok 时则不启动加速
return;
}
}
}
AndroidPlatformServiceImpl.StartOrStopForegroundService(a, nameof(ProxyService), start);
}
protected override bool OnClick(View view)
{
@@ -241,11 +303,13 @@ namespace System.Application.UI.Fragments
return default;
}
void InstallCertificate() => ViewModel!.ExportCertificateFile(cefFilePath =>
internal static void InstallCertificate(Context context, CommunityProxyPageViewModel vm) => vm.ExportCertificateFile(cefFilePath =>
{
GoToPlatformPages.InstallCertificate(RequireContext(), cefFilePath, IHttpProxyService.RootCertificateName);
GoToPlatformPages.InstallCertificate(context, cefFilePath, IHttpProxyService.RootCertificateName);
});
void InstallCertificate() => InstallCertificate(RequireContext(), ViewModel!);
#if DEBUG
async void Test()
{
@@ -36,7 +36,7 @@ namespace System.Application.UI.Fragments
switch (e.Current.Id)
{
case FastLoginChannelViewModel.PhoneNumber:
GoToUsePhoneNumberPage(e.GetView());
GoToUsePhoneNumberPage();
break;
default:
ViewModel!.ChooseChannel.Invoke(e.Current.Id);
@@ -53,9 +53,9 @@ namespace System.Application.UI.Fragments
}
}
void GoToUsePhoneNumberPage(View? view)
void GoToUsePhoneNumberPage()
{
var navController = this.GetNavController(view);
var navController = this.GetNavController();
navController?.Navigate(Resource.Id.action_navigation_login_or_register_fast_to_navigation_login_or_register_phone_number);
}
}
@@ -69,30 +69,6 @@ namespace System.Application.UI.Fragments
SetMenuTitle();
}).AddTo(this);
void OnAuthenticatorsChanged(bool isAuthenticatorsEmpty, bool isFirstActivation)
{
if (binding == null) return;
ViewStates state, state_reverse, /*fab_state,*/ loading_state;
if (isFirstActivation)
{
state = ViewStates.Gone;
state_reverse = ViewStates.Gone;
//fab_state = ViewStates.Gone;
loading_state = ViewStates.Visible;
}
else
{
state = isAuthenticatorsEmpty ? ViewStates.Visible : ViewStates.Gone;
state_reverse = !isAuthenticatorsEmpty ? ViewStates.Visible : ViewStates.Gone;
//fab_state = ViewStates.Visible;
loading_state = ViewStates.Gone;
}
binding.tvEmptyTip.Visibility = state;
binding.rvAuthenticators.Visibility = state_reverse;
//binding.speedDial.Visibility = fab_state;
binding.layoutLoading.Visibility = loading_state;
}
ViewModel!.WhenAnyValue(x => x.IsAuthenticatorsEmpty)
.SubscribeInMainThread(x => OnAuthenticatorsChanged(x, ViewModel!.IsFirstActivation))
.AddTo(this);
@@ -119,7 +95,7 @@ namespace System.Application.UI.Fragments
AuthDetailActivity.StartActivity(Activity, e.Current.Id);
};
binding!.rvAuthenticators.SetLinearLayoutManager();
binding.rvAuthenticators.AddVerticalItemDecorationRes(Resource.Dimension.activity_vertical_margin/*, Resource.Dimension.fab_full_height*/);
binding.rvAuthenticators.AddVerticalItemDecorationRes(Resource.Dimension.activity_vertical_margin, Resource.Dimension.activity_vertical_margin);
binding.rvAuthenticators.SetAdapter(adapter);
//var actionItems = Enum2.GetAll<ActionItem>();
@@ -136,12 +112,47 @@ namespace System.Application.UI.Fragments
binding.swipeRefreshLayout.SetOnRefreshListener(this);
}
void OnAuthenticatorsChanged(bool isAuthenticatorsEmpty, bool isFirstActivation)
{
if (binding == null) return;
ViewStates state, state_reverse, /*fab_state,*/ loading_state;
if (isFirstActivation)
{
state = ViewStates.Gone;
state_reverse = ViewStates.Gone;
//fab_state = ViewStates.Gone;
loading_state = ViewStates.Visible;
}
else
{
state = isAuthenticatorsEmpty ? ViewStates.Visible : ViewStates.Gone;
state_reverse = !isAuthenticatorsEmpty ? ViewStates.Visible : ViewStates.Gone;
//fab_state = ViewStates.Visible;
loading_state = ViewStates.Gone;
}
if (binding.tvEmptyTip.Visibility != state)
binding.tvEmptyTip.Visibility = state;
if (binding.rvAuthenticators.Visibility != state_reverse)
binding.rvAuthenticators.Visibility = state_reverse;
//binding.speedDial.Visibility = fab_state;
if (binding.layoutLoading.Visibility != loading_state)
binding.layoutLoading.Visibility = loading_state;
}
//void OnAuthenticatorsChanged() => OnAuthenticatorsChanged(ViewModel!.IsAuthenticatorsEmpty, ViewModel.IsFirstActivation);
//public override void OnStop()
//{
// base.OnStop();
// AuthService.Current.SaveEditNameAuthenticators();
//}
//public override void OnStart()
//{
// OnAuthenticatorsChanged();
// base.OnStart();
//}
public override void OnResume()
{
base.OnResume();
@@ -42,19 +42,19 @@ namespace System.Application.UI.Fragments
return;
}
#if !DEBUG
var isUnderConstruction = e.Current.Id switch
{
PreferenceButton.BindPhoneNumber or
PreferenceButton.ChangePhoneNumber or PreferenceButton.UserProfile => true,
_ => false,
};
if (isUnderConstruction)
{
MainApplication.ShowUnderConstructionTips();
return;
}
#endif
//#if !DEBUG
// var isUnderConstruction = e.Current.Id switch
// {
// PreferenceButton.BindPhoneNumber or
// PreferenceButton.ChangePhoneNumber or PreferenceButton.UserProfile => true,
// _ => false,
// };
// if (isUnderConstruction)
// {
// MainApplication.ShowUnderConstructionTips();
// return;
// }
//#endif
#if __XAMARIN_FORMS__
var route = e.Current.Id switch
@@ -73,16 +73,23 @@ namespace System.Application.UI.Fragments
}
#endif
var activityType = e.Current.Id switch
switch (e.Current.Id)
{
PreferenceButton.UserProfile => typeof(UserProfileActivity),
PreferenceButton.BindPhoneNumber => typeof(BindPhoneNumberActivity),
PreferenceButton.ChangePhoneNumber => typeof(ChangePhoneNumberActivity),
PreferenceButton.Settings => typeof(SettingsActivity),
PreferenceButton.About => typeof(AboutActivity),
_ => (Type?)null,
};
if (activityType != null) this.StartActivity(activityType);
case PreferenceButton.UserProfile:
this.StartActivity<UserProfileActivity>();
break;
case PreferenceButton.BindPhoneNumber:
case PreferenceButton.ChangePhoneNumber:
UserProfileActivity.StartActivity(RequireActivity(),
UserProfileWindowViewModel.SubPageType.ChangeOrBindPhoneNumber);
break;
case PreferenceButton.Settings:
this.StartActivity<SettingsActivity>();
break;
case PreferenceButton.About:
this.StartActivity<AboutActivity>();
break;
}
};
binding.rvPreferenceButtons.SetLinearLayoutManager();
binding.rvPreferenceButtons.AddVerticalGroupItemDecoration(binding.rvPreferenceButtons.PaddingTop);
@@ -93,9 +100,9 @@ namespace System.Application.UI.Fragments
{
if (view.Id == Resource.Id.layoutUser)
{
#if !DEBUG
MainApplication.ShowUnderConstructionTips();
#else
//#if !DEBUG
// MainApplication.ShowUnderConstructionTips();
//#else
if (UserService.Current.IsAuthenticated)
{
this.StartActivity<UserProfileActivity>();
@@ -104,7 +111,7 @@ namespace System.Application.UI.Fragments
{
this.StartActivity<LoginOrRegisterActivity>();
}
#endif
//#endif
return true;
}
//else if (view.Id == Resource.Id.???)
@@ -0,0 +1,137 @@
using Android.Text;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Binding;
using ReactiveUI;
using System.Application.Services;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Collections.Generic;
using static System.Application.UI.ViewModels.UserProfileWindowViewModel;
namespace System.Application.UI.Fragments
{
[Authorize]
internal sealed class BindPhoneNumberFragment : BaseFragment<fragment_bind_phone_number, UserProfileWindowViewModel>, TextView.IOnEditorActionListener
{
protected override int? LayoutResource => Resource.Layout.fragment_bind_phone_number;
public new BindPhoneNumberWindowViewModel ViewModel => base.ViewModel!.BindPhoneNumberVM;
public override void OnCreateView(View view)
{
base.OnCreateView(view);
binding!.tbPhoneNumber.TextChanged += (_, _)
=> ViewModel.PhoneNumber = binding!.tbPhoneNumber.Text;
binding!.tbSmsCode.TextChanged += (_, _)
=> ViewModel.SmsCode = binding!.tbSmsCode.Text;
OnCreateViewAsync();
// https://developer.android.google.cn/reference/android/widget/TextView.html#protected-methods
binding!.tbPhoneNumber.SetRawInputType(InputTypes.ClassPhone);
binding!.tbPhoneNumber.SetDigitsKeyListener();
binding!.tbPhoneNumber.SetMaxLength(ModelValidatorLengths.PhoneNumber);
binding!.tbPhoneNumber.ImeOptions = ImeAction.Next;
binding!.tbPhoneNumber.SetOnEditorActionListener(this);
binding!.tbSmsCode.SetRawInputType(InputTypes.ClassNumber | InputTypes.NumberVariationNormal);
binding!.tbSmsCode.SetDigitsKeyListener();
binding!.tbSmsCode.SetMaxLength(ModelValidatorLengths.SMS_CAPTCHA);
binding!.tbSmsCode.ImeOptions = ImeAction.Done;
binding!.tbSmsCode.SetOnEditorActionListener(this);
R.Subscribe(() =>
{
if (binding == null) return;
binding.tbPhoneNumber.Hint = AppResources.User_Phone;
binding!.tbPhoneNumber.SetImeActionLabel(AppResources.NextStep, binding!.tbPhoneNumber.ImeOptions);
binding.tbSmsCode.Hint = AppResources.User_SMSCode;
binding.tbSmsCode.SetImeActionLabel(AppResources.Btn_Text_Complete, binding!.tbSmsCode.ImeOptions);
binding.btnDone.Text = AppResources.Btn_Text_Complete;
if (!ViewModel!.IsUnTimeLimit)
{
binding.btnSendSms.Text = AppResources.User_GetSMSCode;
}
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.IsLoading).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.loading.Visibility = value ? ViewStates.Visible : ViewStates.Gone;
binding.group_show_when_loading_false.Visibility = !value ? ViewStates.Visible : ViewStates.Gone;
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.IsUnTimeLimit).SubscribeInMainThread(value =>
{
if (binding == null) return;
var enabled = !value;
if (binding.btnSendSms.Enabled != enabled)
{
binding.btnSendSms.Enabled = enabled;
}
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.BtnSendSmsCodeText).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.btnSendSms.Text = value;
}).AddTo(this);
SetOnClickListener(
binding.btnSendSms,
binding.btnDone);
ViewModel!.TbPhoneNumberFocus = () =>
{
if (binding == null) return;
binding.tbPhoneNumber.RequestFocus();
};
ViewModel!.TbSmsCodeFocus = () =>
{
if (binding == null) return;
binding.tbSmsCode.RequestFocus();
};
}
async void OnCreateViewAsync()
{
binding!.tbPhoneNumber.Text = await ITelephonyService.GetAutoFillPhoneNumberAsync(binding!.tbPhoneNumber.Text);
}
protected override bool OnClick(View view)
{
if (view.Id == Resource.Id.btnSendSms)
{
ViewModel!.SendSms();
return true;
}
else if (view.Id == Resource.Id.btnDone)
{
ViewModel!.Submit();
return true;
}
return base.OnClick(view);
}
bool TextView.IOnEditorActionListener.OnEditorAction(TextView? view, ImeAction actionId, KeyEvent? e)
{
if (view != null && binding != null && ((e != null && e.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter) || e == null))
{
if (view.Id == Resource.Id.tbPhoneNumber)
{
OnClick(binding.btnSendSms);
binding.tbSmsCode.RequestFocus();
return true;
}
else if (view.Id == Resource.Id.tbSmsCode)
{
OnClick(binding.btnDone);
return true;
}
}
return false;
}
}
}
@@ -0,0 +1,183 @@
using Android.Text;
using Android.Views;
using Android.Views.InputMethods;
using Android.Widget;
using Binding;
using ReactiveUI;
using System.Application.Services;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Collections.Generic;
using static System.Application.UI.ViewModels.UserProfileWindowViewModel;
namespace System.Application.UI.Fragments
{
[Authorize]
internal sealed class ChangePhoneNumberFragment : BaseFragment<fragment_change_bind_phone_number, UserProfileWindowViewModel>, TextView.IOnEditorActionListener
{
protected override int? LayoutResource => Resource.Layout.fragment_change_bind_phone_number;
public new ChangeBindPhoneNumberWindowViewModel ViewModel => base.ViewModel!.ChangeBindPhoneNumberVM;
public override void OnCreateView(View view)
{
base.OnCreateView(view);
binding!.tbPhoneNumber.Text = UserService.Current.PhoneNumber;
binding!.tbNewPhoneNumber.TextChanged += (_, _)
=> ViewModel.PhoneNumber = binding!.tbNewPhoneNumber.Text;
binding!.tbSmsCode.TextChanged += (_, _)
=> ViewModel.SmsCodeValidation = binding!.tbSmsCode.Text;
binding!.tbNewSmsCode.TextChanged += (_, _)
=> ViewModel.SmsCodeNew = binding!.tbNewSmsCode.Text;
OnCreateViewAsync();
// https://developer.android.google.cn/reference/android/widget/TextView.html#protected-methods
binding!.tbNewPhoneNumber.SetRawInputType(InputTypes.ClassPhone);
binding!.tbNewPhoneNumber.SetDigitsKeyListener();
binding!.tbNewPhoneNumber.SetMaxLength(ModelValidatorLengths.PhoneNumber);
binding!.tbNewPhoneNumber.ImeOptions = ImeAction.Next;
binding!.tbNewPhoneNumber.SetOnEditorActionListener(this);
binding!.tbSmsCode.SetRawInputType(InputTypes.ClassNumber | InputTypes.NumberVariationNormal);
binding!.tbSmsCode.SetDigitsKeyListener();
binding!.tbSmsCode.SetMaxLength(ModelValidatorLengths.SMS_CAPTCHA);
binding!.tbSmsCode.ImeOptions = ImeAction.Done;
binding!.tbSmsCode.SetOnEditorActionListener(this);
binding!.tbNewSmsCode.SetRawInputType(InputTypes.ClassNumber | InputTypes.NumberVariationNormal);
binding!.tbNewSmsCode.SetDigitsKeyListener();
binding!.tbNewSmsCode.SetMaxLength(ModelValidatorLengths.SMS_CAPTCHA);
binding!.tbNewSmsCode.ImeOptions = ImeAction.Done;
binding!.tbNewSmsCode.SetOnEditorActionListener(this);
R.Subscribe(() =>
{
if (binding == null) return;
binding.tbPhoneNumber.Hint = AppResources.User_Phone;
binding.tbNewPhoneNumber.Hint = AppResources.User_NewPhone;
binding.tbNewPhoneNumber.SetImeActionLabel(AppResources.NextStep, binding!.tbNewPhoneNumber.ImeOptions);
binding.tbSmsCode.Hint = AppResources.User_SMSCode;
binding.tbSmsCode.SetImeActionLabel(AppResources.NextStep, binding!.tbSmsCode.ImeOptions);
binding.tbNewSmsCode.Hint = AppResources.User_SMSCode;
binding.tbNewSmsCode.SetImeActionLabel(AppResources.Btn_Text_Complete, binding!.tbSmsCode.ImeOptions);
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.IsLoading).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.loading.Visibility = value ? ViewStates.Visible : ViewStates.Gone;
binding.group_show_when_loading_false.Visibility = !value ? ViewStates.Visible : ViewStates.Gone;
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.IsUnTimeLimitValidation).SubscribeInMainThread(value =>
{
if (binding == null) return;
var enabled = !value;
if (binding.btnSendSms.Enabled != enabled)
{
binding.btnSendSms.Enabled = enabled;
}
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.BtnSendSmsCodeTextValidation).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.btnSendSms.Text = value;
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.IsUnTimeLimitNew).SubscribeInMainThread(value =>
{
if (binding == null) return;
var enabled = !value;
if (binding.btnNewSendSms.Enabled != enabled)
{
binding.btnNewSendSms.Enabled = enabled;
}
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.BtnSendSmsCodeTextNew).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.btnNewSendSms.Text = value;
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.BtnSubmitText).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.btnDone.Text = value;
}).AddTo(this);
ViewModel!.WhenAnyValue(x => x.CurrentStepIsValidation).SubscribeInMainThread(value =>
{
if (binding == null) return;
binding.tbSmsCode.Enabled = value;
binding.tbNewPhoneNumber.Enabled = value;
}).AddTo(this);
SetOnClickListener(
binding.btnSendSms,
binding.btnNewSendSms,
binding.btnDone);
ViewModel.TbSmsCodeFocusValidation = () =>
{
if (binding == null) return;
binding.tbSmsCode.RequestFocus();
};
ViewModel.TbSmsCodeFocusNew = () =>
{
if (binding == null) return;
binding.tbNewSmsCode.RequestFocus();
};
}
async void OnCreateViewAsync()
{
var value = await ITelephonyService.GetAutoFillPhoneNumberAsync(binding!.tbPhoneNumber.Text);
if (value != IUserManager.Instance.GetCurrentUser()?.PhoneNumber)
{
binding!.tbNewPhoneNumber.Text = value;
}
}
protected override bool OnClick(View view)
{
if (view.Id == Resource.Id.btnSendSms || view.Id == Resource.Id.btnNewSendSms)
{
ViewModel!.SendSms();
return true;
}
else if (view.Id == Resource.Id.btnDone)
{
ViewModel!.Submit();
return true;
}
return base.OnClick(view);
}
bool TextView.IOnEditorActionListener.OnEditorAction(TextView? view, ImeAction actionId, KeyEvent? e)
{
if (view != null && binding != null && ((e != null && e.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter) || e == null))
{
if (view.Id == Resource.Id.tbNewPhoneNumber || view.Id == Resource.Id.tbNewSmsCode)
{
OnClick(binding.btnDone);
return true;
}
else if (view.Id == Resource.Id.tbSmsCode)
{
OnClick(binding.btnSendSms);
binding.tbNewPhoneNumber.RequestFocus();
return true;
}
}
return false;
}
}
}
@@ -12,6 +12,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Application.UI.Activities;
namespace System.Application.UI.Fragments
{
@@ -276,14 +277,18 @@ namespace System.Application.UI.Fragments
{
if (view.Id == Resource.Id.btnModifyPhoneNumber)
{
if (UserService.Current.HasPhoneNumber)
if (RequireActivity() is UserProfileActivity userProfileActivity)
{
ViewModel.OnBtnChangeBindPhoneNumberClick.Invoke();
}
else
{
ViewModel.OnBtnBindPhoneNumberClick.Invoke();
userProfileActivity.GoToSubPage(UserProfileWindowViewModel.SubPageType.ChangeOrBindPhoneNumber);
}
//if (UserService.Current.HasPhoneNumber)
//{
// ViewModel.OnBtnChangeBindPhoneNumberClick.Invoke();
//}
//else
//{
// ViewModel.OnBtnBindPhoneNumberClick.Invoke();
//}
return true;
}
else if (view.Id == Resource.Id.clickBirthDate)
@@ -70,6 +70,9 @@ namespace System.Application.UI
public override void OnCreate()
{
base.OnCreate();
#if SHADOWSOCKS
Shadowsocks.Core.Instance.Init(this);
#endif
//#if DEBUG
// //SetupLeakCanary();
//#endif
@@ -39,6 +39,7 @@ namespace AndroidX.Activity.Result
const string actualIntentExtra = "actual_intent";
const string guidExtra = "guid";
const string requestCodeExtra = "request_code";
const string resultExtra = "droid_app_result";
static readonly ConcurrentDictionary<string?, IntermediateTask> pendingTasks =
new();
@@ -172,6 +173,16 @@ namespace AndroidX.Activity.Result
public Action<Intent>? OnResult { get; }
}
public static Intent SetResult(Intent? data, AndroidAppResult resultCode)
{
if (data == null) data = new();
data.PutExtra(resultExtra, (int)resultCode);
return data;
}
public static AndroidAppResult GetResult(Intent data, int defaultValue = int.MinValue)
=> (AndroidAppResult)data.GetIntExtra(resultExtra, defaultValue);
}
}
}
@@ -10,7 +10,7 @@
<Identity
Name="4651ED44255E.47979655102CE"
Publisher="CN=A90E406B-B2D3-4A23-B061-0FA1D65C4F66"
Version="2.6.9.0" />
Version="2.7.0.0" />
<Properties>
<DisplayName>Steam++</DisplayName>
@@ -33,7 +33,7 @@
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="Steam++"
Description="「Steam++」是一个包含多种Steam工具功能的工具箱。"
Description="「蒸汽++」是一个开源跨平台的多功能游戏工具箱,此工具的大部分功能都是需要您下载安装蒸汽平台才能使用。"
BackgroundColor="transparent"
Square150x150Logo="Images\Square150x150Logo.png"
Square44x44Logo="Images\Square44x44Logo.png">
@@ -62,8 +62,8 @@
<AppxBundlePlatforms>x64</AppxBundlePlatforms>
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
<AppxSymbolPackageEnabled>True</AppxSymbolPackageEnabled>
<PackageCertificateKeyFile>ST.Client.Desktop.Avalonia.App.Bridge.Package_TemporaryKey.pfx</PackageCertificateKeyFile>
<EntryPointProjectUniqueName>..\ST.Client.Desktop.Avalonia.App.Bridge\Steam++.csproj</EntryPointProjectUniqueName>
<PackageCertificateThumbprint>96028D399EC2DDDA358B18CD2A2669C4A0D6A862</PackageCertificateThumbprint>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<AppxBundle>Always</AppxBundle>
@@ -157,7 +157,7 @@
<Content Include="Images\Wide310x150Logo.scale-150.png" />
<Content Include="Images\Wide310x150Logo.scale-200.png" />
<Content Include="Images\Wide310x150Logo.scale-400.png" />
<None Include="ST.Client.Desktop.Avalonia.App.Bridge.Package_TemporaryKey.pfx" />
<None Include="ST.Client.Avalonia.App.Bridge.Package_TemporaryKey.pfx" />
<None Include="Package.StoreAssociation.xml" />
</ItemGroup>
<Import Project="$(WapProjPath)\Microsoft.DesktopBridge.targets" />
@@ -1,3 +1,4 @@
using System.Diagnostics;
using System.Runtime.Versioning;
using Windows.Storage;
@@ -14,9 +15,19 @@ namespace System.Application
// https://github.com/xamarin/Essentials/blob/1.6.1/Xamarin.Essentials/FileSystem/FileSystem.uwp.cs#L12
// https://docs.microsoft.com/zh-cn/windows/msix/desktop/desktop-to-uwp-behind-the-scenes
// 不允许在 C:\Program Files\WindowsApps\package_name 下写入。
// C:\Users\{user}\AppData\Local\Packages\4651ED44255E.47979655102CE_gvn1zxq6vcwjj\LocalState
// C:\Users\{user}\AppData\Local\Packages\4651ED44255E.47979655102CE_gvn1zxq6vcwjj\LocalCache
InitFileSystem(() => ApplicationData.Current.LocalFolder.Path, () => ApplicationData.Current.LocalCacheFolder.Path);
var destAppDataPath = ApplicationData.Current.LocalFolder.Path;
var destCachePath = ApplicationData.Current.LocalCacheFolder.Path;
// %HOMEPATH%\AppData\Local\Packages\4651ED44255E.47979655102CE_gvn1zxq6vcwjj\LocalState
// %HOMEPATH%\AppData\Local\Packages\4651ED44255E.47979655102CE_gvn1zxq6vcwjj\LocalCache
var sourceAppDataPath = ApplicationData.Current.LocalFolder.Path.Replace(DEST_PACKAGE_ID, SOURCE_PACKAGE_ID);
var sourceCachePath = ApplicationData.Current.LocalCacheFolder.Path.Replace(DEST_PACKAGE_ID, SOURCE_PACKAGE_ID);
InitFileSystemWithMigrations(destAppDataPath, destCachePath, sourceAppDataPath, sourceCachePath);
}
const string SOURCE_PACKAGE_ID = "4651ED44255E.47979655102CE_k6txddmbb6c52";
const string DEST_PACKAGE_ID = "31F8A90E.SteamforWindows_0pj7be8rz1f1e";
}
}
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!--<OutputType>Exe</OutputType>-->
<OutputType>WinExe</OutputType>
<!--<OutputType>WinExe</OutputType>-->
<TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
<SupportedOSPlatformVersion>10.0.17763.0</SupportedOSPlatformVersion>
<SignAssembly>false</SignAssembly>
@@ -79,8 +79,11 @@
</AvaloniaResource>
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(Configuration)'=='Release'">
<ProjectReference Include="..\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Avalonia.Native\Avalonia.Native.csproj" />
<ProjectReference Include="..\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
<ProjectReference Include="..\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
@@ -108,6 +111,7 @@
<ItemGroup>
<PackageReference Include="System.CommandLine" />
<PackageReference Include="System.CommandLine.NamingConventionBinder" />
</ItemGroup>
<ItemGroup Condition="Exists('$(MSBuildProjectDirectory)\..\..\aes-key.pfx')">
@@ -1,6 +1,7 @@
using System.Application.Services;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.CommandLine.NamingConventionBinder;
using System.Threading.Tasks;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
@@ -46,6 +46,11 @@ namespace System.Application.UI
AllowEglInitialization = useGpu,
};
builder.With(options);
builder.With(new SkiaOptions
{
MaxGpuResourceSizeBytes = 1024000000,
});
#else
throw new PlatformNotSupportedException();
#endif
@@ -1 +1,24 @@
<?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"><requestedExecutionLevel level="requireAdministrator" uiAccess="false"/></requestedPrivileges></security></trustInfo><compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/><supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/><supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/></application></compatibility><application xmlns="urn:schemas-microsoft-com:asm.v3"><windowsSettings><dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness><dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware></windowsSettings></application></assembly>
<?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">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
</windowsSettings>
</application>
</assembly>
@@ -180,6 +180,7 @@
<ItemGroup>
<PackageReference Include="System.CommandLine" />
<PackageReference Include="System.CommandLine.NamingConventionBinder" />
</ItemGroup>
<ItemGroup Condition=" $(RuntimeIdentifier.Contains(`win`)) Or ('$(OS)' == 'Windows_NT' And !$(DefineConstants.Contains(`PUBLISH`))) ">
@@ -214,4 +215,10 @@
<ItemGroup Condition="'$(Configuration)'=='Release' And Exists('$(MSBuildProjectDirectory)\..\..\rsa-public-key-release.pfx')">
<EmbeddedResource Include="..\..\rsa-public-key-release.pfx" Link="Resources\E88CA4F9" />
</ItemGroup>
<ItemGroup Condition=" '$(ExtraDefineConstants)' == 'osx-arm64' Or '$(ExtraDefineConstants)' == 'dev-osx-arm64'">
<None Include="..\..\references\ARM64\libe_sqlite3.dylib">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
@@ -2,6 +2,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Markup.Xaml;
using System.Application.Services;
using System.Application.Settings;
using System.Application.UI.ViewModels;
using System.Application.UI.Views.Controls;
@@ -42,29 +43,29 @@ namespace System.Application.UI.Views
#endif
}
// protected override void OnClosing(CancelEventArgs e)
// {
//#if !UI_DEMO
// if (StartupOptions.Value.HasNotifyIcon)
// {
// //IsHideWindow = true;
// //e.Cancel = true;
// //Hide();
// protected override void OnClosing(CancelEventArgs e)
// {
//#if !UI_DEMO
// if (StartupOptions.Value.HasNotifyIcon)
// {
// //IsHideWindow = true;
// //e.Cancel = true;
// //Hide();
// //if (ViewModel is not null)
// // foreach (var tab in ViewModel.TabItems)
// // tab.Deactivation();
// }
//#endif
// base.OnClosing(e);
// }
// //if (ViewModel is not null)
// // foreach (var tab in ViewModel.TabItems)
// // tab.Deactivation();
// }
//#endif
// base.OnClosing(e);
// }
protected override void OnClosed(EventArgs e)
{
#if !UI_DEMO
if (StartupOptions.Value.HasNotifyIcon)
{
if (App.Current.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktop)
if (App.Current!.ApplicationLifetime is Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = App.Instance.MainWindow = null;
}
@@ -77,6 +78,13 @@ namespace System.Application.UI.Views
//base.OnClosed(e);
}
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
IApplicationUpdateService.Instance.OnMainOpenTryShowNewVersionWindow();
}
//protected override void FluentWindow_Opened(object? sender, EventArgs e)
//{
// if (ViewModel is not null)
@@ -1,6 +1,8 @@
using Microsoft.Extensions.Options;
using System.Application.Models;
using System.Application.UI;
using System.Application.UI.Resx;
using System.Threading.Tasks;
namespace System.Application.Services.Implementation
{
@@ -9,8 +11,10 @@ namespace System.Application.Services.Implementation
{
readonly IAvaloniaApplication app;
readonly IWindowManager windowManager;
readonly INotificationService notificationService;
public AvaloniaApplicationUpdateServiceImpl(
IAvaloniaApplication app,
INotificationService notificationService,
IWindowManager windowManager,
IToast toast,
ICloudServiceClient client,
@@ -18,6 +22,21 @@ namespace System.Application.Services.Implementation
{
this.app = app;
this.windowManager = windowManager;
this.notificationService = notificationService;
}
protected override async Task ShowNewVersionWindowAsync()
{
await windowManager.Show(typeof(object), CustomWindow.NewVersion, isParent: false);
}
public override async void OnMainOpenTryShowNewVersionWindow()
{
if (ShowNewVersionWindowOnMainOpen)
{
ShowNewVersionWindowOnMainOpen = false;
await ShowNewVersionWindowAsync();
}
}
protected override async void OnExistNewVersion()
@@ -25,7 +44,12 @@ namespace System.Application.Services.Implementation
var hasActiveWindow = app.HasActiveWindow();
if (hasActiveWindow)
{
await windowManager.Show(typeof(object), CustomWindow.NewVersion, isParent: false);
await ShowNewVersionWindowAsync();
}
else
{
ShowNewVersionWindowOnMainOpen = true;
notificationService.Notify(AppResources.NewVersionUpdateNotifyText_.Format(NewVersionInfo?.Version), NotificationType.NewVersion);
}
}
@@ -64,7 +64,7 @@ namespace System.Application.Services.Implementation
[SupportedOSPlatform("Windows10.0.10240.0")]
internal class Window10Impl : WindowImpl
{
public Window10Impl()
public Window10Impl() : base()
{
//Win32Interop.OSVERSIONINFOEX version = new Win32Interop.OSVERSIONINFOEX
//{
Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 B

After

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 B

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 530 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 700 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 552 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 614 B

After

Width:  |  Height:  |  Size: 609 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

@@ -36,6 +36,8 @@
<StyleInclude Source="/Application/UI/Styles/Controls/ToggleSwitch.xaml" />
<StyleInclude Source="/Application/UI/Views/Controls/Badge.xaml" />
<StyleInclude Source="/Application/UI/Views/Controls/OptionsDisplayItem.xaml" />
<StyleInclude Source="/Application/UI/Views/Controls/CustomFilePicker.xaml" />
<StyleInclude Source="/Application/UI/Styles/Window.xaml" />
<StyleInclude Source="/Application/UI/Styles/Settings.xaml" />
@@ -14,35 +14,41 @@
</Design.PreviewWith>
<Styles.Resources>
<BoxShadows x:Key="DialogBoxShadow">0 8 32 0 #66000000</BoxShadows>
<BoxShadows x:Key="InfoBoxShadow">2 2 5 #3F000000</BoxShadows>
<BoxShadows x:Key="InfoBoxShadow">2 2 16 0 #3F000000</BoxShadows>
<CornerRadius x:Key="PaperRadius">8</CornerRadius>
<CornerRadius x:Key="PaperRadiusLeft">8 0 0 8</CornerRadius>
</Styles.Resources>
<Style Selector="Border.card">
<Setter Property="CornerRadius" Value="{StaticResource PaperRadius}" />
<Setter Property="BorderBrush" Value="#2F2F37" />
<Setter Property="BorderBrush" Value="{DynamicResource CardStrokeColorDefaultBrush}" />
<Setter Property="Background" Value="{DynamicResource ControlFillColorDefaultBrush}" />
<Setter Property="BorderThickness" Value="0.88 0.88" />
</Style>
<Style Selector="Border.card:pointerover">
<Setter Property="BorderBrush" Value="#5E5E66" />
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
<Setter Property="BorderThickness" Value="0.88 0.88" />
</Style>
<Style Selector="Border.paper">
<Setter Property="CornerRadius" Value="{StaticResource PaperRadius}" />
<!--<Setter Property="ClipToBounds" Value="True"/>-->
<Setter Property="BoxShadow" Value="{StaticResource InfoBoxShadow}" />
<Setter Property="BorderBrush" Value="{DynamicResource CardStrokeColorDefaultBrush}" />
<Setter Property="BorderThickness" Value="0.88 0.88" />
<!--<Setter Property="ClipToBounds" Value="True"/>-->
</Style>
<!--<Style Selector="Border.paper:pointerover">
<Setter Property="BoxShadow" Value="4 2 10 #55000000" />
</Style>-->
<Style Selector="Border.RightPane">
<!--<Style Selector="Border.RightPane">
<Setter Property="BoxShadow" Value="-4 2 10 #55000000" />
<!--<Setter Property="CornerRadius" Value="{StaticResource PaperRadius}" />
-->
<!--<Setter Property="CornerRadius" Value="{StaticResource PaperRadius}" />
<Setter Property="ClipToBounds" Value="True"/>-->
</Style>
<!--
</Style>-->
<Style Selector="Border.dialog">
<Setter Property="CornerRadius" Value="{StaticResource PaperRadius}" />
@@ -3,9 +3,11 @@
<Border Padding="20" Background="Black">
<StackPanel Spacing="5">
<Button Classes="Hyperlink" Content="Code Font Family" />
<Button Classes="plain" Content="Code Font Family" />
<Button Classes="CodeButton" Content="Code Font Family" />
<Button Classes="flatbutton" Content="Code Font Family" />
<Button Classes="action" Content="Code Font Family" />
<Button Classes="DialogButton" Content="Code Font Family" />
</StackPanel>
</Border>
</Design.PreviewWith>
@@ -16,12 +18,23 @@
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style Selector="Button.DialogButton">
<Setter Property="IsDefault" Value="True" />
<Setter Property="Background" Value="{DynamicResource ButtonBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource ButtonBorderThemeThickness}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="Padding" Value="{DynamicResource ButtonPadding}" />
</Style>
<Style Selector="Button.CodeButton">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="Cursor" Value="Hand" />
</Style>
<Style Selector="Button.CodeButton /template/ ContentPresenter">
<!--<Setter Property="CornerRadius" Value="0" />-->
<Setter Property="Padding" Value="8 10" />
@@ -13,7 +13,7 @@
<CornerRadius x:Key="NavigationViewContentGridCornerRadius">0,0,0,0</CornerRadius>
<Thickness x:Key="NavigationViewContentGridBorderThickness">0,0,0,0</Thickness>
<Thickness x:Key="NavigationViewHeaderMargin">10,0,0,0</Thickness>
<x:Double x:Key="NavigationViewItemOnLeftIconBoxHeight">26</x:Double>
<x:Double x:Key="NavigationViewItemOnLeftIconBoxHeight">20</x:Double>
</Styles.Resources>
<Style Selector="ui|NavigationView.NavBar">
<Setter Property="OpenPaneLength" Value="240" />
@@ -42,11 +42,7 @@
<Setter Property="Icon">
<Setter.Value>
<Template>
<ui:BitmapIcon
Width="26"
Height="26"
HorizontalAlignment="Center"
UriSource="{Binding IconSource}" />
<ui:BitmapIcon HorizontalAlignment="Center" UriSource="{Binding IconSource}" />
</Template>
</Setter.Value>
</Setter>
@@ -129,7 +129,7 @@
<Setter Property="Foreground" Value="{DynamicResource SemiActiveForegroundColorKey}" />
<Setter Property="VerticalAlignment" Value="Center" />
<!--<Setter Property="Margin" Value="10 0" />-->
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<Style Selector="StackPanel.Settings DockPanel &gt; Label">
@@ -142,15 +142,18 @@
<Setter Property="Margin" Value="0 0 20 0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Left" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<Style Selector="StackPanel.Settings DockPanel &gt; Button:not(.plain)">
<Setter Property="Padding" Value="30 5" />
<Setter Property="Height" Value="30" />
<Setter Property="BorderBrush" Value="{DynamicResource ExpanderBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsDefault" Value="True" />
<Setter Property="Background" Value="{DynamicResource ButtonBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource ButtonBorderThemeThickness}" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="(DockPanel.Dock)" Value="Right" />
@@ -167,7 +170,8 @@
</Style>
<Style Selector="StackPanel.Settings DockPanel &gt; TextBox">
<Setter Property="MinWidth" Value="{StaticResource SettingsRightContentWidth}" />
<Setter Property="Width" Value="{StaticResource SettingsRightContentWidth}" />
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="(DockPanel.Dock)" Value="Right" />
@@ -29,8 +29,14 @@
</ControlTemplate>
</Styles.Resources>
<Style Selector="PopupRoot">
<Setter Property="Background" Value="Transparent" />
<Setter Property="TransparencyBackgroundFallback" Value="Transparent" />
</Style>
<Style Selector="Window">
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAltHighBrush}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="{StaticResource TitleBarHeight}" />
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource SystemControlBackgroundAltHighBrush}" />
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
@@ -46,7 +52,7 @@
<Setter Property="Title" Value="{Binding Title, Mode=OneWay}" />
<!--<Setter Property="FontSize" Value="14"></Setter>-->
<Setter Property="FontFamily" Value="{Binding Source={x:Static ms:UISettings.FontName}, Path=Value, Mode=OneWay, Converter={StaticResource NameToFontFamilyConverter}}" />
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="WindowStartupLocation" Value="CenterScreen" />
<Setter Property="ExtendClientAreaTitleBarHeightHint" Value="{StaticResource TitleBarHeight}" />
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource BackgroundColorKey}" />
@@ -0,0 +1,81 @@
<Styles
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:System.Application.UI.Views.Controls"
xmlns:ui="using:FluentAvalonia.UI.Controls">
<Design.PreviewWith>
<Border Padding="40">
<StackPanel Spacing="10">
<controls:CustomFilePicker>
<Image
Width="150"
Height="150"
Source="avares://System.Application.SteamTools.Client.Avalonia/Application/UI/Assets/Icon.ico"
Stretch="UniformToFill" />
</controls:CustomFilePicker>
</StackPanel>
</Border>
</Design.PreviewWith>
<Style Selector="controls|CustomFilePicker">
<Setter Property="Background" Value="Transparent" />
<Setter Property="DragDrop.AllowDrop" Value="True" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Template">
<ControlTemplate>
<Border
BorderBrush="{DynamicResource ButtonBorderBrush}"
BorderThickness="1"
ClipToBounds="True"
CornerRadius="5">
<Panel>
<ContentPresenter
Name="ContentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Panel
Name="FilePickerTipBorder"
MaxWidth="{ReflectionBinding $parent.Bounds.Width}"
MaxHeight="{ReflectionBinding $parent.Bounds.Height}">
<ExperimentalAcrylicBorder>
<ExperimentalAcrylicBorder.Material>
<ExperimentalAcrylicMaterial
MaterialOpacity="0.1"
TintColor="#000000"
TintOpacity="1" />
</ExperimentalAcrylicBorder.Material>
</ExperimentalAcrylicBorder>
<Border
Margin="5"
Background="Transparent"
BorderBrush="{DynamicResource ButtonBorderThemeBrush}"
BorderDashArray="3,3"
BorderLineCap="Round"
BorderLineJoin="Round"
BorderThickness="2">
<StackPanel
Margin="10,5"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ui:SymbolIcon FontSize="22" Symbol="DownloadFilled" />
<TextBlock
Text="选择文件或拖拽到这里"
TextAlignment="Center"
TextWrapping="WrapWithOverflow" />
</StackPanel>
</Border>
</Panel>
</Panel>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="controls|CustomFilePicker /template/ Panel#FilePickerTipBorder">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="controls|CustomFilePicker:pointerover /template/ Panel#FilePickerTipBorder">
<Setter Property="IsVisible" Value="True" />
</Style>
</Styles>
@@ -0,0 +1,85 @@
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Metadata;
using System.Collections;
using static System.Application.FilePicker2;
namespace System.Application.UI.Views.Controls
{
public class CustomFilePicker : ContentControl
{
public static readonly StyledProperty<string?> FileNameProperty = AvaloniaProperty.Register<CustomFilePicker, string?>(nameof(FileName), null);
public static readonly StyledProperty<string?> FileExtensionsProperty = AvaloniaProperty.Register<CustomFilePicker, string?>(nameof(FileExtensions), "*");
public string? FileName
{
get => GetValue(FileNameProperty);
set => SetValue(FileNameProperty, value);
}
public string? FileExtensions
{
get => GetValue(FileExtensionsProperty);
set => SetValue(FileExtensionsProperty, value);
}
public CustomFilePicker()
{
#region 启用拖拽文件的效果
//Windows管理员权限运行无法在低权限的资源管理中拖拽文件到高权限的程序上
//https://docs.microsoft.com/zh-cn/archive/blogs/patricka/q-why-doesnt-drag-and-drop-work-when-my-application-is-running-elevated-a-mandatory-integrity-control-and-uipi?tdsourcetag=s_pctim_aiomsg
void DragOver(object? sender, DragEventArgs e)
{
// Only allow Copy or Link as Drop Operations.
e.DragEffects = e.DragEffects & (DragDropEffects.Copy | DragDropEffects.Link);
// Only allow if the dragged data contains text or filenames.
if (!e.Data.Contains(DataFormats.Text) &&
!e.Data.Contains(DataFormats.FileNames))
e.DragEffects = DragDropEffects.None;
}
void Drop(object? sender, DragEventArgs e)
{
if (e.Data.Contains(DataFormats.Text))
FileName = e.Data.GetText();
else if (e.Data.Contains(DataFormats.FileNames))
FileName = string.Join(Environment.NewLine, e.Data.GetFileNames());
}
AddHandler(DragDrop.DropEvent, Drop);
AddHandler(DragDrop.DragOverEvent, DragOver);
#endregion
this.Tapped += CustomFilePicker_Tapped;
}
private async void CustomFilePicker_Tapped(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
FilePickerFileType fileTypes;
if (string.IsNullOrEmpty(FileExtensions) || FileExtensions == "*")
{
fileTypes = new ValueTuple<string, string[]>[] { ("All Files", new[] { "*" }) };
}
else
{
fileTypes = new ValueTuple<string, string[]>[] {
("Required Files", FileExtensions.Split(",")),
("All Files", new[] { "*"}),
};
}
await PickAsync((file) =>
{
FileName = file;
}, fileTypes);
}
}
}

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