fix # 722

This commit is contained in:
Lightczx
2023-05-14 22:20:45 +08:00
parent d54828ff55
commit 46f58730dc
6 changed files with 108 additions and 83 deletions

View File

@@ -21,8 +21,9 @@ namespace Snap.Hutao;
public sealed partial class App : Application
{
private const string AppInstanceKey = "main";
private readonly ILogger<App> logger;
private readonly IServiceProvider serviceProvider;
private readonly IActivation activation;
private readonly ILogger<App> logger;
/// <summary>
/// Initializes the singleton application object.
@@ -33,6 +34,7 @@ public sealed partial class App : Application
// Load app resource
InitializeComponent();
activation = serviceProvider.GetRequiredService<IActivation>();
logger = serviceProvider.GetRequiredService<ILogger<App>>();
serviceProvider.GetRequiredService<ExceptionRecorder>().Record(this);
@@ -50,9 +52,8 @@ public sealed partial class App : Application
if (firstInstance.IsCurrent)
{
// manually invoke
Activation.NonRedirectToActivate(firstInstance, activatedEventArgs);
firstInstance.Activated += Activation.Activate;
ToastNotificationManagerCompat.OnActivated += Activation.NotificationActivate;
activation.NonRedirectToActivate(firstInstance, activatedEventArgs);
activation.InitializeWith(firstInstance);
LogDiagnosticInformation();
PostLaunchAsync().SafeForget(logger);

View File

@@ -33,11 +33,7 @@ internal static class DependencyInjection
.AddTransient(typeof(TaskCompletionSource))
.AddTransient(typeof(TaskCompletionSource<>))
.BuildServiceProvider(new ServiceProviderOptions()
{
ValidateOnBuild = true,
ValidateScopes = true,
});
.BuildServiceProvider(true);
Ioc.Default.ConfigureServices(serviceProvider);
return serviceProvider;

View File

@@ -9,12 +9,7 @@ using Snap.Hutao.Service.DailyNote;
using Snap.Hutao.Service.Hutao;
using Snap.Hutao.Service.Metadata;
using Snap.Hutao.Service.Navigation;
using Snap.Hutao.Service.Notification;
using System.Diagnostics;
using Windows.ApplicationModel;
#if !DEBUG_AS_FAKE_ELEVATED
using System.Security.Principal;
#endif
namespace Snap.Hutao.Core.LifeCycle;
@@ -22,10 +17,10 @@ namespace Snap.Hutao.Core.LifeCycle;
/// 激活
/// </summary>
[HighQuality]
internal static class Activation
[Injection(InjectAs.Singleton, typeof(IActivation))]
[SuppressMessage("", "CA1001")]
internal sealed class Activation : IActivation
{
// TODO: make this class a dependency
/// <summary>
/// 操作
/// </summary>
@@ -51,29 +46,23 @@ internal static class Activation
private const string UrlActionImport = "/import";
private const string UrlActionRefresh = "/refresh";
private static readonly WeakReference<MainWindow> MainWindowReference = new(default!);
private static readonly SemaphoreSlim ActivateSemaphore = new(1);
private readonly IServiceProvider serviceProvider;
private readonly ITaskContext taskContext;
private readonly WeakReference<MainWindow> mainWindowReference = new(default!);
private readonly SemaphoreSlim activateSemaphore = new(1);
/// <summary>
/// 以管理员模式重启
/// 构造一个新的激活
/// </summary>
/// <returns>任务</returns>
public static async ValueTask RestartAsElevatedAsync()
/// <param name="serviceProvider">服务提供器</param>
public Activation(IServiceProvider serviceProvider)
{
// if (!GetElevated())
{
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
Process.GetCurrentProcess().Kill();
}
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
this.serviceProvider = serviceProvider;
}
/// <summary>
/// 响应激活事件
/// 激活事件一般不会在UI线程上触发
/// </summary>
/// <param name="sender">发送方</param>
/// <param name="args">激活参数</param>
public static void Activate(object? sender, AppActivationArguments args)
/// <inheritdoc/>
public void Activate(object? sender, AppActivationArguments args)
{
_ = sender;
if (!ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
@@ -82,12 +71,8 @@ internal static class Activation
}
}
/// <summary>
/// 触发激活事件
/// </summary>
/// <param name="sender">发送方</param>
/// <param name="args">激活参数</param>
public static void NonRedirectToActivate(object? sender, AppActivationArguments args)
/// <inheritdoc/>
public void NonRedirectToActivate(object? sender, AppActivationArguments args)
{
_ = sender;
if (!ToastNotificationManagerCompat.WasCurrentProcessToastActivated())
@@ -96,11 +81,14 @@ internal static class Activation
}
}
/// <summary>
/// 响应通知激活事件
/// </summary>
/// <param name="args">参数</param>
public static void NotificationActivate(ToastNotificationActivatedEventArgsCompat args)
/// <inheritdoc/>
public void InitializeWith(AppInstance appInstance)
{
appInstance.Activated += Activate;
ToastNotificationManagerCompat.OnActivated += NotificationActivate;
}
private void NotificationActivate(ToastNotificationActivatedEventArgsCompat args)
{
ToastArguments toastArgs = ToastArguments.Parse(args.Argument);
@@ -114,22 +102,18 @@ internal static class Activation
}
}
/// <summary>
/// 异步响应激活事件
/// </summary>
/// <returns>任务</returns>
private static async Task HandleActivationAsync(AppActivationArguments args, bool isRedirected)
private async Task HandleActivationAsync(AppActivationArguments args, bool isRedirected)
{
if (ActivateSemaphore.CurrentCount > 0)
if (activateSemaphore.CurrentCount > 0)
{
using (await ActivateSemaphore.EnterAsync().ConfigureAwait(false))
using (await activateSemaphore.EnterAsync().ConfigureAwait(false))
{
await HandleActivationCoreAsync(args, isRedirected).ConfigureAwait(false);
}
}
}
private static async Task HandleActivationCoreAsync(AppActivationArguments args, bool isRedirected)
private async Task HandleActivationCoreAsync(AppActivationArguments args, bool isRedirected)
{
if (args.Kind == ExtendedActivationKind.Protocol)
{
@@ -160,7 +144,7 @@ internal static class Activation
}
}
private static async Task HandleNormalLaunchActionAsync()
private async Task HandleNormalLaunchActionAsync()
{
// Increase launch times
LocalSetting.Set(SettingKeys.LaunchTimes, LocalSetting.Get(SettingKeys.LaunchTimes, 0) + 1);
@@ -168,28 +152,29 @@ internal static class Activation
await WaitMainWindowAsync().ConfigureAwait(false);
}
private static async Task WaitMainWindowAsync()
private async Task WaitMainWindowAsync()
{
IServiceProvider serviceProvider = Ioc.Default;
ITaskContext taskContext = serviceProvider.GetRequiredService<ITaskContext>();
await taskContext.SwitchToMainThreadAsync();
if (!mainWindowReference.TryGetTarget(out _))
{
await taskContext.SwitchToMainThreadAsync();
MainWindowReference.SetTarget(serviceProvider.GetRequiredService<MainWindow>());
mainWindowReference.SetTarget(serviceProvider.GetRequiredService<MainWindow>());
serviceProvider
.GetRequiredService<IMetadataService>()
.As<IMetadataServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IMetadataService>()
.As<IMetadataServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IHutaoUserService>()
.As<IHutaoUserServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
serviceProvider
.GetRequiredService<IHutaoUserService>()
.As<IHutaoUserServiceInitialization>()?
.InitializeInternalAsync()
.SafeForget();
}
}
private static async Task HandleUrlActivationAsync(Uri uri, bool isRedirected)
private async Task HandleUrlActivationAsync(Uri uri, bool isRedirected)
{
UriBuilder builder = new(uri);
@@ -220,7 +205,7 @@ internal static class Activation
}
}
private static async Task HandleAchievementActionAsync(string action, string parameter, bool isRedirected)
private async Task HandleAchievementActionAsync(string action, string parameter, bool isRedirected)
{
_ = parameter;
_ = isRedirected;
@@ -228,11 +213,10 @@ internal static class Activation
{
case UrlActionImport:
{
ITaskContext taskContext = Ioc.Default.GetRequiredService<ITaskContext>();
await taskContext.SwitchToMainThreadAsync();
INavigationAwaiter navigationAwaiter = new NavigationExtra(ImportUIAFFromClipboard);
await Ioc.Default
await serviceProvider
.GetRequiredService<INavigationService>()
.NavigateAsync<View.Page.AchievementPage>(navigationAwaiter, true)
.ConfigureAwait(false);
@@ -241,14 +225,14 @@ internal static class Activation
}
}
private static async Task HandleDailyNoteActionAsync(string action, string parameter, bool isRedirected)
private async Task HandleDailyNoteActionAsync(string action, string parameter, bool isRedirected)
{
_ = parameter;
switch (action)
{
case UrlActionRefresh:
{
await Ioc.Default
await serviceProvider
.GetRequiredService<IDailyNoteService>()
.RefreshDailyNotesAsync()
.ConfigureAwait(false);
@@ -265,15 +249,15 @@ internal static class Activation
}
}
private static async Task HandleLaunchGameActionAsync(string? uid = null)
private async Task HandleLaunchGameActionAsync(string? uid = null)
{
IServiceProvider serviceProvider = Ioc.Default;
IMemoryCache memoryCache = serviceProvider.GetRequiredService<IMemoryCache>();
memoryCache.Set(ViewModel.Game.LaunchGameViewModel.DesiredUid, uid);
ITaskContext taskContext = serviceProvider.GetRequiredService<ITaskContext>();
serviceProvider
.GetRequiredService<IMemoryCache>()
.Set(ViewModel.Game.LaunchGameViewModel.DesiredUid, uid);
await taskContext.SwitchToMainThreadAsync();
if (!MainWindowReference.TryGetTarget(out _))
if (!mainWindowReference.TryGetTarget(out _))
{
_ = serviceProvider.GetRequiredService<LaunchGameWindow>();
}

View File

@@ -0,0 +1,33 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.Windows.AppLifecycle;
namespace Snap.Hutao.Core.LifeCycle;
/// <summary>
/// 激活
/// </summary>
internal interface IActivation
{
/// <summary>
/// 响应激活事件
/// 激活事件一般不会在UI线程上触发
/// </summary>
/// <param name="sender">发送方</param>
/// <param name="args">激活参数</param>
void Activate(object? sender, AppActivationArguments args);
/// <summary>
/// 使用当前 App 实例初始化激活
/// </summary>
/// <param name="appInstance">App 实例</param>
void InitializeWith(AppInstance appInstance);
/// <summary>
/// 无转发触发激活事件
/// </summary>
/// <param name="sender">发送方</param>
/// <param name="args">激活参数</param>
void NonRedirectToActivate(object? sender, AppActivationArguments args);
}

View File

@@ -1,6 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using System.Runtime.InteropServices;
namespace Snap.Hutao.Model.Metadata.Avatar;
/// <summary>
@@ -61,7 +63,16 @@ internal sealed class SkillDepot
if (compositeSkillsNoInherents == null)
{
compositeSkillsNoInherents = new(Skills.Count + 1);
compositeSkillsNoInherents.AddRange(Skills);
foreach (ref ProudableSkill skill in CollectionsMarshal.AsSpan(Skills))
{
// 跳过 [替换冲刺的技能]
if (skill.Proud.Parameters.Count > 1)
{
compositeSkillsNoInherents.Add(skill);
}
}
compositeSkillsNoInherents.Add(EnergySkill);
}

View File

@@ -21,7 +21,7 @@
<Button
Margin="16"
HorizontalAlignment="Right"
Command="{x:Bind HandleCurrentCookieCommand, Mode=OneWay}"
Command="{x:Bind HandleCurrentCookieCommand}"
Content="{shcm:ResourceString Name=ViewPageLoginMihoyoUserLoggedInAction}"/>
<WebView2 x:Name="WebView" Grid.Row="2"/>
</Grid>