Fix online search dedupe and pane layout scrolling
This commit is contained in:
@@ -1390,6 +1390,12 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
||||
static bool IsArchiveFolder(IMailItemFolder folder)
|
||||
=> folder?.SpecialFolderType == SpecialFolderType.Archive || folder?.RemoteFolderId == ServiceConstants.ARCHIVE_LABEL_ID;
|
||||
|
||||
var distinctFolders = folders?
|
||||
.Where(folder => folder != null)
|
||||
.GroupBy(folder => folder.Id)
|
||||
.Select(group => group.First())
|
||||
.ToList();
|
||||
|
||||
var messageIds = new HashSet<string>(StringComparer.Ordinal);
|
||||
|
||||
async Task CollectMessageIdsAsync(UsersResource.MessagesResource.ListRequest request)
|
||||
@@ -1421,7 +1427,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
||||
bool hasScopedQuery = queryText.StartsWith("label:", StringComparison.OrdinalIgnoreCase) ||
|
||||
queryText.StartsWith("in:", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (hasScopedQuery || folders?.Count == 0)
|
||||
if (hasScopedQuery || distinctFolders?.Count == 0)
|
||||
{
|
||||
var request = _gmailService.Users.Messages.List("me");
|
||||
request.Q = queryText;
|
||||
@@ -1431,7 +1437,7 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var folder in folders)
|
||||
foreach (var folder in distinctFolders)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
|
||||
@@ -1053,10 +1053,15 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
|
||||
{
|
||||
client = await _clientPool.GetClientAsync().ConfigureAwait(false);
|
||||
|
||||
List<MailCopy> searchResults = [];
|
||||
List<string> searchResultFolderMailUids = [];
|
||||
var distinctFolders = folders?
|
||||
.Where(folder => folder != null)
|
||||
.GroupBy(folder => folder.Id)
|
||||
.Select(group => group.First())
|
||||
.ToList() ?? [];
|
||||
|
||||
foreach (var folder in folders)
|
||||
HashSet<string> searchResultFolderMailUids = new(StringComparer.Ordinal);
|
||||
|
||||
foreach (var folder in distinctFolders)
|
||||
{
|
||||
if (folder is not MailItemFolder localFolder)
|
||||
continue;
|
||||
|
||||
@@ -267,18 +267,32 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
return MailSynchronizationResult.CompletedWithFolderResults(unreadNewItems, folderResults);
|
||||
}
|
||||
|
||||
public async Task DownloadSearchResultMessageAsync(string messageId, MailItemFolder assignedFolder, CancellationToken cancellationToken = default)
|
||||
public Task DownloadSearchResultMessageAsync(string messageId, MailItemFolder assignedFolder, CancellationToken cancellationToken = default)
|
||||
=> DownloadSearchResultMessageAsync(messageId, assignedFolder, existingMessageIds: null, cancellationToken);
|
||||
|
||||
private async Task DownloadSearchResultMessageAsync(string messageId,
|
||||
MailItemFolder assignedFolder,
|
||||
ISet<string> existingMessageIds,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(messageId) || assignedFolder == null) return;
|
||||
|
||||
// Online search can return the same message across repeated invocations/races.
|
||||
// Guard before network+MIME download and before database insert.
|
||||
var existing = await _outlookChangeProcessor.AreMailsExistsAsync([messageId]).ConfigureAwait(false);
|
||||
if (existing.Contains(messageId))
|
||||
if (existingMessageIds?.Contains(messageId) == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (existingMessageIds == null)
|
||||
{
|
||||
var existing = await _outlookChangeProcessor.AreMailsExistsAsync([messageId]).ConfigureAwait(false);
|
||||
if (existing.Contains(messageId))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Information("Downloading search result message {messageId} for {Name} - {FolderName}", messageId, Account.Name, assignedFolder.FolderName);
|
||||
|
||||
// Outlook message handling was a little strange.
|
||||
@@ -314,6 +328,8 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
// Use safe upsert path to avoid duplicate rows when message already exists.
|
||||
await _outlookChangeProcessor.CreateMailAsync(Account.Id, package).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
existingMessageIds?.Add(messageId);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<string>> SynchronizeFolderAsync(MailItemFolder folder, CancellationToken cancellationToken = default)
|
||||
@@ -2226,10 +2242,11 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
if (messageIdsWithKnownFolder.Count == 0) return [];
|
||||
|
||||
var locallyExistingMails = await _outlookChangeProcessor.AreMailsExistsAsync(messageIdsWithKnownFolder).ConfigureAwait(false);
|
||||
var existingMessageIds = new HashSet<string>(locallyExistingMails, StringComparer.Ordinal);
|
||||
|
||||
// Find messages that are not downloaded yet.
|
||||
List<Message> messagesToDownload = [];
|
||||
foreach (var id in messageIdsWithKnownFolder.Except(locallyExistingMails, StringComparer.Ordinal))
|
||||
foreach (var id in messageIdsWithKnownFolder.Except(existingMessageIds, StringComparer.Ordinal))
|
||||
{
|
||||
if (messagesById.TryGetValue(id, out var message))
|
||||
{
|
||||
@@ -2239,7 +2256,7 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
||||
|
||||
foreach (var message in messagesToDownload)
|
||||
{
|
||||
await DownloadSearchResultMessageAsync(message.Id, localFolders[message.ParentFolderId], cancellationToken).ConfigureAwait(false);
|
||||
await DownloadSearchResultMessageAsync(message.Id, localFolders[message.ParentFolderId], existingMessageIds, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Get results from database and return.
|
||||
|
||||
Reference in New Issue
Block a user