mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
fix # 722
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>();
|
||||
}
|
||||
|
||||
33
src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/IActivation.cs
Normal file
33
src/Snap.Hutao/Snap.Hutao/Core/LifeCycle/IActivation.cs
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user