This commit is contained in:
qhy040404
2024-06-13 12:51:22 +08:00
parent 4276481284
commit cc71aa9c82
8 changed files with 129 additions and 107 deletions

View File

@@ -0,0 +1,29 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using CommunityToolkit.WinUI.Behaviors;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Snap.Hutao.Control.Behavior;
[DependencyProperty("MilliSecondsDelay", typeof(int))]
internal sealed partial class InfoBarDelayCloseBehavior : BehaviorBase<InfoBar>
{
protected override void OnAssociatedObjectLoaded()
{
DelayCoreAsync().SafeForget();
}
private async ValueTask DelayCoreAsync()
{
if (MilliSecondsDelay > 0)
{
await Delay.FromMilliSeconds(MilliSecondsDelay).ConfigureAwait(true);
if (AssociatedObject is not null)
{
AssociatedObject.IsOpen = false;
}
}
}
}

View File

@@ -1,7 +1,6 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using System.Collections.ObjectModel;
namespace Snap.Hutao.Service.Notification;
@@ -9,7 +8,7 @@ namespace Snap.Hutao.Service.Notification;
[HighQuality]
internal interface IInfoBarService
{
ObservableCollection<InfoBar> Collection { get; }
ObservableCollection<InfoBarOptions> Collection { get; }
void PrepareInfoBarAndShow(Action<IInfoBarOptionsBuilder> configure);
}

View File

@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
namespace Snap.Hutao.Service.Notification;
@@ -16,7 +15,9 @@ internal sealed class InfoBarOptions
public object? Content { get; set; }
public ButtonBase? ActionButton { get; set; }
public string? ActionButtonContent { get; set; }
public ICommand? ActionButtonCommand { get; set; }
public int MilliSecondsDelay { get; set; }
}

View File

@@ -2,8 +2,6 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Snap.Hutao.Control.Builder.ButtonBase;
using Snap.Hutao.Core.Abstraction.Extension;
namespace Snap.Hutao.Service.Notification;
@@ -38,20 +36,17 @@ internal static class InfoBarOptionsBuilderExtension
return builder;
}
public static IInfoBarOptionsBuilder SetActionButton<TBuilder, TButton>(this TBuilder builder, Action<ButtonBaseBuilder<TButton>> configureButton)
public static IInfoBarOptionsBuilder SetActionButtonContent<TBuilder>(this TBuilder builder, string? buttonContent)
where TBuilder : IInfoBarOptionsBuilder
where TButton : ButtonBase, new()
{
ButtonBaseBuilder<TButton> buttonBaseBuilder = new ButtonBaseBuilder<TButton>().Configure(configureButton);
builder.Configure(builder => builder.Options.ActionButton = buttonBaseBuilder.Button);
builder.Configure(builder => builder.Options.ActionButtonContent = buttonContent);
return builder;
}
public static IInfoBarOptionsBuilder SetActionButton<TBuilder>(this TBuilder builder, Action<ButtonBuilder> configureButton)
public static IInfoBarOptionsBuilder SetActionButtonCommand<TBuilder>(this TBuilder builder, ICommand? buttonCommand)
where TBuilder : IInfoBarOptionsBuilder
{
ButtonBuilder buttonBaseBuilder = new ButtonBuilder().Configure(configureButton);
builder.Configure(builder => builder.Options.ActionButton = buttonBaseBuilder.Button);
builder.Configure(builder => builder.Options.ActionButtonCommand = buttonCommand);
return builder;
}

View File

@@ -1,11 +1,8 @@
// Copyright (c) DGP Studio. All rights reserved.
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
using Snap.Hutao.Core.Abstraction.Extension;
using System.Collections.ObjectModel;
using Windows.Foundation;
namespace Snap.Hutao.Service.Notification;
@@ -17,20 +14,16 @@ internal sealed class InfoBarService : IInfoBarService
private readonly ILogger<InfoBarService> logger;
private readonly ITaskContext taskContext;
private readonly TypedEventHandler<InfoBar, InfoBarClosedEventArgs> infobarClosedEventHandler;
private ObservableCollection<InfoBar>? collection;
private ObservableCollection<InfoBarOptions>? collection;
public InfoBarService(IServiceProvider serviceProvider)
{
logger = serviceProvider.GetRequiredService<ILogger<InfoBarService>>();
taskContext = serviceProvider.GetRequiredService<ITaskContext>();
infobarClosedEventHandler = OnInfoBarClosed;
}
/// <inheritdoc/>
public ObservableCollection<InfoBar> Collection
public ObservableCollection<InfoBarOptions> Collection
{
get => collection ??= [];
}
@@ -51,33 +44,7 @@ internal sealed class InfoBarService : IInfoBarService
await taskContext.SwitchToMainThreadAsync();
InfoBar infoBar = new()
{
Severity = builder.Options.Severity,
Title = builder.Options.Title,
Message = builder.Options.Message,
Content = builder.Options.Content,
IsOpen = true,
ActionButton = builder.Options.ActionButton,
Transitions = [new AddDeleteThemeTransition()],
};
infoBar.Closed += infobarClosedEventHandler;
ArgumentNullException.ThrowIfNull(collection);
collection.Add(infoBar);
if (builder.Options.MilliSecondsDelay > 0)
{
await Delay.FromMilliSeconds(builder.Options.MilliSecondsDelay).ConfigureAwait(true);
collection.Remove(infoBar);
infoBar.IsOpen = false;
}
}
private void OnInfoBarClosed(InfoBar sender, InfoBarClosedEventArgs args)
{
ArgumentNullException.ThrowIfNull(collection);
taskContext.BeginInvokeOnMainThread(() => collection.Remove(sender));
sender.Closed -= infobarClosedEventHandler;
collection.Add(builder.Options);
}
}

View File

@@ -2,7 +2,6 @@
// Licensed under the MIT license.
using Microsoft.UI.Xaml.Controls;
using Snap.Hutao.Control.Builder.ButtonBase;
using Snap.Hutao.Core.Abstraction.Extension;
namespace Snap.Hutao.Service.Notification;
@@ -21,7 +20,7 @@ internal static class InfoBarServiceExtension
public static void Information(this IInfoBarService infoBarService, string title, string message, string buttonContent, ICommand buttonCommand, int milliSeconds = 5000)
{
infoBarService.Information(builder => builder.SetTitle(title).SetMessage(message).SetActionButton(buttonBuilder => buttonBuilder.SetContent(buttonContent).SetCommand(buttonCommand)).SetDelay(milliSeconds));
infoBarService.Information(builder => builder.SetTitle(title).SetMessage(message).SetActionButtonContent(buttonContent).SetActionButtonCommand(buttonCommand).SetDelay(milliSeconds));
}
public static void Information(this IInfoBarService infoBarService, Action<IInfoBarOptionsBuilder> configure)
@@ -56,7 +55,7 @@ internal static class InfoBarServiceExtension
public static void Warning(this IInfoBarService infoBarService, string title, string message, string buttonContent, ICommand buttonCommand, int milliSeconds = 30000)
{
infoBarService.Warning(builder => builder.SetTitle(title).SetMessage(message).SetActionButton(buttonBuilder => buttonBuilder.SetContent(buttonContent).SetCommand(buttonCommand)).SetDelay(milliSeconds));
infoBarService.Warning(builder => builder.SetTitle(title).SetMessage(message).SetActionButtonContent(buttonContent).SetActionButtonCommand(buttonCommand).SetDelay(milliSeconds));
}
public static void Warning(this IInfoBarService infoBarService, Action<IInfoBarOptionsBuilder> configure)
@@ -76,7 +75,7 @@ internal static class InfoBarServiceExtension
public static void Error(this IInfoBarService infoBarService, string title, string message, string buttonContent, ICommand buttonCommand, int milliSeconds = 0)
{
infoBarService.Error(builder => builder.SetTitle(title).SetMessage(message).SetActionButton(buttonBuilder => buttonBuilder.SetContent(buttonContent).SetCommand(buttonCommand)).SetDelay(milliSeconds));
infoBarService.Error(builder => builder.SetTitle(title).SetMessage(message).SetActionButtonContent(buttonContent).SetActionButtonCommand(buttonCommand).SetDelay(milliSeconds));
}
public static void Error(this IInfoBarService infoBarService, Exception ex, int milliSeconds = 0)
@@ -91,7 +90,7 @@ internal static class InfoBarServiceExtension
public static void Error(this IInfoBarService infoBarService, Exception ex, string subtitle, string buttonContent, ICommand buttonCommand, int milliSeconds = 0)
{
infoBarService.Error(builder => builder.SetTitle(ex.GetType().Name).SetMessage($"{subtitle}\n{ex.Message}").SetActionButton(buttonBuilder => buttonBuilder.SetContent(buttonContent).SetCommand(buttonCommand)).SetDelay(milliSeconds));
infoBarService.Error(builder => builder.SetTitle(ex.GetType().Name).SetMessage($"{subtitle}\n{ex.Message}").SetActionButtonContent(buttonContent).SetActionButtonCommand(buttonCommand).SetDelay(milliSeconds));
}
public static void Error(this IInfoBarService infoBarService, Action<IInfoBarOptionsBuilder> configure)

View File

@@ -5,68 +5,95 @@
xmlns:cw="using:CommunityToolkit.WinUI"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mxi="using:Microsoft.Xaml.Interactivity"
xmlns:shcb="using:Snap.Hutao.Control.Behavior"
xmlns:shcm="using:Snap.Hutao.Control.Markup"
xmlns:shsn="using:Snap.Hutao.Service.Notification"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<AcrylicBrush
x:Key="InfoBarErrorSeverityBackgroundBrush"
FallbackColor="#FDE7E9"
TintColor="#FDE7E9"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarWarningSeverityBackgroundBrush"
FallbackColor="#FFF4CE"
TintColor="#FFF4CE"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarSuccessSeverityBackgroundBrush"
FallbackColor="#DFF6DD"
TintColor="#DFF6DD"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
FallbackColor="#80F6F6F6"
TintColor="#80F6F6F6"
TintOpacity="0.6"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<AcrylicBrush
x:Key="InfoBarErrorSeverityBackgroundBrush"
FallbackColor="#442726"
TintColor="#442726"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarWarningSeverityBackgroundBrush"
FallbackColor="#433519"
TintColor="#433519"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarSuccessSeverityBackgroundBrush"
FallbackColor="#393D1B"
TintColor="#393D1B"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
FallbackColor="#34424d"
TintColor="#34424d"
TintOpacity="0.6"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<DataTemplate x:Key="InfoBarTemplate" x:DataType="shsn:InfoBarOptions">
<InfoBar
Title="{Binding Title}"
Content="{Binding Content}"
IsOpen="True"
Message="{Binding Message}"
Closed="OnInfoBarClosed"
Severity="{Binding Severity}">
<InfoBar.Transitions>
<AddDeleteThemeTransition/>
</InfoBar.Transitions>
<InfoBar.ActionButton>
<Button
Command="{Binding ActionButtonCommand}"
Content="{Binding ActionButtonContent}"
Visibility="{Binding ActionButtonContent, Converter={StaticResource EmptyObjectToVisibilityConverter}}"/>
</InfoBar.ActionButton>
<mxi:Interaction.Behaviors>
<shcb:InfoBarDelayCloseBehavior MilliSecondsDelay="{Binding MilliSecondsDelay}"/>
</mxi:Interaction.Behaviors>
</InfoBar>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ItemsControl
MaxWidth="640"
Margin="32,48,32,32"
VerticalAlignment="Bottom"
ItemContainerTransitions="{StaticResource RepositionThemeTransitions}"
ItemTemplate="{StaticResource InfoBarTemplate}"
ItemsSource="{x:Bind InfoBars}"
Visibility="{x:Bind VisibilityButton.IsChecked, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}">
<ItemsControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<AcrylicBrush
x:Key="InfoBarErrorSeverityBackgroundBrush"
FallbackColor="#FDE7E9"
TintColor="#FDE7E9"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarWarningSeverityBackgroundBrush"
FallbackColor="#FFF4CE"
TintColor="#FFF4CE"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarSuccessSeverityBackgroundBrush"
FallbackColor="#DFF6DD"
TintColor="#DFF6DD"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
FallbackColor="#80F6F6F6"
TintColor="#80F6F6F6"
TintOpacity="0.6"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<AcrylicBrush
x:Key="InfoBarErrorSeverityBackgroundBrush"
FallbackColor="#442726"
TintColor="#442726"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarWarningSeverityBackgroundBrush"
FallbackColor="#433519"
TintColor="#433519"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarSuccessSeverityBackgroundBrush"
FallbackColor="#393D1B"
TintColor="#393D1B"
TintOpacity="0.6"/>
<AcrylicBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
FallbackColor="#34424d"
TintColor="#34424d"
TintOpacity="0.6"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</ItemsControl.Resources>
</ItemsControl>
Visibility="{x:Bind VisibilityButton.IsChecked, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}"/>
<Border
Margin="16"

View File

@@ -13,7 +13,7 @@ namespace Snap.Hutao.View;
/// <summary>
/// 信息条视图
/// </summary>
[DependencyProperty("InfoBars", typeof(ObservableCollection<InfoBar>))]
[DependencyProperty("InfoBars", typeof(ObservableCollection<InfoBarOptions>))]
internal sealed partial class InfoBarView : UserControl
{
private readonly IInfoBarService infoBarService;
@@ -35,4 +35,9 @@ internal sealed partial class InfoBarView : UserControl
{
LocalSetting.Set(SettingKeys.IsInfoBarToggleChecked, ((ToggleButton)sender).IsChecked ?? false);
}
private void OnInfoBarClosed(InfoBar sender, InfoBarClosedEventArgs args)
{
InfoBars.Remove((InfoBarOptions)sender.DataContext);
}
}