feat(settings): make slide-out alerts persist until dismissed
Add a persisted global App Settings switch. Off keeps the existing per-severity lifetimes (errors remain sticky); on makes every alert non-expiring and closes it when its body is clicked. The NotificationService supplies the current setting to each toast request. StickyNotificationIntegrationTests covers persistence and both request modes. 618 tests green, clean build with 0 warnings. Reference: Notification.Wpf exposes a CloseOnClick request option: https://github.com/G-Stas/Notification.Wpf
This commit is contained in:
@@ -10,7 +10,8 @@ namespace ytLive.Services;
|
||||
/// <summary>
|
||||
/// Toast notifications rendered inside the main window's <c>ToastArea</c>, whose
|
||||
/// position is configurable in App Settings (bottom-right by default). Info/success auto-dismiss after ~4s,
|
||||
/// warnings ~8s, errors stay until dismissed. Calls from any thread are
|
||||
/// warnings ~8s, errors stay until dismissed. App Settings can make all alerts sticky and
|
||||
/// dismissible by clicking the card. Calls from any thread are
|
||||
/// marshalled to the captured dispatcher.
|
||||
/// </summary>
|
||||
public sealed class NotificationService : INotificationService
|
||||
@@ -28,35 +29,49 @@ public sealed class NotificationService : INotificationService
|
||||
|
||||
private readonly NotificationManager _manager = new();
|
||||
private readonly Dispatcher _dispatcher;
|
||||
private readonly Func<bool> _stickyAlertsUntilDismissed;
|
||||
|
||||
public NotificationService()
|
||||
: this(Application.Current?.Dispatcher)
|
||||
: this(Application.Current?.Dispatcher, static () => false)
|
||||
{
|
||||
}
|
||||
|
||||
internal NotificationService(Dispatcher? dispatcher)
|
||||
: this(dispatcher, static () => false)
|
||||
{
|
||||
}
|
||||
|
||||
internal NotificationService(Dispatcher? dispatcher, Func<bool> stickyAlertsUntilDismissed)
|
||||
{
|
||||
_dispatcher = dispatcher ?? Dispatcher.CurrentDispatcher;
|
||||
_stickyAlertsUntilDismissed = stickyAlertsUntilDismissed;
|
||||
NotificationConstants.NotificationCornerRadius = new CornerRadius(8);
|
||||
NotificationConstants.KeepNotificationVisibleOnMouseOver = true;
|
||||
}
|
||||
|
||||
public void Show(string title, string message, AppNotificationSeverity severity)
|
||||
{
|
||||
var request = BuildRequest(title, message, severity);
|
||||
_dispatcher.Invoke(() => _manager.Show(request));
|
||||
_dispatcher.Invoke(() => _manager.Show(BuildRequestForCurrentSettings(title, message, severity)));
|
||||
}
|
||||
|
||||
internal static NotificationRequest BuildRequest(string title, string message, AppNotificationSeverity severity)
|
||||
internal NotificationRequest BuildRequestForCurrentSettings(string title, string message,
|
||||
AppNotificationSeverity severity)
|
||||
=> BuildRequest(title, message, severity, _stickyAlertsUntilDismissed());
|
||||
|
||||
internal static NotificationRequest BuildRequest(string title, string message,
|
||||
AppNotificationSeverity severity, bool stickyUntilDismissed = false)
|
||||
{
|
||||
var (backgroundHex, expirationSeconds) = Cards[severity];
|
||||
var builder = NotificationBuilder
|
||||
.Create(title, message)
|
||||
.InArea(AreaName)
|
||||
.WithBackground(NotificationColor.FromHex(backgroundHex))
|
||||
.WithForeground(NotificationColor.FromHex(ThemeBrush.Hex("Brush.OnSurface")));
|
||||
.WithForeground(NotificationColor.FromHex(ThemeBrush.Hex("Brush.OnSurface")))
|
||||
.CloseOnClick(stickyUntilDismissed);
|
||||
|
||||
if (severity == AppNotificationSeverity.Error)
|
||||
if (stickyUntilDismissed)
|
||||
builder.NeverExpires();
|
||||
else if (severity == AppNotificationSeverity.Error)
|
||||
builder.NeverExpires();
|
||||
else
|
||||
builder.ExpiresInSeconds(expirationSeconds);
|
||||
|
||||
Reference in New Issue
Block a user