Separation of core library from the UWP app.

This commit is contained in:
Burak Kaan Köse
2024-11-30 23:05:07 +01:00
parent 4e25dbf5e3
commit 0cd1568c64
88 changed files with 481 additions and 353 deletions

View File

@@ -6,6 +6,8 @@
<Configurations>Debug;Release</Configurations>
<LangVersion>12</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>

View File

@@ -5,12 +5,13 @@ using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Collections;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.MenuItems;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Extensions;
using Wino.Core.MenuItems;
using Wino.Core.ViewModels;
using Wino.Messaging.Client.Calendar;
using Wino.Messaging.Client.Navigation;

View File

@@ -7,12 +7,12 @@ using System.Threading.Tasks;
using CommunityToolkit.Diagnostics;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Messaging;
using Wino.Core.Domain.Collections;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.MenuItems;
using Wino.Core.ViewModels;
using Wino.Messaging.Client.Calendar;

View File

@@ -4,6 +4,8 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>

View File

@@ -3,8 +3,8 @@ using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.WinUI;
using Windows.UI.Xaml.Controls;
using Wino.Core.Domain.Collections;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.MenuItems;
namespace Wino.Calendar.Controls
{

View File

@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.Collections
{
/// <summary>
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
@@ -25,7 +25,7 @@ namespace Wino.Core.MenuItems
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
/// </summary>
/// <param name="collection">collection: The collection from which the elements are copied.</param>
/// <exception cref="System.ArgumentNullException">The collection parameter cannot be null.</exception>
/// <exception cref="ArgumentNullException">The collection parameter cannot be null.</exception>
public ObservableRangeCollection(IEnumerable<T> collection)
: base(collection)
{
@@ -160,7 +160,7 @@ namespace Wino.Core.MenuItems
return itemAdded;
}
private void RaiseChangeNotificationEvents(NotifyCollectionChangedAction action, List<T>? changedItems = null, int startingIndex = -1)
private void RaiseChangeNotificationEvents(NotifyCollectionChangedAction action, List<T> changedItems = null, int startingIndex = -1)
{
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Count)));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using MimeKit;
using Wino.Core.Domain.Entities.Shared;
namespace Wino.Core.Domain.Interfaces
{
public interface IContactService
{
Task<List<AccountContact>> GetAddressInformationAsync(string queryText);
Task<AccountContact> GetAddressInformationByAddressAsync(string address);
Task SaveAddressInformationAsync(MimeMessage message);
}
}

View File

@@ -0,0 +1,4 @@
namespace Wino.Core.Domain.Interfaces
{
public interface IGmailThreadingStrategy : IThreadingStrategy { }
}

View File

@@ -0,0 +1,4 @@
namespace Wino.Core.Domain.Interfaces
{
public interface IImapThreadingStrategy : IThreadingStrategy { }
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MimeKit;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Reader;
namespace Wino.Core.Domain.Interfaces
{
public interface IMimeFileService
{
/// <summary>
/// Finds the EML file for the given mail id for address, parses and returns MimeMessage.
/// </summary>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Mime message information</returns>
Task<MimeMessageInformation> GetMimeMessageInformationAsync(Guid fileId, Guid accountId, CancellationToken cancellationToken = default);
/// <summary>
/// Gets the mime message information for the given EML file bytes.
/// This override is used when EML file association launch is used
/// because we may not have the access to the file path.
/// </summary>
/// <param name="fileBytes">Byte array of the file.</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Mime message information</returns>
Task<MimeMessageInformation> GetMimeMessageInformationAsync(byte[] fileBytes, string emlFilePath, CancellationToken cancellationToken = default);
/// <summary>
/// Saves EML file to the disk.
/// </summary>
/// <param name="copy">MailCopy of the native message.</param>
/// <param name="mimeMessage">MimeMessage that is parsed from native message.</param>
/// <param name="accountId">Which account Id to save this file for.</param>
Task<bool> SaveMimeMessageAsync(Guid fileId, MimeMessage mimeMessage, Guid accountId);
/// <summary>
/// Returns a path that all Mime resources (including eml) is stored for this MailCopyId
/// This is useful for storing previously rendered attachments as well.
/// </summary>
/// <param name="accountAddress">Account address</param>
/// <param name="mailCopyId">Resource mail copy id</param>
Task<string> GetMimeResourcePathAsync(Guid accountId, Guid fileId);
/// <summary>
/// Returns whether mime file exists locally or not.
/// </summary>
Task<bool> IsMimeExistAsync(Guid accountId, Guid fileId);
/// <summary>
/// Creates HtmlPreviewVisitor for the given MimeMessage.
/// </summary>
/// <param name="message">Mime</param>
/// <param name="mimeLocalPath">File path that mime is located to load resources.</param>
HtmlPreviewVisitor CreateHTMLPreviewVisitor(MimeMessage message, string mimeLocalPath);
/// <summary>
/// Deletes the given mime file from the disk.
/// </summary>
Task<bool> DeleteMimeMessageAsync(Guid accountId, Guid fileId);
/// <summary>
/// Prepares the final model containing rendering details.
/// </summary>
/// <param name="message">Message to render.</param>
/// <param name="mimeLocalPath">File path that physical MimeMessage is located.</param>
/// <param name="options">Rendering options</param>
MailRenderModel GetMailRenderModel(MimeMessage message, string mimeLocalPath, MailRenderingOptions options = null);
}
}

View File

@@ -0,0 +1,4 @@
namespace Wino.Core.Domain.Interfaces
{
public interface IOutlookThreadingStrategy : IThreadingStrategy { }
}

View File

@@ -7,7 +7,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public partial class AccountMenuItem : MenuItemBase<MailAccount, MenuItemBase<IMailItemFolder, FolderMenuItem>>, IAccountMenuItem
{
@@ -22,7 +22,7 @@ namespace Wino.Core.MenuItems
private bool _isEnabled = true;
public bool IsAttentionRequired => AttentionReason != AccountAttentionReason.None;
public bool IsSynchronizationProgressVisible => (SynchronizationProgress > 0 && SynchronizationProgress < 100);
public bool IsSynchronizationProgressVisible => SynchronizationProgress > 0 && SynchronizationProgress < 100;
// We can't determine the progress for gmail synchronization since it is based on history changes.
public bool IsProgressIndeterminate => Parameter?.ProviderType == MailProviderType.Gmail;

View File

@@ -2,7 +2,7 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class FixAccountIssuesMenuItem : MenuItemBase<IMailItemFolder, FolderMenuItem>
{

View File

@@ -7,7 +7,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public partial class FolderMenuItem : MenuItemBase<IMailItemFolder, FolderMenuItem>, IFolderMenuItem
{

View File

@@ -1,4 +1,4 @@
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class ManageAccountsMenuItem : MenuItemBase { }
}

View File

@@ -3,7 +3,7 @@ using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public partial class MenuItemBase : ObservableObject, IMenuItem
{

View File

@@ -2,11 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MoreLinq.Extensions;
using Wino.Core.Domain.Collections;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class MenuItemCollection : ObservableRangeCollection<IMenuItem>
{
@@ -108,7 +108,10 @@ namespace Wino.Core.MenuItems
public void UpdateUnreadItemCountsToZero()
{
// Handle the root folders.
this.OfType<IBaseFolderMenuItem>().ForEach(a => RecursivelyResetUnreadItemCount(a));
foreach (var item in this.OfType<IBaseFolderMenuItem>())
{
RecursivelyResetUnreadItemCount(item);
}
}
private void RecursivelyResetUnreadItemCount(IBaseFolderMenuItem baseFolderMenuItem)
@@ -168,7 +171,10 @@ namespace Wino.Core.MenuItems
await _dispatcher.ExecuteOnUIThread(() =>
{
accountItems.ForEach(a => a.IsEnabled = isEnabled);
foreach (var item in accountItems)
{
item.IsEnabled = isEnabled;
}
});
}

View File

@@ -8,7 +8,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
/// <summary>
/// Menu item that holds a list of folders under the merged account menu item.

View File

@@ -5,7 +5,7 @@ using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public partial class MergedAccountMenuItem : MenuItemBase<MergedInbox, IMenuItem>, IMergedAccountMenuItem
{

View File

@@ -1,7 +1,7 @@
using System;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class MergedAccountMoreFolderMenuItem : MenuItemBase<object, IMenuItem>
{

View File

@@ -1,4 +1,4 @@
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class NewMailMenuItem : MenuItemBase { }
}

View File

@@ -1,4 +1,4 @@
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class RateMenuItem : MenuItemBase { }
}

View File

@@ -1,4 +1,4 @@
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class SeperatorItem : MenuItemBase { }
}

View File

@@ -1,4 +1,4 @@
namespace Wino.Core.MenuItems
namespace Wino.Core.Domain.MenuItems
{
public class SettingsItem : MenuItemBase { }
}

View File

@@ -5,7 +5,7 @@ using MimeKit;
using MimeKit.Text;
using MimeKit.Tnef;
namespace Wino.Core.Mime
namespace Wino.Core.Domain.Models.MailItem
{
/// <summary>
/// Visits a MimeMessage and generates HTML suitable to be rendered by a browser control.

View File

@@ -5,6 +5,8 @@
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<LangVersion>12.0</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>
@@ -58,6 +60,8 @@
<EmbeddedResource Include="Translations\zh_CN\resources.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Diagnostics" Version="8.3.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
<PackageReference Include="IsExternalInit" Version="1.0.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

View File

@@ -1,6 +1,6 @@
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Wino.Core.MenuItems;
using Wino.Core.Domain.MenuItems;
namespace Wino.Core.UWP.Selectors
{

View File

@@ -3,14 +3,10 @@ using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Foundation.Metadata;
using Windows.Security.Authentication.Web;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.System;
using Windows.UI.Shell;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Authorization;
@@ -51,46 +47,6 @@ namespace Wino.Services
return _mimeMessagesFolder;
}
#region Cryptography
public string randomDataBase64url(uint length)
{
IBuffer buffer = CryptographicBuffer.GenerateRandom(length);
return base64urlencodeNoPadding(buffer);
}
public IBuffer sha256(string inputString)
{
HashAlgorithmProvider sha = HashAlgorithmProvider.OpenAlgorithm(HashAlgorithmNames.Sha256);
IBuffer buff = CryptographicBuffer.ConvertStringToBinary(inputString, BinaryStringEncoding.Utf8);
return sha.HashData(buff);
}
public string base64urlencodeNoPadding(IBuffer buffer)
{
string base64 = CryptographicBuffer.EncodeToBase64String(buffer);
// Converts base64 to base64url.
base64 = base64.Replace("+", "-");
base64 = base64.Replace("/", "_");
// Strips padding.
base64 = base64.Replace("=", "");
return base64;
}
#endregion
// GMail Integration.
public GoogleAuthorizationRequest GetGoogleAuthorizationRequest()
{
string state = randomDataBase64url(32);
string code_verifier = randomDataBase64url(32);
string code_challenge = base64urlencodeNoPadding(sha256(code_verifier));
return new GoogleAuthorizationRequest(state, code_verifier, code_challenge);
}
public async Task<string> GetEditorBundlePathAsync()
{

View File

@@ -9,7 +9,7 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Reader;
using Wino.Core.Domain.Translations;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.UWP.Services
{

View File

@@ -2,7 +2,7 @@
using System.Linq;
using System.Net.Mail;
namespace Wino.Core.Services
namespace Wino.Core.UWP.Services
{
public static class ThumbnailService
{
@@ -55,7 +55,7 @@ namespace Wino.Core.Services
return new Tuple<bool, string>(false, host);
}
return new Tuple<bool, string>(ThumbnailService.IsKnown(host), host);
return new Tuple<bool, string>(IsKnown(host), host);
}
public static string GetKnownHostImage(string host)

View File

@@ -8,7 +8,7 @@
xmlns:domain="using:Wino.Core.Domain"
xmlns:helpers="using:Wino.Helpers"
xmlns:local="using:Wino.Core.UWP.Styles"
xmlns:menu="using:Wino.Core.MenuItems"
xmlns:menu="using:Wino.Core.Domain.MenuItems"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:viewModelData="using:Wino.Mail.ViewModels.Data"
xmlns:winuiControls="using:CommunityToolkit.WinUI.Controls">

View File

@@ -144,6 +144,7 @@
<Compile Include="Services\PrintService.cs" />
<Compile Include="Services\StartupBehaviorService.cs" />
<Compile Include="Services\StatePersistenceService.cs" />
<Compile Include="Services\ThumbnailService.cs" />
<Compile Include="Services\WinoServerConnectionManager.cs" />
<Compile Include="Services\BackgroundTaskService.cs" />
<Compile Include="Services\ClipboardService.cs" />
@@ -242,6 +243,10 @@
<Project>{0c307d7e-256f-448c-8265-5622a812fbcc}</Project>
<Name>Wino.Messaging</Name>
</ProjectReference>
<ProjectReference Include="..\Wino.Services\Wino.Services.csproj">
<Project>{4000a374-59fe-4400-acf6-d40473becd73}</Project>
<Name>Wino.Services</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<SDKReference Include="WindowsDesktop, Version=10.0.22621.0">

View File

@@ -23,7 +23,7 @@ using Windows.UI.Xaml.Controls;
using Wino.Activation;
using Wino.Core.Domain;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.UWP
{

View File

@@ -4,6 +4,8 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>

View File

@@ -3,7 +3,6 @@ using Serilog.Core;
using Wino.Authentication;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Integration.Processors;
using Wino.Core.Integration.Threading;
using Wino.Core.Services;
namespace Wino.Core
@@ -15,41 +14,20 @@ namespace Wino.Core
var loggerLevelSwitcher = new LoggingLevelSwitch();
services.AddSingleton(loggerLevelSwitcher);
services.AddSingleton<ILogInitializer, LogInitializer>();
services.AddSingleton<IApplicationConfiguration, ApplicationConfiguration>();
services.AddSingleton<ITranslationService, TranslationService>();
services.AddSingleton<IDatabaseService, DatabaseService>();
services.AddSingleton<IThreadingStrategyProvider, ThreadingStrategyProvider>();
services.AddSingleton<IMimeFileService, MimeFileService>();
services.AddSingleton<ILaunchProtocolService, LaunchProtocolService>();
services.AddSingleton<ISynchronizerFactory, SynchronizerFactory>();
services.AddTransient<IGmailChangeProcessor, GmailChangeProcessor>();
services.AddTransient<IImapChangeProcessor, ImapChangeProcessor>();
services.AddTransient<IOutlookChangeProcessor, OutlookChangeProcessor>();
services.AddTransient<IFolderService, FolderService>();
services.AddTransient<IMailService, MailService>();
services.AddTransient<IAccountService, AccountService>();
services.AddTransient<IContactService, ContactService>();
services.AddTransient<ISignatureService, SignatureService>();
services.AddTransient<IWinoRequestProcessor, WinoRequestProcessor>();
services.AddTransient<IWinoRequestDelegator, WinoRequestDelegator>();
services.AddTransient<IImapTestService, ImapTestService>();
services.AddTransient<IAuthenticationProvider, AuthenticationProvider>();
services.AddTransient<IAutoDiscoveryService, AutoDiscoveryService>();
services.AddTransient<IContextMenuItemService, ContextMenuItemService>();
services.AddTransient<IFontService, FontService>();
services.AddTransient<IUnsubscriptionService, UnsubscriptionService>();
services.AddTransient<IOutlookAuthenticator, OutlookAuthenticator>();
services.AddTransient<IGmailAuthenticator, GmailAuthenticator>();
services.AddTransient<OutlookThreadingStrategy>();
services.AddTransient<GmailThreadingStrategy>();
services.AddTransient<ImapThreadStrategy>();
services.AddSingleton<ISynchronizerFactory, SynchronizerFactory>();
}
}
}

View File

@@ -6,67 +6,21 @@ using Google.Apis.Gmail.v1.Data;
using MimeKit;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Services;
using Wino.Services.Extensions;
namespace Wino.Core.Extensions
{
public static class GoogleIntegratorExtensions
{
public const string INBOX_LABEL_ID = "INBOX";
public const string UNREAD_LABEL_ID = "UNREAD";
public const string IMPORTANT_LABEL_ID = "IMPORTANT";
public const string STARRED_LABEL_ID = "STARRED";
public const string DRAFT_LABEL_ID = "DRAFT";
public const string SENT_LABEL_ID = "SENT";
public const string SPAM_LABEL_ID = "SPAM";
public const string CHAT_LABEL_ID = "CHAT";
public const string TRASH_LABEL_ID = "TRASH";
// Category labels.
public const string FORUMS_LABEL_ID = "FORUMS";
public const string UPDATES_LABEL_ID = "UPDATES";
public const string PROMOTIONS_LABEL_ID = "PROMOTIONS";
public const string SOCIAL_LABEL_ID = "SOCIAL";
public const string PERSONAL_LABEL_ID = "PERSONAL";
// Label visibility identifiers.
private const string SYSTEM_FOLDER_IDENTIFIER = "system";
private const string FOLDER_HIDE_IDENTIFIER = "labelHide";
private const string CATEGORY_PREFIX = "CATEGORY_";
private const string FOLDER_SEPERATOR_STRING = "/";
private const char FOLDER_SEPERATOR_CHAR = '/';
private static Dictionary<string, SpecialFolderType> KnownFolderDictionary = new Dictionary<string, SpecialFolderType>()
{
{ INBOX_LABEL_ID, SpecialFolderType.Inbox },
{ CHAT_LABEL_ID, SpecialFolderType.Chat },
{ IMPORTANT_LABEL_ID, SpecialFolderType.Important },
{ TRASH_LABEL_ID, SpecialFolderType.Deleted },
{ DRAFT_LABEL_ID, SpecialFolderType.Draft },
{ SENT_LABEL_ID, SpecialFolderType.Sent },
{ SPAM_LABEL_ID, SpecialFolderType.Junk },
{ STARRED_LABEL_ID, SpecialFolderType.Starred },
{ UNREAD_LABEL_ID, SpecialFolderType.Unread },
{ FORUMS_LABEL_ID, SpecialFolderType.Forums },
{ UPDATES_LABEL_ID, SpecialFolderType.Updates },
{ PROMOTIONS_LABEL_ID, SpecialFolderType.Promotions },
{ SOCIAL_LABEL_ID, SpecialFolderType.Social},
{ PERSONAL_LABEL_ID, SpecialFolderType.Personal},
};
public static string[] SubCategoryFolderLabelIds =
[
FORUMS_LABEL_ID,
UPDATES_LABEL_ID,
PROMOTIONS_LABEL_ID,
SOCIAL_LABEL_ID,
PERSONAL_LABEL_ID
];
private static string GetNormalizedLabelName(string labelName)
{
// 1. Remove CATEGORY_ prefix.
var normalizedLabelName = labelName.Replace(CATEGORY_PREFIX, string.Empty);
var normalizedLabelName = labelName.Replace(ServiceConstants.CATEGORY_PREFIX, string.Empty);
// 2. Normalize label name by capitalizing first letter.
normalizedLabelName = char.ToUpper(normalizedLabelName[0]) + normalizedLabelName.Substring(1).ToLower();
@@ -81,9 +35,9 @@ namespace Wino.Core.Extensions
// Even though we normalize the label name, check is done by capitalizing the label name.
var capitalNormalizedLabelName = normalizedLabelName.ToUpper();
bool isSpecialFolder = KnownFolderDictionary.ContainsKey(capitalNormalizedLabelName);
bool isSpecialFolder = ServiceConstants.KnownFolderDictionary.ContainsKey(capitalNormalizedLabelName);
var specialFolderType = isSpecialFolder ? KnownFolderDictionary[capitalNormalizedLabelName] : SpecialFolderType.Other;
var specialFolderType = isSpecialFolder ? ServiceConstants.KnownFolderDictionary[capitalNormalizedLabelName] : SpecialFolderType.Other;
// We used to support FOLDER_HIDE_IDENTIFIER to hide invisible folders.
// However, a lot of people complained that they don't see their folders after the initial sync
@@ -96,13 +50,13 @@ namespace Wino.Core.Extensions
bool isHidden = false;
bool isChildOfCategoryFolder = label.Name.StartsWith(CATEGORY_PREFIX);
bool isChildOfCategoryFolder = label.Name.StartsWith(ServiceConstants.CATEGORY_PREFIX);
bool isSticky = isSpecialFolder && specialFolderType != SpecialFolderType.Category && !isChildOfCategoryFolder;
// By default, all special folders update unread count in the UI except Trash.
bool shouldShowUnreadCount = specialFolderType != SpecialFolderType.Deleted || specialFolderType != SpecialFolderType.Other;
bool isSystemFolder = label.Type == SYSTEM_FOLDER_IDENTIFIER;
bool isSystemFolder = label.Type == ServiceConstants.SYSTEM_FOLDER_IDENTIFIER;
var localFolder = new MailItemFolder()
{
@@ -126,16 +80,16 @@ namespace Wino.Core.Extensions
}
public static bool GetIsDraft(this Message message)
=> message?.LabelIds?.Any(a => a == DRAFT_LABEL_ID) ?? false;
=> message?.LabelIds?.Any(a => a == ServiceConstants.DRAFT_LABEL_ID) ?? false;
public static bool GetIsUnread(this Message message)
=> message?.LabelIds?.Any(a => a == UNREAD_LABEL_ID) ?? false;
=> message?.LabelIds?.Any(a => a == ServiceConstants.UNREAD_LABEL_ID) ?? false;
public static bool GetIsFocused(this Message message)
=> message?.LabelIds?.Any(a => a == IMPORTANT_LABEL_ID) ?? false;
=> message?.LabelIds?.Any(a => a == ServiceConstants.IMPORTANT_LABEL_ID) ?? false;
public static bool GetIsFlagged(this Message message)
=> message?.LabelIds?.Any(a => a == STARRED_LABEL_ID) ?? false;
=> message?.LabelIds?.Any(a => a == ServiceConstants.STARRED_LABEL_ID) ?? false;
private static string GetParentFolderRemoteId(string fullLabelName, ListLabelsResponse labelsResponse)
{
@@ -158,9 +112,9 @@ namespace Wino.Core.Extensions
if (string.IsNullOrEmpty(fullFolderName)) return string.Empty;
// Folders with "//" at the end has "/" as the name.
if (fullFolderName.EndsWith(FOLDER_SEPERATOR_STRING)) return FOLDER_SEPERATOR_STRING;
if (fullFolderName.EndsWith(ServiceConstants.FOLDER_SEPERATOR_STRING)) return ServiceConstants.FOLDER_SEPERATOR_STRING;
string[] parts = fullFolderName.Split(FOLDER_SEPERATOR_CHAR);
string[] parts = fullFolderName.Split(ServiceConstants.FOLDER_SEPERATOR_CHAR);
var lastPart = parts[parts.Length - 1];

View File

@@ -7,6 +7,7 @@ using MimeKit;
using MimeKit.IO;
using MimeKit.IO.Filters;
using MimeKit.Utils;
using Wino.Services.Extensions;
namespace Wino.Core.Extensions
{

View File

@@ -7,7 +7,7 @@ using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.Integration.Processors
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Threading.Tasks;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.Integration.Processors
{

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.Integration.Processors
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Threading.Tasks;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.Integration.Processors
{

View File

@@ -1,10 +0,0 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Launch;
namespace Wino.Core.Services;
public class LaunchProtocolService : ILaunchProtocolService
{
public object LaunchParameter { get; set; }
public MailToUri MailToUri { get; set; }
}

View File

@@ -1,6 +1,6 @@
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Integration.Threading;
using Wino.Services.Threading;
namespace Wino.Core.Services
{
@@ -8,11 +8,11 @@ namespace Wino.Core.Services
{
private readonly OutlookThreadingStrategy _outlookThreadingStrategy;
private readonly GmailThreadingStrategy _gmailThreadingStrategy;
private readonly ImapThreadStrategy _imapThreadStrategy;
private readonly ImapThreadingStrategy _imapThreadStrategy;
public ThreadingStrategyProvider(OutlookThreadingStrategy outlookThreadingStrategy,
GmailThreadingStrategy gmailThreadingStrategy,
ImapThreadStrategy imapThreadStrategy)
ImapThreadingStrategy imapThreadStrategy)
{
_outlookThreadingStrategy = outlookThreadingStrategy;
_gmailThreadingStrategy = gmailThreadingStrategy;

View File

@@ -22,7 +22,6 @@ namespace Wino.Core.Services
private readonly IWinoServerConnectionManager _winoServerConnectionManager;
private readonly IFolderService _folderService;
private readonly IMailDialogService _dialogService;
private readonly ILogger _logger = Log.ForContext<WinoRequestDelegator>();
public WinoRequestDelegator(IWinoRequestProcessor winoRequestProcessor,
IWinoServerConnectionManager winoServerConnectionManager,

View File

@@ -23,7 +23,6 @@ namespace Wino.Core.Services
private readonly IFolderService _folderService;
private readonly IKeyPressService _keyPressService;
private readonly IPreferencesService _preferencesService;
private readonly IAccountService _accountService;
private readonly IMailDialogService _dialogService;
private readonly IMailService _mailService;
@@ -41,14 +40,12 @@ namespace Wino.Core.Services
public WinoRequestProcessor(IFolderService folderService,
IKeyPressService keyPressService,
IPreferencesService preferencesService,
IAccountService accountService,
IMailDialogService dialogService,
IMailService mailService)
{
_folderService = folderService;
_keyPressService = keyPressService;
_preferencesService = preferencesService;
_accountService = accountService;
_dialogService = dialogService;
_mailService = mailService;
}

View File

@@ -32,6 +32,7 @@ using Wino.Core.Requests.Bundles;
using Wino.Core.Requests.Folder;
using Wino.Core.Requests.Mail;
using Wino.Messaging.UI;
using Wino.Services;
namespace Wino.Core.Synchronizers.Mail
{
@@ -532,11 +533,11 @@ namespace Wino.Core.Synchronizers.Mail
foreach (var labelId in addedLabel.LabelIds)
{
// When UNREAD label is added mark the message as un-read.
if (labelId == GoogleIntegratorExtensions.UNREAD_LABEL_ID)
if (labelId == ServiceConstants.UNREAD_LABEL_ID)
await _gmailChangeProcessor.ChangeMailReadStatusAsync(messageId, false).ConfigureAwait(false);
// When STARRED label is added mark the message as flagged.
if (labelId == GoogleIntegratorExtensions.STARRED_LABEL_ID)
if (labelId == ServiceConstants.STARRED_LABEL_ID)
await _gmailChangeProcessor.ChangeFlagStatusAsync(messageId, true).ConfigureAwait(false);
await _gmailChangeProcessor.CreateAssignmentAsync(Account.Id, messageId, labelId).ConfigureAwait(false);
@@ -552,11 +553,11 @@ namespace Wino.Core.Synchronizers.Mail
foreach (var labelId in removedLabel.LabelIds)
{
// When UNREAD label is removed mark the message as read.
if (labelId == GoogleIntegratorExtensions.UNREAD_LABEL_ID)
if (labelId == ServiceConstants.UNREAD_LABEL_ID)
await _gmailChangeProcessor.ChangeMailReadStatusAsync(messageId, true).ConfigureAwait(false);
// When STARRED label is removed mark the message as un-flagged.
if (labelId == GoogleIntegratorExtensions.STARRED_LABEL_ID)
if (labelId == ServiceConstants.STARRED_LABEL_ID)
await _gmailChangeProcessor.ChangeFlagStatusAsync(messageId, false).ConfigureAwait(false);
// For other labels remove the mail assignment.
@@ -637,9 +638,9 @@ namespace Wino.Core.Synchronizers.Mail
};
if (isFlagged)
batchModifyRequest.AddLabelIds = new List<string>() { GoogleIntegratorExtensions.STARRED_LABEL_ID };
batchModifyRequest.AddLabelIds = new List<string>() { ServiceConstants.STARRED_LABEL_ID };
else
batchModifyRequest.RemoveLabelIds = new List<string>() { GoogleIntegratorExtensions.STARRED_LABEL_ID };
batchModifyRequest.RemoveLabelIds = new List<string>() { ServiceConstants.STARRED_LABEL_ID };
var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
@@ -656,9 +657,9 @@ namespace Wino.Core.Synchronizers.Mail
};
if (readStatus)
batchModifyRequest.RemoveLabelIds = new List<string>() { GoogleIntegratorExtensions.UNREAD_LABEL_ID };
batchModifyRequest.RemoveLabelIds = new List<string>() { ServiceConstants.UNREAD_LABEL_ID };
else
batchModifyRequest.AddLabelIds = new List<string>() { GoogleIntegratorExtensions.UNREAD_LABEL_ID };
batchModifyRequest.AddLabelIds = new List<string>() { ServiceConstants.UNREAD_LABEL_ID };
var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");
@@ -704,11 +705,11 @@ namespace Wino.Core.Synchronizers.Mail
if (isArchiving)
{
batchModifyRequest.RemoveLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
batchModifyRequest.RemoveLabelIds = new[] { ServiceConstants.INBOX_LABEL_ID };
}
else
{
batchModifyRequest.AddLabelIds = new[] { GoogleIntegratorExtensions.INBOX_LABEL_ID };
batchModifyRequest.AddLabelIds = new[] { ServiceConstants.INBOX_LABEL_ID };
}
var networkCall = _gmailService.Users.Messages.BatchModify(batchModifyRequest, "me");

View File

@@ -27,6 +27,7 @@ using Wino.Core.Requests.Bundles;
using Wino.Core.Requests.Folder;
using Wino.Core.Requests.Mail;
using Wino.Messaging.UI;
using Wino.Services.Extensions;
namespace Wino.Core.Synchronizers.Mail
{

View File

@@ -6,6 +6,8 @@
<Configurations>Debug;Release</Configurations>
<LangVersion>12</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>
@@ -47,5 +49,6 @@
<ProjectReference Include="..\Wino.Authentication\Wino.Authentication.csproj" />
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
<ProjectReference Include="..\Wino.Services\Wino.Services.csproj" />
</ItemGroup>
</Project>

View File

@@ -16,12 +16,11 @@ 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.MenuItems;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.MenuItems;
using Wino.Core.Services;
using Wino.Messaging.Client.Accounts;
using Wino.Messaging.Client.Navigation;
using Wino.Messaging.Client.Shell;
@@ -55,7 +54,7 @@ namespace Wino.Mail.ViewModels
private readonly SettingsItem SettingsItem = new SettingsItem();
private readonly ManageAccountsMenuItem ManageAccountsMenuItem = new ManageAccountsMenuItem();
public NewMailMenuItem CreateMailMenuItem = new NewMailMenuItem();
public IMenuItem CreateMailMenuItem = new NewMailMenuItem();
#endregion

View File

@@ -0,0 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using Wino.Core;
namespace Wino.Mail.ViewModels
{
public static class MailViewModelsContainerSetup
{
public static void RegisterViewModelService(this IServiceCollection services)
{
// View models use core services.
services.RegisterCoreServices();
}
}
}

View File

@@ -1,6 +1,4 @@
using System;
using Wino.Core.MenuItems;
using Wino.Mail.ViewModels.Data;
using Wino.Mail.ViewModels.Data;
namespace Wino.Mail.ViewModels.Messages
{

View File

@@ -4,6 +4,9 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>
@@ -21,6 +24,7 @@
<ProjectReference Include="..\Wino.Core.ViewModels\Wino.Core.ViewModels.csproj" />
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
<ProjectReference Include="..\Wino.Services\Wino.Services.csproj" />
</ItemGroup>
</Project>

View File

@@ -10,7 +10,6 @@ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Views;
namespace Wino.Activation

View File

@@ -17,17 +17,14 @@ namespace Wino.Activation
/// </summary>
internal class ToastNotificationActivationHandler : ActivationHandler<ToastNotificationActivatedEventArgs>
{
private readonly INativeAppService _nativeAppService;
private readonly IMailService _mailService;
private readonly IFolderService _folderService;
private ToastArguments _toastArguments;
public ToastNotificationActivationHandler(INativeAppService nativeAppService,
IMailService mailService,
public ToastNotificationActivationHandler(IMailService mailService,
IFolderService folderService)
{
_nativeAppService = nativeAppService;
_mailService = mailService;
_folderService = folderService;
}

View File

@@ -13,7 +13,6 @@ using Windows.ApplicationModel.Background;
using Windows.UI.Core.Preview;
using Windows.UI.Notifications;
using Wino.Activation;
using Wino.Core;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Exceptions;
@@ -70,7 +69,8 @@ namespace Wino
{
var services = new ServiceCollection();
services.RegisterCoreServices();
services.RegisterViewModelService();
services.RegisterSharedServices();
services.RegisterCoreUWPServices();
services.RegisterCoreViewModels();

View File

@@ -15,7 +15,7 @@
xmlns:enums="using:Wino.Core.Domain.Enums"
xmlns:helpers="using:Wino.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:menu="using:Wino.Core.MenuItems"
xmlns:menu="using:Wino.Core.Domain.MenuItems"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
x:Name="Root"
muxc:BackdropMaterial.ApplyToRootOrPageBackground="{ThemeResource UseMica}"

View File

@@ -1,27 +1,27 @@
using System.Collections.ObjectModel;
using Microsoft.Xaml.Interactivity;
using Windows.UI.Xaml;
using Wino.Core.MenuItems;
using Wino.Core.Domain.Interfaces;
using Wino.Core.UWP.Controls;
namespace Wino.Behaviors
{
public class CreateMailNavigationItemBehavior : Behavior<WinoNavigationViewItem>
{
public MenuItemBase SelectedMenuItem
public IMenuItem SelectedMenuItem
{
get { return (MenuItemBase)GetValue(SelectedMenuItemProperty); }
get { return (IMenuItem)GetValue(SelectedMenuItemProperty); }
set { SetValue(SelectedMenuItemProperty, value); }
}
public ObservableCollection<MenuItemBase> MenuItems
public ObservableCollection<IMenuItem> MenuItems
{
get { return (ObservableCollection<MenuItemBase>)GetValue(MenuItemsProperty); }
get { return (ObservableCollection<IMenuItem>)GetValue(MenuItemsProperty); }
set { SetValue(MenuItemsProperty, value); }
}
public static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(nameof(MenuItems), typeof(ObservableCollection<MenuItemBase>), typeof(CreateMailNavigationItemBehavior), new PropertyMetadata(null, OnMenuItemsChanged));
public static readonly DependencyProperty SelectedMenuItemProperty = DependencyProperty.Register(nameof(SelectedMenuItem), typeof(MenuItemBase), typeof(CreateMailNavigationItemBehavior), new PropertyMetadata(null, OnSelectedMenuItemChanged));
public static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(nameof(MenuItems), typeof(ObservableCollection<IMenuItem>), typeof(CreateMailNavigationItemBehavior), new PropertyMetadata(null, OnMenuItemsChanged));
public static readonly DependencyProperty SelectedMenuItemProperty = DependencyProperty.Register(nameof(SelectedMenuItem), typeof(IMenuItem), typeof(CreateMailNavigationItemBehavior), new PropertyMetadata(null, OnSelectedMenuItemChanged));
public CreateMailNavigationItemBehavior()
{

View File

@@ -11,7 +11,7 @@ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Shapes;
using Wino.Core.Services;
using Wino.Core.UWP.Services;
namespace Wino.Controls
{

View File

@@ -604,10 +604,6 @@
<Project>{53723ae8-7e7e-4d54-adab-0a6033255cc8}</Project>
<Name>Wino.Core.ViewModels</Name>
</ProjectReference>
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj">
<Project>{E6B1632A-8901-41E8-9DDF-6793C7698B0B}</Project>
<Name>Wino.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Wino.Mail.ViewModels\Wino.Mail.ViewModels.csproj">
<Project>{d62f1c03-da57-4709-a640-0283296a8e66}</Project>
<Name>Wino.Mail.ViewModels</Name>
@@ -616,6 +612,10 @@
<Project>{0c307d7e-256f-448c-8265-5622a812fbcc}</Project>
<Name>Wino.Messaging</Name>
</ProjectReference>
<ProjectReference Include="..\Wino.Services\Wino.Services.csproj">
<Project>{4000a374-59fe-4400-acf6-d40473becd73}</Project>
<Name>Wino.Services</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<SDKReference Include="WindowsDesktop, Version=10.0.22621.0">

View File

@@ -4,6 +4,9 @@
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12</LangVersion>
<Platforms>AnyCPU;x64;x86</Platforms>
<AccelerateBuildsInVisualStudio>true</AccelerateBuildsInVisualStudio>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
</PropertyGroup>
<ItemGroup>

View File

@@ -14,7 +14,6 @@ using Wino.Core;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Core.UWP.Services;
using Wino.Server.Core;
using Wino.Server.MessageHandlers;
@@ -68,6 +67,7 @@ namespace Wino.Server
services.AddTransient<ServerViewModel>();
services.RegisterCoreServices();
services.RegisterSharedServices();
// Below services belongs to UWP.Core package and some APIs are not available for WPF.
// We register them here to avoid compilation errors.
@@ -77,6 +77,7 @@ namespace Wino.Server
services.AddSingleton<IPreferencesService, PreferencesService>();
services.AddTransient<INotificationBuilder, NotificationBuilder>();
services.AddTransient<IUnderlyingThemeService, UnderlyingThemeService>();
services.AddSingleton<IApplicationConfiguration, ApplicationConfiguration>();
// Register server message handler factory.
var serverMessageHandlerFactory = new ServerMessageHandlerFactory();

View File

@@ -13,13 +13,13 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Requests;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Integration.Json;
using Wino.Core.Services;
using Wino.Messaging;
using Wino.Messaging.Client.Authorization;
using Wino.Messaging.Enums;
using Wino.Messaging.Server;
using Wino.Messaging.UI;
using Wino.Server.MessageHandlers;
using Wino.Services;
namespace Wino.Server
{

View File

@@ -25,6 +25,7 @@
<Compile Include="..\Wino.Core.UWP\Services\PreferencesService.cs" Link="Services\PreferencesService.cs" />
<Compile Include="..\Wino.Core.UWP\Services\NotificationBuilder.cs" Link="Services\NotificationBuilder.cs" />
<Compile Include="..\Wino.Core.UWP\Services\UnderlyingThemeService.cs" Link="Services\UnderlyingThemeService.cs" />
<Compile Include="..\Wino.Core.UWP\Services\ThumbnailService.cs" Link="Services\ThumbnailService.cs" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Wino_Icon.ico">
@@ -42,5 +43,6 @@
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
<ProjectReference Include="..\Wino.Services\Wino.Services.csproj" />
</ItemGroup>
</Project>

View File

@@ -11,28 +11,25 @@ using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Extensions;
using Wino.Messaging.Client.Accounts;
using Wino.Messaging.UI;
using Wino.Services.Extensions;
namespace Wino.Core.Services
namespace Wino.Services
{
public class AccountService : BaseDatabaseService, IAccountService
{
public IAuthenticator ExternalAuthenticationAuthenticator { get; set; }
private readonly IAuthenticationProvider _authenticationProvider;
private readonly ISignatureService _signatureService;
private readonly IPreferencesService _preferencesService;
private readonly ILogger _logger = Log.ForContext<AccountService>();
public AccountService(IDatabaseService databaseService,
IAuthenticationProvider authenticationProvider,
ISignatureService signatureService,
IPreferencesService preferencesService) : base(databaseService)
{
_authenticationProvider = authenticationProvider;
_signatureService = signatureService;
_preferencesService = preferencesService;
}
@@ -203,13 +200,13 @@ namespace Wino.Core.Services
if (account == null) return;
var authenticator = _authenticationProvider.GetAuthenticator(account.ProviderType);
//var authenticator = _authenticationProvider.GetAuthenticator(account.ProviderType);
// This will re-generate token.
var token = await authenticator.GenerateTokenInformationAsync(account);
//// This will re-generate token.
//var token = await authenticator.GenerateTokenInformationAsync(account);
// TODO: Rest?
Guard.IsNotNull(token);
// Guard.IsNotNull(token);
}
private Task<MailAccountPreferences> GetAccountPreferencesAsync(Guid accountId)
@@ -538,10 +535,10 @@ namespace Wino.Core.Services
var currentIdentifier = account.SynchronizationDeltaIdentifier;
bool shouldUpdateIdentifier = account.ProviderType == MailProviderType.Gmail ?
((string.IsNullOrEmpty(currentIdentifier) ? true : !string.IsNullOrEmpty(currentIdentifier)
string.IsNullOrEmpty(currentIdentifier) ? true : !string.IsNullOrEmpty(currentIdentifier)
&& ulong.TryParse(currentIdentifier, out ulong currentIdentifierValue)
&& ulong.TryParse(newIdentifier, out ulong newIdentifierValue)
&& newIdentifierValue > currentIdentifierValue)) : true;
&& newIdentifierValue > currentIdentifierValue : true;
if (shouldUpdateIdentifier)
{

View File

@@ -1,6 +1,6 @@
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services
namespace Wino.Services
{
public class ApplicationConfiguration : IApplicationConfiguration
{

View File

@@ -2,7 +2,7 @@
using SQLite;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services
namespace Wino.Services
{
public class BaseDatabaseService
{

View File

@@ -4,17 +4,11 @@ using System.Threading.Tasks;
using MimeKit;
using SqlKata;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Extensions;
using Wino.Core.Domain.Interfaces;
using Wino.Services.Extensions;
namespace Wino.Core.Services
namespace Wino.Services
{
public interface IContactService
{
Task<List<AccountContact>> GetAddressInformationAsync(string queryText);
Task<AccountContact> GetAddressInformationByAddressAsync(string address);
Task SaveAddressInformationAsync(MimeMessage message);
}
public class ContactService : BaseDatabaseService, IContactService
{
public ContactService(IDatabaseService databaseService) : base(databaseService) { }

View File

@@ -6,7 +6,7 @@ using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Menus;
namespace Wino.Core.Services
namespace Wino.Services
{
public class ContextMenuItemService : IContextMenuItemService
{
@@ -93,7 +93,7 @@ namespace Wino.Core.Services
};
operationList.AddRange(readOperations);
List<MailOperationMenuItem> flagsOperations = (isAllFlagged, isAllNotFlagged) switch
List<MailOperationMenuItem> flagsOperations = (isAllFlagged, isAllNotFlagged) switch
{
(true, false) => [MailOperationMenuItem.Create(MailOperation.ClearFlag)],
(false, true) => [MailOperationMenuItem.Create(MailOperation.SetFlag)],

View File

@@ -5,7 +5,7 @@ using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services
namespace Wino.Services
{
public interface IDatabaseService : IInitializeAsync
{

View File

@@ -1,10 +1,9 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using HtmlAgilityPack;
namespace Wino.Core.Extensions
namespace Wino.Services.Extensions
{
public static class HtmlAgilityPackExtensions
{
@@ -81,7 +80,7 @@ namespace Wino.Core.Extensions
case HtmlNodeType.Text:
// script and style must not be output
string parentName = node.ParentNode.Name;
if ((parentName == "script") || (parentName == "style"))
if (parentName == "script" || parentName == "style")
break;
// get text

View File

@@ -5,8 +5,9 @@ using MimeKit;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Services.Extensions;
namespace Wino.Core.Extensions
namespace Wino.Services.Extensions
{
public static class MailkitClientExtensions
{

View File

@@ -1,7 +1,7 @@
using SqlKata;
using SqlKata.Compilers;
namespace Wino.Core.Extensions
namespace Wino.Services.Extensions
{
public static class SqlKataExtensions
{

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Serilog;
using SqlKata;
using Wino.Core.Domain;
@@ -11,20 +10,19 @@ 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.MenuItems;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Extensions;
using Wino.Core.MenuItems;
using Wino.Messaging.UI;
using Wino.Services.Extensions;
namespace Wino.Core.Services
namespace Wino.Services
{
public class FolderService : BaseDatabaseService, IFolderService
{
private readonly IAccountService _accountService;
private readonly IMimeFileService _mimeFileService;
private readonly ILogger _logger = Log.ForContext<FolderService>();
private readonly SpecialFolderType[] gmailCategoryFolderTypes =
@@ -37,11 +35,9 @@ namespace Wino.Core.Services
];
public FolderService(IDatabaseService databaseService,
IAccountService accountService,
IMimeFileService mimeFileService) : base(databaseService)
IAccountService accountService) : base(databaseService)
{
_accountService = accountService;
_mimeFileService = mimeFileService;
}
public async Task ChangeStickyStatusAsync(Guid folderId, bool isSticky)
@@ -149,10 +145,10 @@ namespace Wino.Core.Services
}
else if (account.ProviderType == MailProviderType.Outlook || account.ProviderType == MailProviderType.Office365)
{
bool belongsToExistingParent = (await Connection
bool belongsToExistingParent = await Connection
.Table<MailItemFolder>()
.Where(a => unstickyItem.ParentRemoteFolderId == a.RemoteFolderId)
.CountAsync()) > 0;
.CountAsync() > 0;
// No need to include this as unsticky.
if (belongsToExistingParent) continue;
@@ -236,14 +232,14 @@ namespace Wino.Core.Services
foreach (var item in listingFolders)
{
// Category type folders should be skipped. They will be categorized under virtual category folder.
if (GoogleIntegratorExtensions.SubCategoryFolderLabelIds.Contains(item.RemoteFolderId)) continue;
if (ServiceConstants.SubCategoryFolderLabelIds.Contains(item.RemoteFolderId)) continue;
bool skipEmptyParentRemoteFolders = mailAccount.ProviderType == MailProviderType.Gmail;
if (skipEmptyParentRemoteFolders && !string.IsNullOrEmpty(item.ParentRemoteFolderId)) continue;
// Sticky items belong to account menu item directly. Rest goes to More folder.
IMenuItem parentFolderMenuItem = item.IsSticky ? accountMenuItem : (GoogleIntegratorExtensions.SubCategoryFolderLabelIds.Contains(item.FolderName.ToUpper()) ? categoryFolderMenuItem : moreFolderMenuItem);
IMenuItem parentFolderMenuItem = item.IsSticky ? accountMenuItem : ServiceConstants.SubCategoryFolderLabelIds.Contains(item.FolderName.ToUpper()) ? categoryFolderMenuItem : moreFolderMenuItem;
var preparedItem = await GetPreparedFolderMenuItemRecursiveAsync(mailAccount, item, parentFolderMenuItem).ConfigureAwait(false);
@@ -665,9 +661,9 @@ namespace Wino.Core.Services
}
public async Task<bool> IsInboxAvailableForAccountAsync(Guid accountId)
=> (await Connection.Table<MailItemFolder>()
=> await Connection.Table<MailItemFolder>()
.Where(a => a.SpecialFolderType == SpecialFolderType.Inbox && a.MailAccountId == accountId)
.CountAsync()) == 1;
.CountAsync() == 1;
public Task UpdateFolderLastSyncDateAsync(Guid folderId)
=> Connection.ExecuteAsync("UPDATE MailItemFolder SET LastSynchronizedDate = ? WHERE Id = ?", DateTime.UtcNow, folderId);

View File

@@ -0,0 +1,11 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Launch;
namespace Wino.Services
{
public class LaunchProtocolService : ILaunchProtocolService
{
public object LaunchParameter { get; set; }
public MailToUri MailToUri { get; set; }
}
}

View File

@@ -3,7 +3,7 @@ using Serilog.Core;
using Serilog.Exceptions;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services
namespace Wino.Services
{
public class LogInitializer : ILogInitializer
{

View File

@@ -3,9 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Kiota.Abstractions.Extensions;
using MimeKit;
using MoreLinq;
using Serilog;
using SqlKata;
using Wino.Core.Domain;
@@ -17,10 +15,10 @@ using Wino.Core.Domain.Extensions;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Comparers;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Extensions;
using Wino.Messaging.UI;
using Wino.Services.Extensions;
namespace Wino.Core.Services
namespace Wino.Services
{
public class MailService : BaseDatabaseService, IMailService
{
@@ -285,7 +283,10 @@ namespace Wino.Core.Services
if (!isFolderCached)
{
folderAssignment = await _folderService.GetFolderAsync(mailCopy.FolderId).ConfigureAwait(false);
_ = folderCache.TryAdd(mailCopy.FolderId, folderAssignment);
if (!folderCache.ContainsKey(mailCopy.FolderId))
{
folderCache.Add(mailCopy.FolderId, folderAssignment);
}
}
if (folderAssignment != null)
@@ -294,8 +295,11 @@ namespace Wino.Core.Services
if (!isAccountCached)
{
accountAssignment = await _accountService.GetAccountAsync(folderAssignment.MailAccountId).ConfigureAwait(false);
_ = accountCache.TryAdd(folderAssignment.MailAccountId, accountAssignment);
if (!accountCache.ContainsKey(folderAssignment.MailAccountId))
{
accountCache.Add(folderAssignment.MailAccountId, accountAssignment);
}
}
}
@@ -311,7 +315,10 @@ namespace Wino.Core.Services
if (contactAssignment != null)
{
_ = contactCache.TryAdd(mailCopy.FromAddress, contactAssignment);
if (!contactCache.ContainsKey(mailCopy.FromAddress))
{
contactCache.Add(mailCopy.FromAddress, contactAssignment);
}
}
}
@@ -728,7 +735,8 @@ namespace Wino.Core.Services
_ => CreateReferencedDraft(builder, message, draftCreationOptions, account, signature),
};
builder.SetHtmlBody(builder.HtmlBody);
// TODO: Migration
// builder.SetHtmlBody(builder.HtmlBody);
message.Body = builder.ToMessageBody();

View File

@@ -8,72 +8,10 @@ using Serilog;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Reader;
using Wino.Core.Extensions;
using Wino.Core.Mime;
using Wino.Services.Extensions;
namespace Wino.Core.Services
namespace Wino.Services
{
public interface IMimeFileService
{
/// <summary>
/// Finds the EML file for the given mail id for address, parses and returns MimeMessage.
/// </summary>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Mime message information</returns>
Task<MimeMessageInformation> GetMimeMessageInformationAsync(Guid fileId, Guid accountId, CancellationToken cancellationToken = default);
/// <summary>
/// Gets the mime message information for the given EML file bytes.
/// This override is used when EML file association launch is used
/// because we may not have the access to the file path.
/// </summary>
/// <param name="fileBytes">Byte array of the file.</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Mime message information</returns>
Task<MimeMessageInformation> GetMimeMessageInformationAsync(byte[] fileBytes, string emlFilePath, CancellationToken cancellationToken = default);
/// <summary>
/// Saves EML file to the disk.
/// </summary>
/// <param name="copy">MailCopy of the native message.</param>
/// <param name="mimeMessage">MimeMessage that is parsed from native message.</param>
/// <param name="accountId">Which account Id to save this file for.</param>
Task<bool> SaveMimeMessageAsync(Guid fileId, MimeMessage mimeMessage, Guid accountId);
/// <summary>
/// Returns a path that all Mime resources (including eml) is stored for this MailCopyId
/// This is useful for storing previously rendered attachments as well.
/// </summary>
/// <param name="accountAddress">Account address</param>
/// <param name="mailCopyId">Resource mail copy id</param>
Task<string> GetMimeResourcePathAsync(Guid accountId, Guid fileId);
/// <summary>
/// Returns whether mime file exists locally or not.
/// </summary>
Task<bool> IsMimeExistAsync(Guid accountId, Guid fileId);
/// <summary>
/// Creates HtmlPreviewVisitor for the given MimeMessage.
/// </summary>
/// <param name="message">Mime</param>
/// <param name="mimeLocalPath">File path that mime is located to load resources.</param>
HtmlPreviewVisitor CreateHTMLPreviewVisitor(MimeMessage message, string mimeLocalPath);
/// <summary>
/// Deletes the given mime file from the disk.
/// </summary>
Task<bool> DeleteMimeMessageAsync(Guid accountId, Guid fileId);
/// <summary>
/// Prepares the final model containing rendering details.
/// </summary>
/// <param name="message">Message to render.</param>
/// <param name="mimeLocalPath">File path that physical MimeMessage is located.</param>
/// <param name="options">Rendering options</param>
MailRenderModel GetMailRenderModel(MimeMessage message, string mimeLocalPath, MailRenderingOptions options = null);
}
public class MimeFileService : IMimeFileService
{
private readonly INativeAppService _nativeAppService;

View File

@@ -0,0 +1,64 @@
using System.Collections.Generic;
using Wino.Core.Domain.Enums;
namespace Wino.Services
{
public static class ServiceConstants
{
#region Gmail Constants
public const string INBOX_LABEL_ID = "INBOX";
public const string UNREAD_LABEL_ID = "UNREAD";
public const string IMPORTANT_LABEL_ID = "IMPORTANT";
public const string STARRED_LABEL_ID = "STARRED";
public const string DRAFT_LABEL_ID = "DRAFT";
public const string SENT_LABEL_ID = "SENT";
public const string SPAM_LABEL_ID = "SPAM";
public const string CHAT_LABEL_ID = "CHAT";
public const string TRASH_LABEL_ID = "TRASH";
// Category labels.
public const string FORUMS_LABEL_ID = "FORUMS";
public const string UPDATES_LABEL_ID = "UPDATES";
public const string PROMOTIONS_LABEL_ID = "PROMOTIONS";
public const string SOCIAL_LABEL_ID = "SOCIAL";
public const string PERSONAL_LABEL_ID = "PERSONAL";
// Label visibility identifiers.
public const string SYSTEM_FOLDER_IDENTIFIER = "system";
public const string FOLDER_HIDE_IDENTIFIER = "labelHide";
public const string CATEGORY_PREFIX = "CATEGORY_";
public const string FOLDER_SEPERATOR_STRING = "/";
public const char FOLDER_SEPERATOR_CHAR = '/';
public static Dictionary<string, SpecialFolderType> KnownFolderDictionary = new Dictionary<string, SpecialFolderType>()
{
{ INBOX_LABEL_ID, SpecialFolderType.Inbox },
{ CHAT_LABEL_ID, SpecialFolderType.Chat },
{ IMPORTANT_LABEL_ID, SpecialFolderType.Important },
{ TRASH_LABEL_ID, SpecialFolderType.Deleted },
{ DRAFT_LABEL_ID, SpecialFolderType.Draft },
{ SENT_LABEL_ID, SpecialFolderType.Sent },
{ SPAM_LABEL_ID, SpecialFolderType.Junk },
{ STARRED_LABEL_ID, SpecialFolderType.Starred },
{ UNREAD_LABEL_ID, SpecialFolderType.Unread },
{ FORUMS_LABEL_ID, SpecialFolderType.Forums },
{ UPDATES_LABEL_ID, SpecialFolderType.Updates },
{ PROMOTIONS_LABEL_ID, SpecialFolderType.Promotions },
{ SOCIAL_LABEL_ID, SpecialFolderType.Social},
{ PERSONAL_LABEL_ID, SpecialFolderType.Personal},
};
public static string[] SubCategoryFolderLabelIds =
[
FORUMS_LABEL_ID,
UPDATES_LABEL_ID,
PROMOTIONS_LABEL_ID,
SOCIAL_LABEL_ID,
PERSONAL_LABEL_ID
];
#endregion
}
}

View File

@@ -0,0 +1,32 @@
using Microsoft.Extensions.DependencyInjection;
using Wino.Core.Domain.Interfaces;
using Wino.Services.Threading;
namespace Wino.Services
{
public static class ServicesContainerSetup
{
public static void RegisterSharedServices(this IServiceCollection services)
{
services.AddSingleton<ITranslationService, TranslationService>();
services.AddSingleton<IDatabaseService, DatabaseService>();
services.AddSingleton<IApplicationConfiguration, ApplicationConfiguration>();
services.AddSingleton<ILogInitializer, LogInitializer>();
services.AddSingleton<ILaunchProtocolService, LaunchProtocolService>();
services.AddSingleton<IMimeFileService, MimeFileService>();
services.AddTransient<IMailService, MailService>();
services.AddTransient<IFolderService, FolderService>();
services.AddTransient<IAccountService, AccountService>();
services.AddTransient<IContactService, ContactService>();
services.AddTransient<ISignatureService, SignatureService>();
services.AddTransient<IContextMenuItemService, ContextMenuItemService>();
services.AddSingleton<IThreadingStrategyProvider, ThreadingStrategyProvider>();
services.AddTransient<IOutlookThreadingStrategy, OutlookThreadingStrategy>();
services.AddTransient<IGmailThreadingStrategy, GmailThreadingStrategy>();
services.AddTransient<IImapThreadingStrategy, ImapThreadingStrategy>();
}
}
}

View File

@@ -4,7 +4,7 @@ using System.Threading.Tasks;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Services
namespace Wino.Services
{
public class SignatureService(IDatabaseService databaseService) : BaseDatabaseService(databaseService), ISignatureService
{

View File

@@ -7,9 +7,9 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Services;
using Wino.Services;
namespace Wino.Core.Integration.Threading
namespace Wino.Services.Threading
{
public class APIThreadingStrategy : IThreadingStrategy
{

View File

@@ -1,9 +1,8 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
namespace Wino.Core.Integration.Threading
namespace Wino.Services.Threading
{
public class GmailThreadingStrategy : APIThreadingStrategy
public class GmailThreadingStrategy : APIThreadingStrategy, IGmailThreadingStrategy
{
public GmailThreadingStrategy(IDatabaseService databaseService, IFolderService folderService) : base(databaseService, folderService) { }
}

View File

@@ -4,22 +4,20 @@ using System.Linq;
using System.Threading.Tasks;
using SqlKata;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Extensions;
using Wino.Core.Services;
using Wino.Services.Extensions;
namespace Wino.Core.Integration.Threading
namespace Wino.Services.Threading
{
public class ImapThreadStrategy : IThreadingStrategy
public class ImapThreadingStrategy : BaseDatabaseService, IImapThreadingStrategy
{
private readonly IDatabaseService _databaseService;
private readonly IFolderService _folderService;
public ImapThreadStrategy(IDatabaseService databaseService, IFolderService folderService)
public ImapThreadingStrategy(IDatabaseService databaseService, IFolderService folderService) : base(databaseService)
{
_databaseService = databaseService;
_folderService = folderService;
}
@@ -37,7 +35,7 @@ namespace Wino.Core.Integration.Threading
.WhereNot("MailCopy.Id", replyItem.Id)
.Select("MailCopy.*");
return _databaseService.Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery());
return Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery());
}
private Task<MailCopy> GetInReplyToReplyAsync(IMailItem originalItem, Guid accountId, Guid threadingFolderId, Guid sentFolderId, Guid draftFolderId)
@@ -56,7 +54,7 @@ namespace Wino.Core.Integration.Threading
var raq = query.GetRawQuery();
return _databaseService.Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery());
return Connection.FindWithQueryAsync<MailCopy>(query.GetRawQuery());
}
public async Task<List<IMailItem>> ThreadItemsAsync(List<MailCopy> items, IMailItemFolder threadingForFolder)
@@ -75,8 +73,8 @@ namespace Wino.Core.Integration.Threading
if (!mailLookupTable.ContainsKey(mail.Id))
mailLookupTable.Add(mail.Id, false);
var sentFolder = await _folderService.GetSpecialFolderByAccountIdAsync(accountId, Domain.Enums.SpecialFolderType.Sent);
var draftFolder = await _folderService.GetSpecialFolderByAccountIdAsync(accountId, Domain.Enums.SpecialFolderType.Draft);
var sentFolder = await _folderService.GetSpecialFolderByAccountIdAsync(accountId, SpecialFolderType.Sent);
var draftFolder = await _folderService.GetSpecialFolderByAccountIdAsync(accountId, SpecialFolderType.Draft);
// Threading is not possible. Return items as it is.

View File

@@ -1,13 +1,12 @@
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
namespace Wino.Core.Integration.Threading
namespace Wino.Services.Threading
{
// Outlook and Gmail is using the same threading strategy.
// Outlook: ConversationId -> it's set as ThreadId
// Gmail: ThreadId
public class OutlookThreadingStrategy : APIThreadingStrategy
public class OutlookThreadingStrategy : APIThreadingStrategy, IOutlookThreadingStrategy
{
public OutlookThreadingStrategy(IDatabaseService databaseService, IFolderService folderService) : base(databaseService, folderService) { }
}

View File

@@ -0,0 +1,31 @@
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
namespace Wino.Services
{
public class ThreadingStrategyProvider : IThreadingStrategyProvider
{
private readonly IOutlookThreadingStrategy _outlookThreadingStrategy;
private readonly IGmailThreadingStrategy _gmailThreadingStrategy;
private readonly IImapThreadingStrategy _imapThreadStrategy;
public ThreadingStrategyProvider(IOutlookThreadingStrategy outlookThreadingStrategy,
IGmailThreadingStrategy gmailThreadingStrategy,
IImapThreadingStrategy imapThreadStrategy)
{
_outlookThreadingStrategy = outlookThreadingStrategy;
_gmailThreadingStrategy = gmailThreadingStrategy;
_imapThreadStrategy = imapThreadStrategy;
}
public IThreadingStrategy GetStrategy(MailProviderType mailProviderType)
{
return mailProviderType switch
{
MailProviderType.Outlook or MailProviderType.Office365 => _outlookThreadingStrategy,
MailProviderType.Gmail => _gmailThreadingStrategy,
_ => _imapThreadStrategy,
};
}
}
}

View File

@@ -10,7 +10,7 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Translations;
using Wino.Messaging.Client.Shell;
namespace Wino.Core.Services
namespace Wino.Services
{
public class TranslationService : ITranslationService
{

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>12.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.70" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageReference Include="Serilog" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="3.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="SqlKata" Version="2.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
</ItemGroup>
</Project>

View File

@@ -38,6 +38,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Calendar", "Wino.Calen
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "Wino.Calendar.Packaging", "Wino.Calendar.Packaging\Wino.Calendar.Packaging.wapproj", "{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wino.Services", "Wino.Services\Wino.Services.csproj", "{4000A374-59FE-4400-ACF6-D40473BECD73}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -392,6 +394,26 @@ Global
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.ActiveCfg = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.Build.0 = Release|x86
{7485B18C-F5AB-4ABE-BA7F-05B6623C67C8}.Release|x86.Deploy.0 = Release|x86
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|ARM.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|ARM.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|ARM64.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|ARM64.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x64.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x64.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x86.ActiveCfg = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Debug|x86.Build.0 = Debug|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|Any CPU.Build.0 = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|ARM.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|ARM.Build.0 = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|ARM64.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|ARM64.Build.0 = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x64.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x64.Build.0 = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x86.ActiveCfg = Release|Any CPU
{4000A374-59FE-4400-ACF6-D40473BECD73}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -407,6 +429,7 @@ Global
{53723AE8-7E7E-4D54-ADAB-0A6033255CC8} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{039AFFA8-C1CC-4E3B-8A31-6814D7557F74} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{A4DBA01A-F315-49E0-8428-BB99D32B20F9} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
{4000A374-59FE-4400-ACF6-D40473BECD73} = {17FF5FAE-F1AC-4572-BAA3-8B86F01EA758}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {721F946E-F69F-4987-823A-D084B436FC1E}