More abstraction for mail/calendar.
This commit is contained in:
@@ -41,7 +41,7 @@ namespace Wino.Core.Integration.Processors
|
||||
Task<List<MailItemFolder>> GetLocalFoldersAsync(Guid accountId);
|
||||
|
||||
|
||||
Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(SynchronizationOptions options);
|
||||
Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(MailSynchronizationOptions options);
|
||||
|
||||
Task<bool> MapLocalDraftAsync(Guid accountId, Guid localDraftCopyUniqueId, string newMailCopyId, string newDraftId, string newThreadId);
|
||||
Task UpdateFolderLastSyncDateAsync(Guid folderId);
|
||||
@@ -153,7 +153,7 @@ namespace Wino.Core.Integration.Processors
|
||||
public Task<List<MailItemFolder>> GetLocalFoldersAsync(Guid accountId)
|
||||
=> FolderService.GetFoldersAsync(accountId);
|
||||
|
||||
public Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(SynchronizationOptions options)
|
||||
public Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(MailSynchronizationOptions options)
|
||||
=> FolderService.GetSynchronizationFoldersAsync(options);
|
||||
|
||||
public Task DeleteFolderAsync(Guid accountId, string remoteFolderId)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Wino.Core.Services
|
||||
private readonly IOutlookAuthenticator _outlookAuthenticator;
|
||||
private readonly IGmailAuthenticator _gmailAuthenticator;
|
||||
|
||||
private readonly List<IBaseMailSynchronizer> synchronizerCache = new();
|
||||
private readonly List<IWinoSynchronizerBase> synchronizerCache = new();
|
||||
|
||||
public SynchronizerFactory(IOutlookChangeProcessor outlookChangeProcessor,
|
||||
IGmailChangeProcessor gmailChangeProcessor,
|
||||
@@ -39,7 +39,7 @@ namespace Wino.Core.Services
|
||||
_applicationConfiguration = applicationConfiguration;
|
||||
}
|
||||
|
||||
public async Task<IBaseMailSynchronizer> GetAccountSynchronizerAsync(Guid accountId)
|
||||
public async Task<IWinoSynchronizerBase> GetAccountSynchronizerAsync(Guid accountId)
|
||||
{
|
||||
var synchronizer = synchronizerCache.Find(a => a.Account.Id == accountId);
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Wino.Core.Services
|
||||
return synchronizer;
|
||||
}
|
||||
|
||||
private IBaseMailSynchronizer CreateIntegratorWithDefaultProcessor(MailAccount mailAccount)
|
||||
private IWinoSynchronizerBase CreateIntegratorWithDefaultProcessor(MailAccount mailAccount)
|
||||
{
|
||||
var providerType = mailAccount.ProviderType;
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Wino.Core.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
public IBaseMailSynchronizer CreateNewSynchronizer(MailAccount account)
|
||||
public IWinoSynchronizerBase CreateNewSynchronizer(MailAccount account)
|
||||
{
|
||||
var synchronizer = CreateIntegratorWithDefaultProcessor(account);
|
||||
|
||||
|
||||
@@ -143,10 +143,10 @@ namespace Wino.Core.Services
|
||||
{
|
||||
await EnsureServerConnectedAsync();
|
||||
|
||||
var options = new SynchronizationOptions()
|
||||
var options = new MailSynchronizationOptions()
|
||||
{
|
||||
AccountId = accountId,
|
||||
Type = SynchronizationType.ExecuteRequests
|
||||
Type = MailSynchronizationType.ExecuteRequests
|
||||
};
|
||||
|
||||
WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));
|
||||
|
||||
@@ -104,9 +104,9 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
await _gmailChangeProcessor.UpdateRemoteAliasInformationAsync(Account, remoteAliases).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
protected override async Task<SynchronizationResult> SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
protected override async Task<MailSynchronizationResult> SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.Information("Internal synchronization started for {Name}", Account.Name);
|
||||
_logger.Information("Internal mail synchronization started for {Name}", Account.Name);
|
||||
|
||||
// Gmail must always synchronize folders before because it doesn't have a per-folder sync.
|
||||
bool shouldSynchronizeFolders = true;
|
||||
@@ -124,7 +124,7 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
// Therefore we need to stop the synchronization at this point
|
||||
// if type is only folder metadata sync.
|
||||
|
||||
if (options.Type == SynchronizationType.FoldersOnly) return SynchronizationResult.Empty;
|
||||
if (options.Type == MailSynchronizationType.FoldersOnly) return MailSynchronizationResult.Empty;
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -281,7 +281,14 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
var unreadNewItems = await _gmailChangeProcessor.GetDownloadedUnreadMailsAsync(Account.Id, missingMessageIds).ConfigureAwait(false);
|
||||
|
||||
return SynchronizationResult.Completed(unreadNewItems);
|
||||
return MailSynchronizationResult.Completed(unreadNewItems);
|
||||
}
|
||||
|
||||
protected override Task<CalendarSynchronizationResult> SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.Information("Internal calendar synchronization started for {Name}", Account.Name);
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private async Task SynchronizeFoldersAsync(CancellationToken cancellationToken = default)
|
||||
@@ -944,17 +951,16 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
await _gmailChangeProcessor.MapLocalDraftAsync(Account.Id, localDraftCopy.UniqueId, messageDraft.Message.Id, messageDraft.Id, messageDraft.Message.ThreadId);
|
||||
|
||||
var options = new SynchronizationOptions()
|
||||
var options = new MailSynchronizationOptions()
|
||||
{
|
||||
AccountId = Account.Id,
|
||||
Type = SynchronizationType.FullFolders
|
||||
Type = MailSynchronizationType.FullFolders
|
||||
};
|
||||
|
||||
await SynchronizeInternalAsync(options, cancellationToken);
|
||||
await SynchronizeMailsInternalAsync(options, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Maps existing Gmail Draft resources to local mail copies.
|
||||
/// This uses indexed search, therefore it's quite fast.
|
||||
|
||||
@@ -435,7 +435,7 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
];
|
||||
}
|
||||
|
||||
protected override async Task<SynchronizationResult> SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
protected override async Task<MailSynchronizationResult> SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var downloadedMessageIds = new List<string>();
|
||||
|
||||
@@ -444,14 +444,14 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
PublishSynchronizationProgress(1);
|
||||
|
||||
bool shouldDoFolderSync = options.Type == SynchronizationType.FullFolders || options.Type == SynchronizationType.FoldersOnly;
|
||||
bool shouldDoFolderSync = options.Type == MailSynchronizationType.FullFolders || options.Type == MailSynchronizationType.FoldersOnly;
|
||||
|
||||
if (shouldDoFolderSync)
|
||||
{
|
||||
await SynchronizeFoldersAsync(cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (options.Type != SynchronizationType.FoldersOnly)
|
||||
if (options.Type != MailSynchronizationType.FoldersOnly)
|
||||
{
|
||||
var synchronizationFolders = await _imapChangeProcessor.GetSynchronizationFoldersAsync(options).ConfigureAwait(false);
|
||||
|
||||
@@ -474,7 +474,7 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
var unreadNewItems = await _imapChangeProcessor.GetDownloadedUnreadMailsAsync(Account.Id, downloadedMessageIds).ConfigureAwait(false);
|
||||
|
||||
return SynchronizationResult.Completed(unreadNewItems);
|
||||
return MailSynchronizationResult.Completed(unreadNewItems);
|
||||
}
|
||||
|
||||
public override async Task ExecuteNativeRequestsAsync(List<IRequestBundle<ImapRequest>> batchedRequests, CancellationToken cancellationToken = default)
|
||||
@@ -1035,5 +1035,10 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
/// <param name="localFolder">Local folder.</param>
|
||||
public bool ShouldUpdateFolder(IMailFolder remoteFolder, MailItemFolder localFolder)
|
||||
=> !localFolder.FolderName.Equals(remoteFolder.Name, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
protected override Task<CalendarSynchronizationResult> SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
#endregion
|
||||
|
||||
|
||||
protected override async Task<SynchronizationResult> SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
protected override async Task<MailSynchronizationResult> SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var downloadedMessageIds = new List<string>();
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
await SynchronizeFoldersAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (options.Type != SynchronizationType.FoldersOnly)
|
||||
if (options.Type != MailSynchronizationType.FoldersOnly)
|
||||
{
|
||||
var synchronizationFolders = await _outlookChangeProcessor.GetSynchronizationFoldersAsync(options).ConfigureAwait(false);
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
var unreadNewItems = await _outlookChangeProcessor.GetDownloadedUnreadMailsAsync(Account.Id, downloadedMessageIds).ConfigureAwait(false);
|
||||
|
||||
return SynchronizationResult.Completed(unreadNewItems);
|
||||
return MailSynchronizationResult.Completed(unreadNewItems);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<string>> SynchronizeFolderAsync(MailItemFolder folder, CancellationToken cancellationToken = default)
|
||||
@@ -956,5 +956,10 @@ namespace Wino.Core.Synchronizers.Mail
|
||||
|
||||
return [package];
|
||||
}
|
||||
|
||||
protected override Task<CalendarSynchronizationResult> SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ using Wino.Messaging.UI;
|
||||
|
||||
namespace Wino.Core.Synchronizers
|
||||
{
|
||||
public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEventType> : BaseSynchronizer<TBaseRequest>, IBaseMailSynchronizer
|
||||
public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEventType> : BaseSynchronizer<TBaseRequest>, IWinoSynchronizerBase
|
||||
{
|
||||
protected ILogger Logger = Log.ForContext<WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEventType>>();
|
||||
|
||||
@@ -55,18 +55,23 @@ namespace Wino.Core.Synchronizers
|
||||
/// </summary>
|
||||
protected virtual Task SynchronizeAliasesAsync() => Task.CompletedTask;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Internally synchronizes the account with the given options.
|
||||
/// Internally synchronizes the account's mails with the given options.
|
||||
/// Not exposed and overriden for each synchronizer.
|
||||
/// </summary>
|
||||
/// <param name="options">Synchronization options.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>Synchronization result that contains summary of the sync.</returns>
|
||||
protected abstract Task<SynchronizationResult> SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default);
|
||||
|
||||
protected abstract Task<MailSynchronizationResult> SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Internally synchronizes the events of the account with given options.
|
||||
/// Not exposed and overriden for each synchronizer.
|
||||
/// </summary>
|
||||
/// <param name="options">Synchronization options.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>Synchronization result that contains summary of the sync.</returns>
|
||||
protected abstract Task<CalendarSynchronizationResult> SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Batches network requests, executes them, and does the needed synchronization after the batch request execution.
|
||||
@@ -74,7 +79,7 @@ namespace Wino.Core.Synchronizers
|
||||
/// <param name="options">Synchronization options.</param>
|
||||
/// <param name="cancellationToken">Cancellation token.</param>
|
||||
/// <returns>Synchronization result that contains summary of the sync.</returns>
|
||||
public async Task<SynchronizationResult> SynchronizeAsync(SynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
public async Task<MailSynchronizationResult> SynchronizeMailsAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -159,7 +164,7 @@ namespace Wino.Core.Synchronizers
|
||||
// Execute request sync options should be re-calculated after execution.
|
||||
// This is the part we decide which individual folders must be synchronized
|
||||
// after the batch request execution.
|
||||
if (options.Type == SynchronizationType.ExecuteRequests)
|
||||
if (options.Type == MailSynchronizationType.ExecuteRequests)
|
||||
options = GetSynchronizationOptionsAfterRequestExecution(requestCopies);
|
||||
|
||||
State = AccountSynchronizerState.Synchronizing;
|
||||
@@ -169,9 +174,9 @@ namespace Wino.Core.Synchronizers
|
||||
// Handle special synchronization types.
|
||||
|
||||
// Profile information sync.
|
||||
if (options.Type == SynchronizationType.UpdateProfile)
|
||||
if (options.Type == MailSynchronizationType.UpdateProfile)
|
||||
{
|
||||
if (!Account.IsProfileInfoSyncSupported) return SynchronizationResult.Empty;
|
||||
if (!Account.IsProfileInfoSyncSupported) return MailSynchronizationResult.Empty;
|
||||
|
||||
ProfileInformation newProfileInformation = null;
|
||||
|
||||
@@ -183,28 +188,28 @@ namespace Wino.Core.Synchronizers
|
||||
{
|
||||
Log.Error(ex, "Failed to update profile information for {Name}", Account.Name);
|
||||
|
||||
return SynchronizationResult.Failed;
|
||||
return MailSynchronizationResult.Failed;
|
||||
}
|
||||
|
||||
return SynchronizationResult.Completed(newProfileInformation);
|
||||
return MailSynchronizationResult.Completed(newProfileInformation);
|
||||
}
|
||||
|
||||
// Alias sync.
|
||||
if (options.Type == SynchronizationType.Alias)
|
||||
if (options.Type == MailSynchronizationType.Alias)
|
||||
{
|
||||
if (!Account.IsAliasSyncSupported) return SynchronizationResult.Empty;
|
||||
if (!Account.IsAliasSyncSupported) return MailSynchronizationResult.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
await SynchronizeAliasesAsync();
|
||||
|
||||
return SynchronizationResult.Empty;
|
||||
return MailSynchronizationResult.Empty;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to update aliases for {Name}", Account.Name);
|
||||
|
||||
return SynchronizationResult.Failed;
|
||||
return MailSynchronizationResult.Failed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +229,7 @@ namespace Wino.Core.Synchronizers
|
||||
}
|
||||
|
||||
// Start the internal synchronization.
|
||||
var synchronizationResult = await SynchronizeInternalAsync(options, activeSynchronizationCancellationToken).ConfigureAwait(false);
|
||||
var synchronizationResult = await SynchronizeMailsInternalAsync(options, activeSynchronizationCancellationToken).ConfigureAwait(false);
|
||||
|
||||
PublishUnreadItemChanges();
|
||||
|
||||
@@ -234,7 +239,7 @@ namespace Wino.Core.Synchronizers
|
||||
{
|
||||
Logger.Warning("Synchronization canceled.");
|
||||
|
||||
return SynchronizationResult.Canceled;
|
||||
return MailSynchronizationResult.Canceled;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -271,7 +276,7 @@ namespace Wino.Core.Synchronizers
|
||||
/// </summary>
|
||||
/// <param name="batches">Batch requests to run in synchronization.</param>
|
||||
/// <returns>New synchronization options with minimal HTTP effort.</returns>
|
||||
private SynchronizationOptions GetSynchronizationOptionsAfterRequestExecution(List<IRequestBase> requests)
|
||||
private MailSynchronizationOptions GetSynchronizationOptionsAfterRequestExecution(List<IRequestBase> requests)
|
||||
{
|
||||
List<Guid> synchronizationFolderIds = requests
|
||||
.Where(a => a is ICustomFolderSynchronizationRequest)
|
||||
@@ -279,7 +284,7 @@ namespace Wino.Core.Synchronizers
|
||||
.SelectMany(a => a.SynchronizationFolderIds)
|
||||
.ToList();
|
||||
|
||||
var options = new SynchronizationOptions()
|
||||
var options = new MailSynchronizationOptions()
|
||||
{
|
||||
AccountId = Account.Id,
|
||||
};
|
||||
@@ -288,13 +293,13 @@ namespace Wino.Core.Synchronizers
|
||||
{
|
||||
// Gather FolderIds to synchronize.
|
||||
|
||||
options.Type = SynchronizationType.CustomFolders;
|
||||
options.Type = MailSynchronizationType.CustomFolders;
|
||||
options.SynchronizationFolderIds = synchronizationFolderIds;
|
||||
}
|
||||
else
|
||||
{
|
||||
// At this point it's a mix of everything. Do full sync.
|
||||
options.Type = SynchronizationType.FullFolders;
|
||||
options.Type = MailSynchronizationType.FullFolders;
|
||||
}
|
||||
|
||||
return options;
|
||||
|
||||
Reference in New Issue
Block a user