|
@@ -2,7 +2,6 @@ using System;
|
|
|
using System.Collections;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
-using System.Threading.Tasks;
|
|
|
using Avalonia.Controls.Metadata;
|
|
|
using Avalonia.Controls.Primitives;
|
|
|
using Avalonia.Threading;
|
|
@@ -17,8 +16,12 @@ namespace Avalonia.Controls.Notifications
|
|
|
[PseudoClasses(":topleft", ":topright", ":bottomleft", ":bottomright", ":topcenter", ":bottomcenter")]
|
|
|
public class WindowNotificationManager : TemplatedControl, IManagedNotificationManager
|
|
|
{
|
|
|
- private IList? _items;
|
|
|
- private readonly Dictionary<object, NotificationCard> _notificationCards = new ();
|
|
|
+ private IList _items = new List<Control>();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Currently active notifications.
|
|
|
+ /// </summary>
|
|
|
+ internal IEnumerable<NotificationCard> Notifications => _items.OfType<NotificationCard>();
|
|
|
|
|
|
/// <summary>
|
|
|
/// Defines the <see cref="Position"/> property.
|
|
@@ -81,9 +84,13 @@ namespace Avalonia.Controls.Notifications
|
|
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
|
|
{
|
|
|
base.OnApplyTemplate(e);
|
|
|
-
|
|
|
+
|
|
|
var itemsControl = e.NameScope.Find<Panel>("PART_Items");
|
|
|
- _items = itemsControl?.Children;
|
|
|
+
|
|
|
+ if (itemsControl?.Children is not null)
|
|
|
+ {
|
|
|
+ _items = itemsControl.Children;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
@@ -114,11 +121,11 @@ namespace Avalonia.Controls.Notifications
|
|
|
/// <param name="onClick">an Action to be run when the notification is clicked</param>
|
|
|
/// <param name="onClose">an Action to be run when the notification is closed</param>
|
|
|
/// <param name="classes">style classes to apply</param>
|
|
|
- public async void Show(object content,
|
|
|
- NotificationType type,
|
|
|
+ public void Show(object content,
|
|
|
+ NotificationType type,
|
|
|
TimeSpan? expiration = null,
|
|
|
- Action? onClick = null,
|
|
|
- Action? onClose = null,
|
|
|
+ Action? onClick = null,
|
|
|
+ Action? onClose = null,
|
|
|
string[]? classes = null)
|
|
|
{
|
|
|
Dispatcher.UIThread.VerifyAccess();
|
|
@@ -141,9 +148,7 @@ namespace Avalonia.Controls.Notifications
|
|
|
notificationControl.NotificationClosed += (sender, args) =>
|
|
|
{
|
|
|
onClose?.Invoke();
|
|
|
-
|
|
|
- _items?.Remove(sender);
|
|
|
- _notificationCards.Remove(content);
|
|
|
+ _items.Remove(notificationControl);
|
|
|
};
|
|
|
|
|
|
notificationControl.PointerPressed += (sender, args) =>
|
|
@@ -153,49 +158,31 @@ namespace Avalonia.Controls.Notifications
|
|
|
(sender as NotificationCard)?.Close();
|
|
|
};
|
|
|
|
|
|
- Dispatcher.UIThread.Post(() =>
|
|
|
- {
|
|
|
- _items?.Add(notificationControl);
|
|
|
- _notificationCards.Add(content, notificationControl);
|
|
|
+ _items.Add(notificationControl);
|
|
|
|
|
|
- if (_items?.OfType<NotificationCard>().Count(i => !i.IsClosing) > MaxItems)
|
|
|
- {
|
|
|
- _items.OfType<NotificationCard>().First(i => !i.IsClosing).Close();
|
|
|
- }
|
|
|
- });
|
|
|
+ if (Notifications.Count(i => !i.IsClosing) > MaxItems)
|
|
|
+ {
|
|
|
+ Notifications.First(i => !i.IsClosing).Close();
|
|
|
+ }
|
|
|
|
|
|
if (expiration == TimeSpan.Zero)
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- await Task.Delay(expiration ?? TimeSpan.FromSeconds(5));
|
|
|
-
|
|
|
- notificationControl.Close();
|
|
|
-
|
|
|
- _notificationCards.Remove(content);
|
|
|
+ DispatcherTimer.RunOnce(notificationControl.Close, expiration ?? TimeSpan.FromSeconds(5));
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
- public void Close(INotification notification)
|
|
|
- {
|
|
|
- Dispatcher.UIThread.VerifyAccess();
|
|
|
-
|
|
|
- if (_notificationCards.Remove(notification, out var notificationCard))
|
|
|
- {
|
|
|
- notificationCard.Close();
|
|
|
- }
|
|
|
- }
|
|
|
+ public void Close(INotification notification) => Close(notification as object);
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
public void Close(object content)
|
|
|
{
|
|
|
Dispatcher.UIThread.VerifyAccess();
|
|
|
|
|
|
- if (_notificationCards.Remove(content, out var notificationCard))
|
|
|
- {
|
|
|
- notificationCard.Close();
|
|
|
- }
|
|
|
+ var cardsToClose = Notifications.Where(x => x.Content?.Equals(content) ?? false);
|
|
|
+ cardsToClose?.Do(x => x.Close());
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc/>
|
|
@@ -203,12 +190,7 @@ namespace Avalonia.Controls.Notifications
|
|
|
{
|
|
|
Dispatcher.UIThread.VerifyAccess();
|
|
|
|
|
|
- foreach (var kvp in _notificationCards)
|
|
|
- {
|
|
|
- kvp.Value.Close();
|
|
|
- }
|
|
|
-
|
|
|
- _notificationCards.Clear();
|
|
|
+ Notifications.Do(x => x.Close());
|
|
|
}
|
|
|
|
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
@@ -225,7 +207,7 @@ namespace Avalonia.Controls.Notifications
|
|
|
{
|
|
|
base.OnDetachedFromVisualTree(e);
|
|
|
|
|
|
- _notificationCards.Clear();
|
|
|
+ _items.Clear();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -249,7 +231,7 @@ namespace Avalonia.Controls.Notifications
|
|
|
adornerLayer.Children.Remove(this);
|
|
|
AdornerLayer.SetAdornedElement(this, null);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// Reinstall notification manager on template reapplied.
|
|
|
var topLevel = (TopLevel)sender!;
|
|
|
topLevel.TemplateApplied -= TopLevelOnTemplateApplied;
|