Toast notification navigations and some improvements for list view selection.

This commit is contained in:
Burak Kaan Köse
2025-11-12 15:44:43 +01:00
parent 16e06af76f
commit 777219ab87
14 changed files with 300 additions and 190 deletions
@@ -217,6 +217,42 @@ public class WinoMailCollection : ObservableRecipient, IRecipient<SelectedItemsC
return !string.IsNullOrEmpty(threadId) && _threadIdToItemsMap.ContainsKey(threadId);
}
/// <summary>
/// Finds a MailItemViewModel by its UniqueId, searching through all items including those inside threads.
/// </summary>
/// <param name="uniqueId">The UniqueId of the mail item to find.</param>
/// <returns>The MailItemViewModel if found, otherwise null.</returns>
public MailItemViewModel Find(Guid uniqueId)
{
// First check the cache for fast lookup
if (_uniqueIdToMailItemMap.TryGetValue(uniqueId, out var cachedMailItem))
{
return cachedMailItem;
}
// If not in cache, search through all groups
foreach (var group in _mailItemSource)
{
foreach (var item in group)
{
if (item is MailItemViewModel mailItem && mailItem.MailCopy.UniqueId == uniqueId)
{
return mailItem;
}
else if (item is ThreadMailItemViewModel threadItem)
{
var foundInThread = threadItem.ThreadEmails.FirstOrDefault(e => e.MailCopy.UniqueId == uniqueId);
if (foundInThread != null)
{
return foundInThread;
}
}
}
}
return null;
}
private async Task InsertItemInternalAsync(object groupKey, IMailListItem mailItem)
{
UpdateUniqueIdHashes(mailItem, true);
@@ -184,7 +184,19 @@ public partial class ThreadMailItemViewModel : ObservableRecipient, IMailListIte
if (email.MailCopy.ThreadId != _threadId)
throw new ArgumentException($"Email ThreadId '{email.MailCopy.ThreadId}' does not match expander ThreadId '{_threadId}'");
ThreadEmails.Add(email);
// Insert email in sorted order by CreationDate (newest first, oldest last)
var insertIndex = 0;
for (int i = 0; i < ThreadEmails.Count; i++)
{
if (ThreadEmails[i].MailCopy.CreationDate < email.MailCopy.CreationDate)
{
insertIndex = i;
break;
}
insertIndex = i + 1;
}
ThreadEmails.Insert(insertIndex, email);
// Reassign to trigger property change notifications
ThreadEmails = ThreadEmails;
}
+10 -24
View File
@@ -72,6 +72,7 @@ public partial class MailListPageViewModel : MailBaseViewModel,
private readonly IAccountService _accountService;
private readonly IMailDialogService _mailDialogService;
private readonly IMailService _mailService;
private readonly INotificationBuilder _notificationBuilder;
private readonly IFolderService _folderService;
private readonly IContextMenuItemService _contextMenuItemService;
private readonly IWinoRequestDelegator _winoRequestDelegator;
@@ -155,6 +156,7 @@ public partial class MailListPageViewModel : MailBaseViewModel,
IMailDialogService mailDialogService,
IMailService mailService,
IStatePersistanceService statePersistenceService,
INotificationBuilder notificationBuilder,
IFolderService folderService,
IContextMenuItemService contextMenuItemService,
IWinoRequestDelegator winoRequestDelegator,
@@ -175,6 +177,7 @@ public partial class MailListPageViewModel : MailBaseViewModel,
PreferencesService = preferencesService;
ThemeService = themeService;
StatePersistenceService = statePersistenceService;
_notificationBuilder = notificationBuilder;
NavigationService = navigationService;
SelectedFilterOption = FilterOptions[0];
@@ -468,6 +471,10 @@ public partial class MailListPageViewModel : MailBaseViewModel,
[RelayCommand]
private void SyncFolder()
{
var mails = MailCollection.SelectedItems;
_notificationBuilder.CreateNotificationsAsync(mails.Select(a => a.MailCopy));
return;
if (!CanSynchronize) return;
// Only synchronize listed folders.
@@ -710,7 +717,7 @@ public partial class MailListPageViewModel : MailBaseViewModel,
await MailCollection.RemoveAsync(removedMail);
if (nextItem != null)
WeakReferenceMessenger.Default.Send(new SelectMailItemContainerEvent(nextItem, ScrollToItem: true));
WeakReferenceMessenger.Default.Send(new SelectMailItemContainerEvent(nextItem.UniqueId, ScrollToItem: true));
else if (isDeletedMailSelected)
{
// There are no next item to select, but we removed the last item which was selected.
@@ -1022,30 +1029,9 @@ public partial class MailListPageViewModel : MailBaseViewModel,
void IRecipient<MailItemNavigationRequested>.Receive(MailItemNavigationRequested message)
{
Debug.WriteLine($"Mail item navigation requested");
// Find mail item and add to selected items.
// TODO: Remove this.
MailItemViewModel navigatingMailItem = null;
ThreadMailItemViewModel threadMailItemViewModel = null;
for (int i = 0; i < 3; i++)
{
var mailContainer = MailCollection.GetMailItemContainer(message.UniqueMailId);
if (mailContainer != null)
{
navigatingMailItem = mailContainer.ItemViewModel;
threadMailItemViewModel = mailContainer.ThreadViewModel;
break;
}
}
if (threadMailItemViewModel != null)
threadMailItemViewModel.IsThreadExpanded = true;
if (navigatingMailItem != null)
WeakReferenceMessenger.Default.Send(new SelectMailItemContainerEvent(navigatingMailItem, message.ScrollToItem));
WeakReferenceMessenger.Default.Send(new SelectMailItemContainerEvent(message.UniqueMailId, message.ScrollToItem));
}
#endregion
@@ -1,8 +1,8 @@
using Wino.Mail.ViewModels.Data;
using System;
namespace Wino.Mail.ViewModels.Messages;
/// <summary>
/// When listing view model manipulated the selected mail container in the UI.
/// </summary>
public record SelectMailItemContainerEvent(MailItemViewModel SelectedMailViewModel, bool ScrollToItem = false);
public record SelectMailItemContainerEvent(Guid MailUniqueId, bool ScrollToItem = false);