Ground work for Wino Calendar. (#475)

Wino Calendar abstractions.
This commit is contained in:
Burak Kaan Köse
2024-11-10 23:28:25 +01:00
committed by GitHub
parent a979e8430f
commit d1d6f12f05
486 changed files with 7969 additions and 2708 deletions

View File

@@ -1,9 +1,9 @@
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Services;
namespace Wino.Core.Authenticators
namespace Wino.Core.Authenticators.Base
{
public abstract class BaseAuthenticator
{

View File

@@ -0,0 +1,21 @@
using System.Threading.Tasks;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
namespace Wino.Core.Authenticators.Base
{
public abstract class GmailAuthenticatorBase : BaseAuthenticator, IGmailAuthenticator
{
protected GmailAuthenticatorBase(ITokenService tokenService) : base(tokenService)
{
}
public abstract string ClientId { get; }
public bool ProposeCopyAuthURL { get; set; }
public abstract Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken);
public abstract Task<TokenInformation> GetTokenAsync(MailAccount account);
}
}

View File

@@ -0,0 +1,20 @@
using System.Threading.Tasks;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
namespace Wino.Core.Authenticators.Base
{
public abstract class OutlookAuthenticatorBase : BaseAuthenticator, IOutlookAuthenticator
{
protected OutlookAuthenticatorBase(ITokenService tokenService) : base(tokenService)
{
}
public abstract string ClientId { get; }
public abstract Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken);
public abstract Task<TokenInformation> GetTokenAsync(MailAccount account);
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Threading.Tasks;
using Wino.Core.Authenticators.Base;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Services;
namespace Wino.Core.Authenticators.Calendar
{
public class OutlookAuthenticator : OutlookAuthenticatorBase
{
public OutlookAuthenticator(ITokenService tokenService) : base(tokenService)
{
}
public override string ClientId => throw new NotImplementedException();
public override MailProviderType ProviderType => MailProviderType.Outlook;
public override Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken)
{
throw new NotImplementedException();
}
public override Task<TokenInformation> GetTokenAsync(MailAccount account)
{
throw new NotImplementedException();
}
}
}

View File

@@ -4,8 +4,9 @@ using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Authenticators.Base;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
@@ -14,11 +15,11 @@ using Wino.Core.Domain.Models.Authorization;
using Wino.Core.Services;
using Wino.Messaging.UI;
namespace Wino.Core.Authenticators
namespace Wino.Core.Authenticators.Mail
{
public class GmailAuthenticator : BaseAuthenticator, IGmailAuthenticator
public class GmailAuthenticator : GmailAuthenticatorBase
{
public string ClientId { get; } = "973025879644-s7b4ur9p3rlgop6a22u7iuptdc0brnrn.apps.googleusercontent.com";
public override string ClientId { get; } = "973025879644-s7b4ur9p3rlgop6a22u7iuptdc0brnrn.apps.googleusercontent.com";
private const string TokenEndpoint = "https://www.googleapis.com/oauth2/v4/token";
private const string RefreshTokenEndpoint = "https://oauth2.googleapis.com/token";
@@ -26,8 +27,6 @@ namespace Wino.Core.Authenticators
public override MailProviderType ProviderType => MailProviderType.Gmail;
public bool ProposeCopyAuthURL { get; set; }
private readonly INativeAppService _nativeAppService;
public GmailAuthenticator(ITokenService tokenService, INativeAppService nativeAppService) : base(tokenService)
@@ -95,7 +94,7 @@ namespace Wino.Core.Authenticators
};
}
public async Task<TokenInformation> GetTokenAsync(MailAccount account)
public async override Task<TokenInformation> GetTokenAsync(MailAccount account)
{
var cachedToken = await TokenService.GetTokenInformationAsync(account.Id)
?? throw new AuthenticationAttentionException(account);
@@ -117,7 +116,7 @@ namespace Wino.Core.Authenticators
}
public async Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken)
public async override Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken)
{
var authRequest = _nativeAppService.GetGoogleAuthorizationRequest();

View File

@@ -2,7 +2,7 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
namespace Wino.Core.Authenticators
namespace Wino.Core.Authenticators.Mail
{
public class Office365Authenticator : OutlookAuthenticator
{

View File

@@ -4,21 +4,22 @@ using System.Threading.Tasks;
using Microsoft.Identity.Client;
using Microsoft.Identity.Client.Broker;
using Microsoft.Identity.Client.Extensions.Msal;
using Wino.Core.Authenticators.Base;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Extensions;
using Wino.Core.Services;
namespace Wino.Core.Authenticators
namespace Wino.Core.Authenticators.Mail
{
/// <summary>
/// Authenticator for Outlook provider.
/// Authenticator for Outlook Mail provider.
/// Token cache is managed by MSAL, not by Wino.
/// </summary>
public class OutlookAuthenticator : BaseAuthenticator, IOutlookAuthenticator
public class OutlookAuthenticator : OutlookAuthenticatorBase
{
private const string TokenCacheFileName = "OutlookCache.bin";
private bool isTokenCacheAttached = false;
@@ -26,7 +27,7 @@ namespace Wino.Core.Authenticators
// Outlook
private const string Authority = "https://login.microsoftonline.com/common";
public string ClientId { get; } = "b19c2035-d740-49ff-b297-de6ec561b208";
public override string ClientId { get; } = "b19c2035-d740-49ff-b297-de6ec561b208";
private readonly string[] MailScope =
[
@@ -67,7 +68,7 @@ namespace Wino.Core.Authenticators
_publicClientApplication = outlookAppBuilder.Build();
}
public async Task<TokenInformation> GetTokenAsync(MailAccount account)
public override async Task<TokenInformation> GetTokenAsync(MailAccount account)
{
if (!isTokenCacheAttached)
{
@@ -101,7 +102,7 @@ namespace Wino.Core.Authenticators
}
}
public async Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken)
public override async Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken)
{
try
{

View File

@@ -1,6 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Serilog.Core;
using Wino.Core.Authenticators;
using Wino.Core.Authenticators.Mail;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Integration.Processors;
using Wino.Core.Integration.Threading;
@@ -22,6 +22,7 @@ namespace Wino.Core
services.AddSingleton<IDatabaseService, DatabaseService>();
services.AddSingleton<IThreadingStrategyProvider, ThreadingStrategyProvider>();
services.AddSingleton<IMimeFileService, MimeFileService>();
services.AddSingleton<ILaunchProtocolService, LaunchProtocolService>();
services.AddTransient<IGmailChangeProcessor, GmailChangeProcessor>();
services.AddTransient<IImapChangeProcessor, ImapChangeProcessor>();

View File

@@ -0,0 +1,35 @@
using System;
using Wino.Core.Domain.Models.Calendar;
namespace Wino.Core.Extensions
{
public static class DateTimeExtensions
{
/// <summary>
/// Returns a date range for the month of the given date.
/// </summary>
/// <param name="date">Date to get range for.</param>
public static DateRange GetMonthDateRangeStartingWeekday(this DateTime date, DayOfWeek WeekStartDay)
{
var firstDayOfMonth = new DateTime(date.Year, date.Month, 1);
int daysToWeekDay = (int)firstDayOfMonth.DayOfWeek - (int)WeekStartDay;
if (daysToWeekDay < 0) daysToWeekDay += 7;
firstDayOfMonth = firstDayOfMonth.AddDays(-daysToWeekDay);
var lastDayOfMonth = firstDayOfMonth.AddMonths(1).AddDays(-1);
return new DateRange(firstDayOfMonth, lastDayOfMonth);
}
public static DateTime GetWeekStartDateForDate(this DateTime date, DayOfWeek firstDayOfWeek)
{
// Detect the first day of the week that contains the selected date.
int diff = (7 + (date.DayOfWeek - firstDayOfWeek)) % 7;
// Start loading from this date instead of visible date.
return date.AddDays(-diff).Date;
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Web;
using Google.Apis.Gmail.v1.Data;
using MimeKit;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Extensions

View File

@@ -3,7 +3,7 @@ using System.Linq;
using MailKit;
using MimeKit;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Extensions

View File

@@ -1,7 +1,7 @@
using System;
using System.Linq;
using MailKit;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
namespace Wino.Core.Extensions
{

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Microsoft.Graph.Models;
using MimeKit;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Extensions

View File

@@ -1,6 +1,6 @@
using System;
using Microsoft.Identity.Client;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Extensions
{

View File

@@ -3,7 +3,7 @@ using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Google.Apis.Http;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Http
{

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Kiota.Abstractions.Authentication;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Http

View File

@@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Wino.Core.Integration
{
public abstract class BaseCalendarIntegrator<TNativeRequestType, TCalendarEventType>
{
public abstract Task<TCalendarEventType> CreateCalendarEventAsync(TNativeRequestType request);
}
}

View File

@@ -14,7 +14,7 @@ using MailKit.Security;
using MimeKit.Cryptography;
using MoreLinq;
using Serilog;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Models.Connectivity;

View File

@@ -1,5 +1,5 @@
using System.Text.Json.Serialization.Metadata;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Requests;

View File

@@ -2,7 +2,8 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MimeKit;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SqlKata;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;

View File

@@ -1,4 +1,4 @@
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;

View File

@@ -2,7 +2,7 @@
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;

View File

@@ -3,7 +3,7 @@ using System.Linq;
using CommunityToolkit.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;

View File

@@ -1,7 +1,8 @@
using System.Collections.Generic;
using System.Linq;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.MenuItems

View File

@@ -139,6 +139,16 @@ namespace Wino.Core.MenuItems
RaiseChangeNotificationEvents(action: NotifyCollectionChangedAction.Reset);
}
public void InsertRange(IEnumerable<T> items)
{
CheckReentrancy();
foreach (var item in items)
Items.Insert(0, item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
private bool AddArrangeCore(IEnumerable<T> collection)
{
var itemAdded = false;

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.ComponentModel;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -6,7 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Domain.Models.Requests
namespace Wino.Core.Requests.Bundles
{
/// <summary>
/// Bundle that encapsulates batch request and native request without a response.

View File

@@ -1,7 +1,7 @@
using System;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Domain.Models.Requests
namespace Wino.Core.Requests.Bundles
{
///// <summary>
///// Encapsulates request to queue and account for synchronizer.

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.ComponentModel;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;

View File

@@ -1,5 +1,5 @@
using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Requests;
using Wino.Messaging.UI;

View File

@@ -6,7 +6,8 @@ using CommunityToolkit.Diagnostics;
using CommunityToolkit.Mvvm.Messaging;
using Serilog;
using SqlKata;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;

View File

@@ -1,5 +1,5 @@
using System;
using Wino.Core.Authenticators;
using Wino.Core.Authenticators.Mail;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;

View File

@@ -3,7 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using MimeKit;
using SqlKata;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Extensions;
namespace Wino.Core.Services

View File

@@ -2,7 +2,8 @@
using System.IO;
using System.Threading.Tasks;
using SQLite;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services

View File

@@ -7,7 +7,8 @@ using MoreLinq;
using Serilog;
using SqlKata;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;

View File

@@ -1,6 +1,6 @@
using System.IO;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Connectivity;
using Wino.Core.Integration;

View File

@@ -9,7 +9,8 @@ using MoreLinq;
using Serilog;
using SqlKata;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Extensions;

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services

View File

@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Integration.Processors;
using Wino.Core.Synchronizers;
using Wino.Core.Synchronizers.Mail;
namespace Wino.Core.Services
{
@@ -20,7 +20,7 @@ namespace Wino.Core.Services
private readonly IOutlookAuthenticator _outlookAuthenticator;
private readonly IGmailAuthenticator _gmailAuthenticator;
private readonly List<IBaseSynchronizer> synchronizerCache = new();
private readonly List<IBaseMailSynchronizer> synchronizerCache = new();
public SynchronizerFactory(IOutlookChangeProcessor outlookChangeProcessor,
IGmailChangeProcessor gmailChangeProcessor,
@@ -39,7 +39,7 @@ namespace Wino.Core.Services
_applicationConfiguration = applicationConfiguration;
}
public async Task<IBaseSynchronizer> GetAccountSynchronizerAsync(Guid accountId)
public async Task<IBaseMailSynchronizer> GetAccountSynchronizerAsync(Guid accountId)
{
var synchronizer = synchronizerCache.Find(a => a.Account.Id == accountId);
@@ -58,7 +58,7 @@ namespace Wino.Core.Services
return synchronizer;
}
private IBaseSynchronizer CreateIntegratorWithDefaultProcessor(MailAccount mailAccount)
private IBaseMailSynchronizer CreateIntegratorWithDefaultProcessor(MailAccount mailAccount)
{
var providerType = mailAccount.ProviderType;
@@ -78,7 +78,7 @@ namespace Wino.Core.Services
return null;
}
public IBaseSynchronizer CreateNewSynchronizer(MailAccount account)
public IBaseMailSynchronizer CreateNewSynchronizer(MailAccount account)
{
var synchronizer = CreateIntegratorWithDefaultProcessor(account);

View File

@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Services
{

View File

@@ -21,13 +21,13 @@ namespace Wino.Core.Services
private readonly IWinoRequestProcessor _winoRequestProcessor;
private readonly IWinoServerConnectionManager _winoServerConnectionManager;
private readonly IFolderService _folderService;
private readonly IDialogService _dialogService;
private readonly IMailDialogService _dialogService;
private readonly ILogger _logger = Log.ForContext<WinoRequestDelegator>();
public WinoRequestDelegator(IWinoRequestProcessor winoRequestProcessor,
IWinoServerConnectionManager winoServerConnectionManager,
IFolderService folderService,
IDialogService dialogService)
IMailDialogService dialogService)
{
_winoRequestProcessor = winoRequestProcessor;
_winoServerConnectionManager = winoServerConnectionManager;

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
@@ -23,7 +23,7 @@ namespace Wino.Core.Services
private readonly IKeyPressService _keyPressService;
private readonly IPreferencesService _preferencesService;
private readonly IAccountService _accountService;
private readonly IDialogService _dialogService;
private readonly IMailDialogService _dialogService;
private readonly IMailService _mailService;
/// <summary>
@@ -42,7 +42,7 @@ namespace Wino.Core.Services
IKeyPressService keyPressService,
IPreferencesService preferencesService,
IAccountService accountService,
IDialogService dialogService,
IMailDialogService dialogService,
IMailService mailService) : base(databaseService)
{
_folderService = folderService;

View File

@@ -9,7 +9,8 @@ using CommunityToolkit.Mvvm.Messaging;
using MailKit;
using Serilog;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
@@ -22,15 +23,15 @@ using Wino.Messaging.UI;
namespace Wino.Core.Synchronizers
{
public abstract class BaseSynchronizer<TBaseRequest, TMessageType> : BaseMailIntegrator<TBaseRequest>, IBaseSynchronizer
public abstract class BaseMailSynchronizer<TBaseRequest, TMessageType> : BaseMailIntegrator<TBaseRequest>, IBaseMailSynchronizer
{
private SemaphoreSlim synchronizationSemaphore = new(1);
private CancellationToken activeSynchronizationCancellationToken;
protected ConcurrentBag<IRequestBase> changeRequestQueue = [];
protected ILogger Logger = Log.ForContext<BaseSynchronizer<TBaseRequest, TMessageType>>();
protected ILogger Logger = Log.ForContext<BaseMailSynchronizer<TBaseRequest, TMessageType>>();
protected BaseSynchronizer(MailAccount account)
protected BaseMailSynchronizer(MailAccount account)
{
Account = account;
}

View File

@@ -0,0 +1,9 @@
using Wino.Core.Integration;
namespace Wino.Core.Synchronizers.Calendar
{
public abstract class BaseCalendarSynchronizer<TNativeRequestType, TCalendarEventType> : BaseCalendarIntegrator<TNativeRequestType, TCalendarEventType>
{
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Threading.Tasks;
using Microsoft.Graph.Models;
using Microsoft.Kiota.Abstractions;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Synchronizers.Calendar
{
public class OutlookCalendarSynchronizer : BaseCalendarSynchronizer<RequestInformation, Event>
{
public OutlookCalendarSynchronizer(MailAccount account)
{
Account = account;
}
public MailAccount Account { get; }
public override Task<Event> CreateCalendarEventAsync(RequestInformation request)
{
throw new NotImplementedException();
}
}
}

View File

@@ -16,23 +16,24 @@ using Microsoft.IdentityModel.Tokens;
using MimeKit;
using MoreLinq;
using Serilog;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Requests;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Extensions;
using Wino.Core.Http;
using Wino.Core.Integration.Processors;
using Wino.Core.Requests;
using Wino.Core.Requests.Bundles;
using Wino.Messaging.UI;
namespace Wino.Core.Synchronizers
namespace Wino.Core.Synchronizers.Mail
{
public class GmailSynchronizer : BaseSynchronizer<IClientServiceRequest, Message>, IHttpClientFactory
public class GmailSynchronizer : BaseMailSynchronizer<IClientServiceRequest, Message>, IHttpClientFactory
{
public override uint BatchModificationSize => 1000;
public override uint InitialMessageDownloadCountPerFolder => 1200;

View File

@@ -11,7 +11,8 @@ using MailKit.Search;
using MimeKit;
using MoreLinq;
using Serilog;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
@@ -26,9 +27,9 @@ using Wino.Core.Requests;
using Wino.Core.Requests.Bundles;
using Wino.Messaging.UI;
namespace Wino.Core.Synchronizers
namespace Wino.Core.Synchronizers.Mail
{
public class ImapSynchronizer : BaseSynchronizer<ImapRequest, ImapMessageCreationPackage>
public class ImapSynchronizer : BaseMailSynchronizer<ImapRequest, ImapMessageCreationPackage>
{
private CancellationTokenSource idleDoneToken;
private CancellationTokenSource cancelInboxListeningToken = new CancellationTokenSource();
@@ -225,7 +226,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> Move(BatchMoveRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
var uniqueIds = GetUniqueIds(request.Items.Select(a => a.Item.Id));
@@ -241,7 +242,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> ChangeFlag(BatchChangeFlagRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
var folder = request.Items.First().Item.AssignedFolder;
var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId);
@@ -255,7 +256,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> Delete(BatchDeleteRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
var folder = request.Items.First().Item.AssignedFolder;
var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId).ConfigureAwait(false);
@@ -270,7 +271,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> MarkRead(BatchMarkReadRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
var folder = request.Items.First().Item.AssignedFolder;
var remoteFolder = await client.GetFolderAsync(folder.RemoteFolderId);
@@ -284,7 +285,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> CreateDraft(BatchCreateDraftRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
var remoteDraftFolder = await client.GetFolderAsync(request.DraftPreperationRequest.CreatedLocalDraftCopy.AssignedFolder.RemoteFolderId).ConfigureAwait(false);
@@ -305,7 +306,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> SendDraft(BatchSendDraftRequestRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
// Batch sending is not supported. It will always be a single request therefore no need for a loop here.
@@ -381,7 +382,7 @@ namespace Wino.Core.Synchronizers
public override IEnumerable<IRequestBundle<ImapRequest>> RenameFolder(RenameFolderRequest request)
{
return CreateTaskBundle(async (ImapClient client) =>
return CreateTaskBundle(async (client) =>
{
var folder = await client.GetFolderAsync(request.Folder.RemoteFolderId).ConfigureAwait(false);
await folder.RenameAsync(folder.ParentFolder, request.NewFolderName).ConfigureAwait(false);
@@ -663,7 +664,7 @@ namespace Wino.Core.Synchronizers
// Namespaces are not needed as folders.
// Non-existed folders don't need to be synchronized.
if ((remoteFolder.IsNamespace && !remoteFolder.Attributes.HasFlag(FolderAttributes.Inbox)) || !remoteFolder.Exists)
if (remoteFolder.IsNamespace && !remoteFolder.Attributes.HasFlag(FolderAttributes.Inbox) || !remoteFolder.Exists)
continue;
var existingLocalFolder = localFolders.FirstOrDefault(a => a.RemoteFolderId == remoteFolder.FullName);
@@ -926,8 +927,8 @@ namespace Wino.Core.Synchronizers
{
var localMailCopyId = MailkitClientExtensions.CreateUid(folder.Id, changedItem.UniqueId.Id);
var isFlagged = MailkitClientExtensions.GetIsFlagged(changedItem.Flags);
var isRead = MailkitClientExtensions.GetIsRead(changedItem.Flags);
var isFlagged = changedItem.Flags.GetIsFlagged();
var isRead = changedItem.Flags.GetIsRead();
await _imapChangeProcessor.ChangeMailReadStatusAsync(localMailCopyId, isRead);
await _imapChangeProcessor.ChangeFlagStatusAsync(localMailCopyId, isFlagged);

View File

@@ -20,7 +20,8 @@ using Microsoft.Kiota.Http.HttpClientLibrary.Middleware.Options;
using MimeKit;
using MoreLinq.Extensions;
using Serilog;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
@@ -33,10 +34,11 @@ using Wino.Core.Http;
using Wino.Core.Integration.Processors;
using Wino.Core.Misc;
using Wino.Core.Requests;
using Wino.Core.Requests.Bundles;
namespace Wino.Core.Synchronizers
namespace Wino.Core.Synchronizers.Mail
{
public class OutlookSynchronizer : BaseSynchronizer<RequestInformation, Message>
public class OutlookSynchronizer : BaseMailSynchronizer<RequestInformation, Message>
{
public override uint BatchModificationSize => 20;
public override uint InitialMessageDownloadCountPerFolder => 250;
@@ -825,7 +827,7 @@ namespace Wino.Core.Synchronizers
public override async Task ExecuteNativeRequestsAsync(IEnumerable<IRequestBundle<RequestInformation>> batchedRequests, CancellationToken cancellationToken = default)
{
var batchRequestInformations = BatchExtension.Batch(batchedRequests, (int)MaximumAllowedBatchRequestSize);
var batchRequestInformations = batchedRequests.Batch((int)MaximumAllowedBatchRequestSize);
bool serializeRequests = false;
@@ -906,7 +908,7 @@ namespace Wino.Core.Synchronizers
bundle.Request.RevertUIChanges();
var content = await httpResponseMessage.Content.ReadAsStringAsync();
var errorJson = JsonObject.Parse(content);
var errorJson = JsonNode.Parse(content);
var errorString = $"{httpResponseMessage.StatusCode} [{bundle.Request.GetType().Name}]\n{errorJson["error"]["code"]} - {errorJson["error"]["message"]}\n";
exceptionBag.Add(errorString);

View File

@@ -14,30 +14,30 @@
<ItemGroup>
<PackageReference Include="CommunityToolkit.Diagnostics" Version="8.2.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="CommunityToolkit.Diagnostics" Version="8.3.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
<PackageReference Include="Google.Apis.Gmail.v1" Version="1.68.0.3427" />
<PackageReference Include="Google.Apis.PeopleService.v1" Version="1.68.0.3359" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.64" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.70" />
<PackageReference Include="HtmlKit" Version="1.1.0" />
<PackageReference Include="IsExternalInit" Version="1.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="MailKit" Version="4.7.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.Graph" Version="5.56.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.64.0" />
<PackageReference Include="Microsoft.Identity.Client.Broker" Version="4.64.0" />
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.64.0" />
<PackageReference Include="MimeKit" Version="4.7.1" />
<PackageReference Include="MailKit" Version="4.8.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageReference Include="Microsoft.Graph" Version="5.62.0" />
<PackageReference Include="Microsoft.Identity.Client" Version="4.66.1" />
<PackageReference Include="Microsoft.Identity.Client.Broker" Version="4.66.1" />
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="4.66.1" />
<PackageReference Include="MimeKit" Version="4.8.0" />
<PackageReference Include="morelinq" Version="4.3.0" />
<PackageReference Include="Nito.AsyncEx.Tasks" Version="5.1.2" />
<PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="Serilog" Version="4.1.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="SkiaSharp" Version="2.88.8" />
<PackageReference Include="SkiaSharp" Version="2.88.9" />
<PackageReference Include="SqlKata" Version="2.4.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
</ItemGroup>