From f002ccfa3a4fd93a82fbdcaf83266eb15b9ad17d Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Mon, 26 Aug 2024 17:27:27 +0200 Subject: [PATCH 01/16] Replace WinoPivot with segmented --- Wino.Mail/Controls/WinoPivotControl.xaml | 123 ------------ Wino.Mail/Controls/WinoPivotControl.xaml.cs | 195 -------------------- Wino.Mail/Views/MailListPage.xaml | 43 ++--- Wino.Mail/Wino.Mail.csproj | 10 +- 4 files changed, 25 insertions(+), 346 deletions(-) delete mode 100644 Wino.Mail/Controls/WinoPivotControl.xaml delete mode 100644 Wino.Mail/Controls/WinoPivotControl.xaml.cs diff --git a/Wino.Mail/Controls/WinoPivotControl.xaml b/Wino.Mail/Controls/WinoPivotControl.xaml deleted file mode 100644 index a524e6d3..00000000 --- a/Wino.Mail/Controls/WinoPivotControl.xaml +++ /dev/null @@ -1,123 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Wino.Mail/Controls/WinoPivotControl.xaml.cs b/Wino.Mail/Controls/WinoPivotControl.xaml.cs deleted file mode 100644 index 975871bc..00000000 --- a/Wino.Mail/Controls/WinoPivotControl.xaml.cs +++ /dev/null @@ -1,195 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Numerics; -using System.Runtime.InteropServices.WindowsRuntime; -using System.Threading.Tasks; -using Windows.Foundation; -using Windows.Foundation.Collections; -using Windows.UI; -using Windows.UI.Composition; -using Windows.UI.Xaml; -using Windows.UI.Xaml.Controls; -using Windows.UI.Xaml.Controls.Primitives; -using Windows.UI.Xaml.Data; -using Windows.UI.Xaml.Input; -using Windows.UI.Xaml.Media; -using Windows.UI.Xaml.Navigation; -using Wino.Extensions; - -namespace Wino.Controls -{ - // TODO: Memory leak with FolderPivot bindings. - public sealed partial class WinoPivotControl : UserControl - { - private Compositor _compositor; - private ShapeVisual _shapeVisual; - private CompositionSpriteShape _spriteShape; - private CompositionRoundedRectangleGeometry _roundedRectangle; - - public event EventHandler SelectionChanged; - - public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(WinoPivotControl), new PropertyMetadata(null)); - public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(WinoPivotControl), new PropertyMetadata(null)); - public static readonly DependencyProperty SelectorPipeColorProperty = DependencyProperty.Register(nameof(SelectorPipeColor), typeof(SolidColorBrush), typeof(WinoPivotControl), new PropertyMetadata(Colors.Transparent, OnSelectorPipeColorChanged)); - public static readonly DependencyProperty DataTemplateProperty = DependencyProperty.Register(nameof(DataTemplate), typeof(DataTemplate), typeof(WinoPivotControl), new PropertyMetadata(null)); - - public DataTemplate DataTemplate - { - get { return (DataTemplate)GetValue(DataTemplateProperty); } - set { SetValue(DataTemplateProperty, value); } - } - - public SolidColorBrush SelectorPipeColor - { - get { return (SolidColorBrush)GetValue(SelectorPipeColorProperty); } - set { SetValue(SelectorPipeColorProperty, value); } - } - - public object SelectedItem - { - get { return (object)GetValue(SelectedItemProperty); } - set { SetValue(SelectedItemProperty, value); } - } - - public object ItemsSource - { - get { return (object)GetValue(ItemsSourceProperty); } - set { SetValue(ItemsSourceProperty, value); } - } - - private static void OnSelectorPipeColorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) - { - if (obj is WinoPivotControl control) - { - control.UpdateSelectorPipeColor(); - } - } - - private void UpdateSelectorPipeColor() - { - if (_spriteShape != null && _compositor != null) - { - _spriteShape.FillBrush = _compositor.CreateColorBrush(SelectorPipeColor.Color); - } - } - - private void CreateSelectorVisuals() - { - _compositor = this.Visual().Compositor; - - _roundedRectangle = _compositor.CreateRoundedRectangleGeometry(); - _roundedRectangle.CornerRadius = new Vector2(3, 3); - - _spriteShape = _compositor.CreateSpriteShape(_roundedRectangle); - _spriteShape.CenterPoint = new Vector2(100, 100); - - _shapeVisual = _compositor.CreateShapeVisual(); - - _shapeVisual.Shapes.Clear(); - _shapeVisual.Shapes.Add(_spriteShape); - - SelectorPipe.SetChildVisual(_shapeVisual); - - _shapeVisual.EnableImplicitAnimation(VisualPropertyType.Size, 400); - } - - public WinoPivotControl() - { - this.InitializeComponent(); - - CreateSelectorVisuals(); - } - - private bool IsContainerPresent() - { - return SelectedItem != null && PivotHeaders.ContainerFromItem(SelectedItem) != null; - } - - private void PivotHeaders_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - UpdateVisuals(); - - SelectionChanged?.Invoke(sender, e); - } - - private void UpdateVisuals() - { - MoveSelector(); - } - - private void UpdateSelectorVisibility() - { - SelectorPipe.Visibility = IsContainerPresent() ? Visibility.Visible : Visibility.Collapsed; - } - - private async void MoveSelector() - { - if (PivotHeaders.SelectedItem != null) - { - // Get selected item container position - // TODO: It's bad... - while(PivotHeaders.ContainerFromItem(PivotHeaders.SelectedItem) == null) - { - await Task.Delay(100); - } - - UpdateSelectorVisibility(); - - var container = PivotHeaders.ContainerFromItem(PivotHeaders.SelectedItem) as FrameworkElement; - - if (container != null) - { - var transformToVisual = container.TransformToVisual(this); - Point screenCoords = transformToVisual.TransformPoint(new Point(0, 0)); - - float actualWidth = 0, leftMargin = 0, translateX = 0; - - leftMargin = (float)(screenCoords.X); - - if (PivotHeaders.Items.Count > 1) - { - // Multiple items, pipe is centered. - - actualWidth = (float)(container.ActualWidth + 12) / 2; - translateX = leftMargin - 10 + (actualWidth / 2); - } - else - { - actualWidth = (float)(container.ActualWidth) - 12; - translateX = leftMargin + 4; - } - - SelectorPipe.Width = actualWidth; - SelectorPipe.Translation = new Vector3(translateX, 0, 0); - } - else - { - Debug.WriteLine("Container null"); - } - } - } - - private void SelectorPipeSizeChanged(object sender, SizeChangedEventArgs e) - { - _roundedRectangle.Size = e.NewSize.ToVector2(); - _shapeVisual.Size = e.NewSize.ToVector2(); - } - - private void ControlUnloaded(object sender, RoutedEventArgs e) - { - //PivotHeaders.SelectionChanged -= PivotHeaders_SelectionChanged; - //PivotHeaders.SelectedItem = null; - - //SelectedItem = null; - //ItemsSource = null; - } - - private void ControlLoaded(object sender, RoutedEventArgs e) - { - // Bindings.Update(); - } - } -} diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 61328647..cf76ea7e 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -5,7 +5,6 @@ xmlns:abstract="using:Wino.Views.Abstract" xmlns:collections="using:CommunityToolkit.Mvvm.Collections" xmlns:controls="using:Wino.Controls" - xmlns:controls1="using:CommunityToolkit.WinUI.Controls" xmlns:converters="using:Wino.Converters" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:domain="using:Wino.Core.Domain" @@ -18,6 +17,7 @@ xmlns:menuflyouts="using:Wino.MenuFlyouts" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:selectors="using:Wino.Selectors" + xmlns:toolkit="using:CommunityToolkit.WinUI.Controls" xmlns:ui="using:Microsoft.Toolkit.Uwp.UI" xmlns:viewModelData="using:Wino.Mail.ViewModels.Data" xmlns:wino="using:Wino" @@ -45,19 +45,6 @@ - - - - - - - - - - + Style="{StaticResource PivotSegmentedStyle}"> + + + + + + + + + + + + + + - 8.1.240821 + + 8.1.240821 + 8.1.240821 @@ -265,9 +268,6 @@ - - WinoPivotControl.xaml - AccountCreationDialog.xaml @@ -456,10 +456,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile From 552fca8df724442c182470e59a5f57670c9b1fa6 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Thu, 29 Aug 2024 00:19:24 +0200 Subject: [PATCH 02/16] Moved refresh and multi select buttons --- Wino.Mail/App.xaml | 2 + Wino.Mail/Extensions/EnumerableExtensions.cs | 18 -- Wino.Mail/Views/MailListPage.xaml | 275 +++++++++---------- Wino.Mail/Wino.Mail.csproj | 1 - 4 files changed, 138 insertions(+), 158 deletions(-) delete mode 100644 Wino.Mail/Extensions/EnumerableExtensions.cs diff --git a/Wino.Mail/App.xaml b/Wino.Mail/App.xaml index bf1fe890..91b2d0b2 100644 --- a/Wino.Mail/App.xaml +++ b/Wino.Mail/App.xaml @@ -11,6 +11,8 @@ + + diff --git a/Wino.Mail/Extensions/EnumerableExtensions.cs b/Wino.Mail/Extensions/EnumerableExtensions.cs deleted file mode 100644 index 4d94a9be..00000000 --- a/Wino.Mail/Extensions/EnumerableExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections; - -namespace Wino.Extensions -{ - public static class EnumerableExtensions - { - public static IEnumerable OfType(this IEnumerable source) - { - foreach (object item in source) - { - if (item is T1 || item is T2) - { - yield return item; - } - } - } - } -} diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index cf76ea7e..3ce35de8 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -48,7 +48,7 @@ @@ -272,10 +272,7 @@ - + @@ -284,150 +281,122 @@ - - - - - - - - - - - - - - - - - - - - - - - + + - + + - + + - + + - - + Label="{x:Bind domain:Translator.MailOperation_SetFlag}" + ToolTipService.ToolTip="{x:Bind domain:Translator.MailOperation_SetFlag}"> + + SetFlag + + + + + + + + + ClearFlag + + + + + + + + + MarkAsRead + + + + + + + + + MarkAsUnread + + + + + + @@ -479,30 +448,58 @@ - - - - - + - - - - + Orientation="Horizontal"> + + + + + + + + + + + + - From 945c747e3e9dd3f2b12b94b5b3f89673eaf63aa3 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Thu, 29 Aug 2024 01:13:51 +0200 Subject: [PATCH 03/16] Added setting to show/hide action bar in mail list --- Wino.Core.Domain/Interfaces/IPreferencesService.cs | 5 +++++ Wino.Core.Domain/Translations/en_US/resources.json | 6 ++++-- Wino.Core.Domain/Translator.Designer.cs | 14 ++++++++++++-- Wino.Core.UWP/Services/PreferencesService.cs | 6 ++++++ Wino.Mail/Views/MailListPage.xaml | 2 +- Wino.Mail/Views/Settings/MessageListPage.xaml | 7 +++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Wino.Core.Domain/Interfaces/IPreferencesService.cs b/Wino.Core.Domain/Interfaces/IPreferencesService.cs index 505b309c..c5c377ea 100644 --- a/Wino.Core.Domain/Interfaces/IPreferencesService.cs +++ b/Wino.Core.Domain/Interfaces/IPreferencesService.cs @@ -155,5 +155,10 @@ namespace Wino.Core.Domain.Interfaces /// Setting: Gets or sets what should happen to server app when the client is terminated. /// ServerBackgroundMode ServerTerminationBehavior { get; set; } + + /// + /// Setting: Whether the mail list action bar is enabled or not. + /// + bool IsMailListActionBarEnabled { get; set; } } } diff --git a/Wino.Core.Domain/Translations/en_US/resources.json b/Wino.Core.Domain/Translations/en_US/resources.json index c0739152..807d8b08 100644 --- a/Wino.Core.Domain/Translations/en_US/resources.json +++ b/Wino.Core.Domain/Translations/en_US/resources.json @@ -519,7 +519,7 @@ "SettingsRenameMergeAccount_Title": "Rename", "SettingsSemanticZoom_Description": "This will allow you to click on the headers in messages list and go to specific date", "SettingsSemanticZoom_Title": "Semantic Zoom for Date Headers", - "SettingsShowPreviewText_Description": "Hide/show thepreview text.", + "SettingsShowPreviewText_Description": "Hide/show the preview text.", "SettingsShowPreviewText_Title": "Show Preview Text", "SettingsShowSenderPictures_Description": "Hide/show the thumbnail sender pictures.", "SettingsShowSenderPictures_Title": "Show Sender Avatars", @@ -533,7 +533,9 @@ "SettingsStore_Title": "Rate in Store", "SettingsThreads_Description": "Organize messages into conversation threads.", "SettingsThreads_Title": "Conversation Threading", - "SettingsUnlinkAccounts_Description": "Remove the link between accounts. This will not delete your accounts.", + "SettingsMailListActionBar_Description": "Hide/show action bar at top of message list.", + "SettingsMailListActionBar_Title": "Show mail list actions", + "SettingsUnlinkAccounts_Description": "Remove the link between accounts. his will not delete your accounts.", "SettingsUnlinkAccounts_Title": "Unlink Accounts", "SortingOption_Date": "by date", "SortingOption_Name": "by name", diff --git a/Wino.Core.Domain/Translator.Designer.cs b/Wino.Core.Domain/Translator.Designer.cs index 4f086782..ca031f72 100644 --- a/Wino.Core.Domain/Translator.Designer.cs +++ b/Wino.Core.Domain/Translator.Designer.cs @@ -2619,7 +2619,7 @@ namespace Wino.Core.Domain public static string SettingsSemanticZoom_Title => Resources.GetTranslatedString(@"SettingsSemanticZoom_Title"); /// - /// Hide/show thepreview text. + /// Hide/show the preview text. /// public static string SettingsShowPreviewText_Description => Resources.GetTranslatedString(@"SettingsShowPreviewText_Description"); @@ -2689,7 +2689,17 @@ namespace Wino.Core.Domain public static string SettingsThreads_Title => Resources.GetTranslatedString(@"SettingsThreads_Title"); /// - /// Remove the link between accounts. This will not delete your accounts. + /// Hide/show action bar at top of message list. + /// + public static string SettingsMailListActionBar_Description => Resources.GetTranslatedString(@"SettingsMailListActionBar_Description"); + + /// + /// Show mail list actions + /// + public static string SettingsMailListActionBar_Title => Resources.GetTranslatedString(@"SettingsMailListActionBar_Title"); + + /// + /// Remove the link between accounts. his will not delete your accounts. /// public static string SettingsUnlinkAccounts_Description => Resources.GetTranslatedString(@"SettingsUnlinkAccounts_Description"); diff --git a/Wino.Core.UWP/Services/PreferencesService.cs b/Wino.Core.UWP/Services/PreferencesService.cs index 7d77aef5..d7826f0e 100644 --- a/Wino.Core.UWP/Services/PreferencesService.cs +++ b/Wino.Core.UWP/Services/PreferencesService.cs @@ -64,6 +64,12 @@ namespace Wino.Core.UWP.Services set => SetPropertyAndSave(nameof(IsThreadingEnabled), value); } + public bool IsMailListActionBarEnabled + { + get => _configurationService.Get(nameof(IsMailListActionBarEnabled), false); + set => SetPropertyAndSave(nameof(IsMailListActionBarEnabled), value); + } + public bool IsShowSenderPicturesEnabled { get => _configurationService.Get(nameof(IsShowSenderPicturesEnabled), true); diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 3ce35de8..43315861 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -284,7 +284,7 @@ Margin="0,5,5,0" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" CornerRadius="8" - Visibility="Collapsed"> + Visibility="{x:Bind ViewModel.PreferencesService.IsMailListActionBarEnabled}"> + + + + + + + From c6216f54f8aad6c8b42c352442d00ce7d8530119 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Thu, 29 Aug 2024 17:18:46 +0200 Subject: [PATCH 04/16] simplify layout for mail list --- Wino.Mail/Views/MailListPage.xaml | 488 ++++++++++++++---------------- 1 file changed, 228 insertions(+), 260 deletions(-) diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 43315861..ad7ba111 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -195,28 +195,6 @@ Transparent - - - - @@ -259,7 +237,7 @@ - - + + + + + + + + + Archive + + + + + + + + + UnArchive + + + + + + SoftDelete + + + + + + + + + Move + + + + + + + + + SetFlag + + + + + + + + + ClearFlag + + + + + + + + + MarkAsRead + + + + + + + + + MarkAsUnread + + + + + + + + + + + + + + + - + - - - - - - - - - Archive - - - - - - - - - UnArchive - - - - - - SoftDelete - - - - - - - - - Move - - - - - - - - - SetFlag - - - - - - - - - ClearFlag - - - - - - - - - MarkAsRead - - - - - - - - - MarkAsUnread - - - - - - - - - - + - - - - - - - - - + MinWidth="0" + Margin="8,0,0,0" + VerticalAlignment="Center" + Canvas.ZIndex="100" + Checked="SelectAllCheckboxChecked" + Unchecked="SelectAllCheckboxUnchecked" + Visibility="{x:Bind helpers:XamlHelpers.IsSelectionModeMultiple(MailListView.SelectionMode), Mode=OneWay}" /> - - + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + Date: Fri, 30 Aug 2024 01:03:35 +0200 Subject: [PATCH 07/16] Fixed invalid contacts causing folder loading to crash. --- Wino.Core/Services/MailService.cs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/Wino.Core/Services/MailService.cs b/Wino.Core/Services/MailService.cs index 5cea1088..5a9e9123 100644 --- a/Wino.Core/Services/MailService.cs +++ b/Wino.Core/Services/MailService.cs @@ -298,7 +298,11 @@ namespace Wino.Core.Services } } - bool isContactCached = contactCache.TryGetValue(mailCopy.FromAddress, out AccountContact contactAssignment); + AccountContact contactAssignment = null; + + bool isContactCached = !string.IsNullOrEmpty(mailCopy.FromAddress) ? + contactCache.TryGetValue(mailCopy.FromAddress, out contactAssignment) : + false; if (!isContactCached && accountAssignment != null) { @@ -312,11 +316,33 @@ namespace Wino.Core.Services mailCopy.AssignedFolder = folderAssignment; mailCopy.AssignedAccount = accountAssignment; - mailCopy.SenderContact = contactAssignment ?? new AccountContact() { Name = mailCopy.FromName, Address = mailCopy.FromAddress }; + mailCopy.SenderContact = contactAssignment ?? CreateUnknownContact(mailCopy.FromName, mailCopy.FromAddress); } } } + private AccountContact CreateUnknownContact(string fromName, string fromAddress) + { + if (string.IsNullOrEmpty(fromName) && string.IsNullOrEmpty(fromAddress)) + { + return new AccountContact() + { + Name = Translator.UnknownSender, + Address = Translator.UnknownAddress + }; + } + else + { + if (string.IsNullOrEmpty(fromName)) fromName = fromAddress; + + return new AccountContact() + { + Name = fromName, + Address = fromAddress + }; + } + } + private async Task> GetMailItemsAsync(string mailCopyId) { var mailCopies = await Connection.Table().Where(a => a.Id == mailCopyId).ToListAsync(); From a4ff67e8f45d76783427563c1e4d36d0152ddf11 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Sat, 31 Aug 2024 00:42:17 +0200 Subject: [PATCH 08/16] Fix margins --- Wino.Mail/Views/MailListPage.xaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 21e90707..8f0e878d 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -252,6 +252,7 @@ @@ -604,6 +605,7 @@ Date: Sat, 31 Aug 2024 13:25:55 +0200 Subject: [PATCH 09/16] Make TopBar dynamic --- Wino.Mail.ViewModels/MailListPageViewModel.cs | 33 ++++- Wino.Mail/Views/MailListPage.xaml | 138 ++++-------------- Wino.Mail/Views/MailListPage.xaml.cs | 2 +- 3 files changed, 60 insertions(+), 113 deletions(-) diff --git a/Wino.Mail.ViewModels/MailListPageViewModel.cs b/Wino.Mail.ViewModels/MailListPageViewModel.cs index a09c3d67..8e7f6366 100644 --- a/Wino.Mail.ViewModels/MailListPageViewModel.cs +++ b/Wino.Mail.ViewModels/MailListPageViewModel.cs @@ -64,6 +64,8 @@ namespace Wino.Mail.ViewModels public ObservableCollection SelectedItems { get; set; } = []; public ObservableCollection PivotFolders { get; set; } = []; + public ObservableCollection ActionItems { get; set; } = new ObservableCollection(); + private readonly SemaphoreSlim listManipulationSemepahore = new SemaphoreSlim(1); private CancellationTokenSource listManipulationCancellationTokenSource = new CancellationTokenSource(); @@ -200,6 +202,13 @@ namespace Wino.Mail.ViewModels }; } + private void SetupTopBarActions() + { + ActionItems.Clear(); + var actions = GetAvailableMailActions(SelectedItems); + actions.ForEach(a => ActionItems.Add(a)); + } + #region Properties /// @@ -365,6 +374,8 @@ namespace Wino.Mail.ViewModels NotifyItemSelected(); + SetupTopBarActions(); + Messenger.Send(new SelectedMailItemsChanged(SelectedItems.Count)); } @@ -415,19 +426,31 @@ namespace Wino.Mail.ViewModels [RelayCommand] public Task ExecuteHoverAction(MailOperationPreperationRequest request) => ExecuteMailOperationAsync(request); + [RelayCommand] + private async Task OperationClicked(MailOperationMenuItem menuItem) + { + if (menuItem == null || !SelectedItems.Any()) return; + + await HandleMailOperation(menuItem.Operation, SelectedItems); + } + /// /// Executes the requested mail operation for currently selected items. /// /// Action to execute for selected items. [RelayCommand] - private async Task MailOperationAsync(int mailOperationIndex) + private async Task MailOperationAsync(MailOperation mailOperation) { if (!SelectedItems.Any()) return; - // Commands don't like enums. So it has to be int. - var operation = (MailOperation)mailOperationIndex; + await HandleMailOperation(mailOperation, SelectedItems); + } - var package = new MailOperationPreperationRequest(operation, SelectedItems.Select(a => a.MailCopy)); + private async Task HandleMailOperation(MailOperation mailOperation, IEnumerable mailItems) + { + if (!mailItems.Any()) return; + + var package = new MailOperationPreperationRequest(mailOperation, mailItems.Select(a => a.MailCopy)); await ExecuteMailOperationAsync(package); } @@ -649,6 +672,8 @@ namespace Wino.Mail.ViewModels Debug.WriteLine($"Updating {updatedMail.Id}-> {updatedMail.UniqueId}"); await MailCollection.UpdateMailCopy(updatedMail); + + await ExecuteUIThread(() => { SetupTopBarActions(); }); } protected override async void OnMailRemoved(MailCopy removedMail) diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 8f0e878d..4bbbff69 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -12,7 +12,9 @@ xmlns:helpers="using:Wino.Helpers" xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:ic="using:Microsoft.Xaml.Interactions.Core" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:listview="using:Wino.Controls.Advanced" + xmlns:local="using:Wino.Behaviors" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:menuflyouts="using:Wino.MenuFlyouts" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" @@ -31,6 +33,28 @@ IsSourceGrouped="True" Source="{x:Bind ViewModel.MailCollection.MailItems, Mode=OneWay}" /> + + 0,0,0,0 0,0,12,0 0,0,0,0 @@ -251,7 +275,6 @@ - - - - - - Archive - - - - - - - - - UnArchive - - - - - - SoftDelete - - - - - - - - - Move - - - - - - - - - SetFlag - - - - - - - - - ClearFlag - - - - - - - - - MarkAsRead - - - - - - - - - MarkAsUnread - - - - - + + + diff --git a/Wino.Mail/Views/MailListPage.xaml.cs b/Wino.Mail/Views/MailListPage.xaml.cs index af2a0da7..0f939c77 100644 --- a/Wino.Mail/Views/MailListPage.xaml.cs +++ b/Wino.Mail/Views/MailListPage.xaml.cs @@ -375,7 +375,7 @@ namespace Wino.Views { args.Handled = true; - ViewModel?.MailOperationCommand?.Execute((int)MailOperation.SoftDelete); + ViewModel?.MailOperationCommand?.Execute(MailOperation.SoftDelete); } } From ebf196ec73c7eac3936616e567e76829491f03d5 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Sat, 31 Aug 2024 13:39:32 +0200 Subject: [PATCH 10/16] Remove redundant message --- Wino.Mail.ViewModels/MailListPageViewModel.cs | 7 +------ Wino.Messages/Client/Mails/SelectedMailItemsChanged.cs | 8 -------- 2 files changed, 1 insertion(+), 14 deletions(-) delete mode 100644 Wino.Messages/Client/Mails/SelectedMailItemsChanged.cs diff --git a/Wino.Mail.ViewModels/MailListPageViewModel.cs b/Wino.Mail.ViewModels/MailListPageViewModel.cs index 8e7f6366..c5eb2e1c 100644 --- a/Wino.Mail.ViewModels/MailListPageViewModel.cs +++ b/Wino.Mail.ViewModels/MailListPageViewModel.cs @@ -41,8 +41,7 @@ namespace Wino.Mail.ViewModels IRecipient, IRecipient, IRecipient, - IRecipient, - IRecipient + IRecipient { private bool isChangingFolder = false; @@ -375,8 +374,6 @@ namespace Wino.Mail.ViewModels NotifyItemSelected(); SetupTopBarActions(); - - Messenger.Send(new SelectedMailItemsChanged(SelectedItems.Count)); } private void UpdateFolderPivots() @@ -1037,7 +1034,5 @@ namespace Wino.Mail.ViewModels await ExecuteUIThread(() => { IsAccountSynchronizerInSynchronization = isAnyAccountSynchronizing; }); } - - public void Receive(SelectedMailItemsChanged message) => NotifyItemSelected(); } } diff --git a/Wino.Messages/Client/Mails/SelectedMailItemsChanged.cs b/Wino.Messages/Client/Mails/SelectedMailItemsChanged.cs deleted file mode 100644 index 11ca361f..00000000 --- a/Wino.Messages/Client/Mails/SelectedMailItemsChanged.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Wino.Messaging.Client.Mails -{ - /// - /// When selected mail count is changed. - /// - /// New selected mail count. - public record SelectedMailItemsChanged(int SelectedItemCount); -} From d3ddf7b191c654c4537a79acfdc4d4979d086079 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Sat, 31 Aug 2024 13:56:31 +0200 Subject: [PATCH 11/16] style/renaming --- Wino.Mail.ViewModels/MailListPageViewModel.cs | 7 +++---- Wino.Mail/Views/MailListPage.xaml | 4 ++-- Wino.Mail/Views/MailListPage.xaml.cs | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Wino.Mail.ViewModels/MailListPageViewModel.cs b/Wino.Mail.ViewModels/MailListPageViewModel.cs index c5eb2e1c..47dedbd2 100644 --- a/Wino.Mail.ViewModels/MailListPageViewModel.cs +++ b/Wino.Mail.ViewModels/MailListPageViewModel.cs @@ -62,8 +62,7 @@ namespace Wino.Mail.ViewModels public ObservableCollection SelectedItems { get; set; } = []; public ObservableCollection PivotFolders { get; set; } = []; - - public ObservableCollection ActionItems { get; set; } = new ObservableCollection(); + public ObservableCollection ActionItems { get; set; } = []; private readonly SemaphoreSlim listManipulationSemepahore = new SemaphoreSlim(1); private CancellationTokenSource listManipulationCancellationTokenSource = new CancellationTokenSource(); @@ -424,7 +423,7 @@ namespace Wino.Mail.ViewModels public Task ExecuteHoverAction(MailOperationPreperationRequest request) => ExecuteMailOperationAsync(request); [RelayCommand] - private async Task OperationClicked(MailOperationMenuItem menuItem) + private async Task ExecuteTopBarAction(MailOperationMenuItem menuItem) { if (menuItem == null || !SelectedItems.Any()) return; @@ -436,7 +435,7 @@ namespace Wino.Mail.ViewModels /// /// Action to execute for selected items. [RelayCommand] - private async Task MailOperationAsync(MailOperation mailOperation) + private async Task ExecuteMailOperation(MailOperation mailOperation) { if (!SelectedItems.Any()) return; diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 4bbbff69..87b26e77 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -285,7 +285,7 @@ OverflowButtonVisibility="Auto"> @@ -466,7 +466,7 @@ ui:ListViewExtensions.ItemContainerStretchDirection="Horizontal" ui:ScrollViewerExtensions.EnableMiddleClickScrolling="True" ui:ScrollViewerExtensions.VerticalScrollBarMargin="0" - ItemDeletedCommand="{x:Bind ViewModel.MailOperationCommand}" + ItemDeletedCommand="{x:Bind ViewModel.ExecuteMailOperationCommand}" ItemTemplateSelector="{StaticResource MailItemDisplaySelector}" ItemsSource="{x:Bind MailCollectionViewSource.View, Mode=OneWay}" LoadMoreCommand="{x:Bind ViewModel.LoadMoreItemsCommand}" diff --git a/Wino.Mail/Views/MailListPage.xaml.cs b/Wino.Mail/Views/MailListPage.xaml.cs index 0f939c77..740d4d32 100644 --- a/Wino.Mail/Views/MailListPage.xaml.cs +++ b/Wino.Mail/Views/MailListPage.xaml.cs @@ -375,7 +375,7 @@ namespace Wino.Views { args.Handled = true; - ViewModel?.MailOperationCommand?.Execute(MailOperation.SoftDelete); + ViewModel?.ExecuteMailOperationCommand?.Execute(MailOperation.SoftDelete); } } From 85b5469d96665f8f184fedf05b595b9e4b9057a2 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Sat, 31 Aug 2024 14:19:43 +0200 Subject: [PATCH 12/16] Fix wrong logic for set/unset flag --- Wino.Core/Services/ContextMenuItemService.cs | 29 ++++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Wino.Core/Services/ContextMenuItemService.cs b/Wino.Core/Services/ContextMenuItemService.cs index 3c1040fe..e6238e8f 100644 --- a/Wino.Core/Services/ContextMenuItemService.cs +++ b/Wino.Core/Services/ContextMenuItemService.cs @@ -80,27 +80,26 @@ namespace Wino.Core.Services } else { - bool isAllFlagged = selectedMailItems.All(a => a.IsFlagged); bool isAllRead = selectedMailItems.All(a => a.IsRead); bool isAllUnread = selectedMailItems.All(a => !a.IsRead); + bool isAllFlagged = selectedMailItems.All(a => a.IsFlagged); + bool isAllNotFlagged = selectedMailItems.All(a => !a.IsFlagged); - if (isAllRead) - operationList.Add(MailOperationMenuItem.Create(MailOperation.MarkAsUnread)); - else + List readOperations = (isAllRead, isAllUnread) switch { - if (!isAllUnread) - operationList.Add(MailOperationMenuItem.Create(MailOperation.MarkAsUnread)); + (true, false) => [MailOperationMenuItem.Create(MailOperation.MarkAsUnread)], + (false, true) => [MailOperationMenuItem.Create(MailOperation.MarkAsRead)], + _ => [MailOperationMenuItem.Create(MailOperation.MarkAsRead), MailOperationMenuItem.Create(MailOperation.MarkAsUnread)] + }; + operationList.AddRange(readOperations); - operationList.Add(MailOperationMenuItem.Create(MailOperation.MarkAsRead)); - } - - if (isAllFlagged) - operationList.Add(MailOperationMenuItem.Create(MailOperation.ClearFlag)); - else + List flagsOperations = (isAllFlagged, isAllNotFlagged) switch { - operationList.Add(MailOperationMenuItem.Create(MailOperation.ClearFlag)); - operationList.Add(MailOperationMenuItem.Create(MailOperation.SetFlag)); - } + (true, false) => [MailOperationMenuItem.Create(MailOperation.ClearFlag)], + (false, true) => [MailOperationMenuItem.Create(MailOperation.SetFlag)], + _ => [MailOperationMenuItem.Create(MailOperation.SetFlag), MailOperationMenuItem.Create(MailOperation.ClearFlag)] + }; + operationList.AddRange(flagsOperations); } // Ignore From b8ca3f8604325d28315ad5070ef1aad56d95cd58 Mon Sep 17 00:00:00 2001 From: Aleh Khantsevich Date: Sat, 31 Aug 2024 14:29:57 +0200 Subject: [PATCH 13/16] Disable toolbar when nothing selected. --- Wino.Mail/Views/MailListPage.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index 87b26e77..adf57707 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -282,6 +282,7 @@ Date: Sat, 31 Aug 2024 15:11:28 +0200 Subject: [PATCH 14/16] Fix delete action on KeyPress --- Wino.Mail/Controls/Advanced/WinoListView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Wino.Mail/Controls/Advanced/WinoListView.cs b/Wino.Mail/Controls/Advanced/WinoListView.cs index 10f215da..764084e2 100644 --- a/Wino.Mail/Controls/Advanced/WinoListView.cs +++ b/Wino.Mail/Controls/Advanced/WinoListView.cs @@ -120,7 +120,7 @@ namespace Wino.Controls.Advanced { args.Handled = true; - ItemDeletedCommand?.Execute((int)MailOperation.SoftDelete); + ItemDeletedCommand?.Execute(MailOperation.SoftDelete); } } From 209aa1a89f0b2c420abe492bbd920a17a10881b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sat, 31 Aug 2024 15:22:20 +0200 Subject: [PATCH 15/16] 4x top margin for mail list. --- Wino.Mail/Views/MailListPage.xaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index adf57707..c5d37a7e 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -457,6 +457,7 @@ From d58438ab1d70b51e859f0bd6d4360de8198892a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Burak=20Kaan=20K=C3=B6se?= Date: Sat, 31 Aug 2024 15:26:22 +0200 Subject: [PATCH 16/16] Removed margin and increased padding. --- Wino.Mail/Views/MailListPage.xaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index c5d37a7e..e7ec8e49 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -294,7 +294,7 @@ - + @@ -457,7 +457,6 @@