From 43283b7218cf34a4de4ffbbc9d0560225f6e26dd Mon Sep 17 00:00:00 2001 From: Maicol Battistini Date: Sat, 26 Jul 2025 12:51:53 +0200 Subject: [PATCH] =?UTF-8?q?feat(notification):=20=E2=9C=A8=20Remove=20noti?= =?UTF-8?q?fication=20when=20read=20externally=20(#707)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(notification): ✨ Add notification removal feature Implemented a new method `RemoveNotificationAsync` in the `INotificationBuilder` interface to allow the removal of toast notifications for specific emails identified by a unique ID. This change enhances the notification management by ensuring that notifications can be cleared when emails are marked as read. The `NotificationBuilder` class has been updated to include logic for removing existing notifications and to use the unique ID as a tag for the toast notifications, facilitating their removal. Additionally, the `AppShellViewModel` has been modified to call this new method when an email is updated and marked as read. This improvement aims to provide a better user experience by keeping the notification area relevant and up-to-date. * feat(notification): ✨ Add MailReadStatusChanged event handling Introduced a new event system for handling email read status changes. This includes the addition of a listener in `NotificationBuilder` that removes notifications when an email is marked as read. • Added `MailReadStatusChanged` record to represent the event. • Registered a listener in `NotificationBuilder` to handle notification removal. • Removed the `OnMailUpdated` method from `AppShellViewModel`, delegating notification management to the new event system. • Updated `MailService` to send `MailReadStatusChanged` events when emails are marked as read. This change improves the communication between components and enhances the notification management system. * refactor: Remove comments * Little cleanup. --------- Co-authored-by: Burak Kaan Köse --- .../Interfaces/INotificationBuilder.cs | 5 ++++ Wino.Core.UWP/Services/NotificationBuilder.cs | 28 +++++++++++++++++-- Wino.Messages/UI/MailReadStatusChanged.cs | 5 ++++ Wino.Services/MailService.cs | 5 ++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 Wino.Messages/UI/MailReadStatusChanged.cs diff --git a/Wino.Core.Domain/Interfaces/INotificationBuilder.cs b/Wino.Core.Domain/Interfaces/INotificationBuilder.cs index 50528ab2..86961ad7 100644 --- a/Wino.Core.Domain/Interfaces/INotificationBuilder.cs +++ b/Wino.Core.Domain/Interfaces/INotificationBuilder.cs @@ -22,4 +22,9 @@ public interface INotificationBuilder /// Creates test notification for test purposes. /// Task CreateTestNotificationAsync(string title, string message); + + /// + /// Removes the toast notification for a specific mail by unique id. + /// + void RemoveNotification(Guid mailUniqueId); } diff --git a/Wino.Core.UWP/Services/NotificationBuilder.cs b/Wino.Core.UWP/Services/NotificationBuilder.cs index 6770c297..722979c3 100644 --- a/Wino.Core.UWP/Services/NotificationBuilder.cs +++ b/Wino.Core.UWP/Services/NotificationBuilder.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.WinUI.Notifications; using Serilog; using Windows.Data.Xml.Dom; @@ -11,7 +13,7 @@ using Wino.Core.Domain.Entities.Mail; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Interfaces; using Wino.Core.Domain.Models.MailItem; -using System.IO; +using Wino.Messaging.UI; namespace Wino.Core.UWP.Services; @@ -36,6 +38,11 @@ public class NotificationBuilder : INotificationBuilder _folderService = folderService; _mailService = mailService; _thumbnailService = thumbnailService; + + WeakReferenceMessenger.Default.Register(this, (r, msg) => + { + RemoveNotification(msg.UniqueId); + }); } public async Task CreateNotificationsAsync(Guid inboxFolderId, IEnumerable downloadedMailItems) @@ -81,7 +88,11 @@ public class NotificationBuilder : INotificationBuilder foreach (var mailItem in validItems) { if (mailItem.IsRead) + { + // Remove the notification for a specific mail if it exists + ToastNotificationManager.History.Remove(mailItem.UniqueId.ToString()); continue; + } var builder = new ToastContentBuilder(); builder.SetToastScenario(ToastScenario.Default); @@ -117,7 +128,8 @@ public class NotificationBuilder : INotificationBuilder Src = new Uri("ms-winsoundevent:Notification.Mail") }); - builder.Show(); + // Use UniqueId as tag to allow removal + builder.Show(toast => toast.Tag = mailItem.UniqueId.ToString()); } await UpdateTaskbarIconBadgeAsync(); @@ -230,4 +242,16 @@ public class NotificationBuilder : INotificationBuilder //await Task.CompletedTask; } + + public void RemoveNotification(Guid mailUniqueId) + { + try + { + ToastNotificationManager.History.Remove(mailUniqueId.ToString()); + } + catch (Exception ex) + { + Log.Error(ex, $"Failed to remove notification for mail {mailUniqueId}"); + } + } } diff --git a/Wino.Messages/UI/MailReadStatusChanged.cs b/Wino.Messages/UI/MailReadStatusChanged.cs new file mode 100644 index 00000000..0653ca71 --- /dev/null +++ b/Wino.Messages/UI/MailReadStatusChanged.cs @@ -0,0 +1,5 @@ +using System; + +namespace Wino.Messaging.UI; + +public record MailReadStatusChanged(Guid UniqueId); diff --git a/Wino.Services/MailService.cs b/Wino.Services/MailService.cs index 6de9fe22..c060d23e 100644 --- a/Wino.Services/MailService.cs +++ b/Wino.Services/MailService.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using CommunityToolkit.Mvvm.Messaging; using MimeKit; using Serilog; using SqlKata; @@ -584,6 +585,10 @@ public class MailService : BaseDatabaseService, IMailService if (item.IsRead == isRead) return false; item.IsRead = isRead; + if (isRead && item.UniqueId != Guid.Empty) + { + WeakReferenceMessenger.Default.Send(new MailReadStatusChanged(item.UniqueId)); + } return true; });