From c461a4daede1fe3bfdb43e3a33b91c1312e54d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Mon, 27 Oct 2025 23:22:55 +0100 Subject: [PATCH] Swipe action implementations. --- Wino.Mail.ViewModels/MailListPageViewModel.cs | 27 +++- .../Messages/SwipeActionRequested.cs | 9 ++ .../Controls/ListView/WinoListViewStyles.xaml | 148 +++++++++++------- .../Controls/WinoSwipeControlItems.cs | 135 ++++++++++++++++ 4 files changed, 260 insertions(+), 59 deletions(-) create mode 100644 Wino.Mail.ViewModels/Messages/SwipeActionRequested.cs create mode 100644 Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs diff --git a/Wino.Mail.ViewModels/MailListPageViewModel.cs b/Wino.Mail.ViewModels/MailListPageViewModel.cs index a5bab176..ef290739 100644 --- a/Wino.Mail.ViewModels/MailListPageViewModel.cs +++ b/Wino.Mail.ViewModels/MailListPageViewModel.cs @@ -41,7 +41,8 @@ public partial class MailListPageViewModel : MailBaseViewModel, IRecipient, IRecipient, IRecipient, - IRecipient> + IRecipient>, + IRecipient { private bool isChangingFolder = false; @@ -1126,4 +1127,28 @@ public partial class MailListPageViewModel : MailBaseViewModel, } } } + + public async void Receive(SwipeActionRequested message) + { + if (message.MailItem == null) return; + + // Get mail copies based on the mail item type + IEnumerable mailCopies; + + if (message.MailItem is MailItemViewModel singleItem) + { + mailCopies = new[] { singleItem.MailCopy }; + } + else if (message.MailItem is ThreadMailItemViewModel threadItem) + { + mailCopies = threadItem.ThreadEmails.Select(e => e.MailCopy); + } + else + { + return; // Unknown mail item type + } + + var package = new MailOperationPreperationRequest(message.Operation, mailCopies); + await ExecuteMailOperationAsync(package); + } } diff --git a/Wino.Mail.ViewModels/Messages/SwipeActionRequested.cs b/Wino.Mail.ViewModels/Messages/SwipeActionRequested.cs new file mode 100644 index 00000000..236cc440 --- /dev/null +++ b/Wino.Mail.ViewModels/Messages/SwipeActionRequested.cs @@ -0,0 +1,9 @@ +using Wino.Core.Domain.Enums; +using Wino.Mail.ViewModels.Data; + +namespace Wino.Mail.ViewModels.Messages; + +/// +/// When a swipe action is performed on a mail item container. +/// +public record SwipeActionRequested(MailOperation Operation, IMailListItem MailItem); \ No newline at end of file diff --git a/Wino.Mail.WinUI/Controls/ListView/WinoListViewStyles.xaml b/Wino.Mail.WinUI/Controls/ListView/WinoListViewStyles.xaml index 356f1d9f..f1527f36 100644 --- a/Wino.Mail.WinUI/Controls/ListView/WinoListViewStyles.xaml +++ b/Wino.Mail.WinUI/Controls/ListView/WinoListViewStyles.xaml @@ -18,35 +18,52 @@ - - - - - + + + + + + + + + + + + - - - - + + + + + + + + @@ -80,8 +97,7 @@ - - + @@ -95,34 +111,50 @@ - - - - - - + + + + + + + + + + + + + - + + + + @@ -156,7 +188,7 @@ - + diff --git a/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs b/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs new file mode 100644 index 00000000..c3a412af --- /dev/null +++ b/Wino.Mail.WinUI/Controls/WinoSwipeControlItems.cs @@ -0,0 +1,135 @@ +using System.Linq; +using CommunityToolkit.Mvvm.Messaging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Wino.Core.Domain.Enums; +using Wino.Core.Domain.Interfaces; +using Wino.Core.WinUI; +using Wino.Helpers; +using Wino.Mail.ViewModels.Data; + +namespace Wino.Controls; + +public partial class WinoSwipeControlItems : SwipeItems +{ + public static readonly DependencyProperty SwipeOperationProperty = DependencyProperty.Register(nameof(SwipeOperation), typeof(MailOperation), typeof(WinoSwipeControlItems), new PropertyMetadata(default(MailOperation), new PropertyChangedCallback(OnItemsChanged))); + public static readonly DependencyProperty MailItemProperty = DependencyProperty.Register(nameof(MailItem), typeof(IMailListItem), typeof(WinoSwipeControlItems), new PropertyMetadata(null)); + public static readonly DependencyProperty IsRightSwipeProperty = DependencyProperty.Register(nameof(IsRightSwipe), typeof(bool), typeof(WinoSwipeControlItems), new PropertyMetadata(false, new PropertyChangedCallback(OnItemsChanged))); + + public WinoSwipeControlItems() + { + var preferencesService = WinoApplication.Current.Services.GetRequiredService(); + + SwipeOperation = IsRightSwipe ? preferencesService.RightSwipeOperation : preferencesService.LeftSwipeOperation; + } + + public IMailListItem MailItem + { + get { return (IMailListItem)GetValue(MailItemProperty); } + set { SetValue(MailItemProperty, value); } + } + + + public MailOperation SwipeOperation + { + get { return (MailOperation)GetValue(SwipeOperationProperty); } + set { SetValue(SwipeOperationProperty, value); } + } + + public bool IsRightSwipe + { + get { return (bool)GetValue(IsRightSwipeProperty); } + set { SetValue(IsRightSwipeProperty, value); } + } + + private static void OnItemsChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) + { + if (obj is WinoSwipeControlItems control) + { + control.BuildSwipeItems(); + } + } + + private void BuildSwipeItems() + { + this.Clear(); + + var swipeItem = GetSwipeItem(SwipeOperation); + + this.Add(swipeItem); + } + + private SwipeItem GetSwipeItem(MailOperation operation) + { + if (MailItem == null) return null; + + var finalOperation = operation; + + bool isSingleItem = MailItem is MailItemViewModel; + + if (isSingleItem) + { + var singleItem = MailItem as MailItemViewModel; + + if (operation == MailOperation.MarkAsRead && singleItem.IsRead) + finalOperation = MailOperation.MarkAsUnread; + else if (operation == MailOperation.MarkAsUnread && !singleItem.IsRead) + finalOperation = MailOperation.MarkAsRead; + } + else + { + var threadItem = MailItem as ThreadMailItemViewModel; + + if (operation == MailOperation.MarkAsRead && threadItem.ThreadEmails.All(a => a.IsRead)) + finalOperation = MailOperation.MarkAsUnread; + else if (operation == MailOperation.MarkAsUnread && threadItem.ThreadEmails.All(a => !a.IsRead)) + finalOperation = MailOperation.MarkAsRead; + } + + var item = new SwipeItem() + { + IconSource = new WinoFontIconSource() { Icon = XamlHelpers.GetWinoIconGlyph(finalOperation) }, + Text = XamlHelpers.GetOperationString(finalOperation), + }; + + item.Invoked += SwipeItemInvoked; + + return item; + } + + private void SwipeItemInvoked(SwipeItem sender, SwipeItemInvokedEventArgs args) + { + var swipeControl = args.SwipeControl; + swipeControl.Close(); + + if (MailItem == null) return; + + // Determine the final operation based on current settings and mail item state + var finalOperation = SwipeOperation; + + bool isSingleItem = MailItem is MailItemViewModel; + + if (isSingleItem) + { + var singleItem = MailItem as MailItemViewModel; + + if (SwipeOperation == MailOperation.MarkAsRead && singleItem.IsRead) + finalOperation = MailOperation.MarkAsUnread; + else if (SwipeOperation == MailOperation.MarkAsUnread && !singleItem.IsRead) + finalOperation = MailOperation.MarkAsRead; + } + else + { + var threadItem = MailItem as ThreadMailItemViewModel; + + if (SwipeOperation == MailOperation.MarkAsRead && threadItem.ThreadEmails.All(a => a.IsRead)) + finalOperation = MailOperation.MarkAsUnread; + else if (SwipeOperation == MailOperation.MarkAsUnread && threadItem.ThreadEmails.All(a => !a.IsRead)) + finalOperation = MailOperation.MarkAsRead; + } + + // Send message to MailListPageViewModel to handle the operation + CommunityToolkit.Mvvm.Messaging.WeakReferenceMessenger.Default.Send(new Mail.ViewModels.Messages.SwipeActionRequested(finalOperation, MailItem)); + } +}