From bc9018f4bf75d7f95de0ec21f0d32d6001dbaa42 Mon Sep 17 00:00:00 2001 From: qhy040404 Date: Thu, 13 Jun 2024 19:48:06 +0800 Subject: [PATCH] make windows transient --- .../Core/Windowing/WindowExtension.cs | 6 +++ .../Core/Windowing/XamlWindowController.cs | 22 +++++----- .../ContentDialog/ContentDialogFactory.cs | 41 +++++++++++++++++++ .../ContentDialog/IContentDialogFactory.cs | 4 ++ .../Snap.Hutao/LaunchGameWindow.xaml.cs | 2 +- src/Snap.Hutao/Snap.Hutao/MainWindow.xaml.cs | 2 +- src/Snap.Hutao/Snap.Hutao/View/MainView.xaml | 5 +-- .../Snap.Hutao/ViewModel/MainViewModel.cs | 5 ++- 8 files changed, 68 insertions(+), 19 deletions(-) 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..5636a872 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,11 @@ internal sealed class XamlWindowController private void OnWindowClosed(object sender, WindowEventArgs args) { + IContentDialogFactory contentDialogFactory = serviceProvider.GetRequiredService(); + contentDialogFactory.HideAllDialogs(); + if (XamlLifetime.ApplicationLaunchedWithNotifyIcon && !XamlLifetime.ApplicationExiting) { - args.Handled = true; - window.Hide(); - if (!IsNotifyIconVisible()) { new ToastContentBuilder() @@ -119,16 +120,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..6c5680de 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/ContentDialogFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/ContentDialogFactory.cs @@ -18,10 +18,14 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory private readonly ITaskContext taskContext; private readonly AppOptions appOptions; + private Microsoft.UI.Xaml.Controls.ContentDialog? currentContentDialog; + /// public async ValueTask CreateForConfirmAsync(string title, string content) { + await HideAllDialogsAsync().ConfigureAwait(false); await taskContext.SwitchToMainThreadAsync(); + Microsoft.UI.Xaml.Controls.ContentDialog dialog = new() { XamlRoot = currentWindowReference.GetXamlRoot(), @@ -32,13 +36,17 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory RequestedTheme = appOptions.ElementTheme, }; + dialog.Closed += OnContentDialogClosed; + currentContentDialog = dialog; return await dialog.ShowAsync(); } /// public async ValueTask CreateForConfirmCancelAsync(string title, string content, ContentDialogButton defaultButton = ContentDialogButton.Close) { + await HideAllDialogsAsync().ConfigureAwait(false); await taskContext.SwitchToMainThreadAsync(); + Microsoft.UI.Xaml.Controls.ContentDialog dialog = new() { XamlRoot = currentWindowReference.GetXamlRoot(), @@ -50,13 +58,17 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory RequestedTheme = appOptions.ElementTheme, }; + dialog.Closed += OnContentDialogClosed; + currentContentDialog = dialog; return await dialog.ShowAsync(); } /// public async ValueTask CreateForIndeterminateProgressAsync(string title) { + await HideAllDialogsAsync().ConfigureAwait(false); await taskContext.SwitchToMainThreadAsync(); + Microsoft.UI.Xaml.Controls.ContentDialog dialog = new() { XamlRoot = currentWindowReference.GetXamlRoot(), @@ -65,25 +77,54 @@ internal sealed partial class ContentDialogFactory : IContentDialogFactory RequestedTheme = appOptions.ElementTheme, }; + dialog.Closed += OnContentDialogClosed; + currentContentDialog = dialog; return dialog; } public async ValueTask CreateInstanceAsync(params object[] parameters) where TContentDialog : Microsoft.UI.Xaml.Controls.ContentDialog { + await HideAllDialogsAsync().ConfigureAwait(false); await taskContext.SwitchToMainThreadAsync(); + TContentDialog contentDialog = serviceProvider.CreateInstance(parameters); contentDialog.XamlRoot = currentWindowReference.GetXamlRoot(); contentDialog.RequestedTheme = appOptions.ElementTheme; + + contentDialog.Closed += OnContentDialogClosed; + currentContentDialog = contentDialog; return contentDialog; } public TContentDialog CreateInstance(params object[] parameters) where TContentDialog : Microsoft.UI.Xaml.Controls.ContentDialog { + HideAllDialogs(); + TContentDialog contentDialog = serviceProvider.CreateInstance(parameters); contentDialog.XamlRoot = currentWindowReference.GetXamlRoot(); contentDialog.RequestedTheme = appOptions.ElementTheme; + + contentDialog.Closed += OnContentDialogClosed; + currentContentDialog = contentDialog; return contentDialog; } + + public void HideAllDialogs() + { + currentContentDialog?.Hide(); + } + + public async ValueTask HideAllDialogsAsync() + { + await taskContext.SwitchToMainThreadAsync(); + currentContentDialog?.Hide(); + } + + private void OnContentDialogClosed(Microsoft.UI.Xaml.Controls.ContentDialog sender, ContentDialogClosedEventArgs args) + { + currentContentDialog = null; + sender.Closed -= OnContentDialogClosed; + } } \ 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..f7420929 100644 --- a/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/IContentDialogFactory.cs +++ b/src/Snap.Hutao/Snap.Hutao/Factory/ContentDialog/IContentDialogFactory.cs @@ -40,4 +40,8 @@ internal interface IContentDialogFactory ValueTask CreateInstanceAsync(params object[] parameters) where TContentDialog : Microsoft.UI.Xaml.Controls.ContentDialog; + + void HideAllDialogs(); + + ValueTask HideAllDialogsAsync(); } \ 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) {