More abstraction for mail/calendar.

This commit is contained in:
Burak Kaan Köse
2024-12-24 18:30:25 +01:00
parent da2a58a88b
commit 1668dfcce6
28 changed files with 209 additions and 121 deletions

View File

@@ -119,13 +119,13 @@ namespace Wino.Calendar.ViewModels
// Start profile information synchronization.
// It's only available for Outlook and Gmail synchronizers.
var profileSyncOptions = new SynchronizationOptions()
var profileSyncOptions = new MailSynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.UpdateProfile
Type = MailSynchronizationType.UpdateProfile
};
var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client));
var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<MailSynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client));
var profileSynchronizationResult = profileSynchronizationResponse.Data;
@@ -141,10 +141,10 @@ namespace Wino.Calendar.ViewModels
accountCreationDialog.State = AccountCreationDialogState.FetchingEvents;
// Start synchronizing events.
var eventsSyncOptions = new SynchronizationOptions()
var eventsSyncOptions = new MailSynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.Events
Type = MailSynchronizationType.Events
};
}
}

View File

@@ -0,0 +1,9 @@
namespace Wino.Core.Domain.Enums
{
public enum CalendarSynchronizationType
{
AllCalendars, // Sync all calendars.
SingleCalendar, // Sync only one calendar.
UpdateProfile // Update profile information only.
}
}

View File

@@ -1,17 +1,14 @@
namespace Wino.Core.Domain.Enums
{
public enum SynchronizationType
public enum MailSynchronizationType
{
// Shared
UpdateProfile, // Only update profile information
ExecuteRequests, // Run the queued requests, and then synchronize if needed.
// Wino Mail
FoldersOnly, // Only synchronize folder metadata.
InboxOnly, // Only Inbox, Sent and Draft folders.
CustomFolders, // Only sync folders that are specified in the options.
FullFolders, // Synchronize all folders. This won't update profile or alias information.
Alias, // Only update alias information
// Calendar
Events
}
}

View File

@@ -1,7 +0,0 @@
namespace Wino.Core.Domain.Interfaces
{
public interface IBaseCalendarSynchronizer : IBaseSynchronizer
{
}
}

View File

@@ -26,7 +26,7 @@ namespace Wino.Core.Domain.Interfaces
Task ChangeFolderSynchronizationStateAsync(Guid folderId, bool isSynchronizationEnabled);
Task ChangeFolderShowUnreadCountStateAsync(Guid folderId, bool showUnreadCount);
Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(SynchronizationOptions options);
Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(MailSynchronizationOptions options);
/// <summary>
/// Returns the folder - mail mapping for the given mail copy ids.

View File

@@ -5,7 +5,7 @@ namespace Wino.Core.Domain.Interfaces
{
public interface ISynchronizerFactory
{
Task<IBaseMailSynchronizer> GetAccountSynchronizerAsync(Guid accountId);
Task<IWinoSynchronizerBase> GetAccountSynchronizerAsync(Guid accountId);
Task InitializeAsync();
}
}

View File

@@ -6,7 +6,7 @@ using Wino.Core.Domain.Models.Synchronization;
namespace Wino.Core.Domain.Interfaces
{
public interface IBaseMailSynchronizer : IBaseSynchronizer
public interface IWinoSynchronizerBase : IBaseSynchronizer
{
/// <summary>
/// Performs a full synchronization with the server with given options.
@@ -17,7 +17,7 @@ namespace Wino.Core.Domain.Interfaces
/// <param name="options">Options for synchronization.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Result summary of synchronization.</returns>
Task<SynchronizationResult> SynchronizeAsync(SynchronizationOptions options, CancellationToken cancellationToken = default);
Task<MailSynchronizationResult> SynchronizeMailsAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default);
/// <summary>
/// Downloads a single MIME message from the server and saves it to disk.

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Models.Synchronization
{
public class CalendarSynchronizationOptions
{
/// <summary>
/// Unique id of synchronization.
/// </summary>
public Guid Id { get; } = Guid.NewGuid();
/// <summary>
/// Account to execute synchronization for.
/// </summary>
public Guid AccountId { get; set; }
/// <summary>
/// Type of the synchronization to be performed.
/// </summary>
public CalendarSynchronizationType Type { get; set; }
/// <summary>
/// Calendar ids to synchronize.
/// </summary>
public List<Guid> SynchronizationCalendarIds { get; set; }
public override string ToString() => $"Type: {Type}, Calendars: {(SynchronizationCalendarIds == null ? "All" : string.Join(",", SynchronizationCalendarIds))}";
}
}

View File

@@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
namespace Wino.Core.Domain.Models.Synchronization
{
public class CalendarSynchronizationResult
{
public CalendarSynchronizationResult() { }
/// <summary>
/// Gets the new downloaded events from synchronization.
/// Server will create notifications for these event.
/// It's ignored in serialization. Client should not react to this.
/// </summary>
[JsonIgnore]
public IEnumerable<ICalendarItem> DownloadedEvents { get; set; } = [];
public ProfileInformation ProfileInformation { get; set; }
public SynchronizationCompletedState CompletedState { get; set; }
public static CalendarSynchronizationResult Empty => new() { CompletedState = SynchronizationCompletedState.Success };
// Mail synchronization
public static CalendarSynchronizationResult Completed(IEnumerable<ICalendarItem> downloadedEvent)
=> new()
{
DownloadedEvents = downloadedEvent,
CompletedState = SynchronizationCompletedState.Success
};
// Profile synchronization
public static CalendarSynchronizationResult Completed(ProfileInformation profileInformation)
=> new()
{
ProfileInformation = profileInformation,
CompletedState = SynchronizationCompletedState.Success
};
public static CalendarSynchronizationResult Canceled => new() { CompletedState = SynchronizationCompletedState.Canceled };
public static CalendarSynchronizationResult Failed => new() { CompletedState = SynchronizationCompletedState.Failed };
}
}

View File

@@ -4,7 +4,7 @@ using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Models.Synchronization
{
public class SynchronizationOptions
public class MailSynchronizationOptions
{
/// <summary>
/// Unique id of synchronization.
@@ -19,7 +19,7 @@ namespace Wino.Core.Domain.Models.Synchronization
/// <summary>
/// Type of the synchronization to be performed.
/// </summary>
public SynchronizationType Type { get; set; }
public MailSynchronizationType Type { get; set; }
/// <summary>
/// Collection of FolderId to perform SynchronizationType.Custom type sync.
@@ -33,6 +33,6 @@ namespace Wino.Core.Domain.Models.Synchronization
/// </summary>
public Guid? GroupedSynchronizationTrackingId { get; set; }
public override string ToString() => $"Type: {Type}, Folders: {(SynchronizationFolderIds == null ? "None" : string.Join(",", SynchronizationFolderIds))}";
public override string ToString() => $"Type: {Type}, Folders: {(SynchronizationFolderIds == null ? "All" : string.Join(",", SynchronizationFolderIds))}";
}
}

View File

@@ -1,15 +1,14 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Models.Synchronization
{
public class SynchronizationResult
public class MailSynchronizationResult
{
public SynchronizationResult() { }
public MailSynchronizationResult() { }
/// <summary>
/// Gets the new downloaded messages from synchronization.
@@ -19,22 +18,14 @@ namespace Wino.Core.Domain.Models.Synchronization
[JsonIgnore]
public IEnumerable<IMailItem> DownloadedMessages { get; set; } = [];
/// <summary>
/// Gets the new downloaded events from synchronization.
/// Server will create notifications for these events.
/// It's ignored in serialization. Client should not react to this.
/// </summary>
[JsonIgnore]
public IEnumerable<ICalendarItem> DownloadedEvents { get; set; } = [];
public ProfileInformation ProfileInformation { get; set; }
public SynchronizationCompletedState CompletedState { get; set; }
public static SynchronizationResult Empty => new() { CompletedState = SynchronizationCompletedState.Success };
public static MailSynchronizationResult Empty => new() { CompletedState = SynchronizationCompletedState.Success };
// Mail synchronization
public static SynchronizationResult Completed(IEnumerable<IMailItem> downloadedMessages)
public static MailSynchronizationResult Completed(IEnumerable<IMailItem> downloadedMessages)
=> new()
{
DownloadedMessages = downloadedMessages,
@@ -42,14 +33,14 @@ namespace Wino.Core.Domain.Models.Synchronization
};
// Profile synchronization
public static SynchronizationResult Completed(ProfileInformation profileInformation)
public static MailSynchronizationResult Completed(ProfileInformation profileInformation)
=> new()
{
ProfileInformation = profileInformation,
CompletedState = SynchronizationCompletedState.Success
};
public static SynchronizationResult Canceled => new() { CompletedState = SynchronizationCompletedState.Canceled };
public static SynchronizationResult Failed => new() { CompletedState = SynchronizationCompletedState.Failed };
public static MailSynchronizationResult Canceled => new() { CompletedState = SynchronizationCompletedState.Canceled };
public static MailSynchronizationResult Failed => new() { CompletedState = SynchronizationCompletedState.Failed };
}
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -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));

View File

@@ -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.

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;

View File

@@ -159,13 +159,13 @@ namespace Wino.Mail.ViewModels
// Start profile information synchronization.
// It's only available for Outlook and Gmail synchronizers.
var profileSyncOptions = new SynchronizationOptions()
var profileSyncOptions = new MailSynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.UpdateProfile
Type = MailSynchronizationType.UpdateProfile
};
var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client));
var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<MailSynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client));
var profileSynchronizationResult = profileSynchronizationResponse.Data;
@@ -189,13 +189,13 @@ namespace Wino.Mail.ViewModels
creationDialog.State = AccountCreationDialogState.PreparingFolders;
// Start synchronizing folders.
var folderSyncOptions = new SynchronizationOptions()
var folderSyncOptions = new MailSynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.FoldersOnly
Type = MailSynchronizationType.FoldersOnly
};
var folderSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(folderSyncOptions, SynchronizationSource.Client));
var folderSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync<MailSynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(folderSyncOptions, SynchronizationSource.Client));
var folderSynchronizationResult = folderSynchronizationResponse.Data;
@@ -207,13 +207,13 @@ namespace Wino.Mail.ViewModels
{
// Try to synchronize aliases for the account.
var aliasSyncOptions = new SynchronizationOptions()
var aliasSyncOptions = new MailSynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.Alias
Type = MailSynchronizationType.Alias
};
var aliasSyncResponse = await WinoServerConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client));
var aliasSyncResponse = await WinoServerConnectionManager.GetResponseAsync<MailSynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client));
var aliasSynchronizationResult = folderSynchronizationResponse.Data;
if (aliasSynchronizationResult.CompletedState != SynchronizationCompletedState.Success)

View File

@@ -76,13 +76,13 @@ namespace Wino.Mail.ViewModels
{
if (!CanSynchronizeAliases) return;
var aliasSyncOptions = new SynchronizationOptions()
var aliasSyncOptions = new MailSynchronizationOptions()
{
AccountId = Account.Id,
Type = SynchronizationType.Alias
Type = MailSynchronizationType.Alias
};
var aliasSyncResponse = await _winoServerConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client));
var aliasSyncResponse = await _winoServerConnectionManager.GetResponseAsync<MailSynchronizationResult, NewSynchronizationRequested>(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client));
if (aliasSyncResponse.IsSuccess)
await LoadAliasesAsync();

View File

@@ -312,10 +312,10 @@ namespace Wino.Mail.ViewModels
foreach (var account in accounts)
{
var options = new SynchronizationOptions()
var options = new MailSynchronizationOptions()
{
AccountId = account.Id,
Type = SynchronizationType.FullFolders
Type = MailSynchronizationType.FullFolders
};
Messenger.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));
@@ -885,10 +885,10 @@ namespace Wino.Mail.ViewModels
await ChangeLoadedAccountAsync(createdMenuItem);
// Each created account should start a new synchronization automatically.
var options = new SynchronizationOptions()
var options = new MailSynchronizationOptions()
{
AccountId = createdAccount.Id,
Type = SynchronizationType.FullFolders,
Type = MailSynchronizationType.FullFolders,
};
Messenger.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));

View File

@@ -471,10 +471,10 @@ namespace Wino.Mail.ViewModels
foreach (var folder in ActiveFolder.HandlingFolders)
{
var options = new SynchronizationOptions()
var options = new MailSynchronizationOptions()
{
AccountId = folder.MailAccountId,
Type = SynchronizationType.CustomFolders,
Type = MailSynchronizationType.CustomFolders,
SynchronizationFolderIds = [folder.Id],
GroupedSynchronizationTrackingId = trackingSynchronizationId
};
@@ -516,7 +516,7 @@ namespace Wino.Mail.ViewModels
{
if (string.IsNullOrEmpty(SearchQuery) && IsInSearchMode)
{
UpdateFolderPivotsAsync();
await UpdateFolderPivotsAsync();
IsInSearchMode = false;
await InitializeFolderAsync();
}
@@ -892,7 +892,7 @@ namespace Wino.Mail.ViewModels
OnPropertyChanged(nameof(IsArchiveSpecialFolder));
// Prepare Focused - Other or folder name tabs.
UpdateFolderPivotsAsync();
await UpdateFolderPivotsAsync();
// Reset filters and sorting options.
ResetFilters();

View File

@@ -228,7 +228,7 @@ namespace Wino
{
try
{
var synchronizationResultResponse = await AppServiceConnectionManager.GetResponseAsync<SynchronizationResult, NewSynchronizationRequested>(message);
var synchronizationResultResponse = await AppServiceConnectionManager.GetResponseAsync<MailSynchronizationResult, NewSynchronizationRequested>(message);
synchronizationResultResponse.ThrowIfFailed();
}
catch (WinoServerException serverException)

View File

@@ -91,10 +91,10 @@ namespace Wino.Services
WeakReferenceMessenger.Default.Send(new AccountFolderConfigurationUpdated(accountId));
var options = new SynchronizationOptions()
var options = new MailSynchronizationOptions()
{
AccountId = accountId,
Type = SynchronizationType.FullFolders,
Type = MailSynchronizationType.FullFolders,
};
WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));

View File

@@ -8,5 +8,5 @@ namespace Wino.Messaging.Server
/// Triggers a new synchronization if possible.
/// </summary>
/// <param name="Options">Options for synchronization.</param>
public record NewSynchronizationRequested(SynchronizationOptions Options, SynchronizationSource Source) : IClientMessage;
public record NewSynchronizationRequested(MailSynchronizationOptions Options, SynchronizationSource Source) : IClientMessage;
}

View File

@@ -16,10 +16,10 @@ namespace Wino.Server.MessageHandlers
/// <summary>
/// Handler for NewSynchronizationRequested from the client.
/// </summary>
public class SynchronizationRequestHandler : ServerMessageHandler<NewSynchronizationRequested, SynchronizationResult>
public class SynchronizationRequestHandler : ServerMessageHandler<NewSynchronizationRequested, MailSynchronizationResult>
{
public override WinoServerResponse<SynchronizationResult> FailureDefaultResponse(Exception ex)
=> WinoServerResponse<SynchronizationResult>.CreateErrorResponse(ex.Message);
public override WinoServerResponse<MailSynchronizationResult> FailureDefaultResponse(Exception ex)
=> WinoServerResponse<MailSynchronizationResult>.CreateErrorResponse(ex.Message);
private readonly ISynchronizerFactory _synchronizerFactory;
private readonly INotificationBuilder _notificationBuilder;
@@ -34,7 +34,7 @@ namespace Wino.Server.MessageHandlers
_folderService = folderService;
}
protected override async Task<WinoServerResponse<SynchronizationResult>> HandleAsync(NewSynchronizationRequested message, CancellationToken cancellationToken = default)
protected override async Task<WinoServerResponse<MailSynchronizationResult>> HandleAsync(NewSynchronizationRequested message, CancellationToken cancellationToken = default)
{
var synchronizer = await _synchronizerFactory.GetAccountSynchronizerAsync(message.Options.AccountId);
@@ -45,12 +45,12 @@ namespace Wino.Server.MessageHandlers
// It happens very common and there is no need to send a message for each synchronization.
bool shouldReportSynchronizationResult =
message.Options.Type != SynchronizationType.ExecuteRequests &&
message.Options.Type != MailSynchronizationType.ExecuteRequests &&
message.Source == SynchronizationSource.Client;
try
{
var synchronizationResult = await synchronizer.SynchronizeAsync(message.Options, cancellationToken).ConfigureAwait(false);
var synchronizationResult = await synchronizer.SynchronizeMailsAsync(message.Options, cancellationToken).ConfigureAwait(false);
if (synchronizationResult.DownloadedMessages?.Any() ?? false || !synchronizer.Account.Preferences.IsNotificationsEnabled)
{
@@ -79,7 +79,7 @@ namespace Wino.Server.MessageHandlers
WeakReferenceMessenger.Default.Send(completedMessage);
}
return WinoServerResponse<SynchronizationResult>.CreateSuccessResponse(synchronizationResult);
return WinoServerResponse<MailSynchronizationResult>.CreateSuccessResponse(synchronizationResult);
}
// TODO: Following cases might always be thrown from server. Handle them properly.

View File

@@ -90,10 +90,10 @@ namespace Wino.Server
foreach (var account in accounts)
{
var options = new SynchronizationOptions
var options = new MailSynchronizationOptions
{
AccountId = account.Id,
Type = SynchronizationType.InboxOnly,
Type = MailSynchronizationType.InboxOnly,
};
var request = new NewSynchronizationRequested(options, SynchronizationSource.Server);

View File

@@ -542,11 +542,11 @@ namespace Wino.Services
public Task<List<MailFolderPairMetadata>> GetMailFolderPairMetadatasAsync(string mailCopyId)
=> GetMailFolderPairMetadatasAsync(new List<string>() { mailCopyId });
public async Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(SynchronizationOptions options)
public async Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(MailSynchronizationOptions options)
{
var folders = new List<MailItemFolder>();
if (options.Type == SynchronizationType.FullFolders)
if (options.Type == MailSynchronizationType.FullFolders)
{
// Only get sync enabled folders.
@@ -564,11 +564,11 @@ namespace Wino.Services
var mustHaveFolders = await GetInboxSynchronizationFoldersAsync(options.AccountId);
if (options.Type == SynchronizationType.InboxOnly)
if (options.Type == MailSynchronizationType.InboxOnly)
{
return mustHaveFolders;
}
else if (options.Type == SynchronizationType.CustomFolders)
else if (options.Type == MailSynchronizationType.CustomFolders)
{
// Only get the specified and enabled folders.