From c7fb6483872631d36692ebaa804e250a6cdf6ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sat, 7 Feb 2026 15:29:19 +0100 Subject: [PATCH] Thread selection improvements --- .../Views/Mail/MailListPage.xaml.cs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs b/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs index d05785e1..aab539b8 100644 --- a/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs +++ b/Wino.Mail.WinUI/Views/Mail/MailListPage.xaml.cs @@ -192,10 +192,15 @@ public sealed partial class MailListPage : MailListPageAbstract, if (sender is MailItemDisplayInformationControl control && args.TryGetPosition(sender, out Point p)) { IEnumerable targetItems; - if (!ViewModel.MailCollection.SelectedItems.Contains(control.ActionItem)) + + if (control.ActionItem is ThreadMailItemViewModel threadItem) + { + await SelectThreadForContextMenuAsync(threadItem); + } + else if (control.ActionItem is MailItemViewModel mailItem && !ViewModel.MailCollection.SelectedItems.Contains(mailItem)) { // Right clicked item is not selected. Select. - await WinoClickItemInternalAsync(control.ActionItem, true); + await WinoClickItemInternalAsync(mailItem, true); } // Default to all selected items. @@ -214,6 +219,36 @@ public sealed partial class MailListPage : MailListPageAbstract, } } + private async Task SelectThreadForContextMenuAsync(ThreadMailItemViewModel threadItem) + { + bool isThreadFullySelected = threadItem.IsSelected && threadItem.ThreadEmails.All(a => a.IsSelected); + bool hasSelectionsOutsideThread = ViewModel.MailCollection.SelectedItems.Any(a => !threadItem.ThreadEmails.Contains(a)); + + // No-op to avoid visual collapse/re-expand flicker on right-click. + if (threadItem.IsThreadExpanded && isThreadFullySelected && !hasSelectionsOutsideThread) + { + return; + } + + // Context menu on a thread should target the whole thread and keep it expanded. + await ViewModel.MailCollection.UnselectAllAsync(); + await ViewModel.MailCollection.ExecuteWithoutRaiseSelectionChangedAsync(item => + { + if (item is ThreadMailItemViewModel thread && !ReferenceEquals(thread, threadItem)) + { + thread.IsThreadExpanded = false; + } + }, true); + + threadItem.IsSelected = true; + threadItem.IsThreadExpanded = true; + + foreach (var threadMail in threadItem.ThreadEmails) + { + threadMail.IsSelected = true; + } + } + private async Task GetMailOperationFromFlyoutAsync(IEnumerable availableActions, UIElement showAtElement, double x,