using System; using System.Collections.Generic; using System.Linq; using CommunityToolkit.Diagnostics; using OwlCore.AbstractUI.Models; using StrixMusic.Sdk.AppModels; using StrixMusic.Sdk.Services; using Windows.UI.Xaml; namespace StrixMusic.Sdk.WinUI.Services.NotificationService { /// public sealed class NotificationService : INotificationService { private readonly List _pendingNotifications; private readonly List _activeNotifications; /// public event EventHandler? NotificationRaised; /// public event EventHandler? NotificationDismissed; /// /// Raised when the notification margins are requested to be changed. /// public event EventHandler? NotificationMarginChanged; /// /// Raised when the notification alignment is requested to be changed. /// public event EventHandler<(HorizontalAlignment, VerticalAlignment)>? NotificationAlignmentChanged; /// /// Initializes a new instance of the class. /// public NotificationService() { _pendingNotifications = new List(); _activeNotifications = new List(); } /// event EventHandler? INotificationService.NotificationRaised { add => NotificationRaised += value; remove => NotificationRaised -= value; } /// event EventHandler? INotificationService.NotificationDismissed { add => NotificationDismissed += value; remove => NotificationDismissed -= value; } /// public int MaxActiveNotifications { get; set; } = 3; /// public Notification RaiseNotification(string title, string message) { var id = Guid.NewGuid().ToString(); var elementGroup = new AbstractUICollection(id) { Title = title, Subtitle = message, }; return RaiseNotification(elementGroup); } /// public Notification RaiseNotification(AbstractUICollection elementGroup) { var notification = new Notification(elementGroup); notification.Dismissed += Notification_Dismissed; _pendingNotifications.Add(notification); FireIfReady(); return notification; } private void Notification_Dismissed(object sender, EventArgs e) { if (sender is Notification notification) { var index = _activeNotifications.FindIndex(x => ReferenceEquals(x, notification)); if (index == -1) return; DismissNotificationInternal(index); } } /// /// Request that the notification margin be changed. /// /// The margin to put around the notification panel. public void ChangeNotificationMargins(Thickness thickness) { NotificationMarginChanged?.Invoke(this, thickness); } /// /// Request that the notification alignment be changed. /// /// The new horizontal alignment. /// The new verical alignment. public void ChangeNotificationAlignment(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) { NotificationAlignmentChanged?.Invoke(this, (horizontalAlignment, verticalAlignment)); } /// /// Dismisses the top notification and raises the next notification. /// public void DismissNotification(int? index = null) => DismissNotificationInternal(index); private void DismissNotificationInternal(int? index = null) { var targetNotification = _activeNotifications.ElementAtOrDefault(index ?? _pendingNotifications.Count - 1); Guard.IsNotNull(targetNotification, nameof(targetNotification)); _activeNotifications.Remove(targetNotification); NotificationDismissed?.Invoke(this, targetNotification); targetNotification.Dismissed -= Notification_Dismissed; FireIfReady(); } /// /// Fires the next notification if there is space for it. /// private void FireIfReady() { if (_pendingNotifications.Count > 0 && _activeNotifications.Count < MaxActiveNotifications) { var nextNotification = _pendingNotifications.FirstOrDefault(); if (nextNotification == null) return; _pendingNotifications.Remove(nextNotification); _activeNotifications.Add(nextNotification); NotificationRaised?.Invoke(this, nextNotification); } } } }