mirror of
https://github.com/BeyondDimension/SteamTools.git
synced 2026-10-25 11:39:56 +08:00
ShowWindowServiceImpl for Android
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static partial class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加显示窗口服务
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddShowWindowService(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IShowWindowService, ShowWindowServiceImpl>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Avalonia.Controls;
|
||||
using System;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
using System.Application.UI;
|
||||
@@ -7,7 +6,7 @@ using System.Application.UI;
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
public static class ServiceCollectionExtensions
|
||||
public static partial class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加主线程助手类(MainThreadDesktop)服务
|
||||
@@ -20,17 +19,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加显示窗口服务
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
/// <returns></returns>
|
||||
public static IServiceCollection AddShowWindowService(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton<IShowWindowService, ShowWindowServiceImpl>();
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加应用程序更新服务
|
||||
/// </summary>
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace System.Windows
|
||||
window.CanResize = true;
|
||||
break;
|
||||
}
|
||||
p.SetResizeMode(window.PlatformImpl.Handle.Handle, (int)value);
|
||||
p.SetResizeMode(window.PlatformImpl.Handle.Handle, value);
|
||||
}
|
||||
|
||||
static readonly bool IsWin32NT = Environment.OSVersion.Platform == PlatformID.Win32NT;
|
||||
|
||||
+2
-1
@@ -1,12 +1,13 @@
|
||||
using System.Application.Models;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed partial class LinuxDesktopPlatformServiceImpl : IDesktopPlatformService
|
||||
{
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
public void SetResizeMode(IntPtr hWnd, ResizeModeCompat value)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@ using System.Application.Models;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed partial class MacDesktopPlatformServiceImpl : IDesktopPlatformService
|
||||
{
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
public void SetResizeMode(IntPtr hWnd, ResizeModeCompat value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,7 +30,7 @@ namespace System.Application.Services.Implementation
|
||||
Arguments = $"-a \"{name}\" \"{filePath}\"",
|
||||
};
|
||||
pInfo.UseShellExecute = true;
|
||||
var p = Process.Start(pInfo);
|
||||
var p = Process.Start(pInfo);
|
||||
if (p == null) throw new FileNotFoundException(name);
|
||||
p.Close();
|
||||
}
|
||||
|
||||
+4
-3
@@ -1,4 +1,5 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
@@ -85,16 +86,16 @@ namespace System.Application.Services.Implementation
|
||||
_ = SetWindowLong(hWnd, GWL_STYLE, GetWindowLong(hWnd, GWL_STYLE) & ~WS_MAXIMIZEBOX);
|
||||
}
|
||||
|
||||
public void SetResizeMode(IntPtr hWnd, int value)
|
||||
public void SetResizeMode(IntPtr hWnd, ResizeModeCompat value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case IDesktopPlatformService.ResizeMode_NoResize:
|
||||
case ResizeModeCompat.NoResize:
|
||||
_ = DeleteMenu(GetSystemMenu(hWnd, false), SC_MAXIMIZE, MF_BYCOMMAND);
|
||||
_ = DeleteMenu(GetSystemMenu(hWnd, false), SC_MINIMIZE, MF_BYCOMMAND);
|
||||
HideMinimizeAndMaximizeButtons(hWnd);
|
||||
break;
|
||||
case IDesktopPlatformService.ResizeMode_CanMinimize:
|
||||
case ResizeModeCompat.CanMinimize:
|
||||
_ = DeleteMenu(GetSystemMenu(hWnd, false), SC_MAXIMIZE, MF_BYCOMMAND);
|
||||
DisableMaximizeButton(hWnd);
|
||||
break;
|
||||
|
||||
@@ -5,13 +5,18 @@ namespace System.Application
|
||||
/// </summary>
|
||||
public enum CustomWindow
|
||||
{
|
||||
#if !__MOBILE__
|
||||
LoginOrRegister,
|
||||
#endif
|
||||
MessageBox,
|
||||
#if !__MOBILE__
|
||||
AddAuth,
|
||||
ShowAuth,
|
||||
AuthTrade,
|
||||
EncryptionAuth,
|
||||
#endif
|
||||
Password,
|
||||
#if !__MOBILE__
|
||||
TaskBar,
|
||||
ExportAuth,
|
||||
ScriptStore,
|
||||
@@ -23,5 +28,6 @@ namespace System.Application
|
||||
NewVersion,
|
||||
WebView3,
|
||||
BindPhoneNumber,
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Application;
|
||||
using System.Application;
|
||||
using System.Application.Services;
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Properties;
|
||||
@@ -10,20 +10,20 @@ namespace System.Windows
|
||||
/// <summary>
|
||||
/// 显示消息框。
|
||||
/// </summary>
|
||||
public static class MessageBoxCompat
|
||||
public static partial class MessageBoxCompat
|
||||
{
|
||||
const string default_caption = ThisAssembly.AssemblyTrademark;
|
||||
const MessageBoxButtonCompat default_button = MessageBoxButtonCompat.OK;
|
||||
static readonly Lazy<IMessageBoxCompatService?> mbcs =
|
||||
new(DI.Get_Nullable<IMessageBoxCompatService>);
|
||||
|
||||
/// <inheritdoc cref="IMessageBoxCompatService.ShowAsync(string, string, MessageBoxButtonCompat, MessageBoxImageCompat?)"/>
|
||||
public static async Task<MessageBoxResultCompat> ShowAsync(
|
||||
string messageBoxText, string caption, MessageBoxButtonCompat button, MessageBoxImageCompat? icon = null)
|
||||
{
|
||||
var f = DI.Get_Nullable<IMessageBoxCompatService>();
|
||||
|
||||
if (f != null)
|
||||
if (mbcs.Value != null)
|
||||
{
|
||||
return await f.ShowAsync(messageBoxText, caption, button, icon);
|
||||
return await mbcs.Value.ShowAsync(messageBoxText, caption, button, icon);
|
||||
}
|
||||
|
||||
var viewModel = new MessageBoxWindowViewModel
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using System.Application.Services;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Windows
|
||||
{
|
||||
@@ -11,22 +9,22 @@ namespace System.Windows
|
||||
/// <summary>
|
||||
/// 用户无法调整窗口的大小。 不显示 "最大化" 和 "最小化" 框。
|
||||
/// </summary>
|
||||
NoResize = IDesktopPlatformService.ResizeMode_NoResize,
|
||||
NoResize,
|
||||
|
||||
/// <summary>
|
||||
/// 用户只能最小化窗口并从任务栏还原。 同时显示 "最小化" 和 "最大化" 框,但只启用 "最小化" 框。
|
||||
/// </summary>
|
||||
CanMinimize = IDesktopPlatformService.ResizeMode_CanMinimize,
|
||||
CanMinimize,
|
||||
|
||||
/// <summary>
|
||||
/// 用户可以通过使用 "最小化" 和 "最大化" 框以及围绕窗口的可拖动轮廓来完全调整窗口的大小。 显示和启用 "最小化" 和 "最大化" 框。 (默认) 。
|
||||
/// </summary>
|
||||
CanResize = IDesktopPlatformService.ResizeMode_CanResize,
|
||||
CanResize,
|
||||
|
||||
/// <summary>
|
||||
/// 此选项具有与相同的功能 <see cref="CanResize"/> ,但会将 "调整手柄" 添加到窗口的右下角。
|
||||
/// </summary>
|
||||
[Obsolete("not implemented")]
|
||||
CanResizeWithGrip = IDesktopPlatformService.ResizeMode_CanResizeWithGrip,
|
||||
CanResizeWithGrip,
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Security.Cryptography;
|
||||
using ResizeMode = System.Int32;
|
||||
using System.Windows;
|
||||
|
||||
namespace System.Application.Services
|
||||
{
|
||||
@@ -14,7 +14,7 @@ namespace System.Application.Services
|
||||
|
||||
public static IDesktopPlatformService Instance => DI.Get<IDesktopPlatformService>();
|
||||
|
||||
void SetResizeMode(IntPtr hWnd, ResizeMode value);
|
||||
void SetResizeMode(IntPtr hWnd, ResizeModeCompat value);
|
||||
|
||||
/// <summary>
|
||||
/// 获取一个正在运行的进程的命令行参数。
|
||||
@@ -153,11 +153,6 @@ namespace System.Application.Services
|
||||
|
||||
#endregion
|
||||
|
||||
public const ResizeMode ResizeMode_NoResize = 0;
|
||||
public const ResizeMode ResizeMode_CanMinimize = 1;
|
||||
public const ResizeMode ResizeMode_CanResize = 2;
|
||||
public const ResizeMode ResizeMode_CanResizeWithGrip = 3;
|
||||
|
||||
#region MachineUniqueIdentifier
|
||||
|
||||
private static (byte[] key, byte[] iv) GetMachineSecretKey(string? value)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
#if __MOBILE__
|
||||
using WindowViewModel = System.Application.UI.ViewModels.PageViewModel;
|
||||
#endif
|
||||
|
||||
namespace System.Application.Services
|
||||
{
|
||||
@@ -67,8 +70,10 @@ namespace System.Application.Services
|
||||
bool isDialog = true);
|
||||
|
||||
|
||||
#if !__MOBILE__
|
||||
void CloseWindow(WindowViewModel vm);
|
||||
void HideWindow(WindowViewModel vm);
|
||||
void ShowWindow(WindowViewModel vm);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Input;
|
||||
#if __MOBILE__
|
||||
using WindowViewModel = System.Application.UI.ViewModels.PageViewModel;
|
||||
#endif
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
|
||||
@@ -42,15 +42,11 @@ namespace System.Application.UI.ViewModels
|
||||
DelAccountCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
if (!UserService.Current.IsAuthenticated) return;
|
||||
#if !__MOBILE__
|
||||
var r = await MessageBoxCompat.ShowAsync(AppResources.DelAccountTips, ThisAssembly.AssemblyTrademark, MessageBoxButtonCompat.OKCancel);
|
||||
if (r == MessageBoxResultCompat.OK)
|
||||
{
|
||||
await UserService.Current.DelAccountAsync();
|
||||
}
|
||||
#else
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
});
|
||||
|
||||
#if __MOBILE__
|
||||
|
||||
+19
-6
@@ -1,11 +1,11 @@
|
||||
using Newtonsoft.Json.Linq;
|
||||
using ReactiveUI;
|
||||
using System.Application.Models;
|
||||
using System.Application.Services;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Properties;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
#if __MOBILE__
|
||||
using WindowViewModel = System.Application.UI.ViewModels.PageViewModel;
|
||||
#endif
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
@@ -23,7 +23,6 @@ namespace System.Application.UI.ViewModels
|
||||
set => this.RaiseAndSetIfChanged(ref _Password, value);
|
||||
}
|
||||
|
||||
|
||||
public static async Task<string?> ShowPasswordDialog()
|
||||
{
|
||||
var vm = new PasswordWindowViewModel();
|
||||
@@ -31,12 +30,25 @@ namespace System.Application.UI.ViewModels
|
||||
return vm.Password;
|
||||
}
|
||||
|
||||
|
||||
public void Ok()
|
||||
/// <summary>
|
||||
/// 输入内容验证
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool InputValidator()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Password))
|
||||
{
|
||||
Toast.Show(AppResources.LocalAuth_ProtectionAuth_PasswordErrorTip);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !__MOBILE__
|
||||
public void Ok()
|
||||
{
|
||||
if (!InputValidator())
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.Close();
|
||||
@@ -47,5 +59,6 @@ namespace System.Application.UI.ViewModels
|
||||
Password = string.Empty;
|
||||
this.Close();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using ReactiveUI;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<include layout="@layout/shared_toolbar" />
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/tvContent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textIsSelectable="true"
|
||||
tools:text="Ahead-of-time compiler.\n\nSimilar to JIT, this compiler also translates IL to machine code. In contrast to JIT compilation, AOT compilation happens before the application is executed and is usually performed on a different machine. Because AOT tool chains don't compile at run time, they don't have to minimize time spent compiling. That means they can spend more time optimizing. Since the context of AOT is the entire application, the AOT compiler also performs cross-module linking and whole-program analysis, which means that all references are followed and a single executable is produced.\n\nSee CoreRT and .NET Native.\n\nASP.NET\n\nThe original ASP.NET implementation that ships with the .NET Framework, also known as ASP.NET 4.x.\n\nSometimes ASP.NET is an umbrella term that refers to both the original ASP.NET and ASP.NET Core. The meaning that the term carries in any given instance is determined by context. Refer to ASP.NET 4.x when you want to make it clear that you're not using ASP.NET to mean both implementations.\n\nSee ASP.NET documentation.\n\nASP.NET Core\n\nA cross-platform, high-performance, open-source implementation of ASP.NET.\n\nSee ASP.NET Core documentation.CLR\n\nCommon Language Runtime.\n\nThe exact meaning depends on the context. Common Language Runtime usually refers to the runtime of .NET Framework or the runtime of .NET 5 (and .NET Core) and later versions.\n\nA CLR handles memory allocation and management. A CLR is also a virtual machine that not only executes apps but also generates and compiles code on-the-fly using a JIT compiler.\n\nThe CLR implementation for .NET Framework is Windows only.\n\n
|
||||
The CLR implementation for .NET 5 and later versions (also known as the Core CLR) is built from the same code base as the .NET Framework CLR. Originally, the Core CLR was the runtime of Silverlight and was designed to run on multiple platforms, specifically Windows and OS X. It's still a cross-platform runtime, now including support for many Linux distributions.\n\nSee also runtime.\n\nCore CLR\n\nThe Common Language Runtime for .NET 5 (and .NET Core) and later versions.\n\nSee CLR.\n\nCoreRT\n\n
|
||||
In contrast to the CLR, CoreRT is not a virtual machine, which means it doesn't include the facilities to generate and run code on-the-fly because it doesn't include a JIT. It does, however, include the GC and the ability for run-time type identification (RTTI) and reflection. However, its type system is designed so that metadata for reflection isn't required. Not requiring metadata enables having an AOT tool chain that can link away superfluous metadata and (more importantly) identify code that the app doesn't use. CoreRT is in development.\n\nSee Intro to CoreRT and .NET Runtime Lab."
|
||||
xamarin:managedType="AndroidX.AppCompat.Widget.AppCompatTextView" />
|
||||
|
||||
</ScrollView>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:xamarin="http://schemas.xamarin.com/android/xamarin/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/layoutPassword"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:endIconMode="password_toggle"
|
||||
tools:hint="Placeholder"
|
||||
xamarin:managedType="Google.Android.Material.TextField.TextInputLayout">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/tbPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword"
|
||||
tools:text="123"
|
||||
xamarin:managedType="Google.Android.Material.TextField.TextInputEditText" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
@@ -45,5 +45,86 @@ namespace System.Application
|
||||
|
||||
public static void StartActivity<TActivity>(this Fragment fragment) where TActivity : Activity
|
||||
=> StartActivity(fragment, typeof(TActivity));
|
||||
|
||||
const string KEY_ViewModel = "ByteArrayViewModel";
|
||||
static void StartActivity(this Activity activity, Type activityType, byte[] viewModel)
|
||||
{
|
||||
var intent = new Intent(activity, activityType);
|
||||
intent.PutExtra(KEY_ViewModel, viewModel);
|
||||
activity.StartActivity(intent);
|
||||
}
|
||||
|
||||
public static TViewModel? GetViewModel<TViewModel>(this Activity activity)
|
||||
{
|
||||
var intent = activity.Intent;
|
||||
if (intent != null)
|
||||
{
|
||||
var byteArray = intent.GetByteArrayExtra(KEY_ViewModel);
|
||||
if (byteArray != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var value = Serializable.DMP<TViewModel>(byteArray);
|
||||
return value;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
public static void StartActivity(Activity activity, Type activityType, object viewModel, Type? viewModelType = null)
|
||||
{
|
||||
viewModelType ??= viewModel.GetType();
|
||||
var viewModel_ = Serializable.SMP(viewModelType, viewModel);
|
||||
StartActivity(activity, activityType, viewModel_);
|
||||
}
|
||||
|
||||
public static void StartActivity(Fragment fragment, Type activityType, object viewModel, Type? viewModelType = null)
|
||||
{
|
||||
var activity = fragment.Activity;
|
||||
if (activity == null) return;
|
||||
StartActivity(activity, activityType, viewModel, viewModelType);
|
||||
}
|
||||
|
||||
public static void StartActivity<TActivity>(Activity activity, object viewModel, Type? viewModelType = null)
|
||||
{
|
||||
StartActivity(activity, typeof(TActivity), viewModel, viewModelType);
|
||||
}
|
||||
|
||||
public static void StartActivity<TActivity>(Fragment fragment, object viewModel, Type? viewModelType = null)
|
||||
{
|
||||
var activity = fragment.Activity;
|
||||
if (activity == null) return;
|
||||
StartActivity<TActivity>(activity, viewModel, viewModelType);
|
||||
}
|
||||
|
||||
public static void StartActivity<TViewModel>(Activity activity, Type activityType, TViewModel viewModel)
|
||||
{
|
||||
var viewModel_ = Serializable.SMP(viewModel);
|
||||
StartActivity(activity, activityType, viewModel_);
|
||||
}
|
||||
|
||||
public static void StartActivity<TViewModel>(Fragment fragment, Type activityType, TViewModel viewModel)
|
||||
{
|
||||
var activity = fragment.Activity;
|
||||
if (activity == null) return;
|
||||
StartActivity(activity, activityType, viewModel);
|
||||
}
|
||||
|
||||
public static void StartActivity<TActivity, TViewModel>(Activity activity, TViewModel viewModel)
|
||||
{
|
||||
StartActivity(activity, typeof(TActivity), viewModel);
|
||||
}
|
||||
|
||||
public static void StartActivity<TActivity, TViewModel>(Fragment fragment, TViewModel viewModel)
|
||||
{
|
||||
var activity = fragment.Activity;
|
||||
if (activity == null) return;
|
||||
StartActivity<TActivity, TViewModel>(activity, viewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,7 @@
|
||||
<EmbeddedResource Remove="UI\Views.Controls\**" />
|
||||
<None Remove="UI\Views.Controls\**" />
|
||||
<Compile Include="..\Common.ClientLib.Droid\Application\DarkModeUtil.cs" />
|
||||
<Compile Include="..\ST.Client.Desktop.Avalonia\ServiceCollectionExtensions.AddShowWindowService.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)'=='Debug'">
|
||||
@@ -347,6 +348,9 @@
|
||||
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_main.xml">
|
||||
<Link>Resources\layout\activity_main.xml</Link>
|
||||
</AndroidBoundLayout>
|
||||
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\activity_textblock.xml">
|
||||
<Link>Resources\layout\activity_textblock.xml</Link>
|
||||
</AndroidBoundLayout>
|
||||
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\fragment_community_fix.xml">
|
||||
<Link>Resources\layout\fragment_community_fix.xml</Link>
|
||||
</AndroidBoundLayout>
|
||||
@@ -386,6 +390,9 @@
|
||||
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\shared_toolbar.xml">
|
||||
<Link>Resources\layout\shared_toolbar.xml</Link>
|
||||
</AndroidBoundLayout>
|
||||
<AndroidBoundLayout Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\layout\textbox_password.xml">
|
||||
<Link>Resources\layout\textbox_password.xml</Link>
|
||||
</AndroidBoundLayout>
|
||||
<AndroidResource Include="..\ST.Client.Mobile.Droid.Design\ui\src\main\res\menu\bottom_nav_menu.xml">
|
||||
<Link>Resources\menu\bottom_nav_menu.xml</Link>
|
||||
</AndroidResource>
|
||||
@@ -482,3 +489,5 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Extensions.Http;
|
||||
using Microsoft.Extensions.Http;
|
||||
using System.Application.Services;
|
||||
using System.Application.Services.Implementation;
|
||||
using System.Net.Http;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
using Android.Content;
|
||||
using Android.Views;
|
||||
using Binding;
|
||||
using Google.Android.Material.Dialog;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Application.UI.ViewModels;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using AlertDialog = AndroidX.AppCompat.App.AlertDialog;
|
||||
using XEPlatform = Xamarin.Essentials.Platform;
|
||||
|
||||
namespace System.Application.Services.Implementation
|
||||
{
|
||||
internal sealed class ShowWindowServiceImpl : IShowWindowService
|
||||
{
|
||||
static string PositiveButtonText => AppResources.Confirm;
|
||||
static string NegativeButtonText => AppResources.Cancel;
|
||||
|
||||
Task<bool> PlatformShowWindow(CustomWindow customWindow, PageViewModel? viewModel = null, string title = "")
|
||||
{
|
||||
TaskCompletionSource<bool> tcs = new();
|
||||
try
|
||||
{
|
||||
AlertDialog? dialog = null;
|
||||
|
||||
void SetConfirmButton(MaterialAlertDialogBuilder b)
|
||||
{
|
||||
b.SetPositiveButton(PositiveButtonText, (_, e) =>
|
||||
{
|
||||
tcs.TrySetResult(true);
|
||||
});
|
||||
}
|
||||
void SetCancelButton(MaterialAlertDialogBuilder b)
|
||||
{
|
||||
b.SetNegativeButton(NegativeButtonText, (_, e) =>
|
||||
{
|
||||
tcs.TrySetResult(false);
|
||||
});
|
||||
}
|
||||
|
||||
Action<AlertDialog>? CreateMessageBoxDialogWindow(MaterialAlertDialogBuilder b)
|
||||
{
|
||||
SetConfirmButton(b);
|
||||
SetCancelButton(b);
|
||||
if (viewModel is MessageBoxWindowViewModel viewModel_mb)
|
||||
{
|
||||
b.SetMessage(viewModel_mb.Content);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Action<AlertDialog>? CreatePasswordDialogWindow(MaterialAlertDialogBuilder b)
|
||||
{
|
||||
// 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);
|
||||
binding.layoutPassword.Hint = AppResources.LocalAuth_PasswordRequired1;
|
||||
b.SetView(view);
|
||||
return d =>
|
||||
{
|
||||
d.GetButton((int)DialogButtonType.Positive).Click += (_, _) =>
|
||||
{
|
||||
if (viewModel is PasswordWindowViewModel viewModel_p)
|
||||
{
|
||||
viewModel_p.Password = binding.tbPassword.Text;
|
||||
if (viewModel_p.InputValidator())
|
||||
{
|
||||
d.Dismiss();
|
||||
tcs.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Func<MaterialAlertDialogBuilder, Action<AlertDialog>?> @delegate = customWindow switch
|
||||
{
|
||||
CustomWindow.MessageBox => CreateMessageBoxDialogWindow,
|
||||
CustomWindow.Password => CreatePasswordDialogWindow,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
if (!string.IsNullOrEmpty(title) && viewModel != null)
|
||||
{
|
||||
viewModel.Title = title;
|
||||
}
|
||||
var builder = new MaterialAlertDialogBuilder(XEPlatform.CurrentActivity);
|
||||
if (!string.IsNullOrWhiteSpace(viewModel?.Title))
|
||||
{
|
||||
builder.SetTitle(viewModel!.Title);
|
||||
}
|
||||
var dialog_delegate = @delegate(builder);
|
||||
dialog = builder.Create();
|
||||
dialog.CancelEvent += (_, _) =>
|
||||
{
|
||||
tcs.TrySetResult(false);
|
||||
};
|
||||
if (dialog_delegate != null)
|
||||
{
|
||||
dialog.ShowEvent += (_, _) =>
|
||||
{
|
||||
dialog_delegate?.Invoke(dialog);
|
||||
};
|
||||
}
|
||||
dialog.Show();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
tcs.TrySetException(e);
|
||||
}
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public async Task Show<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeModeCompat resizeMode = default, bool isDialog = false, bool isParent = true) where TWindowViewModel : PageViewModel, new()
|
||||
{
|
||||
await PlatformShowWindow(customWindow, viewModel, title);
|
||||
}
|
||||
|
||||
public async Task Show(Type typeWindowViewModel, CustomWindow customWindow, PageViewModel? viewModel = null, string title = "", ResizeModeCompat resizeMode = default, bool isDialog = false, bool isParent = true)
|
||||
{
|
||||
await PlatformShowWindow(customWindow, viewModel, title);
|
||||
}
|
||||
|
||||
public async Task<bool> ShowDialog<TWindowViewModel>(CustomWindow customWindow, TWindowViewModel? viewModel = null, string title = "", ResizeModeCompat resizeMode = default, bool isDialog = true) where TWindowViewModel : PageViewModel, new()
|
||||
{
|
||||
return await PlatformShowWindow(customWindow, viewModel, title);
|
||||
}
|
||||
|
||||
public async Task ShowDialog(Type typeWindowViewModel, CustomWindow customWindow, PageViewModel? viewModel = null, string title = "", ResizeModeCompat resizeMode = default, bool isDialog = true)
|
||||
{
|
||||
await PlatformShowWindow(customWindow, viewModel, title);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,11 @@ namespace System.Application.UI.Activities
|
||||
R.Language));
|
||||
break;
|
||||
case PreferenceButton.开放源代码许可:
|
||||
throw new NotImplementedException();
|
||||
TextBlockActivity.StartActivity(this, new TextBlockViewModel
|
||||
{
|
||||
Title = AppResources.About_OpenSource,
|
||||
ContentSource = TextBlockViewModel.ContentSourceEnum.OpenSourceLibrary,
|
||||
});
|
||||
break;
|
||||
case PreferenceButton.源码仓库:
|
||||
new MaterialAlertDialogBuilder(this).SetItems(SourceRepositories, (_, e) => BrowserOpenByDialogClick(e, value => value switch
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using Android.App;
|
||||
using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Binding;
|
||||
using System.Application.Models;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
namespace System.Application.UI.Activities
|
||||
{
|
||||
[Register(JavaPackageConstants.Activities + nameof(TextBlockActivity))]
|
||||
[Activity(Theme = ManifestConstants.MainTheme_NoActionBar,
|
||||
LaunchMode = LaunchMode.SingleTask,
|
||||
ConfigurationChanges = ManifestConstants.ConfigurationChanges)]
|
||||
internal sealed class TextBlockActivity : BaseActivity<activity_textblock>
|
||||
{
|
||||
protected override int? LayoutResource => Resource.Layout.activity_textblock;
|
||||
|
||||
protected override void OnCreate(Bundle? savedInstanceState)
|
||||
{
|
||||
base.OnCreate(savedInstanceState);
|
||||
|
||||
var vm = this.GetViewModel<TextBlockViewModel>();
|
||||
if (vm == null)
|
||||
{
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
|
||||
this.SetSupportActionBarWithNavigationClick(binding!.toolbar);
|
||||
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
||||
if (!string.IsNullOrWhiteSpace(vm.Title)) Title = vm.Title;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(vm.Content)) binding!.tvContent.Text = vm.Content;
|
||||
else if (vm.ContentSource != default) binding!.tvContent.Text = vm.ContentSource switch
|
||||
{
|
||||
TextBlockViewModel.ContentSourceEnum.OpenSourceLibrary => OpenSourceLibrary.StringValues,
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
|
||||
public static void StartActivity(Activity activity, TextBlockViewModel viewModel)
|
||||
{
|
||||
GoToPlatformPages.StartActivity<TextBlockActivity, TextBlockViewModel>(activity, viewModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Binding;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Properties;
|
||||
using System.Windows;
|
||||
|
||||
namespace System.Application.UI.Fragments
|
||||
{
|
||||
@@ -10,11 +12,14 @@ namespace System.Application.UI.Fragments
|
||||
{
|
||||
protected override int? LayoutResource => Resource.Layout.fragment_community_fix;
|
||||
|
||||
public override void OnCreateView(View view)
|
||||
public override async void OnCreateView(View view)
|
||||
{
|
||||
base.OnCreateView(view);
|
||||
binding!.textView.Text = GetType().Name.TrimEnd("Fragment") + Environment.NewLine + AppResources.UnderConstruction;
|
||||
binding!.textView.Gravity = GravityFlags.Center;
|
||||
|
||||
var r = await MessageBoxCompat.ShowAsync(AppResources.DelAccountTips, ThisAssembly.AssemblyTrademark, MessageBoxButtonCompat.OKCancel);
|
||||
Toast.Show(r.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Binding;
|
||||
using System.Application.UI.Resx;
|
||||
using System.Application.UI.ViewModels;
|
||||
|
||||
namespace System.Application.UI.Fragments
|
||||
{
|
||||
@@ -10,11 +11,14 @@ namespace System.Application.UI.Fragments
|
||||
{
|
||||
protected override int? LayoutResource => Resource.Layout.fragment_game_list;
|
||||
|
||||
public override void OnCreateView(View view)
|
||||
public override async void OnCreateView(View view)
|
||||
{
|
||||
base.OnCreateView(view);
|
||||
binding!.textView.Text = GetType().Name.TrimEnd("Fragment") + Environment.NewLine + AppResources.UnderConstruction;
|
||||
binding!.textView.Gravity = GravityFlags.Center;
|
||||
|
||||
var text = await PasswordWindowViewModel.ShowPasswordDialog();
|
||||
Toast.Show(string.IsNullOrWhiteSpace(text) ? "IsNullOrWhiteSpace" : text!);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using MPKey = MessagePack.KeyAttribute;
|
||||
using MPObj = MessagePack.MessagePackObjectAttribute;
|
||||
|
||||
namespace System.Application.UI.ViewModels
|
||||
{
|
||||
[MPObj]
|
||||
public class TextBlockViewModel
|
||||
{
|
||||
[MPKey(0)]
|
||||
public string? Title { get; set; }
|
||||
|
||||
[MPKey(1)]
|
||||
public string? Content { get; set; }
|
||||
|
||||
[MPKey(2)]
|
||||
public ContentSourceEnum ContentSource { get; set; }
|
||||
|
||||
public enum ContentSourceEnum
|
||||
{
|
||||
None,
|
||||
OpenSourceLibrary,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
@@ -35,7 +35,7 @@
|
||||
<Compile Include="..\ST.Client.Desktop\Mvvm\*.cs">
|
||||
<LinkBase>Mvvm</LinkBase>
|
||||
</Compile>
|
||||
<Compile Remove="..\ST.Client.Desktop\Mvvm\CompositeDisposable.cs"/>
|
||||
<Compile Remove="..\ST.Client.Desktop\Mvvm\CompositeDisposable.cs" />
|
||||
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\AreaUIHelper.cs">
|
||||
<LinkBase>UI\ViewModels</LinkBase>
|
||||
</Compile>
|
||||
@@ -63,22 +63,41 @@
|
||||
<Compile Include="..\ST.Client.Desktop\Services\Implementation\FontManagerImpl.cs">
|
||||
<LinkBase>Services\Implementation</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\ServiceCollectionExtensions.TryAddFontManager.cs"/>
|
||||
<Compile Include="..\ST.Client.Desktop\ServiceCollectionExtensions.TryAddFontManager.cs" />
|
||||
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Pages\About\AboutPageViewModel.shared.cs">
|
||||
<Link>UI\ViewModels\AboutPageViewModel.shared.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\Models\Enum\AppTheme.cs">
|
||||
<LinkBase>Models\Enum</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\MessageBox\*.cs">
|
||||
<LinkBase>MessageBox</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\Services\IMessageBoxCompatService.cs">
|
||||
<LinkBase>Services</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\Services\IShowWindowService.cs">
|
||||
<LinkBase>Services</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\CustomWindow.cs" />
|
||||
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Windows\MessageBoxWindowViewModel.cs">
|
||||
<LinkBase>UI\ViewModels</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Base\DialogWindowViewModel.cs">
|
||||
<LinkBase>UI\ViewModels\Base</LinkBase>
|
||||
</Compile>
|
||||
<Compile Include="..\ST.Client.Desktop\UI\ViewModels\Windows\LocalAuthPage\PasswordWindowViewModel.cs">
|
||||
<LinkBase>UI\ViewModels</LinkBase>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ST.Client\ST.Client.csproj"/>
|
||||
<ProjectReference Include="..\ST.Client\ST.Client.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ReactiveUI" Version="13.3.2"/>
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.32.1"/>
|
||||
<PackageReference Include="ReactiveUI" Version="13.3.2" />
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.32.1" />
|
||||
<!--<PackageReference Include="StatefulModel.Standard" Version="0.1.0" />-->
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+1
-2
@@ -175,7 +175,7 @@ namespace System.Application
|
||||
|
||||
// 添加主线程助手(MainThreadDesktop)
|
||||
services.AddMainThreadPlatformService();
|
||||
|
||||
#endif
|
||||
#region MessageBox
|
||||
|
||||
/* System.Windows.MessageBox 在 WPF 库中,仅支持 Win 平台
|
||||
@@ -203,7 +203,6 @@ namespace System.Application
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
#endif
|
||||
#if StartupTrace
|
||||
StartupTrace.Restart("DI.ConfigureDemandServices.GUI");
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user