Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce222da8ef | ||
|
|
5388425f1d | ||
|
|
56687596c6 | ||
|
|
edf5acc455 | ||
|
|
b21972db50 | ||
|
|
7a12b50ba4 | ||
|
|
cfb5796cb6 | ||
|
|
faecc2b4d8 | ||
|
|
c3c7c889d4 | ||
|
|
e29e7a8f0e | ||
|
|
3723e0866f | ||
|
|
bf5ca108e0 | ||
|
|
69e60440e1 | ||
|
|
76e75abbc2 | ||
|
|
df7c1d62fb | ||
|
|
ceabdaaa64 | ||
|
|
170dc355b7 | ||
|
|
0b9bccf1e3 | ||
|
|
91ce45feda | ||
|
|
61722994b1 | ||
|
|
15557ecd74 | ||
|
|
53b2c514a5 | ||
|
|
517a259e4e | ||
|
|
f15d005771 | ||
|
|
9f9478f0e5 | ||
|
|
3822a646de | ||
|
|
35d4bc83e6 | ||
|
|
f7a5646836 | ||
|
|
29820061e1 | ||
|
|
281332be71 | ||
|
|
92f1eb9585 | ||
|
|
0b9fdcc0b6 | ||
|
|
d83c0536c9 | ||
|
|
d95559e36a | ||
|
|
185532c79a | ||
|
|
c6710ddf2c | ||
|
|
537fc51d49 | ||
|
|
ed3cf8d36e | ||
|
|
09ab684548 | ||
|
|
fbe0d85d12 | ||
|
|
5887602e31 | ||
|
|
e0bbb58c1a | ||
|
|
3b3bcc856a | ||
|
|
846c9feac1 | ||
|
|
8f7930450f | ||
|
|
c913f623e9 | ||
|
|
21a2dc8d31 | ||
|
|
eef90d9aaf | ||
|
|
7e1b4bd820 | ||
|
|
2af95b4491 | ||
|
|
5167c6cbfe | ||
|
|
c551cd278e | ||
|
|
258aa518a9 | ||
|
|
6158b30364 | ||
|
|
f721c6695f | ||
|
|
a8c7a6fe02 | ||
|
|
8969f7008c | ||
|
|
f0e6a4fb8f | ||
|
|
e647d195fa | ||
|
|
229e9644de | ||
|
|
ea59d32c93 | ||
|
|
d794fb6a22 | ||
|
|
62ad711dbd | ||
|
|
2f472a55ad | ||
|
|
588d663216 | ||
|
|
5510b4915c | ||
|
|
f3649d3246 | ||
|
|
fe45b39c8f | ||
|
|
c59fb1076c | ||
|
|
7717188152 | ||
|
|
8e78557f16 | ||
|
|
835083b899 | ||
|
|
1588749280 | ||
|
|
69c6baf39e | ||
|
|
36bff3751d | ||
|
|
86df7af88d | ||
|
|
09edd5dc3d | ||
|
|
cd599de46a | ||
|
|
3d8001dc75 | ||
|
|
da3a1e9d9d | ||
|
|
49aff6e7dc | ||
|
|
bf34c219a1 | ||
|
|
efbc17d15f | ||
|
|
682165d90e | ||
|
|
046d60112c | ||
|
|
927439c80d | ||
|
|
a28f8fa1e1 | ||
|
|
29cc793628 | ||
|
|
42f8971bd7 | ||
|
|
f98473246c | ||
|
|
e9bbbd8a32 | ||
|
|
9a6c52b88f | ||
|
|
a603fdd834 | ||
|
|
a5343bb2b2 | ||
|
|
e14eec48e9 | ||
|
|
2f2923fdb8 | ||
|
|
f41fd35d78 | ||
|
|
32e90b672f | ||
|
|
ad98879d5c | ||
|
|
61a4f05480 | ||
|
|
3a8a232f98 | ||
|
|
52897064dd | ||
|
|
e202f4ae5e | ||
|
|
f51ce974de | ||
|
|
4806dbcf27 | ||
|
|
e1db44af68 | ||
|
|
d6031c8acd | ||
|
|
2852c630e9 | ||
|
|
8a06b7d09f | ||
|
|
c14e548b0f | ||
|
|
0820c880ac | ||
|
|
84e3752f88 | ||
|
|
1f62313978 | ||
|
|
ffcf0f0ff0 | ||
|
|
c01a9157e2 | ||
|
|
13db16b07c | ||
|
|
33b76c6622 | ||
|
|
c5eae6a980 | ||
|
|
8e50c843f0 | ||
|
|
8a4fcaa539 | ||
|
|
15fc32dd46 | ||
|
|
fb9cb68957 | ||
|
|
91152a55fc | ||
|
|
8aebbe2b0a | ||
|
|
ecf085c7c4 | ||
|
|
13d6b6213f | ||
|
|
9c49c82db9 | ||
|
|
428b841712 | ||
|
|
716210b089 | ||
|
|
2b2ccdd3b1 | ||
|
|
8d0e857df5 | ||
|
|
978f0d8f51 | ||
|
|
b4b0303426 | ||
|
|
f4c928c46c | ||
|
|
34a25ceabe | ||
|
|
90a5f30802 | ||
|
|
3f113c96aa | ||
|
|
7ce53f11aa | ||
|
|
90c0513493 | ||
|
|
2a42ce2caf | ||
|
|
6480d258bf | ||
|
|
c1f6781fa9 | ||
|
|
467c0f4975 | ||
|
|
e7d8e636d2 | ||
|
|
3855291c68 | ||
|
|
d0d1baac29 | ||
|
|
1c50fdf4af | ||
|
|
c1b889f887 | ||
|
|
fa84523799 | ||
|
|
160f3d53bb | ||
|
|
ed77ad8d2d | ||
|
|
3fd32b3196 |
@@ -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" />
|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||
[](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)
|
||||
- [](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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
[English](./README.en.md) | 简体中文
|
||||
|
||||
「Steam++」是一个包含多种Steam工具功能的工具箱,此工具的大部分功能都是需要您下载安装Steam才能使用。
|
||||
「Steam++」是一个开源跨平台的多功能游戏工具箱,此工具的大部分功能都是需要您下载安装 Steam 才能使用。
|
||||
|
||||

|
||||
[](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)
|
||||
- [](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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 模拟运行
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
"MSBuild.Sdk.Extras": "3.0.44"
|
||||
},
|
||||
"sdk": {
|
||||
"version": "6.0.200"
|
||||
"version": "6.0.201"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 文件可使用解压工具打开或解压,找到此文件复制即可
|
||||
|
||||
[](https://steampp.net)
|
||||
[]()
|
||||
[]()
|
||||
|
||||
|
||||
##### [不知道该下载哪个文件?](./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 |
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <CFBundleVersion> <CFBundleShortVersionString> </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 -> 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>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
|
||||
@@ -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>
|
||||
/// 查找类似 {
|
||||
/// "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"
|
||||
/// },
|
||||
/// {
|
||||
/// [字符串的其余部分被截断]"; 的本地化字符串。
|
||||
/// </summary>
|
||||
internal static string v2rayPoint_configure {
|
||||
get {
|
||||
return ResourceManager.GetString("v2rayPoint_configure", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
//{
|
||||
|
||||
|
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 944 B |
|
Before Width: | Height: | Size: 568 B After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 788 B After Width: | Height: | Size: 460 B |
|
After Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 530 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 700 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 490 B After Width: | Height: | Size: 727 B |
|
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 614 B After Width: | Height: | Size: 609 B |
|
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 > 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 > 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 > 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
<Styles
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:System.Application.UI.Views.Controls"
|
||||
xmlns:ui="using:FluentAvalonia.UI.Controls">
|
||||
<Design.PreviewWith>
|
||||
<Border MinHeight="300" Padding="20">
|
||||
<ScrollViewer>
|
||||
<StackPanel>
|
||||
<local:OptionsDisplayItem
|
||||
Description="This is a description of whatver this does"
|
||||
Header="Header"
|
||||
Icon="Save"
|
||||
Navigates="True" />
|
||||
|
||||
<local:OptionsDisplayItem
|
||||
Content="Hello World"
|
||||
Description="This is a description of whatver this does"
|
||||
Expands="True"
|
||||
Header="Header"
|
||||
Icon="Save" />
|
||||
|
||||
<local:OptionsDisplayItem
|
||||
Classes="Vertical"
|
||||
Content="Hello World"
|
||||
Description="This is a description of whatver this does"
|
||||
Expands="True"
|
||||
Header="Header"
|
||||
Icon="Save" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Design.PreviewWith>
|
||||
|
||||
<Style Selector="local|OptionsDisplayItem">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorDefaultBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource CardStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="CornerRadius" Value="{StaticResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<StackPanel>
|
||||
<Border
|
||||
Name="LayoutRoot"
|
||||
Padding="12"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto,Auto" RowDefinitions="Auto,Auto,Auto">
|
||||
<Viewbox
|
||||
Name="IconHost"
|
||||
Grid.RowSpan="2"
|
||||
Width="24"
|
||||
Height="24"
|
||||
Margin="8,4,12,4">
|
||||
<ContentPresenter Content="{TemplateBinding Icon}" />
|
||||
</Viewbox>
|
||||
|
||||
<TextBlock
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Classes="BaseTextBlockStyle"
|
||||
Text="{TemplateBinding Header}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Top"
|
||||
Classes="CaptionTextBlockStyle"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{TemplateBinding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<ContentPresenter
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="2"
|
||||
Margin="8,4"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Stretch"
|
||||
Content="{TemplateBinding ActionButton}" />
|
||||
|
||||
<ui:SymbolIcon
|
||||
Name="Chevron"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="3"
|
||||
Margin="8,4"
|
||||
FontSize="20" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<ContentPresenter
|
||||
Name="ExpandedContentPresenter"
|
||||
Grid.Row="2"
|
||||
Grid.ColumnSpan="4"
|
||||
Padding="12"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Background="{DynamicResource CardBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="1,0,1,1"
|
||||
Content="{TemplateBinding Content}" />
|
||||
</StackPanel>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style Selector="local|OptionsDisplayItem /template/ Viewbox#IconHost">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem /template/ ui|SymbolIcon#Chevron">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem /template/ ContentPresenter#ExpandedContentPresenter">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="local|OptionsDisplayItem /template/ Border#LayoutRoot:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorSecondaryBrush}" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem:pressed /template/ Border#LayoutRoot:pointerover">
|
||||
<Setter Property="Background" Value="{DynamicResource ControlFillColorTertiaryBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="local|OptionsDisplayItem:icon /template/ Viewbox#IconHost">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="local|OptionsDisplayItem:navigates /template/ ui|SymbolIcon#Chevron">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Symbol" Value="ChevronRight" />
|
||||
</Style>
|
||||
|
||||
|
||||
<Style Selector="local|OptionsDisplayItem:expands /template/ ui|SymbolIcon#Chevron">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Symbol" Value="ChevronDown" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem:expanded /template/ ui|SymbolIcon#Chevron">
|
||||
<Setter Property="Symbol" Value="ChevronUp" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem:expanded /template/ ContentPresenter#ExpandedContentPresenter">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BottomCornerRadiusFilterConverter}}" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem:expanded /template/ Border#LayoutRoot">
|
||||
<Setter Property="CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TopCornerRadiusFilterConverter}}" />
|
||||
</Style>
|
||||
<Style Selector="local|OptionsDisplayItem:not(:expands):expanded /template/ ContentPresenter#ExpandedContentPresenter">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
|
||||
|
||||
<!-- Vertical Style -->
|
||||
<Style Selector="local|OptionsDisplayItem.Vertical">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border
|
||||
Name="LayoutRoot"
|
||||
Padding="12"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid RowDefinitions="*,*">
|
||||
<Border
|
||||
Width="80"
|
||||
Height="80"
|
||||
Margin="18"
|
||||
Background="Transparent"
|
||||
ClipToBounds="True"
|
||||
CornerRadius="{StaticResource OverlayCornerRadius}">
|
||||
<Viewbox Name="IconHost">
|
||||
<ContentPresenter Content="{TemplateBinding Icon}" />
|
||||
</Viewbox>
|
||||
</Border>
|
||||
|
||||
<StackPanel Grid.Row="1">
|
||||
<TextBlock
|
||||
Grid.Row="1"
|
||||
Margin="0,5"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Bottom"
|
||||
Classes="BaseTextBlockStyle"
|
||||
Text="{TemplateBinding Header}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
|
||||
<TextBlock
|
||||
Grid.Row="2"
|
||||
Margin="0,5"
|
||||
VerticalAlignment="Top"
|
||||
Classes="CaptionTextBlockStyle"
|
||||
Foreground="{DynamicResource TextFillColorSecondaryBrush}"
|
||||
Text="{TemplateBinding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Styles>
|
||||