Compare commits

...

6 Commits

Author SHA1 Message Date
Aigio Liu 82814649e3 misc 2022-10-13 14:36:22 +08:00
Aigio Liu 978411b677 restore sms 2022-09-22 19:10:30 +08:00
Aigio Liu 166f8732dc Misc 2022-09-22 11:17:58 +08:00
Aigio Liu 8c2a7068b9 fix Android reverseProxyService.ProxyIp & Misc 2022-08-31 11:16:04 +08:00
Aigio Liu b832f3c927 fix maui-android projects & update AndroidX packages 2022-08-27 20:00:21 +08:00
Aigio Liu c367cac992 fix maui csproj errors 2022-08-27 13:09:06 +08:00
75 changed files with 1678 additions and 1483 deletions
+2 -2
View File
@@ -262,8 +262,8 @@
<!-- Xamarin.Android -->
<PackageVersion Include="Xamarin.Build.Download" Version="0.11.3" />
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.40.5" />
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="116.1.2.5" />
<PackageVersion Include="Xamarin.Google.Dagger" Version="2.41.0.2" />
<PackageVersion Include="Xamarin.Google.MLKit.BarcodeScanning" Version="117.0.2.2" />
<PackageVersion Include="Plugin.CurrentActivity" Version="2.1.0.4" />
<PackageVersion Include="de.hdodenhof.circleimageview" Version="3.1.0.4" />
<PackageVersion Include="Square.OkHttp3" Version="4.9.3" />
+2 -2
View File
@@ -17,7 +17,7 @@ English | [简体中文](./README.md)
[![C# 10.0](https://img.shields.io/badge/c%23-10.0-green.svg?style=flat-square&color=6da86a)](https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-10)
[![Desktop UI](https://img.shields.io/badge/ui@desktop-AvaloniaUI-purple.svg?style=flat-square&color=8c45ab)](https://github.com/AvaloniaUI/Avalonia)
[![Mobile GUI](https://img.shields.io/badge/gui@mobile-Xamarin.Forms-blue.svg?style=flat-square&color=3498db)](https://github.com/xamarin/Xamarin.Forms)
[![Mobile UI](https://img.shields.io/badge/ui@mobile-MAUI-blue.svg?style=flat-square&color=512BD4)](https://github.com/dotnet/maui)
[![Official WebSite](https://img.shields.io/badge/website@official-Ant%20Design%20of%20React-blue.svg?style=flat-square&color=61dafb)](https://github.com/ant-design/ant-design)
[![BackManage WebSite](https://img.shields.io/badge/website@back_manage-Ant%20Design%20of%20Blazor-purple.svg?style=flat-square&color=512bd4)](https://github.com/ant-design-blazor/ant-design-blazor)
@@ -183,7 +183,7 @@ Read what we [milestones](https://github.com/BeyondDimension/SteamTools/mileston
- [Avalonia for Visual Studio(Optional)](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
- [NUnit VS Templates(Optional)](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
[OpenJDK 11](https://docs.microsoft.com/java/openjdk/download#openjdk-11)
[OpenJDK 17](https://docs.microsoft.com/en-us/java/openjdk/download#openjdk-17)
[Android Studio 2021.1.1 Or Higher](https://developer.android.com/studio/)
[Xcode 13 Or Higher](https://developer.apple.com/xcode/)
+2 -2
View File
@@ -17,7 +17,7 @@
[![C# 10.0](https://img.shields.io/badge/c%23-10.0-brightgreen.svg?style=flat-square&color=6da86a)](https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/csharp-10)
[![Desktop UI](https://img.shields.io/badge/ui@desktop-AvaloniaUI-purple.svg?style=flat-square&color=8c45ab)](https://github.com/AvaloniaUI/Avalonia)
[![Mobile GUI](https://img.shields.io/badge/gui@mobile-Xamarin.Forms-blue.svg?style=flat-square&color=3498db)](https://github.com/xamarin/Xamarin.Forms)
[![Mobile UI](https://img.shields.io/badge/ui@mobile-MAUI-blue.svg?style=flat-square&color=512BD4)](https://github.com/dotnet/maui)
[![Official WebSite](https://img.shields.io/badge/website@official-Ant%20Design%20of%20React-blue.svg?style=flat-square&color=61dafb)](https://github.com/ant-design/ant-design)
[![BackManage WebSite](https://img.shields.io/badge/website@back_manage-Ant%20Design%20of%20Blazor-purple.svg?style=flat-square&color=512bd4)](https://github.com/ant-design-blazor/ant-design-blazor)
@@ -194,7 +194,7 @@ OS | Version | Architectures |
- [Avalonia for Visual Studio(可选)](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio)
- [NUnit VS Templates(可选)](https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio)
[OpenJDK 11](https://docs.microsoft.com/zh-cn/java/openjdk/download#openjdk-11)
[OpenJDK 17](https://docs.microsoft.com/zh-cn/java/openjdk/download#openjdk-17)
[Android Studio 2021.1.1 或更高版本](https://developer.android.google.cn/studio/)
[Xcode 13 或更高版本](https://developer.apple.com/xcode/)
+2 -1
View File
@@ -2670,6 +2670,7 @@ Global
{48417EE3-BACB-4E04-B48D-B3781862AD81} = {8E38AAF2-8C7D-4B0D-AB25-AB37EECB4029}
{41434AB5-48C3-47D4-8721-D118D87F472B} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{07C9AC06-5D84-41AB-A3C9-5C5B1A27F526} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{5C440EC2-9251-4DB5-A14E-68FF37814F12} = {83186945-EC14-4B3F-8C6F-B205AA184CA4}
{1891DD14-628D-4921-8A1E-279320312E95} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
{3381B512-7CCB-4211-87B0-273260531BFC} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
{CCB0CAEB-FEFC-4424-B6F4-53D3BB70154D} = {327FDEE7-C4C8-4AA4-A7B0-8BCE3D75346F}
@@ -2682,7 +2683,7 @@ Global
{8C996C50-B29F-4CB6-90A7-77C9CD3B0B70} = {910D6A0F-42AB-4B65-B532-852E864EC006}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9313F2B4-10DA-43AA-A481-CAA7571C740C}
RESX_NeutralResourcesLanguage = zh-Hans
SolutionGuid = {9313F2B4-10DA-43AA-A481-CAA7571C740C}
EndGlobalSection
EndGlobal
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+5 -1
View File
@@ -5,7 +5,11 @@ using Android.OS;
using Android.Webkit;
using Android.Util;
using Android.Opengl;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using Process = System.Diagnostics.Process;
using AndroidApplication = Android.App.Application;
#endif
@@ -543,7 +547,7 @@ namespace System.Application.UI
b.Append(Essentials.IsSupported.ToLowerString());
b.AppendLine();
#if __ANDROID__
#if __ANDROID__ && !NET6_0_MAUI_LIB
b.Append("[startup.track] ");
b.AppendLine();
b.Append(MainApplication.StartupTrack);
@@ -3,7 +3,11 @@ using Microsoft.Extensions.DependencyInjection;
using AndroidToast = Android.Widget.Toast;
using AndroidToastLength = Android.Widget.ToastLength;
using JException = Java.Lang.Exception;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -7,7 +7,11 @@ using AndroidX.AppCompat.App;
using AndroidX.Fragment.App;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using Fragment = AndroidX.Fragment.App.Fragment;
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
@@ -3,9 +3,17 @@ using Android.OS;
using Android.Provider;
using Android.Webkit;
using System.IO;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using AndroidUri = Android.Net.Uri;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
// ReSharper disable once CheckNamespace
namespace System
+1 -1
View File
@@ -87,7 +87,7 @@ public struct ShortGuid
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is ShortGuid shortGuid)
{
@@ -0,0 +1,15 @@
#if NET6_0_OR_GREATER
using System.Drawing;
using AndroidColor = Android.Graphics.Color;
namespace System;
public static partial class ColorExtensions
{
public static Color ToSystemColor(this AndroidColor color) =>
Color.FromArgb(color.A, color.R, color.G, color.B);
public static AndroidColor ToPlatformColor(this Color color) =>
new(color.R, color.G, color.B, color.A);
}
#endif
@@ -4,28 +4,29 @@ using Android.OS;
using NativeService = System.Application.Services.Native.IServiceBase;
// ReSharper disable once CheckNamespace
namespace System
namespace System;
partial class ContextExtensions
{
partial class ContextExtensions
/// <summary>
/// 启动或关闭前台服务
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="context"></param>
/// <param name="startOrStop"></param>
public static void StartOrStopForegroundService<TService>(this Context context, bool startOrStop) where TService : Service, NativeService
{
/// <summary>
/// 启动或关闭前台服务
/// </summary>
/// <typeparam name="TService"></typeparam>
/// <param name="context"></param>
/// <param name="startOrStop"></param>
public static void StartOrStopForegroundService<TService>(this Context context, bool startOrStop) where TService : Service, NativeService
Intent intent = new(context, typeof(TService));
intent.SetAction(startOrStop ? NativeService.START : NativeService.STOP);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
Intent intent = new(context, typeof(TService));
intent.SetAction(startOrStop ? NativeService.START : NativeService.STOP);
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
context.StartForegroundService(intent);
}
else
{
context.StartService(intent);
}
#pragma warning disable CA1416 // 验证平台兼容性
context.StartForegroundService(intent);
#pragma warning restore CA1416 // 验证平台兼容性
}
else
{
context.StartService(intent);
}
}
}
@@ -1,6 +1,10 @@
using System.Threading.Tasks;
using Android.Telephony;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application;
+10 -4
View File
@@ -1,7 +1,7 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>MonoAndroid12.0</TargetFrameworks>
<TargetFrameworks>MonoAndroid12.0;net6.0-android</TargetFrameworks>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>Xamarin.Forms.Platform.Android.UnitTests</AssemblyName>
<DefineConstants>SHADOWSOCKS;$(DefineConstants)</DefineConstants>
@@ -9,6 +9,11 @@
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-android'))">21.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition=" !($(TargetFramework.StartsWith('MonoAndroid'))) ">
<UseMaui>true</UseMaui>
<DefineConstants>NET6_0_MAUI_LIB;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<!--当前包是否为应用商店渠道包(IS_STORE_PACKAGE)-->
<!--<PropertyGroup>
<DefineConstants>IS_STORE_PACKAGE;$(DefineConstants)</DefineConstants>
@@ -25,7 +30,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="..\Startup.cs" Link="UI\MainApplication.Startup.cs" />
<Compile Condition="!$(TargetFramework.Contains('-android'))" Include="..\Startup.cs" Link="UI\MainApplication.Startup.cs" />
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
@@ -106,7 +111,7 @@
<LinkBase>UI\Adapters</LinkBase>
</Compile>
<Compile Include="..\Common.ClientLib.Droid\Application\DarkModeUtil.cs" />
<Compile Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddWindowManager.cs" />
<Compile Condition="!$(TargetFramework.Contains('-android'))" Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddWindowManager.cs" />
<Compile Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddApplicationUpdateService.cs" />
<AndroidResource Include="Resources\**\*" />
<Compile Remove="Services\V2Ray\**" />
@@ -158,7 +163,8 @@
<ItemGroup>
<ProjectReference Include="..\Common.CoreLib\Common.CoreLib.csproj" />
<ProjectReference Include="..\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj" />
<ProjectReference Condition=" ($(TargetFramework.StartsWith('MonoAndroid'))) " Include="..\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj" />
<ProjectReference Condition=" !($(TargetFramework.StartsWith('MonoAndroid'))) " Include="..\Common.Essentials.Maui\Common.Essentials.Maui.csproj" />
<ProjectReference Condition=" $(DefineConstants.Contains(`V2RAY`)) " Include="..\ST.Client.Android.V2Ray\ST.Client.Android.V2Ray.csproj" />
<ProjectReference Condition=" $(DefineConstants.Contains(`SHADOWSOCKS`)) " Include="..\ST.Client.Android.Shadowsocks\ST.Client.Android.Shadowsocks.csproj" />
<ProjectReference Include="..\ST.Client.AppCenter\ST.Client.AppCenter.csproj" />
@@ -1,7 +1,15 @@
using Android.OS;
using System.IO;
#if NET6_0_OR_GREATER
using Microsoft.Maui.Devices;
#else
using Xamarin.Essentials;
#endif
#if NET6_0_OR_GREATER
using XEDeviceType = Microsoft.Maui.Devices.DeviceType;
#else
using XEDeviceType = Xamarin.Essentials.DeviceType;
#endif
namespace System.Application.Services.Implementation
{
@@ -2,7 +2,11 @@ using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using ASF_FS = System.Application.Services.Native.ArchiSteamFarmForegroundService;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using Android.App;
using System.Application.Services.Native;
@@ -4,7 +4,11 @@ using System.Net;
using AndroidX.AppCompat.App;
using System.Application.UI.Activities;
using AndroidApplication = Android.App.Application;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -12,288 +12,305 @@ using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using System.Collections.Generic;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
using static Microsoft.Maui.ApplicationModel.Platform;
#else
using Xamarin.Essentials;
using static Xamarin.Essentials.Platform;
#endif
using AlertDialog = AndroidX.AppCompat.App.AlertDialog;
namespace System.Application.Services.Implementation
namespace System.Application.Services.Implementation;
/// <inheritdoc cref="IWindowManager"/>
public class AndroidWindowManagerImpl : IWindowManagerImpl
{
/// <inheritdoc cref="IWindowManager"/>
public class AndroidWindowManagerImpl : IWindowManagerImpl
/* AlertDialog
* =======================================
* = Title =
* = Message(Content) =
* = Neutral Negative Positive =
* =======================================
*/
protected static string PositiveButtonText => AppResources.Confirm;
protected static string NegativeButtonText => AppResources.Cancel;
protected static string NeutralButtonText => AppResources.RememberChooseNotToAskAgain;
protected async Task<bool> PlatformShowWindow(CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
{
/* AlertDialog
* =======================================
* = Title =
* = Message(Content) =
* = Neutral Negative Positive =
* =======================================
*/
protected static string PositiveButtonText => AppResources.Confirm;
protected static string NegativeButtonText => AppResources.Cancel;
protected static string NeutralButtonText => AppResources.RememberChooseNotToAskAgain;
protected async Task<bool> PlatformShowWindow(CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
Activity currentActivity;
do
{
Activity currentActivity;
do
{
currentActivity = await WaitForActivityAsync();
await Task.Delay(100);
} while (!currentActivity.HasValue());
return await MainThread.InvokeOnMainThreadAsync(async () =>
{
return await PlatformShowWindowCore(currentActivity, customWindow, viewModel, title);
});
currentActivity = await WaitForActivityAsync();
await Task.Delay(100);
} while (!currentActivity.HasValue());
return await MainThread.InvokeOnMainThreadAsync(async () =>
{
return await PlatformShowWindowCore(currentActivity, customWindow, viewModel, title);
});
}
bool IWindowManager.UseMyAuthenticatorWrapper => true;
protected Task<bool> PlatformShowWindowCore(Activity currentActivity, CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
case CustomWindow.AuthTrade:
if (viewModel is IMyAuthenticatorWrapper viewModel_auth_w && viewModel_auth_w.MyAuthenticator != null)
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
// Android Activity 传参需要序列化后再反序列化,不能直接传递
// 所以此处传递 Id,在 Activity 中从关联的集合中根据 Id 取值
SteamAuthDataActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
case CustomWindow.AuthTrade:
SteamAuthTradeActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
}
}
return Task.FromResult(false);
}
bool IWindowManager.UseMyAuthenticatorWrapper => true;
protected Task<bool> PlatformShowWindowCore(Activity currentActivity, CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
var activityType = customWindow switch
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
case CustomWindow.AuthTrade:
if (viewModel is IMyAuthenticatorWrapper viewModel_auth_w && viewModel_auth_w.MyAuthenticator != null)
{
switch (customWindow)
{
case CustomWindow.ShowAuth:
// Android Activity 传参需要序列化后再反序列化,不能直接传递
// 所以此处传递 Id,在 Activity 中从关联的集合中根据 Id 取值
SteamAuthDataActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
case CustomWindow.AuthTrade:
SteamAuthTradeActivity.StartActivity(currentActivity, viewModel_auth_w.MyAuthenticator.Id);
break;
}
}
return Task.FromResult(false);
}
CustomWindow.AddAuth => typeof(AddAuthActivity),
CustomWindow.ExportAuth => typeof(ExportAuthActivity),
CustomWindow.EncryptionAuth => typeof(EncryptionAuthActivity),
CustomWindow.ProxySettings => typeof(ProxySettingsActivity),
_ => null,
};
if (activityType != null)
{
currentActivity.StartActivity(activityType);
return Task.FromResult(false);
}
var activityType = customWindow switch
{
CustomWindow.AddAuth => typeof(AddAuthActivity),
CustomWindow.ExportAuth => typeof(ExportAuthActivity),
CustomWindow.EncryptionAuth => typeof(EncryptionAuthActivity),
CustomWindow.ProxySettings => typeof(ProxySettingsActivity),
_ => null,
};
if (activityType != null)
{
currentActivity.StartActivity(activityType);
return Task.FromResult(false);
}
TaskCompletionSource<bool> tcs = new();
try
{
AlertDialog? dialog = null;
TaskCompletionSource<bool> tcs = new();
try
void SetConfirmButton(MaterialAlertDialogBuilder b)
{
AlertDialog? dialog = null;
void SetConfirmButton(MaterialAlertDialogBuilder b)
b.SetPositiveButton(PositiveButtonText, (_, e) =>
{
b.SetPositiveButton(PositiveButtonText, (_, e) =>
{
tcs.TrySetResult(true);
});
}
void SetCancelButton(MaterialAlertDialogBuilder b)
{
b.SetNegativeButton(NegativeButtonText, (_, e) =>
{
tcs.TrySetResult(false);
});
}
void SetNeutralButton(MaterialAlertDialogBuilder b, MessageBoxWindowViewModel vm)
{
b.SetNeutralButton(NeutralButtonText, (_, e) =>
{
vm.RememberChoose = true;
tcs.TrySetResult(true);
});
}
Action<AlertDialog>? CreateMessageBoxDialogWindow(MaterialAlertDialogBuilder b)
{
SetConfirmButton(b);
var isCancelcBtn = false;
if (viewModel is MessageBoxWindowViewModel viewModel_mb)
{
b.SetMessage(viewModel_mb.Content);
isCancelcBtn = viewModel_mb.IsCancelcBtn;
if (viewModel_mb.IsShowRememberChoose) SetNeutralButton(b, viewModel_mb);
}
if (isCancelcBtn) SetCancelButton(b);
return null;
}
Action<AlertDialog>? CreateTextBoxDialogWindowCore(MaterialAlertDialogBuilder b, Action<textbox_password, TextBoxWindowViewModel>? action = null)
{
if (viewModel is not TextBoxWindowViewModel viewModel_tb) throw new NotSupportedException();
// https://material.io/components/text-fields/android
// https://material.io/components/dialogs#specs
IDialogInterfaceOnClickListener? listener = null;
b.SetPositiveButton(PositiveButtonText, listener);
SetCancelButton(b);
var view = LayoutInflater.From(b.Context)!.Inflate(Resource.Layout.textbox_password, null, false)!;
var binding = new textbox_password(view);
var selectionIndex = 0;
if (!string.IsNullOrEmpty(viewModel_tb.Value))
{
binding.tbPassword.Text = viewModel_tb.Value;
selectionIndex = viewModel_tb.Value!.Length;
}
binding.layoutPassword.Hint = viewModel_tb.Placeholder;
if (viewModel_tb.MaxLength > 0)
binding.tbPassword.SetMaxLength(viewModel_tb.MaxLength);
action?.Invoke(binding, viewModel_tb);
b.SetView(view);
return d =>
{
if (binding.tbPassword.KeyListener != null)
{
currentActivity.ShowSoftInput(binding.tbPassword, inOnCreate: true);
if (selectionIndex > 0)
{
binding.tbPassword.SetSelection(selectionIndex);
}
}
d.GetButton((int)DialogButtonType.Positive).Click += (_, _) =>
{
if (viewModel is ITextBoxWindowViewModel viewModel_tb)
{
viewModel_tb.Value = binding.tbPassword.Text;
if (viewModel_tb.InputValidator())
{
d.Dismiss();
tcs.TrySetResult(true);
}
}
};
};
}
Action<AlertDialog>? CreateTextBoxDialogWindow(MaterialAlertDialogBuilder b) => CreateTextBoxDialogWindowCore(b, static (binding, viewModel) =>
{
switch (viewModel.InputType)
{
case TextBoxWindowViewModel.TextBoxInputType.TextBox:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconClearText;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
break;
case TextBoxWindowViewModel.TextBoxInputType.ReadOnlyText:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconNone;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
binding.tbPassword.SetReadOnly();
break;
}
tcs.TrySetResult(true);
});
Func<MaterialAlertDialogBuilder, Action<AlertDialog>?> @delegate = customWindow switch
{
CustomWindow.MessageBox => CreateMessageBoxDialogWindow,
CustomWindow.TextBox => CreateTextBoxDialogWindow,
_ => throw new NotImplementedException(),
};
if (!string.IsNullOrEmpty(title) && viewModel != null)
{
viewModel.Title = title;
}
var builder = new MaterialAlertDialogBuilder(currentActivity);
if (!string.IsNullOrWhiteSpace(viewModel?.Title))
{
builder.SetTitle(viewModel!.Title);
}
var dialog_delegate = @delegate(builder);
dialog = builder.Create();
dialog.SetCanceledOnTouchOutside(false);
dialog.CancelEvent += (_, _) =>
}
void SetCancelButton(MaterialAlertDialogBuilder b)
{
b.SetNegativeButton(NegativeButtonText, (_, e) =>
{
tcs.TrySetResult(false);
};
if (dialog_delegate != null)
});
}
void SetNeutralButton(MaterialAlertDialogBuilder b, MessageBoxWindowViewModel vm)
{
b.SetNeutralButton(NeutralButtonText, (_, e) =>
{
dialog.ShowEvent += (_, _) =>
vm.RememberChoose = true;
tcs.TrySetResult(true);
});
}
Action<AlertDialog>? CreateMessageBoxDialogWindow(MaterialAlertDialogBuilder b)
{
SetConfirmButton(b);
var isCancelcBtn = false;
if (viewModel is MessageBoxWindowViewModel viewModel_mb)
{
b.SetMessage(viewModel_mb.Content);
isCancelcBtn = viewModel_mb.IsCancelcBtn;
if (viewModel_mb.IsShowRememberChoose) SetNeutralButton(b, viewModel_mb);
}
if (isCancelcBtn) SetCancelButton(b);
return null;
}
Action<AlertDialog>? CreateTextBoxDialogWindowCore(MaterialAlertDialogBuilder b, Action<textbox_password, TextBoxWindowViewModel>? action = null)
{
if (viewModel is not TextBoxWindowViewModel viewModel_tb) throw new NotSupportedException();
// https://material.io/components/text-fields/android
// https://material.io/components/dialogs#specs
IDialogInterfaceOnClickListener? listener = null;
b.SetPositiveButton(PositiveButtonText, listener);
SetCancelButton(b);
var view = LayoutInflater.From(b.Context)!.Inflate(Resource.Layout.textbox_password, null, false)!;
var binding = new textbox_password(view);
var selectionIndex = 0;
if (!string.IsNullOrEmpty(viewModel_tb.Value))
{
binding.tbPassword.Text = viewModel_tb.Value;
selectionIndex = viewModel_tb.Value!.Length;
}
binding.layoutPassword.Hint = viewModel_tb.Placeholder;
if (viewModel_tb.MaxLength > 0)
binding.tbPassword.SetMaxLength(viewModel_tb.MaxLength);
action?.Invoke(binding, viewModel_tb);
b.SetView(view);
return d =>
{
if (binding.tbPassword.KeyListener != null)
{
dialog_delegate?.Invoke(dialog);
currentActivity.ShowSoftInput(binding.tbPassword, inOnCreate: true);
if (selectionIndex > 0)
{
binding.tbPassword.SetSelection(selectionIndex);
}
}
d.GetButton((int)DialogButtonType.Positive).Click += (_, _) =>
{
if (viewModel is ITextBoxWindowViewModel viewModel_tb)
{
viewModel_tb.Value = binding.tbPassword.Text;
if (viewModel_tb.InputValidator())
{
d.Dismiss();
tcs.TrySetResult(true);
}
}
};
}
dialog.Show();
};
}
catch (Exception e)
Action<AlertDialog>? CreateTextBoxDialogWindow(MaterialAlertDialogBuilder b) => CreateTextBoxDialogWindowCore(b, static (binding, viewModel) =>
{
tcs.TrySetException(e);
}
return tcs.Task;
}
public virtual Type? WindowType => typeof(Activity);
public virtual Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
protected bool IsMatchCurrentActivityViewModel(object vm, [NotNullWhen(true)] out Activity? activity)
{
foreach (var item in MainApplication.Activities)
{
if (item is IViewFor vf && vf.ViewModel == vm)
switch (viewModel.InputType)
{
activity = item;
return true;
case TextBoxWindowViewModel.TextBoxInputType.TextBox:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconClearText;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
break;
case TextBoxWindowViewModel.TextBoxInputType.ReadOnlyText:
binding.layoutPassword.EndIconMode = TextInputLayout.EndIconNone;
binding.tbPassword.InputType = InputTypes.ClassText | InputTypes.TextVariationNormal;
binding.tbPassword.SetReadOnly();
break;
}
}
activity = null;
return false;
}
});
public virtual void CloseWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
Func<MaterialAlertDialogBuilder, Action<AlertDialog>?> @delegate = customWindow switch
{
activity.OnBackPressed();
}
}
public virtual bool IsVisibleWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
CustomWindow.MessageBox => CreateMessageBoxDialogWindow,
CustomWindow.TextBox => CreateTextBoxDialogWindow,
_ => throw new NotImplementedException(),
};
if (!string.IsNullOrEmpty(title) && viewModel != null)
{
return activity.HasValue();
viewModel.Title = title;
}
return default;
var builder = new MaterialAlertDialogBuilder(currentActivity);
if (!string.IsNullOrWhiteSpace(viewModel?.Title))
{
builder.SetTitle(viewModel!.Title);
}
var dialog_delegate = @delegate(builder);
dialog = builder.Create();
dialog.SetCanceledOnTouchOutside(false);
dialog.CancelEvent += (_, _) =>
{
tcs.TrySetResult(false);
};
if (dialog_delegate != null)
{
dialog.ShowEvent += (_, _) =>
{
dialog_delegate?.Invoke(dialog);
};
}
dialog.Show();
}
public virtual void HideWindow(WindowViewModel vm)
catch (Exception e)
{
CloseWindow(vm);
tcs.TrySetException(e);
}
return tcs.Task;
}
public virtual Type? WindowType => typeof(Activity);
public virtual Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task Show(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
public virtual Task ShowDialog(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
return PlatformShowWindow(customWindow, viewModel, title);
}
protected virtual IEnumerable<Activity> Activities
{
get
{
#if NET6_0_MAUI_LIB
throw new NotImplementedException();
#else
return MainApplication.Activities;
#endif
}
}
protected bool IsMatchCurrentActivityViewModel(object vm, [NotNullWhen(true)] out Activity? activity)
{
foreach (var item in Activities)
{
if (item is IViewFor vf && vf.ViewModel == vm)
{
activity = item;
return true;
}
}
activity = null;
return false;
}
public virtual void CloseWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
{
activity.OnBackPressed();
}
}
public virtual bool IsVisibleWindow(WindowViewModel vm)
{
if (IsMatchCurrentActivityViewModel(vm, out var activity))
{
return activity.HasValue();
}
return default;
}
public virtual void HideWindow(WindowViewModel vm)
{
CloseWindow(vm);
}
}
@@ -3,7 +3,11 @@ using Android.OS;
#endif
using Microsoft.Extensions.Options;
using System.Application.Models;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using System.Application.UI;
namespace System.Application.Services.Implementation
@@ -1,11 +1,17 @@
#if ANDROID || __ANDROID__
using Android.Content;
using Android.Net;
#endif
using System.Application.Services;
using System.Application.Services.Implementation;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -3,7 +3,11 @@ using System.Linq;
using System.IO;
using System.Threading.Tasks;
using static AndroidX.Activity.Result.ActivityResultTask;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -1,5 +1,9 @@
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using XEPermissions = Microsoft.Maui.ApplicationModel.Permissions;
#else
using XEPermissions = Xamarin.Essentials.Permissions;
#endif
namespace System.Application.Services.Implementation.Permissions;
@@ -1,6 +1,10 @@
using AndroidX.Biometric;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -16,15 +16,22 @@ using System.Application.Services;
using System.Application.UI.Resx;
using System.Collections.Generic;
using System.Linq;
using Xamarin.Essentials;
using Xamarin.Google.MLKit.Vision.BarCode;
using Xamarin.Google.MLKit.Vision.Common;
using Xamarin.Google.MLKit.Vision.Barcode.Common;
using AUri = Android.Net.Uri;
using Fragment = AndroidX.Fragment.App.Fragment;
using GmsTask = Android.Gms.Tasks.Task;
using JException = Java.Lang.Exception;
using JObject = Java.Lang.Object;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.Media;
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using Xamarin.Essentials;
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.UI.Activities
{
@@ -20,7 +20,13 @@ using System.Threading.Tasks;
using static AndroidX.Activity.Result.ActivityResultTask;
using _ThisAssembly = System.Properties.ThisAssembly;
using ASettings = Android.Provider.Settings;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using Xamarin.Essentials;
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.UI.Activities
{
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using Android.App;
using Android.Content;
using Android.Content.PM;
@@ -15,155 +16,155 @@ using Fragment = AndroidX.Fragment.App.Fragment;
using Google.Android.Material.Navigation;
using AndroidX.ViewPager2.Widget;
namespace System.Application.UI.Activities
namespace System.Application.UI.Activities;
/// <summary>
/// 使用 ViewPager2 + BottomNavigationView 实现的 MainActivity
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(MainActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_NoActionBar,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
internal sealed partial class MainActivity : BaseActivity<activity_main_3>, ViewPagerAdapter.IHost, BottomNavigationView.IOnItemSelectedListener
{
/// <summary>
/// 使用 ViewPager2 + BottomNavigationView 实现的 MainActivity
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(MainActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_NoActionBar,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
internal sealed partial class MainActivity : BaseActivity<activity_main_3>, ViewPagerAdapter.IHost, BottomNavigationView.IOnItemSelectedListener
protected override int? LayoutResource => Resource.Layout.activity_main_3;
protected override bool BackToHome => true;
void SetBottomNavigationMenuTitle(int resId, CharSequence value)
{
protected override int? LayoutResource => Resource.Layout.activity_main_3;
if (binding == null) return;
var menu = binding.nav_view.Menu;
var menuItem = menu.FindItem(resId);
if (menuItem == null) return;
menuItem.SetTitle(value);
}
protected override bool BackToHome => true;
void SetSubPageTitle(int resId, string value)
{
var value_ = value.ToJavaString();
SetBottomNavigationMenuTitle(resId, value_);
this.SetNavigationGraphTitle(resId, value_);
}
void SetBottomNavigationMenuTitle(int resId, CharSequence value)
static MainActivity? mainActivity;
public static MainActivity Instance => mainActivity ?? throw new ArgumentNullException(nameof(mainActivity));
(Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]? fragments;
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
mainActivity = this;
fragments = new (Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]
{
(typeof(LocalAuthFragment), () => LocalAuthPageViewModel.DisplayName, Resource.Id.navigation_local_auth, TabItemViewModel.TabItemId.LocalAuth),
(typeof(ASFPlusFragment), () => ArchiSteamFarmPlusPageViewModel.DisplayName, Resource.Id.navigation_asf_plus, TabItemViewModel.TabItemId.ArchiSteamFarmPlus),
(typeof(CommunityFixFragment), () => AppResources.CommunityFix, Resource.Id.navigation_community_fix, TabItemViewModel.TabItemId.CommunityProxy),
(typeof(MyFragment), () => MyPageViewModel.DisplayName, Resource.Id.navigation_my, default),
};
SetSupportActionBar(binding!.toolbar);
R.Subscribe(() =>
{
if (binding == null) return;
var menu = binding.nav_view.Menu;
var menuItem = menu.FindItem(resId);
if (menuItem == null) return;
menuItem.SetTitle(value);
}
void SetSubPageTitle(int resId, string value)
{
var value_ = value.ToJavaString();
SetBottomNavigationMenuTitle(resId, value_);
this.SetNavigationGraphTitle(resId, value_);
}
static MainActivity? mainActivity;
public static MainActivity Instance => mainActivity ?? throw new ArgumentNullException(nameof(mainActivity));
(Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]? fragments;
protected override void OnCreate2(Bundle? savedInstanceState)
{
base.OnCreate2(savedInstanceState);
mainActivity = this;
fragments = new (Type fragmentType, Func<string> getTitle, int menuId, TabItemViewModel.TabItemId tabItemId)[]
foreach (var (_, getTitle, menuId, _) in fragments)
{
(typeof(LocalAuthFragment), () => LocalAuthPageViewModel.DisplayName, Resource.Id.navigation_local_auth, TabItemViewModel.TabItemId.LocalAuth),
(typeof(ASFPlusFragment), () => ArchiSteamFarmPlusPageViewModel.DisplayName, Resource.Id.navigation_asf_plus, TabItemViewModel.TabItemId.ArchiSteamFarmPlus),
(typeof(CommunityFixFragment), () => AppResources.CommunityFix, Resource.Id.navigation_community_fix, TabItemViewModel.TabItemId.CommunityProxy),
(typeof(MyFragment), () => MyPageViewModel.DisplayName, Resource.Id.navigation_my, default),
};
SetSupportActionBar(binding!.toolbar);
R.Subscribe(() =>
{
if (binding == null) return;
foreach (var (_, getTitle, menuId, _) in fragments)
{
var title = getTitle();
SetSubPageTitle(menuId, title);
}
SetTitleByPosition(binding.viewPager2.CurrentItem);
}).AddTo(this);
var adapter = new ViewPagerAdapter(this, this);
binding.viewPager2.Adapter = adapter;
binding.viewPager2.RegisterOnPageChangeCallback(new OnPageChangeCallback(this));
binding.nav_view.SetOnItemSelectedListener(this);
}
sealed class OnPageChangeCallback : ViewPager2.OnPageChangeCallback
{
readonly MainActivity thiz;
public OnPageChangeCallback(MainActivity thiz)
{
this.thiz = thiz;
var title = getTitle();
SetSubPageTitle(menuId, title);
}
SetTitleByPosition(binding.viewPager2.CurrentItem);
}).AddTo(this);
public override void OnPageSelected(int position)
{
thiz.OnPageSelected(position);
}
var adapter = new ViewPagerAdapter(this, this);
binding.viewPager2.Adapter = adapter;
binding.viewPager2.RegisterOnPageChangeCallback(new OnPageChangeCallback(this));
binding.nav_view.SetOnItemSelectedListener(this);
}
sealed class OnPageChangeCallback : ViewPager2.OnPageChangeCallback
{
readonly MainActivity thiz;
public OnPageChangeCallback(MainActivity thiz)
{
this.thiz = thiz;
}
protected override void OnNewIntent(Intent? intent)
public override void OnPageSelected(int position)
{
base.OnNewIntent(intent);
thiz.OnPageSelected(position);
}
}
if (binding == null || fragments == null) return;
var action = intent?.Action;
if (!string.IsNullOrWhiteSpace(action))
protected override void OnNewIntent(Intent? intent)
{
base.OnNewIntent(intent);
if (binding == null || fragments == null) return;
var action = intent?.Action;
if (!string.IsNullOrWhiteSpace(action))
{
if (Enum.TryParse<TabItemViewModel.TabItemId>(action, out var tabItem))
{
if (Enum.TryParse<TabItemViewModel.TabItemId>(action, out var tabItem))
for (int i = 0; i < fragments!.Length; i++)
{
for (int i = 0; i < fragments!.Length; i++)
if (fragments[i].tabItemId == tabItem)
{
if (fragments[i].tabItemId == tabItem)
{
Navigate(i);
}
Navigate(i);
}
}
}
}
}
int ViewPagerAdapter.IHost.ItemCount => fragments!.Length;
int ViewPagerAdapter.IHost.ItemCount => fragments!.Length;
Fragment ViewPagerAdapter.IHost.CreateFragment(int position) => (Fragment)Activator.CreateInstance(fragments![position].fragmentType);
Fragment ViewPagerAdapter.IHost.CreateFragment(int position) => (Fragment)Activator.CreateInstance(fragments![position].fragmentType);
bool NavigationBarView.IOnItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
bool NavigationBarView.IOnItemSelectedListener.OnNavigationItemSelected(IMenuItem item)
{
if (binding == null || fragments == null) return false;
var itemId = item.ItemId;
for (int i = 0; i < fragments!.Length; i++)
{
if (binding == null || fragments == null) return false;
var itemId = item.ItemId;
for (int i = 0; i < fragments!.Length; i++)
if (fragments[i].menuId == itemId)
{
if (fragments[i].menuId == itemId)
{
Navigate(i);
return true;
}
Navigate(i);
return true;
}
return false;
}
return false;
}
void Navigate(int position)
{
binding!.viewPager2.SetCurrentItem(position, false);
SetTitleByPosition(position);
SetChecked(position);
}
void Navigate(int position)
{
binding!.viewPager2.SetCurrentItem(position, false);
SetTitleByPosition(position);
SetChecked(position);
}
void SetTitleByPosition(int position)
{
var title = fragments![position].getTitle();
Title = title;
}
void SetTitleByPosition(int position)
{
var title = fragments![position].getTitle();
Title = title;
}
void OnPageSelected(int position)
{
if (binding == null) return;
SetTitleByPosition(position);
SetChecked(position);
}
void OnPageSelected(int position)
{
if (binding == null) return;
SetTitleByPosition(position);
SetChecked(position);
}
void SetChecked(int position)
{
var menuItem = binding!.nav_view.Menu.FindItem(fragments![position].menuId);
if (menuItem != null && !menuItem.IsChecked) menuItem.SetChecked(true);
}
void SetChecked(int position)
{
var menuItem = binding!.nav_view.Menu.FindItem(fragments![position].menuId);
if (menuItem != null && !menuItem.IsChecked) menuItem.SetChecked(true);
}
}
#endif
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using Android.App;
using Android.Content.PM;
using Android.OS;
@@ -5,31 +6,31 @@ using Android.Runtime;
using Android.Views;
using System.Application.Security;
namespace System.Application.UI.Activities
{
/// <summary>
/// 页面 - 启动屏幕
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(SplashActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_Splash,
MainLauncher = true,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges,
NoHistory = true)]
internal sealed class SplashActivity : Activity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
//if (!DeviceSecurityCheckUtil.IsAllowStart(this)) return;
StartActivity(IAndroidApplication.Instance.MainActivityType);
OverridePendingTransition(Resource.Animation.abc_fade_in, Resource.Animation.abc_fade_out);
}
namespace System.Application.UI.Activities;
public override void OnBackPressed()
{
GoToPlatformPages.MockHomePressed(this);
return;
}
/// <summary>
/// 页面 - 启动屏幕
/// </summary>
[Register(JavaPackageConstants.Activities + nameof(SplashActivity))]
[Activity(Theme = ManifestConstants.MainTheme2_Splash,
MainLauncher = true,
LaunchMode = LaunchMode.SingleTask,
ConfigurationChanges = ManifestConstants.ConfigurationChanges,
NoHistory = true)]
internal sealed class SplashActivity : Activity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
//if (!DeviceSecurityCheckUtil.IsAllowStart(this)) return;
StartActivity(IAndroidApplication.Instance.MainActivityType);
OverridePendingTransition(Resource.Animation.abc_fade_in, Resource.Animation.abc_fade_out);
}
}
public override void OnBackPressed()
{
GoToPlatformPages.MockHomePressed(this);
return;
}
}
#endif
@@ -2,7 +2,11 @@ using Android.Views;
using Binding;
using ReactiveUI;
using System.Application.UI.ViewModels;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using TViewHolder = System.Application.UI.Adapters.FastLoginChannelViewHolder;
using TViewModel = System.Application.UI.ViewModels.LoginOrRegisterWindowViewModel.FastLoginChannelViewModel;
@@ -1,14 +1,18 @@
using Android.Views;
using Binding;
using ReactiveUI;
using System.Threading.Tasks;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Application.UI.Activities;
using static System.Application.UI.Resx.AppResources;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using TViewHolder = System.Application.UI.Adapters.SteamAuthTradeConfirmationViewHolder;
using TViewModel = WinAuth.WinAuthSteamClient.Confirmation;
using static System.Application.UI.Resx.AppResources;
using System.Application.UI.Activities;
using XEPlatform = Xamarin.Essentials.Platform;
using System.Threading.Tasks;
namespace System.Application.UI.Adapters
{
@@ -13,7 +13,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reflection;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
// ReSharper disable once CheckNamespace
namespace System.Application.UI.Activities
@@ -13,7 +13,11 @@ using System.Application.UI.Adapters;
using System.Application.UI.Resx;
using System.Application.UI.ViewModels;
using System.Text;
#if NET6_0_OR_GREATER
using Microsoft.Maui.ApplicationModel;
#else
using Xamarin.Essentials;
#endif
using static System.Application.UI.ViewModels.AboutPageViewModel;
using M = System.Application.UI.ViewModels.AboutPageViewModel;
using V = Binding.fragment_about;
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
#if !NET6_0_MAUI_LIB
using AndroidApplication = Android.App.Application;
namespace System.Application.UI
@@ -10,3 +8,4 @@ namespace System.Application.UI
}
}
#endif
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using System.Application.Services;
using System.Application.UI.Activities;
using System.Collections.Generic;
@@ -32,3 +33,4 @@ namespace System.Application.UI
IApplication IApplication.IProgramHost.Application => this;
}
}
#endif
+3 -1
View File
@@ -1,3 +1,4 @@
#if !NET6_0_MAUI_LIB
using Android.App;
using Android.Runtime;
using System.Application.UI.Resx;
@@ -286,4 +287,5 @@ namespace System.Application.UI
void IApplication.PlatformInitSettingSubscribe() => PlatformInitSettingSubscribe();
}
}
}
#endif
+16 -13
View File
@@ -1,24 +1,27 @@
using Android.Util;
using AndroidX.SwipeRefreshLayout.Widget;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
namespace System.Application.UI
namespace System.Application.UI;
public static class StylesEx
{
public static class Styles
public static void InitDefaultStyles(this SwipeRefreshLayout swipeRefreshLayout)
{
public static void InitDefaultStyles(this SwipeRefreshLayout swipeRefreshLayout)
{
swipeRefreshLayout.SetColorSchemeColors(new[] { ColorPrimary });
}
swipeRefreshLayout.SetColorSchemeColors(new[] { ColorPrimary });
}
public static int ColorPrimary
public static int ColorPrimary
{
get
{
get
{
using TypedValue typedValue = new();
XEPlatform.CurrentActivity.Theme!.ResolveAttribute(Resource.Attribute.colorPrimary, typedValue, true);
return typedValue.Data;
}
using TypedValue typedValue = new();
XEPlatform.CurrentActivity.Theme!.ResolveAttribute(Resource.Attribute.colorPrimary, typedValue, true);
return typedValue.Data;
}
}
}
@@ -6,7 +6,11 @@ using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using AndroidAppActivity = Android.App.Activity;
#if NET6_0_OR_GREATER
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#else
using XEPlatform = Xamarin.Essentials.Platform;
#endif
using AndroidAppResult = Android.App.Result;
// 将 onActivityResult() 转换为 System.Threading.Tasks.Task
@@ -1,14 +1,29 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<!--<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-android;net6.0-windows</TargetFrameworks>-->
<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-windows</TargetFrameworks>
<TargetFrameworks>MonoAndroid12.0;Xamarin.iOS10;net6.0-android;net6.0-windows;net6.0-ios;net6.0-maccatalyst</TargetFrameworks>
<RootNamespace>System.Application.AppCenter</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.AppCenter</AssemblyName>
<ImplicitUsings>enable</ImplicitUsings>
<AndroidUseIntermediateDesignerFile>false</AndroidUseIntermediateDesignerFile>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<SupportedOSPlatformVersion>21.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<TargetPlatformMinVersion>7.0</TargetPlatformMinVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
@@ -23,17 +38,17 @@
<Link>Properties\AssemblyInfo.OS.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AppCenter" />
<PackageReference Include="Microsoft.AppCenter.Analytics" />
<PackageReference Include="Microsoft.AppCenter.Crashes" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ST.Client.Android.ResSecrets\ST.Client.Android.ResSecrets.csproj" Condition=" $(TargetFramework.StartsWith('MonoAndroid')) OR $(TargetFramework.Contains('-android')) " />
<ProjectReference Include="..\ST.Client.iOS.ResSecrets\ST.Client.iOS.ResSecrets.csproj" Condition=" $(TargetFramework.StartsWith('Xamarin.iOS')) OR $(TargetFramework.Contains('-ios')) " />
@@ -18,6 +18,7 @@
<WindowsSdkPackageVersion>10.0.19041.24</WindowsSdkPackageVersion>
<UseWindowsForms Condition="'$(Configuration)'=='Debug'">true</UseWindowsForms>
<UseWPF>false</UseWPF>
<DefineConstants>AVALONIA;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
@@ -44,7 +45,7 @@
.allowedextension
</AllowedReferenceRelatedFileExtensions>
</PropertyGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<RuntimeHostConfigurationOption Include="System.Net.SocketsHttpHandler.Http3Support" Value="true" />
</ItemGroup>
@@ -4,6 +4,7 @@ using System.Application.Services;
using Program = System.Application.UI.MauiProgram;
#endif
// ReSharper disable once CheckNamespace
namespace System.Application.UI;
static partial class
@@ -9,6 +9,7 @@
<RootNamespace>System.Application.UI</RootNamespace>
<AssemblyName>Steam++</AssemblyName>
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
<DefineConstants>AVALONIA;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
@@ -0,0 +1,57 @@
using System.Application.Services;
using System.Application.Settings;
using System.Application.UI.ViewModels;
using System.Application.UI.Views;
#if !MAUI
using System.Application.UI.Views.Windows;
#endif
namespace System.Application.UI;
partial class App
{
void HandlerViewModelManager(IViewModelManager vmService)
{
switch (vmService.MainWindow)
{
case CloudArchiveWindowViewModel:
ProgramHost.IsMinimize = false;
#if !MAUI
MainWindow = new CloudArchiveWindow();
#endif
break;
case AchievementWindowViewModel:
ProgramHost.IsMinimize = false;
#if !MAUI
MainWindow = new AchievementWindow();
#endif
break;
default:
#region 主窗口启动时加载的资源
#if !UI_DEMO
compositeDisposable.Add(SettingsHost.Save);
compositeDisposable.Add(ProxyService.Current.Exit);
if (IApplication.IsDesktopPlatform)
{
compositeDisposable.Add(SteamConnectService.Current.Dispose);
if (GeneralSettings.IsStartupAppMinimized.Value)
ProgramHost.IsMinimize = true;
}
compositeDisposable.Add(ASFService.Current.StopASF);
#endif
#endregion
#if !MAUI
MainWindow = new MainWindow();
#endif
break;
}
#if !MAUI
MainWindow.DataContext = vmService.MainWindow;
#else
var mainWindowVM = (MainWindowViewModel?)vmService.MainWindow;
MainPage = new AppShell(mainWindowVM.ThrowIsNull());
#endif
}
}
@@ -199,38 +199,7 @@ namespace System.Application.UI
/*if (isTrace) */StartWatchTrace.Record("App.LoadXaml");
#endif
Name = ThisAssembly.AssemblyTrademark;
ProgramHost.OnCreateAppExecuted(handlerViewModelManager: vmService =>
{
switch (vmService.MainWindow)
{
case CloudArchiveWindowViewModel:
ProgramHost.IsMinimize = false;
MainWindow = new CloudArchiveWindow();
break;
case AchievementWindowViewModel:
ProgramHost.IsMinimize = false;
MainWindow = new AchievementWindow();
break;
default:
#region 主窗口启动时加载的资源
#if !UI_DEMO
compositeDisposable.Add(SettingsHost.Save);
compositeDisposable.Add(ProxyService.Current.Exit);
compositeDisposable.Add(SteamConnectService.Current.Dispose);
compositeDisposable.Add(ASFService.Current.StopASF);
#pragma warning disable CA1416 // 验证平台兼容性
if (GeneralSettings.IsStartupAppMinimized.Value)
ProgramHost.IsMinimize = true;
#pragma warning restore CA1416 // 验证平台兼容性
#endif
#endregion
MainWindow = new MainWindow();
break;
}
MainWindow.DataContext = vmService.MainWindow;
}, isTrace: isTrace);
ProgramHost.OnCreateAppExecuted(handlerViewModelManager: HandlerViewModelManager, isTrace: isTrace);
LiveCharts.Configure(config =>
{
@@ -1,27 +1,25 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Application.Services;
#if MAUI
using WindowManagerImpl_ = System.Application.Services.Implementation.MauiWindowManagerImpl;
using WindowManagerImpl = System.Application.Services.Implementation.MauiWindowManagerImpl;
#elif __ANDROID__
using WindowManagerImpl_ = System.Application.Services.Implementation.AndroidWindowManagerImpl;
using WindowManagerImpl = System.Application.Services.Implementation.AndroidWindowManagerImpl;
#elif AVALONIA
using WindowManagerImpl_ = System.Application.Services.Implementation.AvaloniaWindowManagerImpl;
using WindowManagerImpl = System.Application.Services.Implementation.AvaloniaWindowManagerImpl;
#endif
// ReSharper disable once CheckNamespace
namespace Microsoft.Extensions.DependencyInjection
namespace Microsoft.Extensions.DependencyInjection;
public static partial class ServiceCollectionExtensions
{
public static partial class ServiceCollectionExtensions
/// <summary>
/// 添加窗口管理服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddWindowManager(this IServiceCollection services)
{
/// <summary>
/// 添加窗口管理服务
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection TryAddWindowManager(this IServiceCollection services)
{
services.TryAddSingleton<IWindowManager, WindowManagerImpl_>();
return services;
}
services.AddSingleton<IWindowManager, WindowManagerImpl>();
return services;
}
}
+13 -6
View File
@@ -1,12 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<!--<TargetFramework>net6.0-macos</TargetFramework>-->
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0;net6.0-macos;net6.0-maccatalyst</TargetFrameworks>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.Mac</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac20')) OR $(TargetFramework.Contains('-mac')) ">
<DefineConstants>XAMARIN_MAC;$(DefineConstants)</DefineConstants>
</PropertyGroup>
@@ -41,15 +48,15 @@
<!--<PackageReference Include="Gameloop.Vdf" />-->
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('Xamarin.Mac20')) OR $(TargetFramework.Contains('-mac')) ">
<!--<ItemGroup Condition=" ($(TargetFramework.StartsWith('Xamarin.Mac20')) OR $(TargetFramework.Contains('-mac'))) AND !$(TargetFramework.EndsWith('.0')) ">
<ProjectReference Include="..\ST.Client.AppCenter\ST.Client.AppCenter.csproj" />
</ItemGroup>
</ItemGroup>-->
<ItemGroup Condition=" $(TargetFramework.StartsWith('netstandard')) OR $(TargetFramework.EndsWith('net5.0')) OR $(TargetFramework.EndsWith('net6.0')) ">
<PackageReference Include="MonoMac.NetStandard" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\references\Gameloop.Vdf\Gameloop.Vdf\Gameloop.Vdf.csproj" />
<ProjectReference Include="..\..\references\SteamAchievementManager\SAM.API\SAM.API.csproj" />
@@ -15,7 +15,9 @@ namespace Microsoft.Extensions.DependencyInjection
if (OperatingSystem2.IsMacOS())
{
services.AddSingleton<IHttpPlatformHelperService, MacClientHttpPlatformHelperServiceImpl>();
#if !MACCATALYST
services.AddSingleton(AppDelegate.Instance!);
#endif
services.AddSingleton<MacPlatformServiceImpl>();
services.AddSingleton<IPlatformService>(s => s.GetRequiredService<MacPlatformServiceImpl>());
services.AddSingleton<IEmailPlatformService>(s => s.GetRequiredService<MacPlatformServiceImpl>());
@@ -7,32 +7,35 @@ using Foundation;
#endif
using System.Threading.Tasks;
namespace System.Application.Services.Implementation
namespace System.Application.Services.Implementation;
partial class MacPlatformServiceImpl : IEmailPlatformService
{
partial class MacPlatformServiceImpl : IEmailPlatformService
// https://github.com/xamarin/Essentials/blob/main/Xamarin.Essentials/Email/Email.macos.cs
static T? InvokeOnMainThread<T>(Func<T> factory)
{
// https://github.com/xamarin/Essentials/blob/main/Xamarin.Essentials/Email/Email.macos.cs
T? value = default;
NSRunLoop.Main.InvokeOnMainThread(() => value = factory());
return value;
}
static T? InvokeOnMainThread<T>(Func<T> factory)
public Task PlatformComposeAsync(EmailMessage? message)
{
#if MACCATALYST
throw new PlatformNotSupportedException();
#else
var isComposeSupported = InvokeOnMainThread(() => NSWorkspace.SharedWorkspace.UrlForApplication(NSUrl.FromString("mailto:")) != null);
if (!isComposeSupported)
{
T? value = default;
NSRunLoop.Main.InvokeOnMainThread(() => value = factory());
return value;
throw new NotSupportedException();
}
public Task PlatformComposeAsync(EmailMessage? message)
{
var isComposeSupported = InvokeOnMainThread(() => NSWorkspace.SharedWorkspace.UrlForApplication(NSUrl.FromString("mailto:")) != null);
if (!isComposeSupported)
{
throw new NotSupportedException();
}
var url = Email2.GetMailToUri(message);
var url = Email2.GetMailToUri(message);
using var nsurl = NSUrl.FromString(url);
NSWorkspace.SharedWorkspace.OpenUrl(nsurl);
return Task.CompletedTask;
}
using var nsurl = NSUrl.FromString(url);
NSWorkspace.SharedWorkspace.OpenUrl(nsurl);
return Task.CompletedTask;
#endif
}
}
@@ -55,7 +55,7 @@ namespace System.Application.Services.Implementation
internal static bool IsCertificateInstalled(X509Certificate2 certificate2)
{
#if MONO_MAC
//#if MONO_MAC
using var p = new Process();
p.StartInfo.FileName = "security";
p.StartInfo.Arguments = $" verify-cert -c \"{IReverseProxyService.Instance.CertificateManager.GetCerFilePathGeneratedWhenNoFileExists()}\"";
@@ -65,23 +65,23 @@ namespace System.Application.Services.Implementation
var returnStr = p.StandardOutput.ReadToEnd().TrimEnd();
p.Kill();
return returnStr.Contains("...certificate verification successful.", StringComparison.OrdinalIgnoreCase);
#elif XAMARIN_MAC
bool result = false;
var scer = new SecCertificate(cer);
var addCertificate = new SecRecord(scer);
var cerTrust = SecKeyChain.QueryAsRecord(addCertificate, out var t2code);
if (cerTrust != SecStatusCode.ItemNotFound)
{
using (var trust = new SecTrust(cerTrust, null))
{
trust.SetPolicy(policy);
trust.SetAnchorCertificates(fcollection);
result=trust.Evaluate(out var error);
Toast.Show(error.Description);
}
}
return result;
#endif
//#elif XAMARIN_MAC
// bool result = false;
// var scer = new SecCertificate(cer);
// var addCertificate = new SecRecord(scer);
// var cerTrust = SecKeyChain.QueryAsRecord(addCertificate, out var t2code);
// if (cerTrust != SecStatusCode.ItemNotFound)
// {
// using (var trust = new SecTrust(cerTrust, null))
// {
// trust.SetPolicy(policy);
// trust.SetAnchorCertificates(fcollection);
// result = trust.Evaluate(out var error);
// Toast.Show(error.Description);
// }
// }
// return result;
//#endif
}
@@ -182,7 +182,14 @@ namespace System.Application.Services.Implementation
Toast.Show(msg);
}
public static void OpenFile(string appName, string filePath) => NSWorkspace.SharedWorkspace.OpenFile(filePath, appName);
public static void OpenFile(string appName, string filePath)
{
#if MACCATALYST
throw new PlatformNotSupportedException();
#else
NSWorkspace.SharedWorkspace.OpenFile(filePath, appName);
#endif
}
public void SetSystemSessionEnding(Action action)
{
@@ -191,13 +198,21 @@ namespace System.Application.Services.Implementation
public void OpenFolderByDirectoryPath(DirectoryInfo info)
{
#if MACCATALYST
throw new PlatformNotSupportedException();
#else
//NSWorkspace.SharedWorkspace.SelectFile(string.Empty, info.FullName);
NSWorkspace.SharedWorkspace.ActivateFileViewer(new[] { new NSUrl(info.FullName, isDir: true) });
#endif
}
public void OpenFolderSelectFilePath(FileInfo info)
{
#if MACCATALYST
throw new PlatformNotSupportedException();
#else
NSWorkspace.SharedWorkspace.ActivateFileViewer(new[] { new NSUrl(info.FullName, isDir: false) });
#endif
}
public string? GetFileName(TextReaderProvider provider) => provider switch
+127 -124
View File
@@ -7,136 +7,139 @@ using AppKit;
using Foundation;
#endif
namespace System.Application.UI
#if !MACCATALYST
namespace System.Application.UI;
/// <summary>
/// This class is an AppDelegate helper specifically for Mac OSX
/// Int it's infinite wisdom and unlike Linux and or Windows Mac does not pass in the URL from a sqrl:// invokation
/// directly as a startup app paramter, instead it uses a System Event to do this which has to be registered
/// and listed to.
/// This requires us to use Xamarin.Mac to make it work with .net standard
/// </summary>
[Register("AppDelegate")]
public class AppDelegate : NSApplicationDelegate
{
/// <summary>
/// This class is an AppDelegate helper specifically for Mac OSX
/// Int it's infinite wisdom and unlike Linux and or Windows Mac does not pass in the URL from a sqrl:// invokation
/// directly as a startup app paramter, instead it uses a System Event to do this which has to be registered
/// and listed to.
/// This requires us to use Xamarin.Mac to make it work with .net standard
/// </summary>
[Register("AppDelegate")]
public class AppDelegate : NSApplicationDelegate
public AppDelegate()
{
public AppDelegate()
}
/// <summary>
/// Because we are creating our own mac application delegate we are removing / overriding
/// the one that Avalonia creates. This causes the application to not be handled as it should.
/// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
/// So what we are doing here is re-creating this implementation to mimick their behavior.
/// </summary>
/// <param name="notification"></param>
public override void WillFinishLaunching(NSNotification notification)
{
if (NSApplication.SharedApplication.ActivationPolicy != NSApplicationActivationPolicy.Regular)
{
foreach (var x in NSRunningApplication.GetRunningApplications(@"com.apple.dock"))
{
x.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
break;
}
NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Regular;
}
/// <summary>
/// Because we are creating our own mac application delegate we are removing / overriding
/// the one that Avalonia creates. This causes the application to not be handled as it should.
/// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
/// So what we are doing here is re-creating this implementation to mimick their behavior.
/// </summary>
/// <param name="notification"></param>
public override void WillFinishLaunching(NSNotification notification)
Console.WriteLine("开始注册通知");
try
{
if (NSApplication.SharedApplication.ActivationPolicy != NSApplicationActivationPolicy.Regular)
{
foreach (var x in NSRunningApplication.GetRunningApplications(@"com.apple.dock"))
{
x.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
break;
}
NSApplication.SharedApplication.ActivationPolicy = NSApplicationActivationPolicy.Regular;
}
Console.WriteLine("开始注册通知");
try
{
var manager = NSAppleEventManager.SharedAppleEventManager;
manager.SetEventHandler(this,
new MonoMac.ObjCRuntime.Selector("handleGetURLEvent:withReplyEvent:"),
AEEventClass.Internet,
AEEventID.GetUrl);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
var manager = NSAppleEventManager.SharedAppleEventManager;
manager.SetEventHandler(this,
new("handleGetURLEvent:withReplyEvent:"),
AEEventClass.Internet,
AEEventID.GetUrl);
}
#if MONO_MAC
[Export("handleGetURLEvent:withReplyEvent:")]
private void HandleGetURLEvent(NSAppleEventDescriptor descriptor, NSAppleEventDescriptor replyEvent)
catch (Exception e)
{
try
{
// stackoverflow.com/questions/1945
// https://forums.xamarin.com/discussion/9774/custom-url-schema-handling
var keyDirectObject = "----";
var keyword =
((uint)keyDirectObject[0]) << 24 |
((uint)keyDirectObject[1]) << 16 |
((uint)keyDirectObject[2]) << 8 |
((uint)keyDirectObject[3]);
var urlString = descriptor.ParamDescriptorForKeyword(keyword).StringValue;
using (var alert = new NSAlert())
{
alert.MessageText = urlString;
alert.RunSheetModal(null);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
#elif XAMARIN_MAC
public override void OpenUrls(NSApplication application, NSUrl[] urls)
{
throw new System.Exception("opened with: " + urls[0].AbsoluteString);
}
#endif
/// <summary>
/// Because we are creating our own mac application delegate we are removing / overriding
/// the one that Avalonia creates. This causes the application to not be handled as it should.
/// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
/// So what we are doing here is re-creating this implementation to mimick their behavior.
/// </summary>
/// <param name="notification"></param>
public override void DidFinishLaunching(NSNotification notification)
{
#if !NETSTANDARD && !NET5_0 && !NET6_0
VisualStudioAppCenterSDK.Init();
#endif
NSRunningApplication.CurrentApplication.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
}
public override bool ApplicationShouldHandleReopen(NSApplication sender, bool hasVisibleWindows)
{
if (hasVisibleWindows)
{
return false;
}
else
{
// 点击 Dock 重新打开已关闭的窗口
IApplication.Instance.RestoreMainWindow();
return true;
}
}
static bool isInitialized;
internal static AppDelegate? Instance { get; private set; }
public static void Init(string[] args)
{
if (!isInitialized)
{
isInitialized = true;
NSApplication.Init();
//NSApplication.Main(args);
Instance = new();
NSApplication.SharedApplication.Delegate = Instance;
}
Console.WriteLine(e.Message);
}
}
}
#if MONO_MAC
[Export("handleGetURLEvent:withReplyEvent:")]
private void HandleGetURLEvent(NSAppleEventDescriptor descriptor, NSAppleEventDescriptor replyEvent)
{
try
{
// stackoverflow.com/questions/1945
// https://forums.xamarin.com/discussion/9774/custom-url-schema-handling
var keyDirectObject = "----";
var keyword =
((uint)keyDirectObject[0]) << 24 |
((uint)keyDirectObject[1]) << 16 |
((uint)keyDirectObject[2]) << 8 |
((uint)keyDirectObject[3]);
var urlString = descriptor.ParamDescriptorForKeyword(keyword).StringValue;
using (var alert = new NSAlert())
{
alert.MessageText = urlString;
alert.RunSheetModal(null);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
#elif XAMARIN_MAC
public override void OpenUrls(NSApplication application, NSUrl[] urls)
{
throw new System.Exception("opened with: " + urls[0].AbsoluteString);
}
#endif
/// <summary>
/// Because we are creating our own mac application delegate we are removing / overriding
/// the one that Avalonia creates. This causes the application to not be handled as it should.
/// This is the Avalonia Implementation: https://github.com/AvaloniaUI/Avalonia/blob/5a2ef35dacbce0438b66d9f012e5f629045beb3d/native/Avalonia.Native/src/OSX/app.mm
/// So what we are doing here is re-creating this implementation to mimick their behavior.
/// </summary>
/// <param name="notification"></param>
public override void DidFinishLaunching(NSNotification notification)
{
#if !NETSTANDARD && !NET5_0 && !NET6_0
VisualStudioAppCenterSDK.Init();
#endif
NSRunningApplication.CurrentApplication.Activate(NSApplicationActivationOptions.ActivateIgnoringOtherWindows);
}
public override bool ApplicationShouldHandleReopen(NSApplication sender, bool hasVisibleWindows)
{
if (hasVisibleWindows)
{
return false;
}
else
{
// 点击 Dock 重新打开已关闭的窗口
IApplication.Instance.RestoreMainWindow();
return true;
}
}
static bool isInitialized;
internal static AppDelegate? Instance { get; private set; }
public static void Init(string[] args)
{
if (!isInitialized)
{
isInitialized = true;
NSApplication.Init();
//NSApplication.Main(args);
Instance = new();
NSApplication.SharedApplication.Delegate = Instance;
}
}
}
#endif
+12 -2
View File
@@ -15,6 +15,7 @@ using Android.Runtime;
using Android.Content.PM;
#endif
// ReSharper disable once CheckNamespace
namespace System.Application.UI;
public static partial class MauiProgram
@@ -25,6 +26,10 @@ public static partial class MauiProgram
static string[] GetCommandLineArgs()
{
#if ANDROID
// Android 中 Environment.GetCommandLineArgs 返回 apk 安装目录的 string[1]
return Array.Empty<string>();
#else
try
{
var args = Environment.GetCommandLineArgs();
@@ -34,6 +39,7 @@ public static partial class MauiProgram
{
return Array.Empty<string>();
}
#endif
}
internal static MauiApp CreateMauiApp(string[]? args = null)
@@ -65,8 +71,12 @@ public static partial class MauiProgram
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
})
;
}).ConfigureMauiHandlers(handlers =>
{
#if ANDROID
handlers.AddHandler<Shell, ShellRenderer>();
#endif
});
ConfigureServices(host, level, builder.Services);
};
@@ -1,10 +0,0 @@
{
"profiles": {
"Watt Toolkit (Package)": {
"commandName": "MsixPackage"
},
"Watt Toolkit (Unpackaged)": {
"commandName": "Project"
}
}
}
@@ -8,10 +8,12 @@
<OutputType>Exe</OutputType>
<AssemblyName>Watt Toolkit</AssemblyName>
<RootNamespace>System.Application.UI</RootNamespace>
<AndroidResgenNamespace>System.Application.UI.AndroidResgen</AndroidResgenNamespace>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<ImplicitUsings>enable</ImplicitUsings>
<DefineConstants>MAUI;$(DefineConstants)</DefineConstants>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
<!-- Display name -->
<ApplicationTitle>Watt Toolkit</ApplicationTitle>
@@ -23,8 +25,6 @@
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<ApplicationVersion>1</ApplicationVersion>
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
@@ -69,14 +69,36 @@
<ItemGroup>
<ProjectReference Include="..\Common.CoreLib\Common.CoreLib.csproj" />
<ProjectReference Include="..\Common.Essentials.Maui\Common.Essentials.Maui.csproj" />
<ProjectReference Include="..\ST.Client\ST.Client.csproj" />
<ProjectReference Include="..\ST.Client.CommandLine\ST.Client.CommandLine.csproj" />
<ProjectReference Include="..\ST.Client.Maui\ST.Client.Maui.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy.Yarp\ST.Client.ReverseProxy.Yarp.csproj" />
<ProjectReference Include="..\ST.Client.AppCenter\ST.Client.AppCenter.csproj" />
<ProjectReference Include="..\ST.Client.ResSecrets\ST.Client.ResSecrets.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<ProjectReference Include="..\ST.Client.Desktop.Windows\ST.Client.Windows.csproj" />
<ProjectReference Include="..\ST.Client.JumpList\ST.Client.JumpList.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy.Yarp\ST.Client.ReverseProxy.Yarp.csproj" />
<ProjectReference Include="..\ST.Client.Windows.ScheduledTasks\ST.Client.Windows.ScheduledTasks.csproj" />
<ProjectReference Include="..\ST.Client.Windows.ResSecrets\ST.Client.Windows.ResSecrets.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<ProjectReference Include="..\ST.Client.iOS\ST.Client.iOS.csproj" />
<ProjectReference Include="..\ST.Client.iOS.ResSecrets\ST.Client.iOS.ResSecrets.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<ProjectReference Include="..\ST.Client.Desktop.Mac\ST.Client.Mac.csproj" />
<ProjectReference Include="..\ST.Client.Mac.ResSecrets\ST.Client.Mac.ResSecrets.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<ProjectReference Include="..\ST.Client.Android\ST.Client.Android.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy.Titanium\ST.Client.ReverseProxy.Titanium.csproj" />
<ProjectReference Include="..\ST.Client.Android.ResSecrets\ST.Client.Android.ResSecrets.csproj" />
</ItemGroup>
</Project>
+53 -20
View File
@@ -6,6 +6,7 @@
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net6.0-tizen</TargetFrameworks> -->
<RootNamespace>System.Application</RootNamespace>
<AndroidResgenNamespace>System.Application.AndroidResgen</AndroidResgenNamespace>
<AssemblyName>System.Application.SteamTools.Client.Maui</AssemblyName>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
@@ -14,7 +15,30 @@
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<SupportedOSPlatformVersion>21.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">
<SupportedOSPlatformVersion>6.5</SupportedOSPlatformVersion>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\ST.Client.Desktop.Avalonia\Application\UI\App.OnCreateAppExecuted.HandlerViewModelManager.cs">
<Link>UI\App.OnCreateAppExecuted.HandlerViewModelManager.cs</Link>
</Compile>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
</Compile>
@@ -54,26 +78,6 @@
</Compile>
</ItemGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<SupportedOSPlatformVersion>14.2</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<SupportedOSPlatformVersion>14.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<SupportedOSPlatformVersion>21.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">
<SupportedOSPlatformVersion>6.5</SupportedOSPlatformVersion>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Common.Essentials.Maui\Common.Essentials.Maui.csproj" />
<ProjectReference Include="..\ST.Client\ST.Client.csproj" />
@@ -105,4 +109,33 @@
<MauiAsset Remove="UI\Assets\Raw\AboutAssets.txt" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">
<ProjectReference Include="..\ST.Client.Desktop.Windows\ST.Client.Windows.csproj" />
<ProjectReference Include="..\ST.Client.JumpList\ST.Client.JumpList.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy.Yarp\ST.Client.ReverseProxy.Yarp.csproj" />
<ProjectReference Include="..\ST.Client.Windows.ScheduledTasks\ST.Client.Windows.ScheduledTasks.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">
<ProjectReference Include="..\ST.Client.iOS\ST.Client.iOS.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">
<ProjectReference Include="..\ST.Client.Desktop.Mac\ST.Client.Mac.csproj" />
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">
<ProjectReference Include="..\ST.Client.Android\ST.Client.Android.csproj" />
<ProjectReference Include="..\ST.Client.ReverseProxy.Titanium\ST.Client.ReverseProxy.Titanium.csproj" />
</ItemGroup>
<ItemGroup>
<MauiXaml Update="UI\Views\Controls\FlyoutFooter.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="UI\Views\Controls\FlyoutHeader.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
</ItemGroup>
</Project>
@@ -3,48 +3,47 @@
using System.Application.UI;
using System.Application.UI.ViewModels;
namespace System.Application.Services.Implementation
namespace System.Application.Services.Implementation;
/// <inheritdoc cref="IWindowManager"/>
internal sealed class MauiWindowManagerImpl : IWindowManagerImpl
{
/// <inheritdoc cref="IWindowManager"/>
internal sealed class MauiWindowManagerImpl : IWindowManagerImpl
readonly IMauiApplication app;
public MauiWindowManagerImpl(IMauiApplication app)
{
readonly IMauiApplication app;
this.app = app;
}
public MauiWindowManagerImpl(IMauiApplication app)
{
this.app = app;
}
Type? IWindowManagerImpl.WindowType => typeof(Page);
Type? IWindowManagerImpl.WindowType => typeof(Page);
public Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
throw new NotImplementedException();
}
public Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
throw new NotImplementedException();
}
public Task Show(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
throw new NotImplementedException();
}
public Task Show(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
throw new NotImplementedException();
}
public Task Show(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
throw new NotImplementedException();
}
public Task Show(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = false, bool isParent = true)
{
throw new NotImplementedException();
}
public Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
throw new NotImplementedException();
}
public Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true, bool isParent = true) where TWindowViewModel : WindowViewModel, new()
{
throw new NotImplementedException();
}
public Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
throw new NotImplementedException();
}
public Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
throw new NotImplementedException();
}
public Task ShowDialog(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
throw new NotImplementedException();
}
public Task ShowDialog(CustomWindow customWindow, WindowViewModel? viewModel = null, string title = "", ResizeMode resizeMode = ResizeMode.NoResize, bool isDialog = true)
{
throw new NotImplementedException();
}
}
+14 -13
View File
@@ -1,14 +1,15 @@
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:System.Application.UI"
xmlns:styles="clr-namespace:System.Application.UI.Styles"
x:Class="System.Application.UI.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary Source="Styles\ThemeLight.xaml" />
<ResourceDictionary Source="Styles\Controls.xaml" />
<styles:DrawingSvg x:Key="DrawingSvg" />
</ResourceDictionary>
</Application.Resources>
<?xml version="1.0" encoding="UTF-8" ?>
<Application
x:Class="System.Application.UI.App"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:System.Application.UI"
xmlns:styles="clr-namespace:System.Application.UI.Styles">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary Source="Styles\ThemeLight.xaml" />
<ResourceDictionary Source="Styles\Controls.xaml" />
<styles:DrawingSvg x:Key="DrawingSvg" />
</ResourceDictionary>
</Application.Resources>
</Application>
+3 -29
View File
@@ -1,8 +1,8 @@
using System.Application.Mvvm;
using System.Application.Services;
using System.Application.Settings;
using System.Application.UI.Styles;
using System.Application.UI.ViewModels;
using System.Application.UI.Styles;
using System.Reactive.Disposables;
using System.Windows.Input;
using EAppTheme = System.Application.Models.AppTheme;
@@ -43,37 +43,11 @@ public partial class App : MauiApplication, IDisposableHolder, IApplication, IMa
{
const bool isTrace =
#if StartWatchTrace
true;
true;
#else
false;
#endif
ProgramHost.OnCreateAppExecuted(handlerViewModelManager: vmService =>
{
switch (vmService.MainWindow)
{
case AchievementWindowViewModel:
ProgramHost.IsMinimize = false;
//MainWindow = new AchievementWindow();
break;
default:
#region 主窗口启动时加载的资源
#if !UI_DEMO
compositeDisposable.Add(SettingsHost.Save);
compositeDisposable.Add(ProxyService.Current.Dispose);
compositeDisposable.Add(SteamConnectService.Current.Dispose);
compositeDisposable.Add(ASFService.Current.StopASF);
#pragma warning disable CA1416 // 验证平台兼容性
if (GeneralSettings.IsStartupAppMinimized.Value)
ProgramHost.IsMinimize = true;
#pragma warning restore CA1416 // 验证平台兼容性
#endif
#endregion
//MainWindow = new MainWindow();
break;
}
MainPage = new AppShell((MainWindowViewModel)vmService.MainWindow);
}, isTrace: isTrace);
ProgramHost.OnCreateAppExecuted(handlerViewModelManager: HandlerViewModelManager, isTrace: isTrace);
}
public Window GetActiveWindow()
+7 -25
View File
@@ -3,35 +3,17 @@
x:Class="System.Application.UI.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
xmlns:local="clr-namespace:System.Application.UI.Views"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client"
xmlns:vm="clr-namespace:System.Application.UI.ViewModels;assembly=System.Application.SteamTools.Client"
Title="{Binding Title}"
x:DataType="vm:MainWindowViewModel">
<Shell.FlyoutHeaderTemplate>
<DataTemplate>
<StackLayout Padding="24,24,24,22" Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnFlyoutHeaderTapped" />
</StackLayout.GestureRecognizers>
<Image Source="avatar.jpg"
HeightRequest="64"
WidthRequest="64">
<Image.Clip>
<EllipseGeometry Center="32,32"
RadiusX="32"
RadiusY="32" />
</Image.Clip>
</Image>
<Label Margin="16,0,0,0"
FontSize="16"
LineBreakMode="TailTruncation"
MaxLines="2"
Text="{x:Static resx:AppResources.User_UnLogin}"
TextColor="{DynamicResource ShellTitleColor}"
VerticalTextAlignment="Center" />
</StackLayout>
</DataTemplate>
</Shell.FlyoutHeaderTemplate>
<Shell.FlyoutHeader>
<controls:FlyoutHeader />
</Shell.FlyoutHeader>
<Shell.FlyoutFooter>
<controls:FlyoutFooter />
</Shell.FlyoutFooter>
</Shell>
+58 -190
View File
@@ -9,12 +9,9 @@ namespace System.Application.UI;
public partial class AppShell : Shell, IViewFor<MainWindowViewModel>
{
/// <summary>
/// 是否使用底部导航菜单
/// </summary>
internal static bool IsUseBottomNav { private get; set; }
//readonly IPlatformPageRouteService? pageRouteService = IPlatformPageRouteService.Instance;
readonly IPlatformPageRouteService? pageRouteService = IPlatformPageRouteService.Instance;
#region VM
MainWindowViewModel viewModel;
@@ -36,6 +33,8 @@ public partial class AppShell : Shell, IViewFor<MainWindowViewModel>
set => BindingContext = value;
}
#endregion
public AppShell(MainWindowViewModel viewModel)
{
BindingContext = this.viewModel = viewModel;
@@ -49,194 +48,35 @@ public partial class AppShell : Shell, IViewFor<MainWindowViewModel>
// });
//#endif
if (!IsUseBottomNav)
#region InitTabItems
FlyoutItem flyoutItem = new()
{
#region Flyout
var topTabs = IApplication.IsDesktopPlatform ? Array.Empty<TabItemId>() : new[] { TabItemId.LocalAuth, TabItemId.ArchiSteamFarmPlus };
InitTabItems(viewModel, topTabs);
AddPage(MyPageViewModel.Instance, isVisible: false);
#if DEBUG
AddPage(new LoginOrRegisterWindowViewModel());
#endif
#endregion
}
else
{
#region BottomNav
FlyoutBehavior = FlyoutBehavior.Disabled;
InitButtomTabItems(viewModel);
AddPage(SettingsPageViewModel.Instance, isVisible: false);
AddPage(AboutPageViewModel.Instance, isVisible: false);
#endregion
}
}
#region Flyout(左侧导航菜单)
void InitTabItems(MainWindowViewModel mainWindow, params TabItemId[] topTabs)
{
IEnumerable<TabItemId> topTabs_ = topTabs;
InitTabItems(mainWindow, topTabs_);
}
void InitTabItems(MainWindowViewModel mainWindow, IEnumerable<TabItemId>? topTabs = null)
{
var tabItems = mainWindow.TabItems.Where(x => x.Id != TabItemId.GameList);
if (topTabs.Any_Nullable())
{
tabItems = tabItems.Where(x => topTabs.Contains(x.Id)).Concat(tabItems.Where(x => !topTabs.Contains(x.Id)));
}
foreach (var item in tabItems)
{
InitTabItem(item);
}
void InitTabItem(TabItemViewModel tab)
{
if (pageRouteService?.IsUseNativePage(tab.Id) ?? false)
{
var tab_item = new MenuItem
{
IconImageSource = tab.IconKey,
BindingContext = tab,
};
tab_item.Clicked += (_, _) => pageRouteService!.GoToNativePage(tab.Id);
tab_item.SetBinding(MenuItem.TextProperty, nameof(tab.Name), BindingMode.OneWay);
Items.Add(tab_item);
}
else
{
var tab_item = new FlyoutItem
{
Icon = tab.IconKey,
BindingContext = tab,
};
tab_item.SetBinding(BaseShellItem.TitleProperty, nameof(tab.Name), BindingMode.OneWay);
tab_item.Items.Add(new ShellContent
{
Route = tab.IconKey!.TrimEnd("ViewModel"),
ContentTemplate = new DataTemplate(GetPageType(tab)),
});
Items.Add(tab_item);
}
}
}
void AddPage(ViewModelBase vm, bool isVisible = true)
{
var data = GetShellItemData(vm);
if (data == default) return;
var tab_item = new FlyoutItem
{
BindingContext = vm,
FlyoutItemIsVisible = isVisible,
FlyoutDisplayOptions = FlyoutDisplayOptions.AsMultipleItems,
};
tab_item.SetBinding(BaseShellItem.TitleProperty, data.bindingPathName, BindingMode.OneWay);
var pageType = GetPageType(vm);
var content = new ShellContent
AddPage(viewModel.LocalAuthPage);
AddPage(viewModel.ASFPage);
if (!OperatingSystem.IsIOS())
AddPage(viewModel.CommunityProxyPage);
AddPage(MyPageViewModel.Instance, flyoutItemIsVisible: false);
Items.Add(flyoutItem);
AddPage(SettingsPageViewModel.Instance, isSecondary: false);
AddPage(AboutPageViewModel.Instance, isSecondary: false);
void AddPage(ViewModelBase vm, bool flyoutItemIsVisible = true, bool isSecondary = true)
{
ContentTemplate = new DataTemplate(pageType),
};
if (data.route != null) content.Route = pageType.Name;
tab_item.Items.Add(content);
Items.Add(tab_item);
var shellContent = CreateShellContent(vm);
if (shellContent == null) return;
shellContent.FlyoutItemIsVisible = flyoutItemIsVisible;
if (isSecondary) flyoutItem.Items.Add(shellContent);
else Items.Add(shellContent);
}
#endregion
}
#endregion
#region BottomNav(底部导航菜单)
void InitButtomTabItems(MainWindowViewModel mainWindow)
{
var tabItems = new ViewModelBase[] {
mainWindow.LocalAuthPage,
mainWindow.ASFPage,
MyPageViewModel.Instance,
};
TabBar tabBar = new();
foreach (var tab in tabItems)
{
var data = GetShellItemData(tab);
if (data == default) continue;
var tab_item = new Tab
{
BindingContext = tab,
Icon = data.icon,
};
tab_item.SetBinding(BaseShellItem.TitleProperty, data.bindingPathName, BindingMode.OneWay);
var content = new ShellContent
{
ContentTemplate = new DataTemplate(GetPageType(tab)),
};
if (data.route != null) content.Route = data.route;
tab_item.Items.Add(content);
tabBar.Items.Add(tab_item);
}
Items.Add(tabBar);
}
#endregion
static (string icon, string bindingPathName, string route) GetShellItemData(ViewModelBase vm, bool rSubscribe = true)
{
string? icon = null;
string? bindingPathName = null;
string? route = null;
if (vm is TabItemViewModel tabItemVM)
{
if (tabItemVM.IconKey == null) return default;
if (IsUseBottomNav)
{
if (tabItemVM is LocalAuthPageViewModel)
{
icon = "baseline_verified_user_black_24";
}
else if (tabItemVM is ArchiSteamFarmPlusPageViewModel)
{
icon = "icon_asf_24";
}
else
{
return default;
}
}
else
{
icon = tabItemVM.IconKey;
}
bindingPathName = nameof(tabItemVM.Name);
route = tabItemVM.IconKey.TrimEnd("ViewModel");
if (tabItemVM is SettingsPageViewModel || tabItemVM is AboutPageViewModel)
{
route = $"MyPage/{route}";
//route = null;
}
rSubscribe = false;
}
else if (vm is PageViewModel pageVM)
{
bindingPathName = nameof(pageVM.Title);
route = pageVM.GetType().Name.TrimEnd("ViewModel");
if (pageVM is MyPageViewModel)
{
icon = "baseline_person_black_24";
}
}
if (icon == null || bindingPathName == null || route == null) return default;
if (rSubscribe)
{
R.Subscribe(() =>
{
vm.RaisePropertyChanged(nameof(PageViewModel.Title));
}).AddTo(vm);
}
return (icon, bindingPathName, route);
}
#region TabItems
static Type GetPageType(ViewModelBase vm)
{
@@ -268,11 +108,39 @@ public partial class AppShell : Shell, IViewFor<MainWindowViewModel>
return typeof(UnderConstructionPage);
}
void OnFlyoutHeaderTapped(object? sender, EventArgs e)
static ShellContent? CreateShellContent(ViewModelBase vm)
{
Current.FlyoutIsPresented = false;
var pageType = GetPageType(vm);
var content = new ShellContent
{
ContentTemplate = new DataTemplate(pageType),
BindingContext = vm,
};
string? bindingPathName;
if (vm is TabItemViewModel tabVM)
{
content.Icon = tabVM.IconKey;
content.Route = tabVM.Id.ToString();
bindingPathName = nameof(TabItemViewModel.Name);
}
else if (vm is PageViewModel)
{
bindingPathName = nameof(PageViewModel.Title);
content.Icon = "baseline_person_black_24";
}
else
{
bindingPathName = default;
}
if (bindingPathName != default)
{
content.SetBinding(BaseShellItem.TitleProperty, bindingPathName, BindingMode.OneWay);
}
return content;
}
#endregion
public static Task PopAsync()
{
// https://docs.microsoft.com/zh-cn/xamarin/xamarin-forms/app-fundamentals/shell/navigation#backwards-navigation
@@ -0,0 +1,16 @@
#if ANDROID
using AndroidX.Fragment.App;
using AView = Android.Views.View;
using BaseShellRenderer = Microsoft.Maui.Controls.Handlers.Compatibility.ShellRenderer;
namespace System.Application.UI;
public sealed partial class ShellRenderer : BaseShellRenderer
{
protected override void SwitchFragment(FragmentManager manager, AView targetView, ShellItem newItem, bool animate)
{
// 禁用 Android 上的切换 Page 时动画
base.SwitchFragment(manager, targetView, newItem, false);
}
}
#endif
+353 -352
View File
@@ -1,383 +1,384 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="System.Application.UI.Styles.Controls">
<ResourceDictionary
x:Class="System.Application.UI.Styles.Controls"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Style TargetType="ActivityIndicator">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="ActivityIndicator">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="IndicatorView">
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}"/>
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}"/>
</Style>
<Style TargetType="IndicatorView">
<Setter Property="IndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="SelectedIndicatorColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray100}}" />
</Style>
<Style TargetType="Border">
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="StrokeShape" Value="Rectangle"/>
<Setter Property="StrokeThickness" Value="1"/>
</Style>
<Style TargetType="Border">
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="StrokeShape" Value="Rectangle" />
<Setter Property="StrokeThickness" Value="1" />
</Style>
<Style TargetType="BoxView">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="BoxView">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="CornerRadius" Value="8"/>
<Setter Property="Padding" Value="14,10"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Button">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Primary}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="Padding" Value="14,10" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="CheckBox">
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="DatePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="DatePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Editor">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Editor">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Frame">
<Setter Property="HasShadow" Value="False" />
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="CornerRadius" Value="8" />
</Style>
<Style TargetType="Frame">
<Setter Property="HasShadow" Value="False" />
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="CornerRadius" Value="8" />
</Style>
<Style TargetType="ImageButton">
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderColor" Value="Transparent"/>
<Setter Property="BorderWidth" Value="0"/>
<Setter Property="CornerRadius" Value="0"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Opacity" Value="0.5" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ImageButton">
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderColor" Value="Transparent" />
<Setter Property="BorderWidth" Value="0" />
<Setter Property="CornerRadius" Value="0" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="Opacity" Value="0.5" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ListView">
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="ListView">
<Setter Property="SeparatorColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray500}}" />
<Setter Property="RefreshControlColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="Picker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Picker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="TitleColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ProgressBar">
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="ProgressBar">
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="ProgressColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Background" Value="Transparent" />
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Black}, Dark={StaticResource White}}" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="RefreshView">
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="RefreshView">
<Setter Property="RefreshColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="SearchBar">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SearchBar">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="CancelButtonColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SearchHandler">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SearchHandler">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="PlaceholderColor" Value="{StaticResource Gray500}" />
<Setter Property="BackgroundColor" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Shadow">
<Setter Property="Radius" Value="15" />
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Offset" Value="10,10" />
</Style>
<Style TargetType="Shadow">
<Setter Property="Radius" Value="15" />
<Setter Property="Opacity" Value="0.5" />
<Setter Property="Brush" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Offset" Value="10,10" />
</Style>
<Style TargetType="Slider">
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Slider">
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="MinimumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="MaximumTrackColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="SwipeItem">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style TargetType="SwipeItem">
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style TargetType="Switch">
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="ThumbColor" Value="{StaticResource White}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Off">
<VisualState.Setters>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Switch">
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="ThumbColor" Value="{StaticResource White}" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Property="OnColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Gray200}}" />
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Off">
<VisualState.Setters>
<Setter Property="ThumbColor" Value="{AppThemeBinding Light={StaticResource Gray400}, Dark={StaticResource Gray500}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="TimePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="FontFamily" Value="OpenSansRegular"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="TimePicker">
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource White}}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="FontFamily" Value="OpenSansRegular" />
<Setter Property="FontSize" Value="14" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Gray300}, Dark={StaticResource Gray600}}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Page" ApplyToDerivedTypes="True">
<Setter Property="Padding" Value="0"/>
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style ApplyToDerivedTypes="True" TargetType="Page">
<Setter Property="Padding" Value="0" />
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
</Style>
<Style TargetType="Shell" ApplyToDerivedTypes="True">
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}"></Setter>
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
<Setter Property="Shell.NavBarHasShadow" Value="False" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style ApplyToDerivedTypes="True" TargetType="Shell">
<Setter Property="Shell.BackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.ForegroundColor" Value="{OnPlatform WinUI={StaticResource Primary}, Default={StaticResource White}}" />
<Setter Property="Shell.TitleColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource White}}" />
<Setter Property="Shell.DisabledColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="Shell.UnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray200}}" />
<Setter Property="Shell.NavBarHasShadow" Value="False" />
<Setter Property="Shell.TabBarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Black}}" />
<Setter Property="Shell.TabBarForegroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarTitleColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="Shell.TabBarUnselectedColor" Value="{AppThemeBinding Light={StaticResource Gray900}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
<Setter Property="IconColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource White}}" />
</Style>
<Style TargetType="TabbedPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style>
<Style TargetType="TabbedPage">
<Setter Property="BarBackgroundColor" Value="{AppThemeBinding Light={StaticResource White}, Dark={StaticResource Gray950}}" />
<Setter Property="BarTextColor" Value="{AppThemeBinding Light={StaticResource Primary}, Dark={StaticResource White}}" />
<Setter Property="UnselectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray200}, Dark={StaticResource Gray950}}" />
<Setter Property="SelectedTabColor" Value="{AppThemeBinding Light={StaticResource Gray950}, Dark={StaticResource Gray200}}" />
</Style>
</ResourceDictionary>
+52 -51
View File
@@ -1,55 +1,56 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="System.Application.UI.Styles.ThemeLight">
<Color x:Key="Primary">#2196F3</Color>
<!-- 背景颜色 -->
<Color x:Key="GreyWindowBackground">#F9F9F9</Color>
<!-- 主要文本 -->
<Color x:Key="TextPrimary">#333333</Color>
<!-- 次要文本 -->
<Color x:Key="TextSecondary">#666666</Color>
<!-- 点击文字颜色 -->
<Color x:Key="TextLink">#007ffc</Color>
<Color x:Key="ShellBackgroundColor">White</Color>
<Color x:Key="ShellTitleColor">#222222</Color>
<!--<Color x:Key="ShellForegroundColor">#767676</Color>-->
<ResourceDictionary
x:Class="System.Application.UI.Styles.ThemeLight"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Color x:Key="Primary">#2196F3</Color>
<!-- 背景颜色 -->
<Color x:Key="GreyWindowBackground">#F9F9F9</Color>
<!-- 主要文本 -->
<Color x:Key="TextPrimary">#333333</Color>
<!-- 次要文本 -->
<Color x:Key="TextSecondary">#666666</Color>
<!-- 点击文字颜色 -->
<Color x:Key="TextLink">#007ffc</Color>
<Color x:Key="ShellBackgroundColor">White</Color>
<Color x:Key="ShellTitleColor">#222222</Color>
<!--<Color x:Key="ShellForegroundColor">#767676</Color>-->
<!-- MAUI 默认模板资源 -->
<!--<Color x:Key="Primary">#512BD4</Color>-->
<Color x:Key="Secondary">#DFD8F7</Color>
<Color x:Key="Tertiary">#2B0B98</Color>
<Color x:Key="White">White</Color>
<Color x:Key="Black">Black</Color>
<Color x:Key="Gray100">#E1E1E1</Color>
<Color x:Key="Gray200">#C8C8C8</Color>
<Color x:Key="Gray300">#ACACAC</Color>
<Color x:Key="Gray400">#919191</Color>
<Color x:Key="Gray500">#6E6E6E</Color>
<Color x:Key="Gray600">#404040</Color>
<Color x:Key="Gray900">#212121</Color>
<Color x:Key="Gray950">#141414</Color>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}"/>
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}"/>
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}"/>
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}"/>
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}"/>
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}"/>
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}"/>
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}"/>
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}"/>
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}"/>
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}"/>
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}"/>
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}"/>
<!-- MAUI 默认模板资源 -->
<!--<Color x:Key="Primary">#512BD4</Color>-->
<Color x:Key="Secondary">#DFD8F7</Color>
<Color x:Key="Tertiary">#2B0B98</Color>
<Color x:Key="White">White</Color>
<Color x:Key="Black">Black</Color>
<Color x:Key="Gray100">#E1E1E1</Color>
<Color x:Key="Gray200">#C8C8C8</Color>
<Color x:Key="Gray300">#ACACAC</Color>
<Color x:Key="Gray400">#919191</Color>
<Color x:Key="Gray500">#6E6E6E</Color>
<Color x:Key="Gray600">#404040</Color>
<Color x:Key="Gray900">#212121</Color>
<Color x:Key="Gray950">#141414</Color>
<SolidColorBrush x:Key="PrimaryBrush" Color="{StaticResource Primary}" />
<SolidColorBrush x:Key="SecondaryBrush" Color="{StaticResource Secondary}" />
<SolidColorBrush x:Key="TertiaryBrush" Color="{StaticResource Tertiary}" />
<SolidColorBrush x:Key="WhiteBrush" Color="{StaticResource White}" />
<SolidColorBrush x:Key="BlackBrush" Color="{StaticResource Black}" />
<SolidColorBrush x:Key="Gray100Brush" Color="{StaticResource Gray100}" />
<SolidColorBrush x:Key="Gray200Brush" Color="{StaticResource Gray200}" />
<SolidColorBrush x:Key="Gray300Brush" Color="{StaticResource Gray300}" />
<SolidColorBrush x:Key="Gray400Brush" Color="{StaticResource Gray400}" />
<SolidColorBrush x:Key="Gray500Brush" Color="{StaticResource Gray500}" />
<SolidColorBrush x:Key="Gray600Brush" Color="{StaticResource Gray600}" />
<SolidColorBrush x:Key="Gray900Brush" Color="{StaticResource Gray900}" />
<SolidColorBrush x:Key="Gray950Brush" Color="{StaticResource Gray950}" />
<Color x:Key="Yellow100Accent">#F7B548</Color>
<Color x:Key="Yellow200Accent">#FFD590</Color>
<Color x:Key="Yellow300Accent">#FFE5B9</Color>
<Color x:Key="Cyan100Accent">#28C2D1</Color>
<Color x:Key="Cyan200Accent">#7BDDEF</Color>
<Color x:Key="Cyan300Accent">#C3F2F4</Color>
<Color x:Key="Blue100Accent">#3E8EED</Color>
<Color x:Key="Blue200Accent">#72ACF1</Color>
<Color x:Key="Blue300Accent">#A7CBF6</Color>
<Color x:Key="Yellow100Accent">#F7B548</Color>
<Color x:Key="Yellow200Accent">#FFD590</Color>
<Color x:Key="Yellow300Accent">#FFE5B9</Color>
<Color x:Key="Cyan100Accent">#28C2D1</Color>
<Color x:Key="Cyan200Accent">#7BDDEF</Color>
<Color x:Key="Cyan300Accent">#C3F2F4</Color>
<Color x:Key="Blue100Accent">#3E8EED</Color>
<Color x:Key="Blue200Accent">#72ACF1</Color>
<Color x:Key="Blue300Accent">#A7CBF6</Color>
</ResourceDictionary>
@@ -0,0 +1,12 @@
<ContentView
x:Class="System.Application.UI.Views.Controls.FlyoutFooter"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls">
<Label
Padding="8"
FontSize="12"
HorizontalOptions="Center"
Text="{Binding Source={x:Static controls:FlyoutFooter.FooterText}, Mode=OneTime}"
TextColor="{DynamicResource ShellTitleColor}" />
</ContentView>
@@ -0,0 +1,11 @@
namespace System.Application.UI.Views.Controls;
public partial class FlyoutFooter : ContentView
{
public FlyoutFooter()
{
InitializeComponent();
}
public static string FooterText { get; } = $"Powered by .NET {Environment.Version}";
}
@@ -0,0 +1,31 @@
<ContentView
x:Class="System.Application.UI.Views.Controls.FlyoutHeader"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:System.Application.UI.Views.Controls"
xmlns:resx="clr-namespace:System.Application.UI.Resx;assembly=System.Application.SteamTools.Client">
<StackLayout Padding="24,24,24,22" Orientation="Horizontal">
<StackLayout.GestureRecognizers>
<TapGestureRecognizer Tapped="OnFlyoutHeaderTapped" />
</StackLayout.GestureRecognizers>
<Image
HeightRequest="64"
Source="avatar.jpg"
WidthRequest="64">
<Image.Clip>
<EllipseGeometry
Center="32,32"
RadiusX="32"
RadiusY="32" />
</Image.Clip>
</Image>
<Label
Margin="16,0,0,0"
FontSize="16"
LineBreakMode="TailTruncation"
MaxLines="2"
Text="{x:Static resx:AppResources.User_UnLogin}"
TextColor="{DynamicResource ShellTitleColor}"
VerticalTextAlignment="Center" />
</StackLayout>
</ContentView>
@@ -0,0 +1,14 @@
namespace System.Application.UI.Views.Controls;
public partial class FlyoutHeader : ContentView
{
public FlyoutHeader()
{
this.InitializeComponent();
}
void OnFlyoutHeaderTapped(object? sender, EventArgs e)
{
Shell.Current.FlyoutIsPresented = false;
}
}
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220814" android:versionName="2.8.3" package="net.steampp.app" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="20220831" android:versionName="2.8.4" package="net.steampp.app" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<application android:fullBackupContent="@xml/auto_backup_rules"></application>
<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
+8 -8
View File
@@ -4,14 +4,14 @@
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:styles="clr-namespace:System.Application.UI.Styles">
<!--
<!--
Define global resources and styles here, that apply to all pages in your app.
-->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary Source="Styles\ThemeLight.xaml" />
<styles:DrawingSvg x:Key="DrawingSvg" />
<!--<Color x:Key="Primary">#2196F3</Color>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary Source="Styles\ThemeLight.xaml" />
<styles:DrawingSvg x:Key="DrawingSvg" />
<!--<Color x:Key="Primary">#2196F3</Color>
<Style TargetType="Button">
<Setter Property="TextColor" Value="White"></Setter>
<Setter Property="VisualStateManager.VisualStateGroups">
@@ -31,6 +31,6 @@
</VisualStateGroupList>
</Setter>
</Style>-->
</ResourceDictionary>
</Application.Resources>
</ResourceDictionary>
</Application.Resources>
</Application>
@@ -3,16 +3,16 @@
x:Class="System.Application.UI.Styles.ThemeLight"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<Color x:Key="Primary">#2196F3</Color>
<!-- 背景颜色 -->
<Color x:Key="GreyWindowBackground">#F9F9F9</Color>
<!-- 主要文本 -->
<Color x:Key="TextPrimary">#333333</Color>
<!-- 次要文本 -->
<Color x:Key="TextSecondary">#666666</Color>
<!-- 点击文字颜色 -->
<Color x:Key="TextLink">#007ffc</Color>
<Color x:Key="ShellBackgroundColor">White</Color>
<Color x:Key="ShellTitleColor">#222222</Color>
<!--<Color x:Key="ShellForegroundColor">#767676</Color>-->
<Color x:Key="Primary">#2196F3</Color>
<!-- 背景颜色 -->
<Color x:Key="GreyWindowBackground">#F9F9F9</Color>
<!-- 主要文本 -->
<Color x:Key="TextPrimary">#333333</Color>
<!-- 次要文本 -->
<Color x:Key="TextSecondary">#666666</Color>
<!-- 点击文字颜色 -->
<Color x:Key="TextLink">#007ffc</Color>
<Color x:Key="ShellBackgroundColor">White</Color>
<Color x:Key="ShellTitleColor">#222222</Color>
<!--<Color x:Key="ShellForegroundColor">#767676</Color>-->
</ResourceDictionary>
+12 -3
View File
@@ -1,13 +1,17 @@
<Project Sdk="MSBuild.Sdk.Extras">
<PropertyGroup>
<TargetFrameworks>Xamarin.iOS10</TargetFrameworks>
<TargetFrameworks>Xamarin.iOS10;net6.0-ios</TargetFrameworks>
<RootNamespace>System.Application</RootNamespace>
<AssemblyName>System.Application.SteamTools.Client.iOS</AssemblyName>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-ios'))">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-maccatalyst'))">14.0</SupportedOSPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition=" !($(TargetFramework.StartsWith('Xamarin.iOS'))) ">
<UseMaui>true</UseMaui>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Common.CoreLib\Properties\AssemblyInfo.cs">
<Link>Properties\AssemblyInfo.cs</Link>
@@ -24,11 +28,16 @@
<Compile Include="..\ST.Client.Android\UI\Views.Controls\*.shared.cs">
<LinkBase>UI\Views.Controls</LinkBase>
</Compile>
<Compile Include="..\ST.Client.Desktop\ServiceCollectionExtensions.AddGeneralLogging.cs" />
<Compile Include="..\ST.Client.Android\Services\Implementation\DnsAnalysisServiceImpl.cs">
<LinkBase>Services\Implementation</LinkBase>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj" />
<ProjectReference Condition=" ($(TargetFramework.StartsWith('Xamarin.iOS'))) " Include="..\Common.Essentials.Xamarin\Common.Essentials.Xamarin.csproj" />
<ProjectReference Condition=" !($(TargetFramework.StartsWith('Xamarin.iOS'))) " Include="..\Common.Essentials.Maui\Common.Essentials.Maui.csproj" />
<ProjectReference Include="..\ST.Client.AppCenter\ST.Client.AppCenter.csproj" />
<ProjectReference Include="..\ST.Client\ST.Client.csproj" />
<ProjectReference Include="..\ST.Client.iOS.ResSecrets\ST.Client.iOS.ResSecrets.csproj" />
@@ -36,7 +45,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Toast.iOS" Aliases="NUGET_PACKAGE_TOAST_IOS" />
<!--<PackageReference Include="Toast.iOS" Aliases="NUGET_PACKAGE_TOAST_IOS" />-->
</ItemGroup>
<ItemGroup>
@@ -18,7 +18,7 @@ namespace Microsoft.Extensions.DependencyInjection
services.AddSingleton<IPlatformService>(s => s.GetRequiredService<ApplePlatformServiceImpl>());
//services.AddPlatformNotificationService();
services.TryAddAppleClientHttpPlatformHelperService();
PlatformToastImpl.TryAddToast(services);
//PlatformToastImpl.TryAddToast(services);
//if (options.HasGUI)
//{
// services.AddSingleton<IBiometricService, PlatformBiometricServiceImpl>();
@@ -1,4 +1,8 @@
#if XAMARINIOS
using XEPlatform = Xamarin.Essentials.Platform;
#else
using XEPlatform = Microsoft.Maui.ApplicationModel.Platform;
#endif
namespace System.Application.Services.Implementation
{
@@ -1,36 +1,36 @@
extern alias NUGET_PACKAGE_TOAST_IOS;
//extern alias NUGET_PACKAGE_TOAST_IOS;
using Microsoft.Extensions.DependencyInjection;
using System.Threading.Tasks;
using iOSToast = NUGET_PACKAGE_TOAST_IOS::GlobalToast.Toast;
//using Microsoft.Extensions.DependencyInjection;
//using System.Threading.Tasks;
//using iOSToast = NUGET_PACKAGE_TOAST_IOS::GlobalToast.Toast;
// TODO Use CommunityToolkit.Maui.Core.Views.PlatformToast
// https://github.com/CommunityToolkit/Maui/blob/main/src/CommunityToolkit.Maui/Alerts/Toast/Toast.macios.cs
// https://github.com/CommunityToolkit/Maui/blob/main/src/CommunityToolkit.Maui.Core/Views/Toast/PlatformToast.macios.cs
//// TODO Use CommunityToolkit.Maui.Core.Views.PlatformToast
//// https://github.com/CommunityToolkit/Maui/blob/main/src/CommunityToolkit.Maui/Alerts/Toast/Toast.macios.cs
//// https://github.com/CommunityToolkit/Maui/blob/main/src/CommunityToolkit.Maui.Core/Views/Toast/PlatformToast.macios.cs
namespace System.Application.Services.Implementation
{
/// <summary>
/// https://github.com/andrius-k/Toast
/// </summary>
internal sealed class PlatformToastImpl : ToastBaseImpl
{
public PlatformToastImpl(IToastIntercept intercept) : base(intercept)
{
}
//namespace System.Application.Services.Implementation
//{
// /// <summary>
// /// https://github.com/andrius-k/Toast
// /// </summary>
// internal sealed class PlatformToastImpl : ToastBaseImpl
// {
// public PlatformToastImpl(IToastIntercept intercept) : base(intercept)
// {
// }
protected override async void PlatformShow(string text, int duration)
{
var toast = iOSToast.ShowToast(text)
.SetDuration(duration)
.SetShowShadow(false)
.SetAutoDismiss(true)
.Show();
await Task.Delay(duration);
toast.Dismiss();
}
// protected override async void PlatformShow(string text, int duration)
// {
// var toast = iOSToast.ShowToast(text)
// .SetDuration(duration)
// .SetShowShadow(false)
// .SetAutoDismiss(true)
// .Show();
// await Task.Delay(duration);
// toast.Dismiss();
// }
internal static IServiceCollection TryAddToast(IServiceCollection services)
=> TryAddToast<PlatformToastImpl>(services);
}
}
// internal static IServiceCollection TryAddToast(IServiceCollection services)
// => TryAddToast<PlatformToastImpl>(services);
// }
//}
@@ -1,4 +1,4 @@
namespace System.Application.Models
namespace System.Application.Models
{
/// <summary>
/// 文本阅读器提供商
+6 -3
View File
@@ -85,10 +85,13 @@ namespace System.Application.Services
reverseProxyService.ProxyIp = IPAddress2.TryParse(ProxySettings.SystemProxyIp.Value, out var ip) ? ip : IPAddress.Any;
// macOS\Linux 上目前因权限问题仅支持 0.0.0.0(IPAddress.Any)
if ((OperatingSystem2.IsMacOS() || OperatingSystem2.IsLinux()) && IPAddress.IsLoopback(IReverseProxyService.Instance.ProxyIp))
if (!OperatingSystem2.IsAndroid())
{
reverseProxyService.ProxyIp = IPAddress.Any;
// macOS\Linux 上目前因权限问题仅支持 0.0.0.0(IPAddress.Any)
if ((OperatingSystem2.IsMacOS() || OperatingSystem2.IsLinux()) && IPAddress.IsLoopback(IReverseProxyService.Instance.ProxyIp))
{
reverseProxyService.ProxyIp = IPAddress.Any;
}
}
// Android VPN 模式使用 tun2socks
+4 -4
View File
@@ -10,10 +10,10 @@ public enum SmsCodeType
/// </summary>
Register = 200,
///// <summary>
///// [通过手机号码重设密码]找回密码
///// </summary>
//ForgotPassword = 201,
/// <summary>
/// [通过手机号码重设密码]找回密码
/// </summary>
ForgotPassword = 201,
/// <summary>
/// [换新手机号要旧手机号短信验证]绑定新手机号
+15 -16
View File
@@ -40,20 +40,15 @@ using System.Windows;
using Microsoft.Extensions.Http;
using Xamarin.Android.Net;
using Program = System.Application.UI.MainApplication;
using PlatformApplication = System.Application.UI.MainApplication;
#elif __IOS__
using Program = System.Application.UI.AppDelegate;
#elif !__MOBILE__
#endif
using ReactiveUI;
using System.Reactive;
#endif
#if !MAUI && !__MOBILE__
using AvaloniaApplication = Avalonia.Application;
#endif
#if __ANDROID__ && !MAUI
#else
using PlatformApplication = System.Application.UI.App;
#endif
#if ANDROID || IOS || __ANDROID__
#if MAUI
using EssentialsFileSystem = Microsoft.Maui.Storage.FileSystem;
@@ -75,7 +70,13 @@ using CreateHttpHandlerArgs = System.ValueTuple<
System.Net.CookieContainer,
System.Net.IWebProxy?,
int>;
#if MAUI || AVALONIA
using PlatformApplication = System.Application.UI.App;
#elif ANDROID || __ANDROID__
using PlatformApplication = System.Application.UI.MainApplication;
#endif
// ReSharper disable once CheckNamespace
namespace System.Application.UI
{
partial class
@@ -242,7 +243,7 @@ namespace System.Application.UI
#if MAUI || __MOBILE__ || ANDROID || IOS || __ANDROID__
services.TryAddEssentials();
#endif
#if __MOBILE__ || ANDROID || IOS || __ANDROID__
#if !MACCATALYST && (__MOBILE__ || ANDROID || IOS || __ANDROID__)
// 添加运行时权限
services.AddPlatformPermissions();
#endif
@@ -305,14 +306,12 @@ namespace System.Application.UI
services.AddSingleton(_ => PlatformApplication.Instance);
services.AddSingleton<IApplication>(s => s.GetRequiredService<PlatformApplication>());
#if __ANDROID__
#if !MAUI && __ANDROID__
services.AddSingleton<IAndroidApplication>(s => s.GetRequiredService<PlatformApplication>());
#endif
#if __MOBILE__
//services.AddMSALPublicClientApp(AppSettings.MASLClientId);
#elif MAUI
#if MAUI
services.AddSingleton<IMauiApplication>(s => s.GetRequiredService<PlatformApplication>());
#else
#elif AVALONIA
services.AddSingleton<IAvaloniaApplication>(s => s.GetRequiredService<PlatformApplication>());
services.TryAddSingleton<IClipboardPlatformService>(s => s.GetRequiredService<PlatformApplication>());
@@ -340,7 +339,7 @@ namespace System.Application.UI
* - 按钮文本(ButtonText)缺少本地化翻译(Translate)
* - 某些图标图片与枚举值不太匹配,例如 Information
*/
services.TryAddWindowManager();
services.AddWindowManager();
#if WINDOWS
// 可选项,在 Win 平台使用 WPF 实现的 MessageBox
@@ -369,7 +368,7 @@ namespace System.Application.UI
if (options.HasHttpClientFactory)
{
#if __MOBILE__
#if __MOBILE__ && !MACCATALYST
// 添加 HttpClientFactory 平台原生实现
services.AddNativeHttpClient();
#endif
@@ -380,7 +379,7 @@ namespace System.Application.UI
services.TryAddScriptManager();
if (isTrace) StartWatchTrace.Record("DI.D.ScriptManager");
#if !CONSOLEAPP
#if !CONSOLEAPP && !MACCATALYST && !IOS
if (options.HasHttpProxy)
{
// 通用 Http 代理服务
@@ -435,7 +434,7 @@ namespace System.Application.UI
#endif
if (options.HasSteam)
{
#if !__ANDROID__
#if !__ANDROID__ && !IOS
// Steam 相关助手、工具类服务
services.AddSteamService();