< Summary

Information
Class: MyNet.UI.Notifications.NotificationsManager
Assembly: MyNet.UI
File(s): https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/Notifications/NotificationsManager.cs
Tag: 323_28699572109
Line coverage
90%
Covered lines: 47
Uncovered lines: 5
Coverable lines: 52
Total lines: 146
Line coverage: 90.3%
Branch coverage
77%
Covered branches: 17
Total branches: 22
Branch coverage: 77.2%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
OnNotificationReceived(...)100%22100%
IsDuplicate(...)100%22100%
HookLifecycle(...)100%22100%
UnhookLifecycle(...)75%4485.71%
Remove(...)100%11100%
RemoveCore(...)50%4475%
Clear()100%11100%
ClearCore()75%4483.33%
Dispose()75%4487.5%

File(s)

https://raw.githubusercontent.com/sandre58/MyNet/85372080fe102cd9ee155ceab49ae000e7f66103/src/MyNet.UI/Notifications/NotificationsManager.cs

#LineLine coverage
 1// -----------------------------------------------------------------------
 2// <copyright file="NotificationsManager.cs" company="Stéphane ANDRE">
 3// Copyright (c) Stéphane ANDRE. All rights reserved.
 4// </copyright>
 5// -----------------------------------------------------------------------
 6
 7using System;
 8using System.Collections.Generic;
 9using System.Collections.ObjectModel;
 10using System.Linq;
 11using System.Reactive.Concurrency;
 12using System.Reactive.Linq;
 13using MyNet.UI.Notifications.Models;
 14using MyNet.UI.Threading;
 15
 16namespace MyNet.UI.Notifications;
 17
 18/// <summary>
 19/// Implements the <see cref="INotificationsManager"/> interface, managing a collection of notifications received from a
 20/// </summary>
 21public sealed class NotificationsManager : INotificationsManager, IDisposable
 22{
 1523    private readonly ObservableCollection<INotification> _items = [];
 1524    private readonly Dictionary<Guid, EventHandler<CloseRequestedEventArgs>> _closeHandlers = [];
 25    private readonly ISchedulerProvider _schedulerProvider;
 26    private readonly IDisposable _subscription;
 27    private bool _isDisposed;
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="NotificationsManager"/> class, subscribing to the notification stre
 31    /// </summary>
 32    /// <param name="service">The notification service to subscribe to for receiving notifications.</param>
 33    /// <param name="schedulerProvider">The scheduler provider to ensure UI thread safety.</param>
 34    public NotificationsManager(
 35        INotificationService service,
 36        ISchedulerProvider schedulerProvider)
 37    {
 1538        _schedulerProvider = schedulerProvider;
 1539        Notifications = new(_items);
 40
 1541        _subscription = service.Notifications
 1542            .ObserveOn(schedulerProvider.Ui)
 1543            .Subscribe(OnNotificationReceived);
 1544    }
 45
 46    /// <inheritdoc />
 47    public ReadOnlyObservableCollection<INotification> Notifications { get; }
 48
 49    /// <summary>
 50    /// Handles incoming notifications, checks for duplicates, then tracks lifecycle hooks for closable notifications.
 51    /// </summary>
 52    /// <param name="notification">The notification received from the service.</param>
 53    private void OnNotificationReceived(INotification notification)
 54    {
 1555        if (IsDuplicate(notification))
 356            return;
 57
 1258        _items.Add(notification);
 59
 1260        HookLifecycle(notification);
 1261    }
 62
 63    /// <summary>
 64    /// Determines whether the given notification is a duplicate of any existing notification in the collection, based o
 65    /// </summary>
 66    /// <param name="notification">The notification to check for duplication.</param>
 67    /// <returns>True if the notification is a duplicate; otherwise, false.</returns>
 68    private bool IsDuplicate(INotification notification) =>
 1569        notification is IDeduplicableNotification dedup && _items.Any(x =>
 1570            x is IDeduplicableNotification existing &&
 1571            dedup.IsDuplicateOf(existing));
 72
 73    /// <summary>
 74    /// Hooks into the lifecycle of a closable notification by subscribing to its CloseRequested event, allowing for aut
 75    /// </summary>
 76    /// <param name="notification">The closable notification to hook into.</param>
 77    private void HookLifecycle(INotification notification)
 78    {
 1279        if (notification is not IClosableNotification closableNotification)
 980            return;
 81
 382        _closeHandlers[notification.Id] = handler;
 383        closableNotification.CloseRequested += handler;
 384        return;
 85
 86        void handler(object? sender, CloseRequestedEventArgs e) => Remove(notification);
 87    }
 88
 89    private void UnhookLifecycle(INotification notification)
 90    {
 1291        if (notification is not IClosableNotification closableNotification)
 992            return;
 93
 394        if (!_closeHandlers.TryGetValue(notification.Id, out var handler))
 095            return;
 96
 397        closableNotification.CloseRequested -= handler;
 398        _closeHandlers.Remove(notification.Id);
 399    }
 100
 101    /// <inheritdoc />
 6102    public void Remove(INotification notification) => _schedulerProvider.Ui.Schedule(() => RemoveCore(notification));
 103
 104    private void RemoveCore(INotification notification)
 105    {
 6106        if (_isDisposed)
 0107            return;
 108
 6109        var item = _items.FirstOrDefault(x => x.Id == notification.Id);
 6110        if (item is null)
 0111            return;
 112
 6113        UnhookLifecycle(item);
 6114        _items.Remove(item);
 6115    }
 116
 117    /// <inheritdoc />
 3118    public void Clear() => _schedulerProvider.Ui.Schedule(ClearCore);
 119
 120    private void ClearCore()
 121    {
 3122        if (_isDisposed)
 0123            return;
 124
 12125        foreach (var item in _items.ToList())
 3126            UnhookLifecycle(item);
 127
 3128        _items.Clear();
 3129    }
 130
 131    /// <inheritdoc />
 132    public void Dispose()
 133    {
 15134        if (_isDisposed)
 0135            return;
 136
 15137        _isDisposed = true;
 15138        _subscription.Dispose();
 139
 36140        foreach (var item in _items.ToList())
 3141            UnhookLifecycle(item);
 142
 15143        _items.Clear();
 15144    }
 145}
 146