diff --git a/Wino.Calendar.ViewModels/AccountManagementViewModel.cs b/Wino.Calendar.ViewModels/AccountManagementViewModel.cs index b3a6b0e1..ae78ede5 100644 --- a/Wino.Calendar.ViewModels/AccountManagementViewModel.cs +++ b/Wino.Calendar.ViewModels/AccountManagementViewModel.cs @@ -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(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client)); + var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync(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 }; } } diff --git a/Wino.Core.Domain/Enums/CalendarSynchronizationType.cs b/Wino.Core.Domain/Enums/CalendarSynchronizationType.cs new file mode 100644 index 00000000..0d16fe97 --- /dev/null +++ b/Wino.Core.Domain/Enums/CalendarSynchronizationType.cs @@ -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. + } +} diff --git a/Wino.Core.Domain/Enums/SynchronizationType.cs b/Wino.Core.Domain/Enums/MailSynchronizationType.cs similarity index 85% rename from Wino.Core.Domain/Enums/SynchronizationType.cs rename to Wino.Core.Domain/Enums/MailSynchronizationType.cs index 031f5c55..5fd16667 100644 --- a/Wino.Core.Domain/Enums/SynchronizationType.cs +++ b/Wino.Core.Domain/Enums/MailSynchronizationType.cs @@ -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 } } diff --git a/Wino.Core.Domain/Interfaces/IBaseCalendarSynchronizer.cs b/Wino.Core.Domain/Interfaces/IBaseCalendarSynchronizer.cs deleted file mode 100644 index f88556df..00000000 --- a/Wino.Core.Domain/Interfaces/IBaseCalendarSynchronizer.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Wino.Core.Domain.Interfaces -{ - public interface IBaseCalendarSynchronizer : IBaseSynchronizer - { - - } -} diff --git a/Wino.Core.Domain/Interfaces/IFolderService.cs b/Wino.Core.Domain/Interfaces/IFolderService.cs index 74d59d8f..c7a27a87 100644 --- a/Wino.Core.Domain/Interfaces/IFolderService.cs +++ b/Wino.Core.Domain/Interfaces/IFolderService.cs @@ -26,7 +26,7 @@ namespace Wino.Core.Domain.Interfaces Task ChangeFolderSynchronizationStateAsync(Guid folderId, bool isSynchronizationEnabled); Task ChangeFolderShowUnreadCountStateAsync(Guid folderId, bool showUnreadCount); - Task> GetSynchronizationFoldersAsync(SynchronizationOptions options); + Task> GetSynchronizationFoldersAsync(MailSynchronizationOptions options); /// /// Returns the folder - mail mapping for the given mail copy ids. diff --git a/Wino.Core.Domain/Interfaces/ISynchronizerFactory.cs b/Wino.Core.Domain/Interfaces/ISynchronizerFactory.cs index d5e06cb8..d86fff66 100644 --- a/Wino.Core.Domain/Interfaces/ISynchronizerFactory.cs +++ b/Wino.Core.Domain/Interfaces/ISynchronizerFactory.cs @@ -5,7 +5,7 @@ namespace Wino.Core.Domain.Interfaces { public interface ISynchronizerFactory { - Task GetAccountSynchronizerAsync(Guid accountId); + Task GetAccountSynchronizerAsync(Guid accountId); Task InitializeAsync(); } } diff --git a/Wino.Core.Domain/Interfaces/IBaseMailSynchronizer.cs b/Wino.Core.Domain/Interfaces/IWinoSynchronizerBase.cs similarity index 86% rename from Wino.Core.Domain/Interfaces/IBaseMailSynchronizer.cs rename to Wino.Core.Domain/Interfaces/IWinoSynchronizerBase.cs index 87e7bd3a..4a424998 100644 --- a/Wino.Core.Domain/Interfaces/IBaseMailSynchronizer.cs +++ b/Wino.Core.Domain/Interfaces/IWinoSynchronizerBase.cs @@ -6,7 +6,7 @@ using Wino.Core.Domain.Models.Synchronization; namespace Wino.Core.Domain.Interfaces { - public interface IBaseMailSynchronizer : IBaseSynchronizer + public interface IWinoSynchronizerBase : IBaseSynchronizer { /// /// Performs a full synchronization with the server with given options. @@ -17,7 +17,7 @@ namespace Wino.Core.Domain.Interfaces /// Options for synchronization. /// Cancellation token. /// Result summary of synchronization. - Task SynchronizeAsync(SynchronizationOptions options, CancellationToken cancellationToken = default); + Task SynchronizeMailsAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default); /// /// Downloads a single MIME message from the server and saves it to disk. diff --git a/Wino.Core.Domain/Models/Synchronization/CalendarSynchronizationOptions.cs b/Wino.Core.Domain/Models/Synchronization/CalendarSynchronizationOptions.cs new file mode 100644 index 00000000..8bdc4585 --- /dev/null +++ b/Wino.Core.Domain/Models/Synchronization/CalendarSynchronizationOptions.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using Wino.Core.Domain.Enums; + +namespace Wino.Core.Domain.Models.Synchronization +{ + public class CalendarSynchronizationOptions + { + /// + /// Unique id of synchronization. + /// + public Guid Id { get; } = Guid.NewGuid(); + + /// + /// Account to execute synchronization for. + /// + public Guid AccountId { get; set; } + + /// + /// Type of the synchronization to be performed. + /// + public CalendarSynchronizationType Type { get; set; } + + /// + /// Calendar ids to synchronize. + /// + public List SynchronizationCalendarIds { get; set; } + + public override string ToString() => $"Type: {Type}, Calendars: {(SynchronizationCalendarIds == null ? "All" : string.Join(",", SynchronizationCalendarIds))}"; + } +} diff --git a/Wino.Core.Domain/Models/Synchronization/CalendarSynchronizationResult.cs b/Wino.Core.Domain/Models/Synchronization/CalendarSynchronizationResult.cs new file mode 100644 index 00000000..1f12d819 --- /dev/null +++ b/Wino.Core.Domain/Models/Synchronization/CalendarSynchronizationResult.cs @@ -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() { } + + /// + /// 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. + /// + [JsonIgnore] + public IEnumerable 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 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 }; + } +} diff --git a/Wino.Core.Domain/Models/Synchronization/SynchronizationOptions.cs b/Wino.Core.Domain/Models/Synchronization/MailSynchronizationOptions.cs similarity index 85% rename from Wino.Core.Domain/Models/Synchronization/SynchronizationOptions.cs rename to Wino.Core.Domain/Models/Synchronization/MailSynchronizationOptions.cs index baa292b4..acbf611a 100644 --- a/Wino.Core.Domain/Models/Synchronization/SynchronizationOptions.cs +++ b/Wino.Core.Domain/Models/Synchronization/MailSynchronizationOptions.cs @@ -4,7 +4,7 @@ using Wino.Core.Domain.Enums; namespace Wino.Core.Domain.Models.Synchronization { - public class SynchronizationOptions + public class MailSynchronizationOptions { /// /// Unique id of synchronization. @@ -19,7 +19,7 @@ namespace Wino.Core.Domain.Models.Synchronization /// /// Type of the synchronization to be performed. /// - public SynchronizationType Type { get; set; } + public MailSynchronizationType Type { get; set; } /// /// Collection of FolderId to perform SynchronizationType.Custom type sync. @@ -33,6 +33,6 @@ namespace Wino.Core.Domain.Models.Synchronization /// 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))}"; } } diff --git a/Wino.Core.Domain/Models/Synchronization/SynchronizationResult.cs b/Wino.Core.Domain/Models/Synchronization/MailSynchronizationResult.cs similarity index 53% rename from Wino.Core.Domain/Models/Synchronization/SynchronizationResult.cs rename to Wino.Core.Domain/Models/Synchronization/MailSynchronizationResult.cs index 7145dacb..271d64ab 100644 --- a/Wino.Core.Domain/Models/Synchronization/SynchronizationResult.cs +++ b/Wino.Core.Domain/Models/Synchronization/MailSynchronizationResult.cs @@ -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() { } /// /// Gets the new downloaded messages from synchronization. @@ -19,22 +18,14 @@ namespace Wino.Core.Domain.Models.Synchronization [JsonIgnore] public IEnumerable DownloadedMessages { get; set; } = []; - /// - /// 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. - /// - [JsonIgnore] - public IEnumerable 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 downloadedMessages) + public static MailSynchronizationResult Completed(IEnumerable 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 }; } } diff --git a/Wino.Core/Integration/Processors/DefaultChangeProcessor.cs b/Wino.Core/Integration/Processors/DefaultChangeProcessor.cs index 19a78f6e..9c9e501f 100644 --- a/Wino.Core/Integration/Processors/DefaultChangeProcessor.cs +++ b/Wino.Core/Integration/Processors/DefaultChangeProcessor.cs @@ -41,7 +41,7 @@ namespace Wino.Core.Integration.Processors Task> GetLocalFoldersAsync(Guid accountId); - Task> GetSynchronizationFoldersAsync(SynchronizationOptions options); + Task> GetSynchronizationFoldersAsync(MailSynchronizationOptions options); Task 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> GetLocalFoldersAsync(Guid accountId) => FolderService.GetFoldersAsync(accountId); - public Task> GetSynchronizationFoldersAsync(SynchronizationOptions options) + public Task> GetSynchronizationFoldersAsync(MailSynchronizationOptions options) => FolderService.GetSynchronizationFoldersAsync(options); public Task DeleteFolderAsync(Guid accountId, string remoteFolderId) diff --git a/Wino.Core/Services/SynchronizerFactory.cs b/Wino.Core/Services/SynchronizerFactory.cs index 342a6553..62814e5d 100644 --- a/Wino.Core/Services/SynchronizerFactory.cs +++ b/Wino.Core/Services/SynchronizerFactory.cs @@ -20,7 +20,7 @@ namespace Wino.Core.Services private readonly IOutlookAuthenticator _outlookAuthenticator; private readonly IGmailAuthenticator _gmailAuthenticator; - private readonly List synchronizerCache = new(); + private readonly List synchronizerCache = new(); public SynchronizerFactory(IOutlookChangeProcessor outlookChangeProcessor, IGmailChangeProcessor gmailChangeProcessor, @@ -39,7 +39,7 @@ namespace Wino.Core.Services _applicationConfiguration = applicationConfiguration; } - public async Task GetAccountSynchronizerAsync(Guid accountId) + public async Task 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); diff --git a/Wino.Core/Services/WinoRequestDelegator.cs b/Wino.Core/Services/WinoRequestDelegator.cs index fca62af1..b3a4705d 100644 --- a/Wino.Core/Services/WinoRequestDelegator.cs +++ b/Wino.Core/Services/WinoRequestDelegator.cs @@ -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)); diff --git a/Wino.Core/Synchronizers/GmailSynchronizer.cs b/Wino.Core/Synchronizers/GmailSynchronizer.cs index dd64f8ab..567b927a 100644 --- a/Wino.Core/Synchronizers/GmailSynchronizer.cs +++ b/Wino.Core/Synchronizers/GmailSynchronizer.cs @@ -104,9 +104,9 @@ namespace Wino.Core.Synchronizers.Mail await _gmailChangeProcessor.UpdateRemoteAliasInformationAsync(Account, remoteAliases).ConfigureAwait(false); } - protected override async Task SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default) + protected override async Task 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 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); } } - /// /// Maps existing Gmail Draft resources to local mail copies. /// This uses indexed search, therefore it's quite fast. diff --git a/Wino.Core/Synchronizers/ImapSynchronizer.cs b/Wino.Core/Synchronizers/ImapSynchronizer.cs index 2778cf04..eed08707 100644 --- a/Wino.Core/Synchronizers/ImapSynchronizer.cs +++ b/Wino.Core/Synchronizers/ImapSynchronizer.cs @@ -435,7 +435,7 @@ namespace Wino.Core.Synchronizers.Mail ]; } - protected override async Task SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default) + protected override async Task SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default) { var downloadedMessageIds = new List(); @@ -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> batchedRequests, CancellationToken cancellationToken = default) @@ -1035,5 +1035,10 @@ namespace Wino.Core.Synchronizers.Mail /// Local folder. public bool ShouldUpdateFolder(IMailFolder remoteFolder, MailItemFolder localFolder) => !localFolder.FolderName.Equals(remoteFolder.Name, StringComparison.OrdinalIgnoreCase); + + protected override Task SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } } diff --git a/Wino.Core/Synchronizers/OutlookSynchronizer.cs b/Wino.Core/Synchronizers/OutlookSynchronizer.cs index f2bfa7bb..985ca653 100644 --- a/Wino.Core/Synchronizers/OutlookSynchronizer.cs +++ b/Wino.Core/Synchronizers/OutlookSynchronizer.cs @@ -133,7 +133,7 @@ namespace Wino.Core.Synchronizers.Mail #endregion - protected override async Task SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default) + protected override async Task SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default) { var downloadedMessageIds = new List(); @@ -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> SynchronizeFolderAsync(MailItemFolder folder, CancellationToken cancellationToken = default) @@ -956,5 +956,10 @@ namespace Wino.Core.Synchronizers.Mail return [package]; } + + protected override Task SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } } } diff --git a/Wino.Core/Synchronizers/WinoSynchronizer.cs b/Wino.Core/Synchronizers/WinoSynchronizer.cs index f39dea22..96b739e4 100644 --- a/Wino.Core/Synchronizers/WinoSynchronizer.cs +++ b/Wino.Core/Synchronizers/WinoSynchronizer.cs @@ -23,7 +23,7 @@ using Wino.Messaging.UI; namespace Wino.Core.Synchronizers { - public abstract class WinoSynchronizer : BaseSynchronizer, IBaseMailSynchronizer + public abstract class WinoSynchronizer : BaseSynchronizer, IWinoSynchronizerBase { protected ILogger Logger = Log.ForContext>(); @@ -55,18 +55,23 @@ namespace Wino.Core.Synchronizers /// protected virtual Task SynchronizeAliasesAsync() => Task.CompletedTask; - - /// - /// 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. /// /// Synchronization options. /// Cancellation token. /// Synchronization result that contains summary of the sync. - protected abstract Task SynchronizeInternalAsync(SynchronizationOptions options, CancellationToken cancellationToken = default); - + protected abstract Task SynchronizeMailsInternalAsync(MailSynchronizationOptions options, CancellationToken cancellationToken = default); + /// + /// Internally synchronizes the events of the account with given options. + /// Not exposed and overriden for each synchronizer. + /// + /// Synchronization options. + /// Cancellation token. + /// Synchronization result that contains summary of the sync. + protected abstract Task SynchronizeCalendarEventsInternalAsync(CalendarSynchronizationOptions options, CancellationToken cancellationToken = default); /// /// Batches network requests, executes them, and does the needed synchronization after the batch request execution. @@ -74,7 +79,7 @@ namespace Wino.Core.Synchronizers /// Synchronization options. /// Cancellation token. /// Synchronization result that contains summary of the sync. - public async Task SynchronizeAsync(SynchronizationOptions options, CancellationToken cancellationToken = default) + public async Task 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 /// /// Batch requests to run in synchronization. /// New synchronization options with minimal HTTP effort. - private SynchronizationOptions GetSynchronizationOptionsAfterRequestExecution(List requests) + private MailSynchronizationOptions GetSynchronizationOptionsAfterRequestExecution(List requests) { List 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; diff --git a/Wino.Mail.ViewModels/AccountManagementViewModel.cs b/Wino.Mail.ViewModels/AccountManagementViewModel.cs index 8cab69a8..cdd81e10 100644 --- a/Wino.Mail.ViewModels/AccountManagementViewModel.cs +++ b/Wino.Mail.ViewModels/AccountManagementViewModel.cs @@ -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(new NewSynchronizationRequested(profileSyncOptions, SynchronizationSource.Client)); + var profileSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync(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(new NewSynchronizationRequested(folderSyncOptions, SynchronizationSource.Client)); + var folderSynchronizationResponse = await WinoServerConnectionManager.GetResponseAsync(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(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client)); + var aliasSyncResponse = await WinoServerConnectionManager.GetResponseAsync(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client)); var aliasSynchronizationResult = folderSynchronizationResponse.Data; if (aliasSynchronizationResult.CompletedState != SynchronizationCompletedState.Success) diff --git a/Wino.Mail.ViewModels/AliasManagementPageViewModel.cs b/Wino.Mail.ViewModels/AliasManagementPageViewModel.cs index e72bd312..978736a4 100644 --- a/Wino.Mail.ViewModels/AliasManagementPageViewModel.cs +++ b/Wino.Mail.ViewModels/AliasManagementPageViewModel.cs @@ -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(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client)); + var aliasSyncResponse = await _winoServerConnectionManager.GetResponseAsync(new NewSynchronizationRequested(aliasSyncOptions, SynchronizationSource.Client)); if (aliasSyncResponse.IsSuccess) await LoadAliasesAsync(); diff --git a/Wino.Mail.ViewModels/AppShellViewModel.cs b/Wino.Mail.ViewModels/AppShellViewModel.cs index b16a8c53..40a8744f 100644 --- a/Wino.Mail.ViewModels/AppShellViewModel.cs +++ b/Wino.Mail.ViewModels/AppShellViewModel.cs @@ -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)); diff --git a/Wino.Mail.ViewModels/MailListPageViewModel.cs b/Wino.Mail.ViewModels/MailListPageViewModel.cs index 64154835..58e820c0 100644 --- a/Wino.Mail.ViewModels/MailListPageViewModel.cs +++ b/Wino.Mail.ViewModels/MailListPageViewModel.cs @@ -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(); diff --git a/Wino.Mail/App.xaml.cs b/Wino.Mail/App.xaml.cs index f5496c79..943194a1 100644 --- a/Wino.Mail/App.xaml.cs +++ b/Wino.Mail/App.xaml.cs @@ -228,7 +228,7 @@ namespace Wino { try { - var synchronizationResultResponse = await AppServiceConnectionManager.GetResponseAsync(message); + var synchronizationResultResponse = await AppServiceConnectionManager.GetResponseAsync(message); synchronizationResultResponse.ThrowIfFailed(); } catch (WinoServerException serverException) diff --git a/Wino.Mail/Services/DialogService.cs b/Wino.Mail/Services/DialogService.cs index 775714e8..edccc560 100644 --- a/Wino.Mail/Services/DialogService.cs +++ b/Wino.Mail/Services/DialogService.cs @@ -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)); diff --git a/Wino.Messages/Server/NewSynchronizationRequested.cs b/Wino.Messages/Server/NewSynchronizationRequested.cs index af7e343f..85610c83 100644 --- a/Wino.Messages/Server/NewSynchronizationRequested.cs +++ b/Wino.Messages/Server/NewSynchronizationRequested.cs @@ -8,5 +8,5 @@ namespace Wino.Messaging.Server /// Triggers a new synchronization if possible. /// /// Options for synchronization. - public record NewSynchronizationRequested(SynchronizationOptions Options, SynchronizationSource Source) : IClientMessage; + public record NewSynchronizationRequested(MailSynchronizationOptions Options, SynchronizationSource Source) : IClientMessage; } diff --git a/Wino.Server/MessageHandlers/SynchronizationRequestHandler.cs b/Wino.Server/MessageHandlers/SynchronizationRequestHandler.cs index 7cb1b70e..a2c997e7 100644 --- a/Wino.Server/MessageHandlers/SynchronizationRequestHandler.cs +++ b/Wino.Server/MessageHandlers/SynchronizationRequestHandler.cs @@ -16,10 +16,10 @@ namespace Wino.Server.MessageHandlers /// /// Handler for NewSynchronizationRequested from the client. /// - public class SynchronizationRequestHandler : ServerMessageHandler + public class SynchronizationRequestHandler : ServerMessageHandler { - public override WinoServerResponse FailureDefaultResponse(Exception ex) - => WinoServerResponse.CreateErrorResponse(ex.Message); + public override WinoServerResponse FailureDefaultResponse(Exception ex) + => WinoServerResponse.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> HandleAsync(NewSynchronizationRequested message, CancellationToken cancellationToken = default) + protected override async Task> 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.CreateSuccessResponse(synchronizationResult); + return WinoServerResponse.CreateSuccessResponse(synchronizationResult); } // TODO: Following cases might always be thrown from server. Handle them properly. diff --git a/Wino.Server/ServerContext.cs b/Wino.Server/ServerContext.cs index e3875573..8db390bd 100644 --- a/Wino.Server/ServerContext.cs +++ b/Wino.Server/ServerContext.cs @@ -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); diff --git a/Wino.Services/FolderService.cs b/Wino.Services/FolderService.cs index 2d65c39a..3b970e11 100644 --- a/Wino.Services/FolderService.cs +++ b/Wino.Services/FolderService.cs @@ -542,11 +542,11 @@ namespace Wino.Services public Task> GetMailFolderPairMetadatasAsync(string mailCopyId) => GetMailFolderPairMetadatasAsync(new List() { mailCopyId }); - public async Task> GetSynchronizationFoldersAsync(SynchronizationOptions options) + public async Task> GetSynchronizationFoldersAsync(MailSynchronizationOptions options) { var folders = new List(); - 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.