145 lines
4.2 KiB
C#
145 lines
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using MareSynchronos.Services.Mediator;
|
|
using MareSynchronos.MareConfiguration;
|
|
using MareSynchronos.MareConfiguration.Configurations;
|
|
using MareSynchronos.MareConfiguration.Models;
|
|
|
|
namespace MareSynchronos.Services.Notifications;
|
|
|
|
public enum NotificationCategory
|
|
{
|
|
AutoDetect,
|
|
Syncshell,
|
|
}
|
|
|
|
public sealed record NotificationEntry(NotificationCategory Category, string Id, string Title, string? Description, DateTime CreatedAt)
|
|
{
|
|
public static NotificationEntry AutoDetect(string uid, string displayName)
|
|
=> new(NotificationCategory.AutoDetect, uid, displayName, "Nouvelle demande d'appairage via AutoDetect.", DateTime.UtcNow);
|
|
|
|
public static NotificationEntry SyncshellPublic(string gid, string aliasOrGid)
|
|
=> new(NotificationCategory.Syncshell, gid, $"Syncshell publique: {aliasOrGid}", "La Syncshell est désormais visible via AutoDetect.", DateTime.UtcNow);
|
|
|
|
public static NotificationEntry SyncshellNotPublic(string gid, string aliasOrGid)
|
|
=> new(NotificationCategory.Syncshell, gid, $"Syncshell non publique: {aliasOrGid}", "La Syncshell n'est plus visible via AutoDetect.", DateTime.UtcNow);
|
|
}
|
|
|
|
public sealed class NotificationTracker
|
|
{
|
|
private const int MaxStored = 100;
|
|
|
|
private readonly MareMediator _mediator;
|
|
private readonly NotificationsConfigService _configService;
|
|
private readonly Dictionary<(NotificationCategory Category, string Id), NotificationEntry> _entries = new();
|
|
private readonly object _lock = new();
|
|
|
|
public NotificationTracker(MareMediator mediator, NotificationsConfigService configService)
|
|
{
|
|
_mediator = mediator;
|
|
_configService = configService;
|
|
LoadPersisted();
|
|
PublishState();
|
|
}
|
|
|
|
public void Upsert(NotificationEntry entry)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
_entries[(entry.Category, entry.Id)] = entry;
|
|
TrimIfNecessary_NoLock();
|
|
Persist_NoLock();
|
|
}
|
|
PublishState();
|
|
}
|
|
|
|
public void Remove(NotificationCategory category, string id)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
_entries.Remove((category, id));
|
|
Persist_NoLock();
|
|
}
|
|
PublishState();
|
|
}
|
|
|
|
public IReadOnlyList<NotificationEntry> GetEntries()
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return _entries.Values
|
|
.OrderBy(e => e.CreatedAt)
|
|
.ToList();
|
|
}
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
lock (_lock)
|
|
{
|
|
return _entries.Count;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void PublishState()
|
|
{
|
|
_mediator.Publish(new NotificationStateChanged(Count));
|
|
}
|
|
|
|
private void LoadPersisted()
|
|
{
|
|
try
|
|
{
|
|
var list = _configService.Current.Notifications ?? new List<StoredNotification>();
|
|
foreach (var s in list)
|
|
{
|
|
if (!Enum.TryParse<NotificationCategory>(s.Category, out var cat)) continue;
|
|
var entry = new NotificationEntry(cat, s.Id, s.Title, s.Description, s.CreatedAtUtc);
|
|
_entries[(entry.Category, entry.Id)] = entry;
|
|
}
|
|
TrimIfNecessary_NoLock();
|
|
}
|
|
catch
|
|
{
|
|
// ignore load errors, start empty
|
|
}
|
|
}
|
|
|
|
private void Persist_NoLock()
|
|
{
|
|
try
|
|
{
|
|
var stored = _entries.Values
|
|
.OrderBy(e => e.CreatedAt)
|
|
.Select(e => new StoredNotification
|
|
{
|
|
Category = e.Category.ToString(),
|
|
Id = e.Id,
|
|
Title = e.Title,
|
|
Description = e.Description,
|
|
CreatedAtUtc = e.CreatedAt
|
|
})
|
|
.ToList();
|
|
_configService.Current.Notifications = stored;
|
|
_configService.Save();
|
|
}
|
|
catch
|
|
{
|
|
// ignore persistence errors
|
|
}
|
|
}
|
|
|
|
private void TrimIfNecessary_NoLock()
|
|
{
|
|
if (_entries.Count <= MaxStored) return;
|
|
foreach (var kv in _entries.Values.OrderByDescending(v => v.CreatedAt).Skip(MaxStored).ToList())
|
|
{
|
|
_entries.Remove((kv.Category, kv.Id));
|
|
}
|
|
}
|
|
}
|