mirror of
https://jihulab.com/DGP-Studio/Snap.Hutao.git
synced 2025-11-19 21:02:53 +08:00
Merge pull request #1722 from DGP-Studio/feat/window
make windows transient
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
x:Name="ContentGrid"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
x:Load="False">
|
||||
x:Load="True">
|
||||
<ContentPresenter.RenderTransform>
|
||||
<CompositeTransform/>
|
||||
</ContentPresenter.RenderTransform>
|
||||
|
||||
@@ -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<byte, Guid>(ref MemoryMarshal.GetArrayDataReference(MD5.HashData(Encoding.UTF8.GetBytes(iconFile.Path))));
|
||||
RuntimeOptions runtimeOptions = serviceProvider.GetRequiredService<RuntimeOptions>();
|
||||
string iconPath = Path.Combine(runtimeOptions.InstalledLocation, "Assets/Logo.ico");
|
||||
icon = new(iconPath);
|
||||
id = Unsafe.As<byte, Guid>(ref MemoryMarshal.GetArrayDataReference(MD5.HashData(Encoding.UTF8.GetBytes(iconPath))));
|
||||
|
||||
xamlHostWindow = new(serviceProvider);
|
||||
xamlHostWindow.MoveAndResize(default);
|
||||
|
||||
@@ -31,6 +31,12 @@ internal static class WindowExtension
|
||||
return WindowControllers.TryGetValue(window, out _);
|
||||
}
|
||||
|
||||
public static void UninitializeController<TWindow>(this TWindow window)
|
||||
where TWindow : Window
|
||||
{
|
||||
WindowControllers.Remove(window);
|
||||
}
|
||||
|
||||
public static DesktopWindowXamlSource? GetDesktopWindowXamlSource(this Window window)
|
||||
{
|
||||
if (window.SystemBackdrop is SystemBackdropDesktopWindowXamlSourceAccess access)
|
||||
|
||||
@@ -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<AppOptions>().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()
|
||||
|
||||
@@ -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<Func<Task>> dialogQueue = [];
|
||||
private bool isDialogShowing;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async ValueTask<ContentDialogResult> 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<ContentDialogResult> 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<Microsoft.UI.Xaml.Controls.ContentDialog> 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<TContentDialog>(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<TContentDialog>(parameters);
|
||||
contentDialog.XamlRoot = currentWindowReference.GetXamlRoot();
|
||||
contentDialog.RequestedTheme = appOptions.ElementTheme;
|
||||
|
||||
return contentDialog;
|
||||
}
|
||||
|
||||
[SuppressMessage("", "SH003")]
|
||||
public Task<ContentDialogResult> EnqueueAndShowAsync(Microsoft.UI.Xaml.Controls.ContentDialog contentDialog)
|
||||
{
|
||||
TaskCompletionSource<ContentDialogResult> 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<Task>? showNextDialogAsync))
|
||||
{
|
||||
isDialogShowing = true;
|
||||
return showNextDialogAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
isDialogShowing = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,4 +40,6 @@ internal interface IContentDialogFactory
|
||||
|
||||
ValueTask<TContentDialog> CreateInstanceAsync<TContentDialog>(params object[] parameters)
|
||||
where TContentDialog : Microsoft.UI.Xaml.Controls.ContentDialog;
|
||||
|
||||
Task<ContentDialogResult> EnqueueAndShowAsync(Microsoft.UI.Xaml.Controls.ContentDialog contentDialog);
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Snap.Hutao;
|
||||
/// 主窗体
|
||||
/// </summary>
|
||||
[HighQuality]
|
||||
[Injection(InjectAs.Singleton)]
|
||||
[Injection(InjectAs.Transient)]
|
||||
internal sealed partial class MainWindow : Window,
|
||||
IXamlWindowExtendContentIntoTitleBar,
|
||||
IXamlWindowRectPersisted,
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<mxi:Interaction.Behaviors>
|
||||
<shcb:PeriodicInvokeCommandOrOnActualThemeChangedBehavior
|
||||
Command="{Binding UpdateBackgroundCommand}"
|
||||
CommandParameter="{x:Bind BackgroundImagePresenter}"
|
||||
Period="0:5:0"/>
|
||||
<shcb:PeriodicInvokeCommandOrOnActualThemeChangedBehavior Command="{Binding UpdateBackgroundCommand}" Period="0:5:0"/>
|
||||
</mxi:Interaction.Behaviors>
|
||||
|
||||
<UserControl.Resources>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user