diff --git a/src/Snap.Hutao/Snap.Hutao/Control/Loading.xaml b/src/Snap.Hutao/Snap.Hutao/Control/Loading.xaml
index d7567bf5..f2052287 100644
--- a/src/Snap.Hutao/Snap.Hutao/Control/Loading.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/Control/Loading.xaml
@@ -24,7 +24,7 @@
x:Name="ContentGrid"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
- x:Load="False">
+ x:Load="True">
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs
index 6f924ebb..901341be 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/NotifyIcon/NotifyIconController.cs
@@ -4,6 +4,7 @@
using Snap.Hutao.Core.ExceptionService;
using Snap.Hutao.Win32.Foundation;
using Snap.Hutao.Win32.UI.WindowsAndMessaging;
+using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
@@ -26,9 +27,10 @@ internal sealed class NotifyIconController : IDisposable
{
lazyMenu = new(() => new(serviceProvider));
- StorageFile iconFile = StorageFile.GetFileFromApplicationUriAsync("ms-appx:///Assets/Logo.ico".ToUri()).AsTask().GetAwaiter().GetResult();
- icon = new(iconFile.Path);
- id = Unsafe.As(ref MemoryMarshal.GetArrayDataReference(MD5.HashData(Encoding.UTF8.GetBytes(iconFile.Path))));
+ RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService();
+ string iconPath = Path.Combine(runtimeOptions.InstalledLocation, "Assets/Logo.ico");
+ icon = new(iconPath);
+ id = Unsafe.As(ref MemoryMarshal.GetArrayDataReference(MD5.HashData(Encoding.UTF8.GetBytes(iconPath))));
xamlHostWindow = new(serviceProvider);
xamlHostWindow.MoveAndResize(default);
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs
index 19262af0..bf5edb3c 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/WindowExtension.cs
@@ -31,6 +31,12 @@ internal static class WindowExtension
return WindowControllers.TryGetValue(window, out _);
}
+ public static void UninitializeController(this TWindow window)
+ where TWindow : Window
+ {
+ WindowControllers.Remove(window);
+ }
+
public static DesktopWindowXamlSource? GetDesktopWindowXamlSource(this Window window)
{
if (window.SystemBackdrop is SystemBackdropDesktopWindowXamlSourceAccess access)
diff --git a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs
index 98ab3d69..8be2e106 100644
--- a/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Core/Windowing/XamlWindowController.cs
@@ -13,6 +13,7 @@ using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Core.Setting;
using Snap.Hutao.Core.Windowing.Abstraction;
using Snap.Hutao.Core.Windowing.NotifyIcon;
+using Snap.Hutao.Factory.ContentDialog;
using Snap.Hutao.Service;
using Snap.Hutao.Win32;
using Snap.Hutao.Win32.Foundation;
@@ -99,11 +100,10 @@ internal sealed class XamlWindowController
private void OnWindowClosed(object sender, WindowEventArgs args)
{
+ serviceProvider.GetRequiredService().PropertyChanged -= OnOptionsPropertyChanged;
+
if (XamlLifetime.ApplicationLaunchedWithNotifyIcon && !XamlLifetime.ApplicationExiting)
{
- args.Handled = true;
- window.Hide();
-
if (!IsNotifyIconVisible())
{
new ToastContentBuilder()
@@ -119,16 +119,15 @@ internal sealed class XamlWindowController
GC.Collect(GC.MaxGeneration);
}
- else
- {
- if (window is IXamlWindowRectPersisted rectPersisted)
- {
- SaveOrSkipWindowSize(rectPersisted);
- }
- subclass?.Dispose();
- windowNonRudeHWND?.Dispose();
+ if (window is IXamlWindowRectPersisted rectPersisted)
+ {
+ SaveOrSkipWindowSize(rectPersisted);
}
+
+ subclass?.Dispose();
+ windowNonRudeHWND?.Dispose();
+ window.UninitializeController();
}
private bool IsNotifyIconVisible()
diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/ContentDialogFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/ContentDialogFactory.cs
index 7c06a1b7..4ea5e8b5 100644
--- a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/ContentDialogFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/ContentDialogFactory.cs
@@ -4,6 +4,7 @@
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Core.LifeCycle;
using Snap.Hutao.Service;
+using System.Collections.Concurrent;
namespace Snap.Hutao.Factory.ContentDialog;
@@ -18,10 +19,14 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
private readonly ITaskContext taskContext;
private readonly AppOptions appOptions;
+ private readonly ConcurrentQueue> dialogQueue = [];
+ private bool isDialogShowing;
+
///
public async ValueTask CreateForConfirmAsync(string title, string content)
{
await taskContext.SwitchToMainThreadAsync();
+
Microsoft.UI.Xaml.Controls.ContentDialog dialog = new()
{
XamlRoot = currentWindowReference.GetXamlRoot(),
@@ -39,6 +44,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
public async ValueTask CreateForConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close)
{
await taskContext.SwitchToMainThreadAsync();
+
Microsoft.UI.Xaml.Controls.ContentDialog dialog = new()
{
XamlRoot = currentWindowReference.GetXamlRoot(),
@@ -57,6 +63,7 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
public async ValueTask CreateForIndeterminateProgressAsync(string title)
{
await taskContext.SwitchToMainThreadAsync();
+
Microsoft.UI.Xaml.Controls.ContentDialog dialog = new()
{
XamlRoot = currentWindowReference.GetXamlRoot(),
@@ -72,9 +79,11 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
where TContentDialog : Microsoft.UI.Xaml.Controls.ContentDialog
{
await taskContext.SwitchToMainThreadAsync();
+
TContentDialog contentDialog = serviceProvider.CreateInstance(parameters);
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
contentDialog.RequestedTheme = appOptions.ElementTheme;
+
return contentDialog;
}
@@ -84,6 +93,51 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory
TContentDialog contentDialog = serviceProvider.CreateInstance(parameters);
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
contentDialog.RequestedTheme = appOptions.ElementTheme;
+
return contentDialog;
}
+
+ [SuppressMessage("", "SH003")]
+ public Task EnqueueAndShowAsync(Microsoft.UI.Xaml.Controls.ContentDialog contentDialog)
+ {
+ TaskCompletionSource dialogShowCompletionSource = new();
+
+ dialogQueue.Enqueue(async () =>
+ {
+ try
+ {
+ ContentDialogResult result = await contentDialog.ShowAsync();
+ dialogShowCompletionSource.SetResult(result);
+ }
+ catch (Exception ex)
+ {
+ dialogShowCompletionSource.SetException(ex);
+ }
+ finally
+ {
+ await ShowNextDialog().ConfigureAwait(false);
+ }
+ });
+
+ if (!isDialogShowing)
+ {
+ ShowNextDialog();
+ }
+
+ return dialogShowCompletionSource.Task;
+
+ Task ShowNextDialog()
+ {
+ if (dialogQueue.TryDequeue(out Func? showNextDialogAsync))
+ {
+ isDialogShowing = true;
+ return showNextDialogAsync();
+ }
+ else
+ {
+ isDialogShowing = false;
+ return Task.CompletedTask;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/IContentDialogFactory.cs b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/IContentDialogFactory.cs
index 00c434c3..703378df 100644
--- a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/IContentDialogFactory.cs
+++ b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/IContentDialogFactory.cs
@@ -40,4 +40,6 @@ internal interface IContentDialogFactory
ValueTask CreateInstanceAsync(params object[] parameters)
where TContentDialog : Microsoft.UI.Xaml.Controls.ContentDialog;
+
+ Task EnqueueAndShowAsync(Microsoft.UI.Xaml.Controls.ContentDialog contentDialog);
}
\ No newline at end of file
diff --git a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs
index 71f93653..02b19c8c 100644
--- a/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/LaunchGameWindow.xaml.cs
@@ -13,7 +13,7 @@ using Windows.Graphics;
namespace Snap.Hutao;
[HighQuality]
-[Injection(InjectAs.Singleton)]
+[Injection(InjectAs.Transient)]
internal sealed partial class LaunchGameWindow : Window,
IDisposable,
IXamlWindowExtendContentIntoTitleBar,
diff --git a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs
index 54e0e4c9..2e1a4b51 100644
--- a/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs
+++ b/src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs
@@ -14,7 +14,7 @@ namespace Snap.Hutao;
/// 主窗体
///
[HighQuality]
-[Injection(InjectAs.Singleton)]
+[Injection(InjectAs.Transient)]
internal sealed partial class MainWindow : Window,
IXamlWindowExtendContentIntoTitleBar,
IXamlWindowRectPersisted,
diff --git a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml
index 0edacf43..4b31ce7e 100644
--- a/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml
+++ b/src/Snap.Hutao/Snap.Hutao/View/MainView.xaml
@@ -17,10 +17,7 @@
mc:Ignorable="d">
-
+
diff --git a/src/Snap.Hutao/Snap.Hutao/ViewModel/MainViewModel.cs b/src/Snap.Hutao/Snap.Hutao/ViewModel/MainViewModel.cs
index 5e199f54..a6e876bd 100644
--- a/src/Snap.Hutao/Snap.Hutao/ViewModel/MainViewModel.cs
+++ b/src/Snap.Hutao/Snap.Hutao/ViewModel/MainViewModel.cs
@@ -31,6 +31,7 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
public void Initialize(IBackgroundImagePresenterAccessor accessor)
{
backgroundImagePresenter = accessor.BackgroundImagePresenter;
+ UpdateBackgroundAsync(true).SafeForget();
}
public void Receive(BackgroundImageTypeChangedMessage message)
@@ -39,14 +40,14 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewMo
}
[Command("UpdateBackgroundCommand")]
- private async Task UpdateBackgroundAsync()
+ private async Task UpdateBackgroundAsync(bool forceRefresh = false)
{
if (backgroundImagePresenter is null)
{
return;
}
- (bool shouldRefresh, BackgroundImage? backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
+ (bool shouldRefresh, BackgroundImage? backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(forceRefresh ? default : previousBackgroundImage).ConfigureAwait(false);
if (shouldRefresh)
{