Merge pull request #1419 from DGP-Studio/feat/real_time_bg

This commit is contained in:
DismissedLight
2024-02-23 09:36:25 +08:00
committed by GitHub
11 changed files with 110 additions and 22 deletions

View File

@@ -0,0 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Control;
internal interface IXamlElementAccessor;

View File

@@ -0,0 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.Message;
internal sealed class BackgroundImageTypeChangedMessage;

View File

@@ -1,8 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
namespace Snap.Hutao.Service.Navigation;
/// <summary>
@@ -10,10 +8,5 @@ namespace Snap.Hutao.Service.Navigation;
/// </summary>
internal interface INavigationInitialization
{
/// <summary>
/// 使用指定的对象进行初始化
/// </summary>
/// <param name="navigationView">管理的 <see cref="NavigationView"/></param>
/// <param name="frame">管理的 <see cref="Frame"/></param>
void Initialize(NavigationView navigationView, Frame frame);
void Initialize(INavigationViewAccessor accessor);
}

View File

@@ -0,0 +1,14 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control;
namespace Snap.Hutao.Service.Navigation;
internal interface INavigationViewAccessor : IXamlElementAccessor
{
NavigationView NavigationView { get; }
Frame Frame { get; }
}

View File

@@ -147,10 +147,10 @@ internal sealed class NavigationService : INavigationService, INavigationInitial
}
/// <inheritdoc/>
public void Initialize(NavigationView navigationView, Frame frame)
public void Initialize(INavigationViewAccessor accessor)
{
NavigationView = navigationView;
this.frame = frame;
NavigationView = accessor.NavigationView;
frame = accessor.Frame;
NavigationView.IsPaneOpen = LocalSetting.Get(SettingKeys.IsNavPaneOpen, true);
}

View File

@@ -18,7 +18,7 @@
<mxi:Interaction.Behaviors>
<shcb:PeriodicInvokeCommandOrOnActualThemeChangedBehavior
Command="{Binding UpdateBackgroundCommand}"
CommandParameter="{x:Bind BackdroundImagePresenter}"
CommandParameter="{x:Bind BackgroundImagePresenter}"
Period="0:5:0"/>
</mxi:Interaction.Behaviors>
@@ -31,7 +31,7 @@
<!-- Background="{ThemeResource SolidBackgroundFillColorBaseBrush}" -->
<Grid Transitions="{ThemeResource EntranceThemeTransitions}">
<Image
x:Name="BackdroundImagePresenter"
x:Name="BackgroundImagePresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Opacity="0"

View File

@@ -27,17 +27,44 @@ internal sealed partial class MainView : UserControl
/// </summary>
public MainView()
{
DataContext = Ioc.Default.GetRequiredService<MainViewModel>();
IServiceProvider serviceProvider = Ioc.Default;
MainViewModel mainViewModel = serviceProvider.GetRequiredService<MainViewModel>();
DataContext = mainViewModel;
InitializeComponent();
IServiceProvider serviceProvider = Ioc.Default;
mainViewModel.Initialize(new BackgroundImagePresenterAccessor(BackgroundImagePresenter));
navigationService = serviceProvider.GetRequiredService<INavigationService>();
if (navigationService is INavigationInitialization navigationInitialization)
{
navigationInitialization.Initialize(NavView, ContentFrame);
navigationInitialization.Initialize(new NavigationViewAccessor(NavView, ContentFrame));
}
navigationService.Navigate<AnnouncementPage>(INavigationAwaiter.Default, true);
}
private class NavigationViewAccessor : INavigationViewAccessor
{
public NavigationViewAccessor(NavigationView navigationView, Frame frame)
{
NavigationView = navigationView;
Frame = frame;
}
public NavigationView NavigationView { get; private set; }
public Frame Frame { get; private set; }
}
private class BackgroundImagePresenterAccessor : IBackgroundImagePresenterAccessor
{
public BackgroundImagePresenterAccessor(Image backgroundImagePresenter)
{
BackgroundImagePresenter = backgroundImagePresenter;
}
public Image BackgroundImagePresenter { get; private set; }
}
}

View File

@@ -0,0 +1,12 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control;
namespace Snap.Hutao.ViewModel;
internal interface IBackgroundImagePresenterAccessor : IXamlElementAccessor
{
Image BackgroundImagePresenter { get; }
}

View File

@@ -0,0 +1,9 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
namespace Snap.Hutao.ViewModel;
internal interface IMainViewModelInitialization
{
void Initialize(IBackgroundImagePresenterAccessor accessor);
}

View File

@@ -1,27 +1,45 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI.Animations;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
using Snap.Hutao.Control.Animation;
using Snap.Hutao.Control.Theme;
using Snap.Hutao.Message;
using Snap.Hutao.Service.BackgroundImage;
namespace Snap.Hutao.ViewModel;
[ConstructorGenerated]
[Injection(InjectAs.Singleton)]
internal sealed partial class MainViewModel : Abstraction.ViewModel
internal sealed partial class MainViewModel : Abstraction.ViewModel, IMainViewModelInitialization, IRecipient<BackgroundImageTypeChangedMessage>
{
private readonly IBackgroundImageService backgroundImageService;
private readonly ITaskContext taskContext;
private BackgroundImage? previousBackgroundImage;
private Image? backgroundImagePresenter;
public void Initialize(IBackgroundImagePresenterAccessor accessor)
{
backgroundImagePresenter = accessor.BackgroundImagePresenter;
}
public void Receive(BackgroundImageTypeChangedMessage message)
{
UpdateBackgroundAsync().SafeForget();
}
[Command("UpdateBackgroundCommand")]
private async Task UpdateBackgroundAsync(Image presenter)
private async Task UpdateBackgroundAsync()
{
if (backgroundImagePresenter is null)
{
return;
}
(bool isOk, BackgroundImage backgroundImage) = await backgroundImageService.GetNextBackgroundImageAsync(previousBackgroundImage).ConfigureAwait(false);
if (isOk)
@@ -36,11 +54,11 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel
duration: ControlAnimationConstants.ImageOpacityFadeInOut,
easingType: EasingType.Quartic,
easingMode: EasingMode.EaseInOut)
.StartAsync(presenter)
.StartAsync(backgroundImagePresenter)
.ConfigureAwait(true);
presenter.Source = backgroundImage.ImageSource;
double targetOpacity = ThemeHelper.IsDarkMode(presenter.ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
backgroundImagePresenter.Source = backgroundImage.ImageSource;
double targetOpacity = ThemeHelper.IsDarkMode(backgroundImagePresenter.ActualTheme) ? 1 - backgroundImage.Luminance : backgroundImage.Luminance;
await AnimationBuilder
.Create()
@@ -49,7 +67,7 @@ internal sealed partial class MainViewModel : Abstraction.ViewModel
duration: ControlAnimationConstants.ImageOpacityFadeInOut,
easingType: EasingType.Quartic,
easingMode: EasingMode.EaseInOut)
.StartAsync(presenter)
.StartAsync(backgroundImagePresenter)
.ConfigureAwait(true);
}
}

View File

@@ -1,6 +1,7 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.AppLifecycle;
using Snap.Hutao.Core;
@@ -54,6 +55,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
private readonly IUserService userService;
private readonly ITaskContext taskContext;
private readonly AppOptions appOptions;
private readonly IMessenger messenger;
private NameValue<BackdropType>? selectedBackdropType;
private NameValue<BackgroundImageType>? selectedBackgroundImageType;
@@ -100,6 +102,7 @@ internal sealed partial class SettingViewModel : Abstraction.ViewModel
if (SetProperty(ref selectedBackgroundImageType, value) && value is not null)
{
AppOptions.BackgroundImageType = value.Value;
messenger.Send(new Message.BackgroundImageTypeChangedMessage());
}
}
}