Fixed Archive implementation for Gmail.

This commit is contained in:
Burak Kaan Köse
2024-06-21 23:48:03 +02:00
parent 8c830761f3
commit 82ae13ba3e
7 changed files with 121 additions and 5 deletions

View File

@@ -11,7 +11,8 @@
ChangeFlag, ChangeFlag,
AlwaysMoveTo, AlwaysMoveTo,
MoveToFocused, MoveToFocused,
RenameFolder RenameFolder,
Archive
} }
// UI requests // UI requests

View File

@@ -0,0 +1,66 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;
namespace Wino.Core.Requests
{
/// <summary>
/// Archive message request.
/// By default, the message will be moved to the Archive folder.
/// For Gmail, 'Archive' label will be removed from the message.
/// </summary>
/// <param name="IsArchiving">Whether are archiving or unarchiving</param>
/// <param name="Item">Mail to archive</param>
/// <param name="FromFolder">Source folder.</param>
/// <param name="ToFolder">Optional Target folder. Required for ImapSynchronizer and OutlookSynchronizer.</param>
public record ArchiveRequest(bool IsArchiving, MailCopy Item, MailItemFolder FromFolder, MailItemFolder ToFolder = null) : RequestBase<BatchArchiveRequest>(Item, MailSynchronizerOperation.Archive), ICustomFolderSynchronizationRequest
{
public List<Guid> SynchronizationFolderIds
{
get
{
var folderIds = new List<Guid> { FromFolder.Id };
if (ToFolder != null)
{
folderIds.Add(ToFolder.Id);
}
return folderIds;
}
}
public override IBatchChangeRequest CreateBatch(IEnumerable<IRequest> matchingItems)
=> new BatchArchiveRequest(IsArchiving, matchingItems, FromFolder, ToFolder);
public override void ApplyUIChanges()
{
WeakReferenceMessenger.Default.Send(new MailRemovedMessage(Item));
}
public override void RevertUIChanges()
{
WeakReferenceMessenger.Default.Send(new MailAddedMessage(Item));
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public record BatchArchiveRequest(bool IsArchiving, IEnumerable<IRequest> Items, MailItemFolder FromFolder, MailItemFolder ToFolder = null) : BatchRequestBase(Items, MailSynchronizerOperation.Archive)
{
public override void ApplyUIChanges()
{
Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailRemovedMessage(item.Item)));
}
public override void RevertUIChanges()
{
Items.ForEach(item => WeakReferenceMessenger.Default.Send(new MailAddedMessage(item.Item)));
}
}
}

View File

@@ -160,20 +160,37 @@ namespace Wino.Core.Services
} }
else if (action == MailOperation.Archive) else if (action == MailOperation.Archive)
{ {
// Validate archive folder exists. // For IMAP and Outlook: Validate archive folder exists.
// Gmail doesn't need archive folder existence.
var archiveFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Archive) MailItemFolder archiveFolder = null;
bool shouldRequireArchiveFolder = mailItem.AssignedAccount.ProviderType == MailProviderType.Outlook
|| mailItem.AssignedAccount.ProviderType == MailProviderType.IMAP4
|| mailItem.AssignedAccount.ProviderType == MailProviderType.Office365;
if (shouldRequireArchiveFolder)
{
archiveFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Archive)
?? throw new UnavailableSpecialFolderException(SpecialFolderType.Archive, mailItem.AssignedAccount.Id); ?? throw new UnavailableSpecialFolderException(SpecialFolderType.Archive, mailItem.AssignedAccount.Id);
}
return new MoveRequest(mailItem, mailItem.AssignedFolder, archiveFolder); return new ArchiveRequest(true, mailItem, mailItem.AssignedFolder, archiveFolder);
} }
else if (action == MailOperation.UnArchive || action == MailOperation.MarkAsNotJunk) else if (action == MailOperation.MarkAsNotJunk)
{ {
var inboxFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Inbox) var inboxFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Inbox)
?? throw new UnavailableSpecialFolderException(SpecialFolderType.Inbox, mailItem.AssignedAccount.Id); ?? throw new UnavailableSpecialFolderException(SpecialFolderType.Inbox, mailItem.AssignedAccount.Id);
return new MoveRequest(mailItem, mailItem.AssignedFolder, inboxFolder); return new MoveRequest(mailItem, mailItem.AssignedFolder, inboxFolder);
} }
else if (action == MailOperation.UnArchive)
{
var inboxFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Inbox)
?? throw new UnavailableSpecialFolderException(SpecialFolderType.Inbox, mailItem.AssignedAccount.Id);
return new ArchiveRequest(false, mailItem, mailItem.AssignedFolder, inboxFolder);
}
else if (action == MailOperation.SoftDelete) else if (action == MailOperation.SoftDelete)
{ {
var trashFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Deleted) var trashFolder = await _folderService.GetSpecialFolderByAccountIdAsync(mailItem.AssignedAccount.Id, SpecialFolderType.Deleted)

View File

@@ -272,6 +272,9 @@ namespace Wino.Core.Synchronizers
case MailSynchronizerOperation.CreateDraft: case MailSynchronizerOperation.CreateDraft:
yield return CreateDraft((BatchCreateDraftRequest)item); yield return CreateDraft((BatchCreateDraftRequest)item);
break; break;
case MailSynchronizerOperation.Archive:
yield return Archive((BatchArchiveRequest)item);
break;
} }
} }
}; };
@@ -324,6 +327,7 @@ namespace Wino.Core.Synchronizers
public virtual IEnumerable<IRequestBundle<TBaseRequest>> MoveToFocused(BatchMoveToFocusedRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType())); public virtual IEnumerable<IRequestBundle<TBaseRequest>> MoveToFocused(BatchMoveToFocusedRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
public virtual IEnumerable<IRequestBundle<TBaseRequest>> CreateDraft(BatchCreateDraftRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType())); public virtual IEnumerable<IRequestBundle<TBaseRequest>> CreateDraft(BatchCreateDraftRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
public virtual IEnumerable<IRequestBundle<TBaseRequest>> SendDraft(BatchSendDraftRequestRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType())); public virtual IEnumerable<IRequestBundle<TBaseRequest>> SendDraft(BatchSendDraftRequestRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
public virtual IEnumerable<IRequestBundle<TBaseRequest>> Archive(BatchArchiveRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
/// <summary> /// <summary>
/// Downloads a single missing message from synchronizer and saves it to given FileId from IMailItem. /// Downloads a single missing message from synchronizer and saves it to given FileId from IMailItem.

View File

@@ -635,6 +635,28 @@ namespace Wino.Core.Synchronizers
}); });
} }
public override IEnumerable<IRequestBundle<IClientServiceRequest>> Archive(BatchArchiveRequest request)
{
return CreateBatchedHttpBundleFromGroup(request, (items) =>
{
var batchModifyRequest = new BatchModifyMessagesRequest
{
Ids = items.Select(a => a.Item.Id.ToString()).ToList()
};
if (request.IsArchiving)
{
batchModifyRequest.RemoveLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
}
else
{
batchModifyRequest.AddLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
}
return _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
});
}
public override IEnumerable<IRequestBundle<IClientServiceRequest>> SendDraft(BatchSendDraftRequestRequest request) public override IEnumerable<IRequestBundle<IClientServiceRequest>> SendDraft(BatchSendDraftRequestRequest request)
{ {
return CreateHttpBundle(request, (item) => return CreateHttpBundle(request, (item) =>

View File

@@ -272,6 +272,9 @@ namespace Wino.Core.Synchronizers
}, request); }, request);
} }
public override IEnumerable<IRequestBundle<ImapRequest>> Archive(BatchArchiveRequest request)
=> Move(new BatchMoveRequest(request.Items, request.FromFolder, request.ToFolder));
public override IEnumerable<IRequestBundle<ImapRequest>> SendDraft(BatchSendDraftRequestRequest request) public override IEnumerable<IRequestBundle<ImapRequest>> SendDraft(BatchSendDraftRequestRequest request)
{ {
return CreateTaskBundle(async (ImapClient client) => return CreateTaskBundle(async (ImapClient client) =>

View File

@@ -572,6 +572,9 @@ namespace Wino.Core.Synchronizers
return [deleteBundle, sendMailRequest]; return [deleteBundle, sendMailRequest];
} }
public override IEnumerable<IRequestBundle<RequestInformation>> Archive(BatchArchiveRequest request)
=> Move(new BatchMoveRequest(request.Items, request.FromFolder, request.ToFolder));
public override async Task DownloadMissingMimeMessageAsync(IMailItem mailItem, public override async Task DownloadMissingMimeMessageAsync(IMailItem mailItem,
MailKit.ITransferProgress transferProgress = null, MailKit.ITransferProgress transferProgress = null,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)