Bunch of changes for ItemsView and threads.
This commit is contained in:
+26
-26
@@ -15,56 +15,56 @@
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
|
||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250926-build.2293" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.3" />
|
||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.DependencyPropertyGenerator" Version="0.1.250926-build.2293" />
|
||||
<PackageVersion Include="EmailValidation" Version="1.3.0" />
|
||||
<PackageVersion Include="gravatar-dotnet" Version="0.1.3" />
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.12.0" />
|
||||
<PackageVersion Include="HtmlAgilityPack" Version="1.12.4" />
|
||||
<PackageVersion Include="Ical.Net" Version="4.3.1" />
|
||||
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.9" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
|
||||
<PackageVersion Include="Microsoft.Graph" Version="5.75.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Graph" Version="5.94.0" />
|
||||
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client" Version="4.77.1" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Broker" Version="4.70.1" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.70.1" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Broker" Version="4.77.1" />
|
||||
<PackageVersion Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.77.1" />
|
||||
<PackageVersion Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.2.14" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="3.0.0" />
|
||||
<PackageVersion Include="MimeKit" Version="4.11.0" />
|
||||
<PackageVersion Include="MimeKit" Version="4.14.0" />
|
||||
<PackageVersion Include="morelinq" Version="4.4.0" />
|
||||
<PackageVersion Include="Nito.AsyncEx" Version="5.1.2" />
|
||||
<PackageVersion Include="Nito.AsyncEx.Tasks" Version="5.1.2" />
|
||||
<PackageVersion Include="NodaTime" Version="3.2.2" />
|
||||
<PackageVersion Include="Sentry.Serilog" Version="5.15.1" />
|
||||
<PackageVersion Include="Serilog" Version="4.2.0" />
|
||||
<PackageVersion Include="Sentry.Serilog" Version="5.16.1" />
|
||||
<PackageVersion Include="Serilog" Version="4.3.0" />
|
||||
<PackageVersion Include="Serilog.Exceptions" Version="8.4.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.Debug" Version="3.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.ApplicationInsights" Version="4.0.0" />
|
||||
<PackageVersion Include="SkiaSharp" Version="3.116.1" />
|
||||
<PackageVersion Include="SkiaSharp" Version="3.119.1" />
|
||||
<PackageVersion Include="sqlite-net-pcl" Version="1.9.172" />
|
||||
<PackageVersion Include="SqlKata" Version="4.0.1" />
|
||||
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.4" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.4" />
|
||||
<PackageVersion Include="System.Text.Encoding.CodePages" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.10" />
|
||||
<PackageVersion Include="H.NotifyIcon.Wpf" Version="2.3.0" />
|
||||
<PackageVersion Include="H.NotifyIcon.WinUI" Version="2.3.0" />
|
||||
<PackageVersion Include="H.NotifyIcon.WinUI" Version="2.3.1" />
|
||||
<PackageVersion Include="CommunityToolkit.WinUI.Notifications" Version="7.1.2" />
|
||||
<PackageVersion Include="Google.Apis.Auth" Version="1.69.0" />
|
||||
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.69.0.3667" />
|
||||
<PackageVersion Include="Google.Apis.Gmail.v1" Version="1.68.0.3427" />
|
||||
<PackageVersion Include="Google.Apis.PeopleService.v1" Version="1.68.0.3359" />
|
||||
<PackageVersion Include="Google.Apis.Auth" Version="1.72.0" />
|
||||
<PackageVersion Include="Google.Apis.Calendar.v3" Version="1.69.0.3746" />
|
||||
<PackageVersion Include="Google.Apis.Gmail.v1" Version="1.70.0.3833" />
|
||||
<PackageVersion Include="Google.Apis.PeopleService.v1" Version="1.69.0.3785" />
|
||||
<PackageVersion Include="HtmlKit" Version="1.2.0" />
|
||||
<PackageVersion Include="MailKit" Version="4.11.0" />
|
||||
<PackageVersion Include="MailKit" Version="4.14.1" />
|
||||
<PackageVersion Include="TimePeriodLibrary.NET" Version="2.1.6" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.4" />
|
||||
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.4" />
|
||||
<PackageVersion Include="System.Reactive" Version="6.1.0" />
|
||||
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" />
|
||||
<PackageVersion Include="System.Text.Encodings.Web" Version="9.0.10" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6584" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.8.250916003" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.8.0" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.0.250930001-experimental1" />
|
||||
<PackageVersion Include="WinUIEx" Version="2.9.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -12,5 +12,7 @@ public record MailListInitializationOptions(IEnumerable<IMailItemFolder> Folders
|
||||
bool CreateThreads,
|
||||
bool? IsFocusedOnly,
|
||||
string SearchQuery,
|
||||
IEnumerable<Guid> ExistingUniqueIds,
|
||||
List<MailCopy> PreFetchMailCopies = null);
|
||||
HashSet<Guid> ExistingUniqueIds = null,
|
||||
List<MailCopy> PreFetchMailCopies = null,
|
||||
int Skip = 0,
|
||||
int Take = 0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
|
||||
<Platforms>x86;x64;arm64</Platforms>
|
||||
@@ -57,7 +57,6 @@
|
||||
<PackageReference Include="MimeKit" />
|
||||
<PackageReference Include="MailKit" />
|
||||
<PackageReference Include="sqlite-net-pcl" />
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<PackageReference Include="TimePeriodLibrary.NET" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -26,6 +26,7 @@ public static class XamlHelpers
|
||||
|
||||
#region Converters
|
||||
|
||||
public static Thickness GetMailItemControlMargin(bool isDisplayedInThread) => isDisplayedInThread ? new Thickness(40, 0, 6, 0) : new Thickness(6, 0, 6, 0);
|
||||
public static bool IsMultiple(int count) => count > 1;
|
||||
public static bool ReverseIsMultiple(int count) => count < 1;
|
||||
public static PopupPlacementMode GetPlaccementModeForCalendarType(CalendarDisplayType type)
|
||||
|
||||
@@ -39,6 +39,7 @@ public partial class GroupedEmailCollection : ObservableObject, IRecipient<Prope
|
||||
private readonly Dictionary<string, int> _groupHeaderIndexCache = [];
|
||||
private readonly Dictionary<string, List<object>> _groupItems = [];
|
||||
private readonly Dictionary<string, ThreadMailItemViewModel> _threadExpanders = [];
|
||||
private readonly HashSet<Guid> _mailCopyIdHashSet = [];
|
||||
private bool _disposed;
|
||||
private bool _isUpdating;
|
||||
|
||||
@@ -78,6 +79,11 @@ public partial class GroupedEmailCollection : ObservableObject, IRecipient<Prope
|
||||
/// </summary>
|
||||
public int TotalUnreadCount => _sourceItems.Count(e => e.MailCopy?.IsRead == false);
|
||||
|
||||
/// <summary>
|
||||
/// HashSet containing unique IDs of all mail copies in the collection for pagination tracking
|
||||
/// </summary>
|
||||
public HashSet<Guid> MailCopyIdHashSet => _mailCopyIdHashSet;
|
||||
|
||||
/// <summary>
|
||||
/// Gets all email items across all groups as a flat collection
|
||||
/// </summary>
|
||||
@@ -227,6 +233,9 @@ public partial class GroupedEmailCollection : ObservableObject, IRecipient<Prope
|
||||
if (email?.MailCopy == null)
|
||||
return;
|
||||
|
||||
// Add to unique ID tracking
|
||||
_mailCopyIdHashSet.Add(email.MailCopy.UniqueId);
|
||||
|
||||
_isUpdating = true;
|
||||
try
|
||||
{
|
||||
@@ -306,6 +315,9 @@ public partial class GroupedEmailCollection : ObservableObject, IRecipient<Prope
|
||||
if (email?.MailCopy == null)
|
||||
return;
|
||||
|
||||
// Remove from unique ID tracking
|
||||
_mailCopyIdHashSet.Remove(email.MailCopy.UniqueId);
|
||||
|
||||
_isUpdating = true;
|
||||
try
|
||||
{
|
||||
@@ -386,6 +398,12 @@ public partial class GroupedEmailCollection : ObservableObject, IRecipient<Prope
|
||||
_isUpdating = true;
|
||||
try
|
||||
{
|
||||
// Add to unique ID tracking
|
||||
foreach (var email in emailList)
|
||||
{
|
||||
_mailCopyIdHashSet.Add(email.MailCopy.UniqueId);
|
||||
}
|
||||
|
||||
// For bulk loading, add to source and refresh
|
||||
foreach (var email in emailList)
|
||||
{
|
||||
@@ -430,6 +448,7 @@ public partial class GroupedEmailCollection : ObservableObject, IRecipient<Prope
|
||||
_groupHeaderIndexCache.Clear();
|
||||
_groupItems.Clear();
|
||||
_threadExpanders.Clear();
|
||||
_mailCopyIdHashSet.Clear();
|
||||
|
||||
OnPropertyChanged(nameof(TotalCount));
|
||||
OnPropertyChanged(nameof(TotalUnreadCount));
|
||||
|
||||
@@ -13,14 +13,13 @@ using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Extensions;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
using Wino.Messaging.Server;
|
||||
|
||||
namespace Wino.Mail.ViewModels;
|
||||
|
||||
@@ -412,7 +411,7 @@ public partial class ComposePageViewModel : MailBaseViewModel
|
||||
// Download missing MIME message using SynchronizationManager
|
||||
await SynchronizationManager.Instance.DownloadMimeMessageAsync(
|
||||
CurrentMailDraftItem.MailCopy,
|
||||
CurrentMailDraftItem.AssignedAccount.Id);
|
||||
CurrentMailDraftItem.MailCopy.AssignedAccount.Id);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@@ -53,16 +53,13 @@ public partial class ThreadMailItemViewModel : ObservableRecipient, IDisposable
|
||||
/// </summary>
|
||||
public IReadOnlyList<MailItemViewModel> ThreadEmails => _threadEmails.AsReadOnly();
|
||||
|
||||
public MailItemViewModel LatestMailViewModel => _threadEmails.OrderByDescending(e => e.MailCopy?.CreationDate).FirstOrDefault()!;
|
||||
|
||||
public ThreadMailItemViewModel(string threadId)
|
||||
{
|
||||
_threadId = threadId;
|
||||
}
|
||||
|
||||
partial void OnIsSelectedChanged(bool value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
@@ -86,6 +83,8 @@ public partial class ThreadMailItemViewModel : ObservableRecipient, IDisposable
|
||||
{
|
||||
OnPropertyChanged(nameof(Subject));
|
||||
OnPropertyChanged(nameof(FromName));
|
||||
OnPropertyChanged(nameof(LatestEmailDate));
|
||||
OnPropertyChanged(nameof(LatestMailViewModel));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,14 +60,6 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
private IObservable<System.Reactive.EventPattern<NotifyCollectionChangedEventArgs>> selectionChangedObservable = null;
|
||||
|
||||
public GroupedEmailCollection MailCollection { get; set; } = new GroupedEmailCollection();
|
||||
|
||||
//public IEnumerable<MailItemViewModel> SelectedItems
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
|
||||
// }
|
||||
//}
|
||||
public ObservableCollection<MailItemViewModel> SelectedItems { get; set; } = [];
|
||||
public ObservableCollection<FolderPivotViewModel> PivotFolders { get; set; } = [];
|
||||
public ObservableCollection<MailOperationMenuItem> ActionItems { get; set; } = [];
|
||||
@@ -246,11 +238,10 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
{
|
||||
if (SetProperty(ref _selectedSortingOption, value))
|
||||
{
|
||||
// TODO: Update sorting in mail collection.
|
||||
//if (value != null && MailCollection != null)
|
||||
//{
|
||||
// MailCollection.SortingType = value.Type;
|
||||
//}
|
||||
if (value != null && MailCollection != null)
|
||||
{
|
||||
MailCollection.GroupingType = value.Type == SortingOptionType.ReceiveDate ? EmailGroupingType.ByDate : EmailGroupingType.ByFromName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -562,24 +553,24 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
[RelayCommand]
|
||||
private async Task LoadMoreItemsAsync()
|
||||
{
|
||||
//if (IsInitializingFolder || IsOnlineSearchEnabled) return;
|
||||
if (IsInitializingFolder || IsOnlineSearchEnabled) return;
|
||||
|
||||
//await ExecuteUIThread(() => { IsInitializingFolder = true; });
|
||||
await ExecuteUIThread(() => { IsInitializingFolder = true; });
|
||||
|
||||
//var initializationOptions = new MailListInitializationOptions(ActiveFolder.HandlingFolders,
|
||||
// SelectedFilterOption.Type,
|
||||
// SelectedSortingOption.Type,
|
||||
// PreferencesService.IsThreadingEnabled,
|
||||
// SelectedFolderPivot.IsFocused,
|
||||
// IsInSearchMode ? SearchQuery : string.Empty,
|
||||
// MailCollection.MailCopyIdHashSet);
|
||||
var initializationOptions = new MailListInitializationOptions(ActiveFolder.HandlingFolders,
|
||||
SelectedFilterOption.Type,
|
||||
SelectedSortingOption.Type,
|
||||
PreferencesService.IsThreadingEnabled,
|
||||
SelectedFolderPivot.IsFocused,
|
||||
IsInSearchMode ? SearchQuery : string.Empty,
|
||||
MailCollection.MailCopyIdHashSet);
|
||||
|
||||
//var items = await _mailService.FetchMailsAsync(initializationOptions).ConfigureAwait(false);
|
||||
var items = await _mailService.FetchMailsAsync(initializationOptions).ConfigureAwait(false);
|
||||
|
||||
//var viewModels = PrepareMailViewModels(items);
|
||||
var viewModels = PrepareMailViewModels(items);
|
||||
|
||||
//await ExecuteUIThread(() => { MailCollection.AddRange(viewModels, clearIdCache: false); });
|
||||
//await ExecuteUIThread(() => { IsInitializingFolder = false; });
|
||||
await ExecuteUIThread(() => { MailCollection.AddEmails(viewModels); });
|
||||
await ExecuteUIThread(() => { IsInitializingFolder = false; });
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -589,7 +580,6 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
public IEnumerable<MailOperationMenuItem> GetAvailableMailActions(IEnumerable<MailItemViewModel> contextMailItems)
|
||||
=> _contextMenuItemService.GetMailItemContextMenuActions(contextMailItems.Select(a => a.MailCopy));
|
||||
|
||||
|
||||
private bool ShouldPreventItemAdd(MailCopy mailItem)
|
||||
{
|
||||
bool condition = mailItem.IsRead
|
||||
@@ -733,13 +723,6 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
private IEnumerable<MailItemViewModel> PrepareMailViewModels(IEnumerable<MailCopy> mailItems)
|
||||
{
|
||||
return mailItems.Select(a => new MailItemViewModel(a));
|
||||
//foreach (var item in mailItems)
|
||||
//{
|
||||
// if (item is MailCopy singleMailItem)
|
||||
// yield return new MailItemViewModel(singleMailItem);
|
||||
// else if (item is ThreadMailItem threadMailItem)
|
||||
// yield return new ThreadMailItemViewModel(threadMailItem);
|
||||
//}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -784,7 +767,6 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
// Here items are sorted and filtered.
|
||||
|
||||
List<MailCopy> items = null;
|
||||
List<MailCopy> onlineSearchItems = null;
|
||||
|
||||
bool isDoingSearch = !string.IsNullOrEmpty(SearchQuery);
|
||||
bool isDoingOnlineSearch = false;
|
||||
@@ -851,8 +833,7 @@ public partial class MailListPageViewModel : MailBaseViewModel,
|
||||
PreferencesService.IsThreadingEnabled,
|
||||
SelectedFolderPivot.IsFocused,
|
||||
SearchQuery,
|
||||
default,
|
||||
onlineSearchItems);
|
||||
MailCollection.MailCopyIdHashSet);
|
||||
|
||||
items = await _mailService.FetchMailsAsync(initializationOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ using Wino.Core.Services;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Messages;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
using Wino.Messaging.Server;
|
||||
using Wino.Messaging.UI;
|
||||
using IMailService = Wino.Core.Domain.Interfaces.IMailService;
|
||||
|
||||
@@ -356,7 +355,7 @@ public partial class MailRenderingPageViewModel : MailBaseViewModel,
|
||||
// Download missing MIME message using SynchronizationManager
|
||||
await SynchronizationManager.Instance.DownloadMimeMessageAsync(
|
||||
mailItemViewModel.MailCopy,
|
||||
mailItemViewModel.AssignedAccount.Id);
|
||||
mailItemViewModel.MailCopy.AssignedAccount.Id);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:abstract="using:Wino.Views.Abstract"
|
||||
xmlns:advanced="using:Wino.Controls.Advanced"
|
||||
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
||||
xmlns:controls="using:Wino.Controls"
|
||||
@@ -356,7 +355,6 @@
|
||||
<Grid
|
||||
x:Name="RootGrid"
|
||||
Padding="0"
|
||||
Background="{ThemeResource WinoApplicationBackgroundColor}"
|
||||
ColumnSpacing="0"
|
||||
RowSpacing="0">
|
||||
|
||||
|
||||
@@ -1,14 +1,46 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Mail.WinUI.Controls.Advanced;
|
||||
|
||||
public partial class WinoItemsView : ItemsView
|
||||
{
|
||||
private const string PART_ScrollView = nameof(PART_ScrollView);
|
||||
|
||||
private ScrollView? _internalScrollView;
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial ICommand LoadMoreCommand { get; set; }
|
||||
|
||||
public IEnumerable<object>? CastedItemsSource => ItemsSource as IEnumerable<object>;
|
||||
|
||||
public WinoItemsView()
|
||||
{
|
||||
DefaultStyleKey = typeof(ItemsView);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_internalScrollView = GetTemplateChild("PART_ScrollView") as ScrollView ?? throw new System.Exception("Can't find the ScrollView in WinoItemsView.");
|
||||
|
||||
_internalScrollView.ViewChanged -= InternalScrollViewPositionChanged;
|
||||
_internalScrollView.ViewChanged += InternalScrollViewPositionChanged;
|
||||
}
|
||||
|
||||
private void InternalScrollViewPositionChanged(ScrollView sender, object args)
|
||||
{
|
||||
if (_internalScrollView == null) return;
|
||||
|
||||
// No need to raise init request if there are no items in the list.
|
||||
if (ItemsSource == null) return;
|
||||
|
||||
double progress = sender.VerticalOffset / sender.ScrollableHeight;
|
||||
|
||||
// Trigger when scrolled past 90% of total height
|
||||
if (progress >= 0.9) LoadMoreCommand?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models;
|
||||
using Wino.Core.Domain.Models.Reader;
|
||||
using Wino.Core.WinUI;
|
||||
using Wino.Core.WinUI.Extensions;
|
||||
using Wino.Mail.WinUI;
|
||||
|
||||
@@ -140,7 +139,7 @@ public sealed partial class WebViewEditorControl : Control, IDisposable
|
||||
{
|
||||
this.DefaultStyleKey = typeof(WebViewEditorControl);
|
||||
|
||||
IsEditorDarkMode = WinoApplication.Current.UnderlyingThemeService.IsUnderlyingThemeDark();
|
||||
IsEditorDarkMode = Core.WinUI.WinoApplication.Current.UnderlyingThemeService.IsUnderlyingThemeDark();
|
||||
}
|
||||
|
||||
protected override async void OnApplyTemplate()
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<!-- SystemBackdrop will be set by NewThemeService -->
|
||||
|
||||
<Grid>
|
||||
<Grid Background="{ThemeResource WinoApplicationBackgroundColor}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
@@ -25,10 +25,10 @@
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
BackRequested="BackButtonClicked"
|
||||
Background="Transparent"
|
||||
IsBackButtonVisible="{x:Bind StatePersistanceService.IsBackButtonVisible, Mode=OneWay}"
|
||||
IsPaneToggleButtonVisible="True"
|
||||
PaneToggleRequested="PaneButtonClicked" />
|
||||
|
||||
<Frame
|
||||
x:Name="MainShellFrame"
|
||||
Grid.Row="1"
|
||||
|
||||
@@ -67,104 +67,34 @@
|
||||
<animations:OpacityAnimation To="0.0" Duration="0:0:1" />
|
||||
</animations:Implicit.HideAnimations>
|
||||
|
||||
<Grid Height="80">
|
||||
<!-- Thread background -->
|
||||
<Grid
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
Visibility="{x:Bind IsDisplayedInThread, Mode=OneWay}" />
|
||||
|
||||
<Grid Padding="8,4,12,4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left: PersonPicture -->
|
||||
<PersonPicture
|
||||
Grid.Column="0"
|
||||
Width="40"
|
||||
Height="40"
|
||||
Margin="0,0,12,0"
|
||||
VerticalAlignment="Center"
|
||||
DisplayName="{x:Bind FromName, Mode=OneWay}" />
|
||||
|
||||
<!-- Center: Content -->
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="2">
|
||||
<!-- Subject -->
|
||||
<TextBlock
|
||||
FontWeight="{x:Bind helpers:XamlHelpers.GetFontWeightByReadState(IsRead), Mode=OneWay}"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
MaxLines="1"
|
||||
Text="{x:Bind Subject, Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
|
||||
<!-- Sender Name -->
|
||||
<TextBlock
|
||||
FontWeight="{x:Bind helpers:XamlHelpers.GetFontWeightByReadState(IsRead), Mode=OneWay}"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
MaxLines="1"
|
||||
Text="{x:Bind FromName, Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
|
||||
<!-- Preview Text -->
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorTertiaryBrush}"
|
||||
MaxLines="1"
|
||||
Text="{x:Bind PreviewText, Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Right: Indicators -->
|
||||
<StackPanel
|
||||
Grid.Column="2"
|
||||
Margin="12,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="4">
|
||||
|
||||
<!-- Unread Indicator (show when IsRead is false) -->
|
||||
<Ellipse
|
||||
Width="8"
|
||||
Height="8"
|
||||
Fill="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Visibility="{x:Bind helpers:XamlHelpers.ReverseBoolToVisibilityConverter(IsRead), Mode=OneWay}" />
|
||||
|
||||
<!-- Flagged Indicator -->
|
||||
<FontIcon
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind IsFlagged, Mode=OneWay}" />
|
||||
|
||||
<!-- Attachment Indicator -->
|
||||
<FontIcon
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind HasAttachments, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<controls:MailItemDisplayInformationControl
|
||||
Margin="{x:Bind helpers:XamlHelpers.GetMailItemControlMargin(IsDisplayedInThread), Mode=OneWay}"
|
||||
x:DefaultBindMode="OneWay"
|
||||
CenterHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.CenterHoverAction, Mode=OneWay}"
|
||||
ContextRequested="MailItemContextRequested"
|
||||
DisplayMode="{Binding ElementName=root, Path=ViewModel.PreferencesService.MailItemDisplayMode, Mode=OneWay}"
|
||||
HoverActionExecutedCommand="{Binding ElementName=root, Path=ViewModel.ExecuteHoverActionCommand}"
|
||||
IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}"
|
||||
IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}"
|
||||
IsThumbnailUpdated="{x:Bind ThumbnailUpdatedEvent, Mode=OneWay}"
|
||||
LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}"
|
||||
MailItem="{x:Bind MailCopy, Mode=OneWay}"
|
||||
Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}"
|
||||
RightHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.RightHoverAction, Mode=OneWay}"
|
||||
ShowPreviewText="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowPreviewEnabled, Mode=OneWay}" />
|
||||
</ItemContainer>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="ThreadExpanderTemplate" x:DataType="viewModelData:ThreadMailItemViewModel">
|
||||
<ItemContainer Tag="{x:Bind}" Tapped="ThreadContainerTapped">
|
||||
<Grid
|
||||
Padding="4,12,0,12"
|
||||
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||
ColumnSpacing="8">
|
||||
<ItemContainer
|
||||
CanUserSelect="UserCannotSelect"
|
||||
RightTapped="ThreadContainerRightTapped"
|
||||
Tag="{x:Bind}"
|
||||
Tapped="ThreadContainerTapped">
|
||||
<Grid Padding="4,0,0,0" ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Expansion indicator -->
|
||||
@@ -177,42 +107,34 @@
|
||||
Glyph="" />
|
||||
</Viewbox>
|
||||
|
||||
<!-- Thread content -->
|
||||
<StackPanel Grid.Column="1" VerticalAlignment="Center">
|
||||
<TextBlock
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Text="{x:Bind Subject, Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind LatestEmailDate, Mode=OneWay}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Email count badge -->
|
||||
<Border
|
||||
Grid.Column="2"
|
||||
Margin="8,0,12,0"
|
||||
Padding="6,2"
|
||||
VerticalAlignment="Center"
|
||||
Background="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
CornerRadius="8">
|
||||
<TextBlock
|
||||
Foreground="White"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind EmailCount, Mode=OneWay}" />
|
||||
</Border>
|
||||
<controls:MailItemDisplayInformationControl
|
||||
Grid.Column="1"
|
||||
x:DefaultBindMode="OneWay"
|
||||
CenterHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.CenterHoverAction, Mode=OneWay}"
|
||||
ContextRequested="MailItemContextRequested"
|
||||
DisplayMode="{Binding ElementName=root, Path=ViewModel.PreferencesService.MailItemDisplayMode, Mode=OneWay}"
|
||||
HoverActionExecutedCommand="{Binding ElementName=root, Path=ViewModel.ExecuteHoverActionCommand}"
|
||||
IsAvatarVisible="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowSenderPicturesEnabled, Mode=OneWay}"
|
||||
IsHoverActionsEnabled="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsHoverActionsEnabled, Mode=OneWay}"
|
||||
IsThumbnailUpdated="{x:Bind LatestMailViewModel.ThumbnailUpdatedEvent, Mode=OneWay}"
|
||||
LeftHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.LeftHoverAction, Mode=OneWay}"
|
||||
MailItem="{x:Bind LatestMailViewModel.MailCopy, Mode=OneWay}"
|
||||
Prefer24HourTimeFormat="{Binding ElementName=root, Path=ViewModel.PreferencesService.Prefer24HourTimeFormat, Mode=OneWay}"
|
||||
RightHoverAction="{Binding ElementName=root, Path=ViewModel.PreferencesService.RightHoverAction, Mode=OneWay}"
|
||||
ShowPreviewText="{Binding ElementName=root, Path=ViewModel.PreferencesService.IsShowPreviewEnabled, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</ItemContainer>
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="DateGroupHeaderTemplate" x:DataType="data:DateGroupHeader">
|
||||
<ItemContainer IsHitTestVisible="False">
|
||||
<ItemContainer
|
||||
CanUserSelect="UserCannotSelect"
|
||||
IsEnabled="False"
|
||||
IsHitTestVisible="False">
|
||||
<Grid Padding="12,8" Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
|
||||
<TextBlock
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||
Style="{ThemeResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind DisplayName, Mode=OneWay}" />
|
||||
@@ -221,7 +143,10 @@
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:Key="SenderGroupHeaderTemplate" x:DataType="data:SenderGroupHeader">
|
||||
<ItemContainer IsHitTestVisible="False">
|
||||
<ItemContainer
|
||||
CanUserSelect="UserCannotSelect"
|
||||
IsEnabled="False"
|
||||
IsHitTestVisible="False">
|
||||
<Grid Padding="12,8" Background="{ThemeResource CardBackgroundFillColorDefaultBrush}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -503,15 +428,18 @@
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<advanced:WinoItemsView
|
||||
x:Name="MailListView"
|
||||
Margin="4"
|
||||
ItemTemplate="{StaticResource MailItemContainerSelector}"
|
||||
ItemsSource="{x:Bind ViewModel.MailCollection.Items, Mode=OneTime}"
|
||||
Layout="{StaticResource DefaultItemsViewLayout}"
|
||||
LoadMoreCommand="{x:Bind ViewModel.LoadMoreItemsCommand}"
|
||||
SelectionChanged="ListSelectionChanged"
|
||||
SelectionMode="Extended" />
|
||||
|
||||
|
||||
<!-- Try online search panel. -->
|
||||
<Grid Grid.Row="1" Visibility="{x:Bind ViewModel.IsOnlineSearchButtonVisible, Mode=OneWay}">
|
||||
<Button
|
||||
|
||||
@@ -13,6 +13,7 @@ using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using MoreLinq;
|
||||
using Windows.Foundation;
|
||||
using Wino.Controls;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
@@ -74,7 +75,7 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
||||
|
||||
// Dispose all WinoListView items.
|
||||
|
||||
MailListView.Dispose();
|
||||
// MailListView.Dispose();
|
||||
|
||||
this.Bindings.StopTracking();
|
||||
|
||||
@@ -162,31 +163,24 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
||||
// Context is requested from a single mail point, but we might have multiple selected items.
|
||||
// This menu should be calculated based on all selected items by providers.
|
||||
|
||||
//if (sender is MailItemDisplayInformationControl control && args.TryGetPosition(sender, out Point p))
|
||||
//{
|
||||
// await FocusManager.TryFocusAsync(control, FocusState.Keyboard);
|
||||
if (sender is MailItemDisplayInformationControl control && args.TryGetPosition(sender, out Point p))
|
||||
{
|
||||
if (control.DataContext is MailItemViewModel clickedMailItemContext)
|
||||
{
|
||||
var targetItems = ViewModel.MailCollection.AllItems.Where(a => a.IsSelected);
|
||||
var availableActions = ViewModel.GetAvailableMailActions(targetItems);
|
||||
|
||||
// if (control.DataContext is IMailItem clickedMailItemContext)
|
||||
// {
|
||||
// var targetItems = ViewModel.GetTargetMailItemViewModels(clickedMailItemContext);
|
||||
// var availableActions = ViewModel.GetAvailableMailActions(targetItems);
|
||||
if (!availableActions?.Any() ?? false) return;
|
||||
|
||||
// if (!availableActions?.Any() ?? false) return;
|
||||
// var t = targetItems.ElementAt(0);
|
||||
var clickedOperation = await GetMailOperationFromFlyoutAsync(availableActions, control, p.X, p.Y);
|
||||
|
||||
// ViewModel.ChangeCustomFocusedState(targetItems, true);
|
||||
if (clickedOperation == null) return;
|
||||
|
||||
// var clickedOperation = await GetMailOperationFromFlyoutAsync(availableActions, control, p.X, p.Y);
|
||||
var prepRequest = new MailOperationPreperationRequest(clickedOperation.Operation, targetItems.Select(a => a.MailCopy));
|
||||
|
||||
// ViewModel.ChangeCustomFocusedState(targetItems, false);
|
||||
|
||||
// if (clickedOperation == null) return;
|
||||
|
||||
// var prepRequest = new MailOperationPreperationRequest(clickedOperation.Operation, targetItems.Select(a => a.MailCopy));
|
||||
|
||||
// await ViewModel.ExecuteMailOperationAsync(prepRequest);
|
||||
// }
|
||||
//}
|
||||
await ViewModel.ExecuteMailOperationAsync(prepRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<MailOperationMenuItem> GetMailOperationFromFlyoutAsync(IEnumerable<MailOperationMenuItem> availableActions,
|
||||
@@ -507,22 +501,7 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
||||
private void DeleteAllInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||
=> ViewModel.ExecuteMailOperationCommand.Execute(MailOperation.SoftDelete);
|
||||
|
||||
private void ThreadContainerTapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
if (sender is ItemContainer container && container.Tag is ThreadMailItemViewModel expander)
|
||||
{
|
||||
// Toggle expansion state
|
||||
expander.IsThreadExpanded = !expander.IsThreadExpanded;
|
||||
|
||||
// Find the expander icon and animate its rotation using Composition APIs
|
||||
var expanderIcon = WinoVisualTreeHelper.GetChildObject<FontIcon>(container, "ExpanderIcon");
|
||||
if (expanderIcon != null)
|
||||
{
|
||||
var targetAngle = expander.IsThreadExpanded ? 90f : 0f;
|
||||
AnimateRotationWithComposition(expanderIcon, targetAngle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animates the rotation using high-performance Composition APIs
|
||||
@@ -561,4 +540,32 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
||||
UpdateSelectAllButtonStatus();
|
||||
UpdateAdaptiveness();
|
||||
}
|
||||
|
||||
private void ThreadContainerRightTapped(object sender, RightTappedRoutedEventArgs e)
|
||||
{
|
||||
if (sender is ItemContainer container && container.Tag is ThreadMailItemViewModel expander)
|
||||
{
|
||||
expander.IsThreadExpanded = !expander.IsThreadExpanded;
|
||||
|
||||
// Select all.
|
||||
ViewModel.MailCollection.AllItems.Where(a => expander.ThreadEmails.Contains(a)).ForEach(a => a.IsSelected = true);
|
||||
}
|
||||
}
|
||||
|
||||
private void ThreadContainerTapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
if (sender is ItemContainer container && container.Tag is ThreadMailItemViewModel expander)
|
||||
{
|
||||
// Toggle expansion state
|
||||
expander.IsThreadExpanded = !expander.IsThreadExpanded;
|
||||
|
||||
// Find the expander icon and animate its rotation using Composition APIs
|
||||
var expanderIcon = WinoVisualTreeHelper.GetChildObject<FontIcon>(container, "ExpanderIcon");
|
||||
if (expanderIcon != null)
|
||||
{
|
||||
var targetAngle = expander.IsThreadExpanded ? 90f : 0f;
|
||||
AnimateRotationWithComposition(expanderIcon, targetAngle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@
|
||||
|
||||
<TextBlock
|
||||
x:Name="ElementThemeSelectionDisabledTextBlock"
|
||||
Margin="4,0,0,0"
|
||||
x:Load="{x:Bind ViewModel.CanSelectElementTheme, Mode=OneWay, Converter={StaticResource ReverseBooleanConverter}}"
|
||||
Foreground="{ThemeResource InfoBarWarningSeverityIconBackground}"
|
||||
Text="{x:Bind domain:Translator.SettingsElementThemeSelectionDisabled}" />
|
||||
@@ -149,7 +150,10 @@
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<!-- Backdrop Selection -->
|
||||
<controls:SettingsCard Description="Choose the backdrop effect for your app window" Header="Window Backdrop">
|
||||
<controls:SettingsCard
|
||||
Description="Choose the backdrop effect for your app window"
|
||||
Header="Window Backdrop"
|
||||
IsEnabled="{x:Bind ViewModel.CanSelectElementTheme, Mode=OneWay}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<PathIcon Data="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm-1-13h2v6h-2zm0 8h2v2h-2z" />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
|
||||
@@ -28,6 +28,7 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
private readonly IContactService _contactService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly ISignatureService _signatureService;
|
||||
|
||||
private readonly IMimeFileService _mimeFileService;
|
||||
private readonly IPreferencesService _preferencesService;
|
||||
|
||||
@@ -192,15 +193,23 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
.OrWhereContains("MailCopy.FromName", options.SearchQuery)
|
||||
.OrWhereContains("MailCopy.FromAddress", options.SearchQuery));
|
||||
|
||||
// Support pagination by excluding already fetched items
|
||||
if (options.ExistingUniqueIds?.Any() ?? false)
|
||||
{
|
||||
query.WhereNotIn("MailCopy.UniqueId", options.ExistingUniqueIds);
|
||||
}
|
||||
|
||||
//if (options.Skip > 0)
|
||||
//{
|
||||
// query.Skip(options.Skip);
|
||||
//}
|
||||
// Support skip for pagination
|
||||
if (options.Skip > 0)
|
||||
{
|
||||
query.Skip(options.Skip);
|
||||
}
|
||||
|
||||
// Support custom take count for pagination
|
||||
if (options.Take > 0)
|
||||
{
|
||||
query.Take(options.Take);
|
||||
}
|
||||
|
||||
return query.GetRawQuery();
|
||||
}
|
||||
@@ -218,7 +227,6 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
{
|
||||
// If not just do the query.
|
||||
var query = BuildMailFetchQuery(options);
|
||||
|
||||
mails = await Connection.QueryAsync<MailCopy>(query);
|
||||
}
|
||||
|
||||
@@ -239,9 +247,6 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// Threading is disabled. Just return everything as it is.
|
||||
// mails.Sort(options.SortingOptionType == SortingOptionType.ReceiveDate ? new DateComparer() : new NameComparer());
|
||||
|
||||
return [.. mails];
|
||||
}
|
||||
|
||||
@@ -1005,7 +1010,7 @@ public class MailService : BaseDatabaseService, IMailService
|
||||
|
||||
public async Task<List<MailCopy>> GetExistingMailsAsync(Guid folderId, IEnumerable<MailKit.UniqueId> uniqueIds)
|
||||
{
|
||||
var localMailIds = uniqueIds.Where(a => a != null).Select(a => MailkitClientExtensions.CreateUid(folderId, a.Id)).ToArray();
|
||||
var localMailIds = uniqueIds.Select(a => MailkitClientExtensions.CreateUid(folderId, a.Id)).ToArray();
|
||||
|
||||
var query = new Query(nameof(MailCopy))
|
||||
.WhereIn("Id", localMailIds)
|
||||
|
||||
@@ -14,9 +14,14 @@
|
||||
<!-- key value for <packageSource> should match key values from <packageSources> element -->
|
||||
<packageSource key="nuget">
|
||||
<package pattern="*" />
|
||||
<package pattern="CommunityToolkit.Common" />
|
||||
<package pattern="Microsoft.*" />
|
||||
<package pattern="Newtonsoft.Json" />
|
||||
<package pattern="CommunityToolkit.WinUI.Extensions" />
|
||||
</packageSource>
|
||||
<packageSource key="labsFeed">
|
||||
<package pattern="CommunityToolkit.Labs.*" />
|
||||
<package pattern="CommunityToolkit.WinUI.Extensions" />
|
||||
</packageSource>
|
||||
</packageSourceMapping>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user