diff --git a/Wino.Core.Domain/Interfaces/IThreadingStrategy.cs b/Wino.Core.Domain/Interfaces/IThreadingStrategy.cs
index cd0cec9c..8b5c5d14 100644
--- a/Wino.Core.Domain/Interfaces/IThreadingStrategy.cs
+++ b/Wino.Core.Domain/Interfaces/IThreadingStrategy.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
+using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Interfaces
@@ -12,7 +13,7 @@ namespace Wino.Core.Domain.Interfaces
///
/// Original mails.
/// Original mails with thread mails.
- Task> ThreadItemsAsync(List items);
+ Task> ThreadItemsAsync(List items, IMailItemFolder threadingForFolder);
bool ShouldThreadWithItem(IMailItem originalItem, IMailItem targetItem);
}
}
diff --git a/Wino.Core.Domain/Models/MailItem/ThreadMailItem.cs b/Wino.Core.Domain/Models/MailItem/ThreadMailItem.cs
index 0c59af3a..1b3a486f 100644
--- a/Wino.Core.Domain/Models/MailItem/ThreadMailItem.cs
+++ b/Wino.Core.Domain/Models/MailItem/ThreadMailItem.cs
@@ -14,19 +14,19 @@ namespace Wino.Core.Domain.Models.MailItem
public IMailItem LatestMailItem => ThreadItems.LastOrDefault();
public IMailItem FirstMailItem => ThreadItems.FirstOrDefault();
- public void AddThreadItem(IMailItem item)
+ public bool AddThreadItem(IMailItem item)
{
- if (item == null) return;
+ if (item == null) return false;
if (ThreadItems.Any(a => a.Id == item.Id))
{
- return;
+ return false;
}
if (item != null && item.IsDraft)
{
ThreadItems.Insert(0, item);
- return;
+ return true;
}
var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate);
@@ -39,6 +39,8 @@ namespace Wino.Core.Domain.Models.MailItem
ThreadItems.Insert(index, item);
}
+
+ return true;
}
public IEnumerable GetContainingIds() => ThreadItems?.Select(a => a.UniqueId) ?? default;
diff --git a/Wino.Core/Integration/Threading/APIThreadingStrategy.cs b/Wino.Core/Integration/Threading/APIThreadingStrategy.cs
index f1258f9d..4d43ff42 100644
--- a/Wino.Core/Integration/Threading/APIThreadingStrategy.cs
+++ b/Wino.Core/Integration/Threading/APIThreadingStrategy.cs
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Services;
@@ -27,7 +28,7 @@ namespace Wino.Core.Integration.Threading
}
///
- public async Task> ThreadItemsAsync(List items)
+ public async Task> ThreadItemsAsync(List items, IMailItemFolder threadingForFolder)
{
var assignedAccount = items[0].AssignedAccount;
@@ -62,11 +63,43 @@ namespace Wino.Core.Integration.Threading
}
var thread = new ThreadMailItem();
+
foreach (var childThreadItem in threadItem)
{
- thread.AddThreadItem(childThreadItem);
+ if (thread.ThreadItems.Any(a => a.Id == childThreadItem.Id))
+ {
+ // Mail already exist in the thread.
+ // There should be only 1 instance of the mail in the thread.
+ // Make sure we add the correct one.
+
+ // Add the one with threading folder.
+ var threadingFolderItem = threadItem.FirstOrDefault(a => a.Id == childThreadItem.Id && a.FolderId == threadingForFolder.Id);
+
+ if (threadingFolderItem == null) continue;
+
+ // Remove the existing one.
+ thread.ThreadItems.Remove(thread.ThreadItems.First(a => a.Id == childThreadItem.Id));
+
+ // Add the correct one for listing.
+ thread.AddThreadItem(threadingFolderItem);
+ }
+ else
+ {
+ thread.AddThreadItem(childThreadItem);
+ }
+ }
+
+ if (thread.ThreadItems.Count > 1)
+ {
+ resultList.Add(thread);
+ }
+ else
+ {
+ // Don't make threads if the thread has only one item.
+ // Gmail has may have multiple assignments for the same item.
+
+ resultList.Add(thread.ThreadItems.First());
}
- resultList.Add(thread);
}
}
diff --git a/Wino.Core/Integration/Threading/ImapThreadStrategy.cs b/Wino.Core/Integration/Threading/ImapThreadStrategy.cs
index 97aded37..047c4883 100644
--- a/Wino.Core/Integration/Threading/ImapThreadStrategy.cs
+++ b/Wino.Core/Integration/Threading/ImapThreadStrategy.cs
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using SqlKata;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Extensions;
using Wino.Core.Services;
@@ -58,7 +59,7 @@ namespace Wino.Core.Integration.Threading
return _databaseService.Connection.FindWithQueryAsync(query.GetRawQuery());
}
- public async Task> ThreadItemsAsync(List items)
+ public async Task> ThreadItemsAsync(List items, IMailItemFolder threadingForFolder)
{
var threads = new List();
diff --git a/Wino.Core/Services/MailService.cs b/Wino.Core/Services/MailService.cs
index 4a970593..4a5e16a7 100644
--- a/Wino.Core/Services/MailService.cs
+++ b/Wino.Core/Services/MailService.cs
@@ -241,7 +241,7 @@ namespace Wino.Core.Services
// Only thread items from Draft and Sent folders must present here.
// Otherwise this strategy will fetch the items that are in Deleted folder as well.
- var accountThreadedItems = await threadingStrategy.ThreadItemsAsync([.. group]);
+ var accountThreadedItems = await threadingStrategy.ThreadItemsAsync([.. group], options.Folders.First());
// Populate threaded items with folder and account assignments.
// Almost everything already should be in cache from initial population.