This commit is contained in:
Burak Kaan Köse
2025-10-03 15:46:38 +02:00
parent 2bec513d2c
commit 7b41f558d4
62 changed files with 1811 additions and 2514 deletions
+1 -2
View File
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using SQLite;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Entities.Mail;
@@ -11,7 +10,7 @@ namespace Wino.Core.Domain.Entities.Mail;
/// Summary of the parsed MIME messages.
/// Wino will do non-network operations on this table and others from the original MIME.
/// </summary>
public class MailCopy : IMailItem
public class MailCopy
{
/// <summary>
/// Unique Id of the mail.
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Menus;
namespace Wino.Core.Domain.Interfaces;
@@ -8,6 +8,6 @@ namespace Wino.Core.Domain.Interfaces;
public interface IContextMenuItemService
{
IEnumerable<FolderOperationMenuItem> GetFolderContextMenuActions(IBaseFolderMenuItem folderInformation);
IEnumerable<MailOperationMenuItem> GetMailItemContextMenuActions(IEnumerable<IMailItem> selectedMailItems);
IEnumerable<MailOperationMenuItem> GetMailItemRenderMenuActions(IMailItem mailItem, bool isDarkEditor);
IEnumerable<MailOperationMenuItem> GetMailItemContextMenuActions(IEnumerable<MailCopy> selectedMailItems);
IEnumerable<MailOperationMenuItem> GetMailItemRenderMenuActions(MailCopy mailItem, bool isDarkEditor);
}
@@ -1,6 +1,6 @@
using System.Collections.Generic;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Menus;
namespace Wino.Core.Domain.Interfaces;
@@ -18,12 +18,12 @@ public interface IContextMenuProvider
/// </summary>
/// <param name="folderInformation">Current folder that asks for the menu items.</param>
/// <param name="selectedMailItems">Selected menu items in the given folder.</param>
IEnumerable<MailOperationMenuItem> GetMailItemContextMenuActions(IMailItemFolder folderInformation, IEnumerable<IMailItem> selectedMailItems);
IEnumerable<MailOperationMenuItem> GetMailItemContextMenuActions(IMailItemFolder folderInformation, IEnumerable<MailCopy> selectedMailItems);
/// <summary>
/// Calculates and returns available mail operations for mail rendering CommandBar.
/// </summary>
/// <param name="mailItem">Rendered mail item.</param>
/// <param name="activeFolder">Folder that mail item belongs to.</param>
IEnumerable<MailOperationMenuItem> GetMailItemRenderMenuActions(IMailItem mailItem, IMailItemFolder activeFolder, bool isDarkEditor);
IEnumerable<MailOperationMenuItem> GetMailItemRenderMenuActions(MailCopy mailItem, IMailItemFolder activeFolder, bool isDarkEditor);
}
@@ -1,3 +0,0 @@
namespace Wino.Core.Domain.Interfaces;
public interface IGmailThreadingStrategy : IThreadingStrategy { }
@@ -1,3 +0,0 @@
namespace Wino.Core.Domain.Interfaces;
public interface IImapThreadingStrategy : IThreadingStrategy { }
+1 -1
View File
@@ -25,7 +25,7 @@ public interface IMailService
/// Caution: This method is not safe. Use other overrides.
/// </summary>
Task<List<MailCopy>> GetMailItemsAsync(IEnumerable<string> mailCopyIds);
Task<List<IMailItem>> FetchMailsAsync(MailListInitializationOptions options, CancellationToken cancellationToken = default);
Task<List<MailCopy>> FetchMailsAsync(MailListInitializationOptions options, CancellationToken cancellationToken = default);
/// <summary>
/// Deletes all mail copies for all folders.
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Entities.Mail;
namespace Wino.Core.Domain.Interfaces;
@@ -10,7 +10,7 @@ public interface INotificationBuilder
/// <summary>
/// Creates toast notifications for new mails.
/// </summary>
Task CreateNotificationsAsync(Guid inboxFolderId, IEnumerable<IMailItem> newMailItems);
Task CreateNotificationsAsync(Guid inboxFolderId, IEnumerable<MailCopy> newMailItems);
/// <summary>
/// Gets the unread Inbox messages for each account and updates the taskbar icon.
@@ -1,3 +0,0 @@
namespace Wino.Core.Domain.Interfaces;
public interface IOutlookThreadingStrategy : IThreadingStrategy { }
@@ -1,18 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Interfaces;
public interface IThreadingStrategy
{
/// <summary>
/// Attach thread mails to the list.
/// </summary>
/// <param name="items">Original mails.</param>
/// <returns>Original mails with thread mails.</returns>
Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder);
bool ShouldThreadWithItem(IMailItem originalItem, IMailItem targetItem);
}
@@ -1,12 +0,0 @@
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Interfaces;
public interface IThreadingStrategyProvider
{
/// <summary>
/// Returns corresponding threading strategy that applies to given provider type.
/// </summary>
/// <param name="mailProviderType">Provider type.</param>
IThreadingStrategy GetStrategy(MailProviderType mailProviderType);
}
@@ -4,7 +4,6 @@ using System.Threading.Tasks;
using MailKit;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
namespace Wino.Core.Domain.Interfaces;
@@ -30,7 +29,7 @@ public interface IWinoSynchronizerBase : IBaseSynchronizer
/// <param name="mailItem">Mail item to download from server.</param>
/// <param name="transferProgress">Optional progress reporting for download operation.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task DownloadMissingMimeMessageAsync(IMailItem mailItem, ITransferProgress transferProgress, CancellationToken cancellationToken = default);
Task DownloadMissingMimeMessageAsync(MailCopy mailItem, ITransferProgress transferProgress, CancellationToken cancellationToken = default);
/// <summary>
/// 1. Cancel active synchronization.
@@ -1,31 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Models.Comparers;
public class DateComparer : IComparer<IMailItem>, IEqualityComparer
{
public int Compare(IMailItem x, IMailItem y)
{
return DateTime.Compare(y.CreationDate, x.CreationDate);
}
public new bool Equals(object x, object y)
{
if (x is IMailItem firstItem && y is IMailItem secondItem)
{
return firstItem.Equals(secondItem);
}
return false;
}
public int GetHashCode(object obj) => (obj as IMailItem).GetHashCode();
public DateComparer()
{
}
}
@@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Models.Comparers;
public class ListItemComparer : IComparer<object>
{
public bool SortByName { get; set; }
public DateComparer DateComparer = new DateComparer();
public readonly NameComparer NameComparer = new NameComparer();
public int Compare(object x, object y)
{
if (x is IMailItem xMail && y is IMailItem yMail)
{
var itemComparer = GetItemComparer();
return itemComparer.Compare(xMail, yMail);
}
else if (x is DateTime dateX && y is DateTime dateY)
return DateTime.Compare(dateY, dateX);
else if (x is string stringX && y is string stringY)
return stringY.CompareTo(stringX);
return 0;
}
public IComparer<IMailItem> GetItemComparer()
{
if (SortByName)
return NameComparer;
else
return DateComparer;
}
}
@@ -1,12 +0,0 @@
using System.Collections.Generic;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Models.Comparers;
public class NameComparer : IComparer<IMailItem>
{
public int Compare(IMailItem x, IMailItem y)
{
return string.Compare(x.FromName, y.FromName);
}
}
@@ -1,14 +0,0 @@
using System;
using System.Collections.Generic;
namespace Wino.Core.Domain.Models.MailItem;
/// <summary>
/// An interface that returns the UniqueId store for IMailItem.
/// For threads, it may be multiple items.
/// For single mails, it'll always be one item.
/// </summary>
public interface IMailHashContainer
{
IEnumerable<Guid> GetContainingIds();
}
@@ -1,34 +0,0 @@
using System;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Domain.Models.MailItem;
/// <summary>
/// Interface of simplest representation of a MailCopy.
/// </summary>
public interface IMailItem : IMailHashContainer
{
Guid UniqueId { get; }
string Id { get; }
string Subject { get; }
string ThreadId { get; }
string MessageId { get; }
string References { get; }
string InReplyTo { get; }
string PreviewText { get; }
string FromName { get; }
DateTime CreationDate { get; }
string FromAddress { get; }
bool HasAttachments { get; }
bool IsFlagged { get; }
bool IsFocused { get; }
bool IsRead { get; }
string DraftId { get; }
bool IsDraft { get; }
Guid FileId { get; }
MailItemFolder AssignedFolder { get; }
MailAccount AssignedAccount { get; }
AccountContact SenderContact { get; }
}
@@ -1,15 +0,0 @@
using System.Collections.ObjectModel;
namespace Wino.Core.Domain.Models.MailItem;
/// <summary>
/// Interface that represents conversation threads.
/// Even though this type has 1 single UI representation most of the time,
/// it can contain multiple IMailItem.
/// </summary>
public interface IMailItemThread : IMailItem
{
ObservableCollection<IMailItem> ThreadItems { get; }
IMailItem LatestMailItem { get; }
IMailItem FirstMailItem { get; }
}
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Wino.Core.Domain.Entities.Mail;
namespace Wino.Core.Domain.Models.MailItem;
@@ -7,12 +8,12 @@ namespace Wino.Core.Domain.Models.MailItem;
/// </summary>
public class MailDragPackage
{
public MailDragPackage(IEnumerable<IMailItem> draggingMails)
public MailDragPackage(IEnumerable<MailCopy> draggingMails)
{
DraggingMails = draggingMails;
}
public MailDragPackage(IMailItem draggingMail)
public MailDragPackage(MailCopy draggingMail)
{
DraggingMails =
[
@@ -20,5 +21,5 @@ public class MailDragPackage
];
}
public IEnumerable<IMailItem> DraggingMails { get; set; }
public IEnumerable<MailCopy> DraggingMails { get; set; }
}
@@ -1,94 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Domain.Models.MailItem;
public class ThreadMailItem : IMailItemThread
{
// TODO: Ideally this should be SortedList.
public ObservableCollection<IMailItem> ThreadItems { get; } = new ObservableCollection<IMailItem>();
public IMailItem LatestMailItem => ThreadItems.LastOrDefault();
public IMailItem FirstMailItem => ThreadItems.FirstOrDefault();
public bool AddThreadItem(IMailItem item)
{
if (item == null) return false;
if (ThreadItems.Any(a => a.Id == item.Id))
{
return false;
}
if (item != null && item.IsDraft)
{
ThreadItems.Insert(0, item);
return true;
}
var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate);
if (insertItem == null)
ThreadItems.Insert(ThreadItems.Count, item);
else
{
var index = ThreadItems.IndexOf(insertItem);
ThreadItems.Insert(index, item);
}
return true;
}
public IEnumerable<Guid> GetContainingIds() => ThreadItems?.Select(a => a.UniqueId) ?? default;
#region IMailItem
public Guid UniqueId => LatestMailItem?.UniqueId ?? Guid.Empty;
public string Id => LatestMailItem?.Id ?? string.Empty;
// Show subject from last item.
public string Subject => LatestMailItem?.Subject ?? string.Empty;
public string ThreadId => LatestMailItem?.ThreadId ?? string.Empty;
public string PreviewText => FirstMailItem?.PreviewText ?? string.Empty;
public string FromName => LatestMailItem?.FromName ?? string.Empty;
public string FromAddress => LatestMailItem?.FromAddress ?? string.Empty;
public bool HasAttachments => ThreadItems.Any(a => a.HasAttachments);
public bool IsFlagged => ThreadItems.Any(a => a.IsFlagged);
public bool IsFocused => LatestMailItem?.IsFocused ?? false;
public bool IsRead => ThreadItems.All(a => a.IsRead);
public DateTime CreationDate => FirstMailItem?.CreationDate ?? DateTime.MinValue;
public bool IsDraft => ThreadItems.Any(a => a.IsDraft);
public string DraftId => string.Empty;
public string MessageId => LatestMailItem?.MessageId;
public string References => LatestMailItem?.References ?? string.Empty;
public string InReplyTo => LatestMailItem?.InReplyTo ?? string.Empty;
public MailItemFolder AssignedFolder => LatestMailItem?.AssignedFolder;
public MailAccount AssignedAccount => LatestMailItem?.AssignedAccount;
public Guid FileId => LatestMailItem?.FileId ?? Guid.Empty;
public AccountContact SenderContact => LatestMailItem?.SenderContact;
#endregion
}
@@ -1,4 +1,5 @@
using System;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Models.MailItem;
@@ -10,4 +11,4 @@ namespace Wino.Core.Domain.Models.MailItem;
/// <param name="SourceAction"></param>
/// <param name="TargetAction"></param>
/// <param name="Condition"></param>
public record ToggleRequestRule(MailOperation SourceAction, MailOperation TargetAction, Func<IMailItem, bool> Condition);
public record ToggleRequestRule(MailOperation SourceAction, MailOperation TargetAction, Func<MailCopy, bool> Condition);
@@ -1,7 +1,4 @@
using System.Collections.Generic;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Comparers;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Models.Reader;
@@ -9,16 +6,6 @@ public class SortingOption
{
public SortingOptionType Type { get; set; }
public string Title { get; set; }
public IComparer<IMailItem> Comparer
{
get
{
if (Type == SortingOptionType.ReceiveDate)
return new DateComparer();
else
return new NameComparer();
}
}
public SortingOption(string title, SortingOptionType type)
{
@@ -1,8 +1,8 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Models.Synchronization;
@@ -16,7 +16,7 @@ public class MailSynchronizationResult
/// It's ignored in serialization. Client should not react to this.
/// </summary>
[JsonIgnore]
public IEnumerable<IMailItem> DownloadedMessages { get; set; } = [];
public IEnumerable<MailCopy> DownloadedMessages { get; set; } = [];
public ProfileInformation ProfileInformation { get; set; }
@@ -25,7 +25,7 @@ public class MailSynchronizationResult
public static MailSynchronizationResult Empty => new() { CompletedState = SynchronizationCompletedState.Success };
// Mail synchronization
public static MailSynchronizationResult Completed(IEnumerable<IMailItem> downloadedMessages)
public static MailSynchronizationResult Completed(IEnumerable<MailCopy> downloadedMessages)
=> new()
{
DownloadedMessages = downloadedMessages,