Initial commit.
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Accounts
|
||||
{
|
||||
public class ImapAuthenticationMethodModel(ImapAuthenticationMethod imapAuthenticationMethod, string displayName)
|
||||
{
|
||||
public ImapAuthenticationMethod ImapAuthenticationMethod { get; } = imapAuthenticationMethod;
|
||||
public string DisplayName { get; } = displayName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Accounts
|
||||
{
|
||||
public class ImapConnectionSecurityModel(ImapConnectionSecurity imapConnectionSecurity, string displayName)
|
||||
{
|
||||
public ImapConnectionSecurity ImapConnectionSecurity { get; } = imapConnectionSecurity;
|
||||
public string DisplayName { get; } = displayName;
|
||||
}
|
||||
}
|
||||
47
Wino.Core.Domain/Models/Accounts/ProviderDetail.cs
Normal file
47
Wino.Core.Domain/Models/Accounts/ProviderDetail.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Accounts
|
||||
{
|
||||
public class ProviderDetail : IProviderDetail
|
||||
{
|
||||
public MailProviderType Type { get; }
|
||||
|
||||
public string Name { get; }
|
||||
|
||||
public string Description { get; }
|
||||
|
||||
public string ProviderImage => $"ms-appx:///Assets/Providers/{Type}.png";
|
||||
|
||||
public bool IsSupported => Type == MailProviderType.Outlook || Type == MailProviderType.Gmail || Type == MailProviderType.IMAP4;
|
||||
|
||||
public ProviderDetail(MailProviderType type)
|
||||
{
|
||||
Type = type;
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case MailProviderType.Outlook:
|
||||
Name = "Outlook";
|
||||
Description = "Outlook.com, Live.com, Hotmail, MSN";
|
||||
break;
|
||||
case MailProviderType.Office365:
|
||||
Name = "Office 365";
|
||||
Description = "Office 365, Exchange";
|
||||
break;
|
||||
case MailProviderType.Gmail:
|
||||
Name = "Gmail";
|
||||
Description = Translator.ProviderDetail_Gmail_Description;
|
||||
break;
|
||||
case MailProviderType.Yahoo:
|
||||
Name = "Yahoo";
|
||||
Description = "Yahoo Mail";
|
||||
break;
|
||||
case MailProviderType.IMAP4:
|
||||
Name = Translator.ProviderDetail_IMAP_Title;
|
||||
Description = Translator.ProviderDetail_IMAP_Description;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Authentication
|
||||
{
|
||||
public class TokenInformationBase
|
||||
{
|
||||
public string AccessToken { get; set; }
|
||||
public string RefreshToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// UTC date for token expiration.
|
||||
/// </summary>
|
||||
public DateTime ExpiresAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value indicating whether the token is expired or not.
|
||||
/// </summary>
|
||||
public bool IsExpired => DateTime.UtcNow >= ExpiresAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Authorization
|
||||
{
|
||||
public class GoogleAuthorizationRequest
|
||||
{
|
||||
public const string RedirectUri = "google.pw.oauth2:/oauth2redirect";
|
||||
|
||||
const string authorizationEndpoint = "https://accounts.google.com/o/oauth2/v2/auth";
|
||||
const string CodeChallangeMethod = "S256";
|
||||
|
||||
public GoogleAuthorizationRequest(string state, string codeVerifier, string codeChallange)
|
||||
{
|
||||
State = state;
|
||||
CodeVerifier = codeVerifier;
|
||||
CodeChallange = codeChallange;
|
||||
}
|
||||
|
||||
// Pre
|
||||
public string State { get; set; }
|
||||
public string CodeVerifier { get; set; }
|
||||
public string CodeChallange { get; set; }
|
||||
public string ClientId { get; set; }
|
||||
|
||||
// Post
|
||||
public string AuthorizationCode { get; set; }
|
||||
|
||||
public string BuildRequest(string clientId)
|
||||
{
|
||||
ClientId = clientId;
|
||||
|
||||
// Creates the OAuth 2.0 authorization request.
|
||||
return string.Format("{0}?response_type=code&scope=https://mail.google.com/ https://www.googleapis.com/auth/gmail.labels&redirect_uri={1}&client_id={2}&state={3}&code_challenge={4}&code_challenge_method={5}",
|
||||
authorizationEndpoint,
|
||||
Uri.EscapeDataString(RedirectUri),
|
||||
ClientId,
|
||||
State,
|
||||
CodeChallange,
|
||||
CodeChallangeMethod);
|
||||
}
|
||||
|
||||
public void ValidateAuthorizationCode(Uri callbackUri)
|
||||
{
|
||||
if (callbackUri == null)
|
||||
throw new GoogleAuthenticationException(Translator.Exception_GoogleAuthCallbackNull);
|
||||
|
||||
string queryString = callbackUri.Query;
|
||||
|
||||
Dictionary<string, string> queryStringParams = queryString.Substring(1).Split('&').ToDictionary(c => c.Split('=')[0], c => Uri.UnescapeDataString(c.Split('=')[1]));
|
||||
|
||||
if (queryStringParams.ContainsKey("error"))
|
||||
throw new GoogleAuthenticationException(string.Format(Translator.Exception_GoogleAuthError, queryStringParams["error"]));
|
||||
|
||||
if (!queryStringParams.ContainsKey("code") || !queryStringParams.ContainsKey("state"))
|
||||
throw new GoogleAuthenticationException(Translator.Exception_GoogleAuthCorruptedCode + queryString);
|
||||
|
||||
// Gets the Authorization code & state
|
||||
string code = queryStringParams["code"];
|
||||
string incomingState = queryStringParams["state"];
|
||||
|
||||
// Compares the receieved state to the expected value, to ensure that
|
||||
// this app made the request which resulted in authorization
|
||||
if (incomingState != State)
|
||||
throw new GoogleAuthenticationException(string.Format(Translator.Exception_GoogleAuthInvalidResponse, incomingState));
|
||||
|
||||
AuthorizationCode = code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Authorization
|
||||
{
|
||||
public class GoogleTokenizationRequest
|
||||
{
|
||||
public GoogleTokenizationRequest(GoogleAuthorizationRequest authorizationRequest)
|
||||
{
|
||||
if (authorizationRequest == null)
|
||||
throw new GoogleAuthenticationException("Authorization request is empty.");
|
||||
|
||||
AuthorizationRequest = authorizationRequest;
|
||||
|
||||
if (string.IsNullOrEmpty(AuthorizationRequest.AuthorizationCode))
|
||||
throw new GoogleAuthenticationException("Authorization request has empty code.");
|
||||
}
|
||||
|
||||
public GoogleAuthorizationRequest AuthorizationRequest { get; set; }
|
||||
|
||||
public string BuildRequest()
|
||||
{
|
||||
return string.Format("code={0}&redirect_uri={1}&client_id={2}&code_verifier={3}&scope=&grant_type=authorization_code",
|
||||
AuthorizationRequest.AuthorizationCode, Uri.EscapeDataString(GoogleAuthorizationRequest.RedirectUri), AuthorizationRequest.ClientId, AuthorizationRequest.CodeVerifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.Domain.Models.AutoDiscovery
|
||||
{
|
||||
public class AutoDiscoveryConnectionTestFailedPackage
|
||||
{
|
||||
public AutoDiscoveryConnectionTestFailedPackage(AutoDiscoverySettings settings, Exception error)
|
||||
{
|
||||
Settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
Error = error ?? throw new ArgumentNullException(nameof(error));
|
||||
}
|
||||
|
||||
public AutoDiscoveryConnectionTestFailedPackage(Exception error)
|
||||
{
|
||||
Error = error ?? throw new ArgumentNullException(nameof(error));
|
||||
}
|
||||
|
||||
public AutoDiscoverySettings Settings { get; set; }
|
||||
public Exception Error { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Wino.Core.Domain.Models.AutoDiscovery
|
||||
{
|
||||
public class AutoDiscoveryMinimalSettings
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Wino.Core.Domain.Models.AutoDiscovery
|
||||
{
|
||||
public class AutoDiscoveryProviderSetting
|
||||
{
|
||||
[JsonProperty("protocol")]
|
||||
public string Protocol { get; set; }
|
||||
|
||||
[JsonProperty("address")]
|
||||
public string Address { get; set; }
|
||||
|
||||
[JsonProperty("port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[JsonProperty("secure")]
|
||||
public string Secure { get; set; }
|
||||
|
||||
[JsonProperty("username")]
|
||||
public string Username { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.AutoDiscovery
|
||||
{
|
||||
public class AutoDiscoverySettings
|
||||
{
|
||||
[JsonProperty("domain")]
|
||||
public string Domain { get; set; }
|
||||
|
||||
[JsonProperty("password")]
|
||||
public string Password { get; set; }
|
||||
|
||||
[JsonProperty("settings")]
|
||||
public List<AutoDiscoveryProviderSetting> Settings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this domain requires additional steps for password like app-specific password or sth.
|
||||
/// </summary>
|
||||
public bool IsPasswordSupportLinkAvailable => !string.IsNullOrEmpty(Password) && Uri.TryCreate(Password, UriKind.Absolute, out _);
|
||||
|
||||
public AutoDiscoveryMinimalSettings UserMinimalSettings { get; set; }
|
||||
|
||||
public CustomServerInformation ToServerInformation()
|
||||
{
|
||||
var imapSettings = GetImapSettings();
|
||||
var smtpSettings = GetSmptpSettings();
|
||||
|
||||
if (imapSettings == null || smtpSettings == null) return null;
|
||||
|
||||
bool imapRequiresSSL = imapSettings.Secure == "SSL";
|
||||
bool smtpRequiresSSL = smtpSettings.Secure == "SSL";
|
||||
|
||||
string imapUrl = imapSettings.Address;
|
||||
string smtpUrl = smtpSettings.Address;
|
||||
|
||||
string imapUsername = imapSettings.Username;
|
||||
string smtpUsername = smtpSettings.Username;
|
||||
|
||||
int imapPort = imapSettings.Port;
|
||||
int smtpPort = smtpSettings.Port;
|
||||
|
||||
var serverInfo = new CustomServerInformation
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
DisplayName = UserMinimalSettings.DisplayName,
|
||||
Address = UserMinimalSettings.Email,
|
||||
IncomingServerPassword = UserMinimalSettings.Password,
|
||||
OutgoingServerPassword = UserMinimalSettings.Password,
|
||||
IncomingRequiresSSL = imapRequiresSSL,
|
||||
OutgoingRequresSSL = smtpRequiresSSL,
|
||||
IncomingServer = imapUrl,
|
||||
OutgoingServer = smtpUrl,
|
||||
IncomingServerPort = imapPort.ToString(),
|
||||
OutgoingServerPort = smtpPort.ToString(),
|
||||
IncomingServerType = Enums.CustomIncomingServerType.IMAP4,
|
||||
IncomingServerUsername = imapUsername,
|
||||
OutgoingServerUsername = smtpUsername
|
||||
};
|
||||
|
||||
return serverInfo;
|
||||
}
|
||||
|
||||
public AutoDiscoveryProviderSetting GetImapSettings()
|
||||
=> Settings?.Find(a => a.Protocol == "IMAP");
|
||||
|
||||
public AutoDiscoveryProviderSetting GetSmptpSettings()
|
||||
=> Settings?.Find(a => a.Protocol == "SMTP");
|
||||
}
|
||||
}
|
||||
32
Wino.Core.Domain/Models/Comparers/DateComparer.cs
Normal file
32
Wino.Core.Domain/Models/Comparers/DateComparer.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Comparers
|
||||
{
|
||||
public class DateComparer : IComparer<IMailItem>, IEqualityComparer
|
||||
{
|
||||
public int Compare(IMailItem x, IMailItem y)
|
||||
{
|
||||
return DateTime.Compare(y.CreationDate, x.CreationDate);
|
||||
}
|
||||
|
||||
public new bool Equals(object x, object y)
|
||||
{
|
||||
if (x is IMailItem firstItem && y is IMailItem secondItem)
|
||||
{
|
||||
return firstItem.Equals(secondItem);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetHashCode(object obj) => (obj as IMailItem).GetHashCode();
|
||||
|
||||
public DateComparer()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Wino.Core.Domain/Models/Comparers/DateTimeComparer.cs
Normal file
16
Wino.Core.Domain/Models/Comparers/DateTimeComparer.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Comparers
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to insert date grouping into proper place in Reader page.
|
||||
/// </summary>
|
||||
public class DateTimeComparer : IComparer<DateTime>
|
||||
{
|
||||
public int Compare(DateTime x, DateTime y)
|
||||
{
|
||||
return DateTime.Compare(y, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Wino.Core.Domain/Models/Comparers/FolderNameComparer.cs
Normal file
13
Wino.Core.Domain/Models/Comparers/FolderNameComparer.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Comparers
|
||||
{
|
||||
public class FolderNameComparer : IComparer<MailItemFolder>
|
||||
{
|
||||
public int Compare(MailItemFolder x, MailItemFolder y)
|
||||
{
|
||||
return x.FolderName.CompareTo(y.FolderName);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Wino.Core.Domain/Models/Comparers/ListItemComparer.cs
Normal file
38
Wino.Core.Domain/Models/Comparers/ListItemComparer.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Comparers
|
||||
{
|
||||
public class ListItemComparer : IComparer<object>
|
||||
{
|
||||
public bool SortByName { get; set; }
|
||||
|
||||
public DateComparer DateComparer = new DateComparer();
|
||||
public readonly NameComparer NameComparer = new NameComparer();
|
||||
|
||||
public int Compare(object x, object y)
|
||||
{
|
||||
if (x is IMailItem xMail && y is IMailItem yMail)
|
||||
{
|
||||
var itemComparer = GetItemComparer();
|
||||
|
||||
return itemComparer.Compare(xMail, yMail);
|
||||
}
|
||||
else if (x is DateTime dateX && y is DateTime dateY)
|
||||
return DateTime.Compare(dateY, dateX);
|
||||
else if (x is string stringX && y is string stringY)
|
||||
return stringY.CompareTo(stringX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public IComparer<IMailItem> GetItemComparer()
|
||||
{
|
||||
if (SortByName)
|
||||
return NameComparer;
|
||||
else
|
||||
return DateComparer;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Wino.Core.Domain/Models/Comparers/NameComparer.cs
Normal file
13
Wino.Core.Domain/Models/Comparers/NameComparer.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Comparers
|
||||
{
|
||||
public class NameComparer : IComparer<IMailItem>
|
||||
{
|
||||
public int Compare(IMailItem x, IMailItem y)
|
||||
{
|
||||
return string.Compare(x.FromName, y.FromName);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Wino.Core.Domain/Models/Folders/AccountFolderTree.cs
Normal file
33
Wino.Core.Domain/Models/Folders/AccountFolderTree.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Folders
|
||||
{
|
||||
/// <summary>
|
||||
/// Grouped folder information for the menu for given account.
|
||||
/// </summary>
|
||||
public class AccountFolderTree
|
||||
{
|
||||
public MailAccount Account { get; }
|
||||
public List<IMailItemFolder> Folders { get; set; } = new List<IMailItemFolder>();
|
||||
|
||||
public AccountFolderTree(MailAccount account)
|
||||
{
|
||||
Account = account;
|
||||
}
|
||||
|
||||
public bool HasSpecialTypeFolder(SpecialFolderType type)
|
||||
{
|
||||
foreach (var folderStructure in Folders)
|
||||
{
|
||||
bool hasSpecialFolder = folderStructure.ContainsSpecialFolderType(type);
|
||||
|
||||
if (hasSpecialFolder)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Wino.Core.Domain/Models/Folders/FolderOperationMenuItem.cs
Normal file
14
Wino.Core.Domain/Models/Folders/FolderOperationMenuItem.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Menus;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Folders
|
||||
{
|
||||
public class FolderOperationMenuItem : MenuOperationItemBase<FolderOperation>, IMenuOperation
|
||||
{
|
||||
protected FolderOperationMenuItem(FolderOperation operation, bool isEnabled) : base(operation, isEnabled) { }
|
||||
|
||||
public static FolderOperationMenuItem Create(FolderOperation operation, bool isEnabled = true)
|
||||
=> new FolderOperationMenuItem(operation, isEnabled);
|
||||
}
|
||||
}
|
||||
31
Wino.Core.Domain/Models/Folders/IMailItemFolder.cs
Normal file
31
Wino.Core.Domain/Models/Folders/IMailItemFolder.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Folders
|
||||
{
|
||||
public interface IMailItemFolder
|
||||
{
|
||||
string BackgroundColorHex { get; set; }
|
||||
string DeltaToken { get; set; }
|
||||
string FolderName { get; set; }
|
||||
long HighestModeSeq { get; set; }
|
||||
Guid Id { get; set; }
|
||||
bool IsHidden { get; set; }
|
||||
bool IsSticky { get; set; }
|
||||
bool IsSynchronizationEnabled { get; set; }
|
||||
bool IsSystemFolder { get; set; }
|
||||
DateTime? LastSynchronizedDate { get; set; }
|
||||
Guid MailAccountId { get; set; }
|
||||
string ParentRemoteFolderId { get; set; }
|
||||
string RemoteFolderId { get; set; }
|
||||
SpecialFolderType SpecialFolderType { get; set; }
|
||||
string TextColorHex { get; set; }
|
||||
uint UidValidity { get; set; }
|
||||
List<IMailItemFolder> ChildFolders { get; set; }
|
||||
bool IsMoveTarget { get; }
|
||||
bool ShowUnreadCount { get; set; }
|
||||
|
||||
bool ContainsSpecialFolderType(SpecialFolderType type);
|
||||
}
|
||||
}
|
||||
40
Wino.Core.Domain/Models/MailItem/DraftCreationOptions.cs
Normal file
40
Wino.Core.Domain/Models/MailItem/DraftCreationOptions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public class DraftCreationOptions
|
||||
{
|
||||
public MimeMessage ReferenceMimeMessage { get; set; }
|
||||
public MailCopy ReferenceMailCopy { get; set; }
|
||||
public DraftCreationReason Reason { get; set; }
|
||||
|
||||
#region Mailto Protocol Related Stuff
|
||||
|
||||
public const string MailtoSubjectParameterKey = "subject";
|
||||
public const string MailtoBodyParameterKey = "body";
|
||||
public const string MailtoToParameterKey = "mailto";
|
||||
public const string MailtoCCParameterKey = "cc";
|
||||
public const string MailtoBCCParameterKey = "bcc";
|
||||
|
||||
public NameValueCollection MailtoParameters { get; set; }
|
||||
|
||||
private bool IsMailtoParameterExists(string parameterKey)
|
||||
=> MailtoParameters != null
|
||||
&& MailtoParameters.AllKeys.Contains(parameterKey);
|
||||
|
||||
public bool TryGetMailtoValue(string key, out string value)
|
||||
{
|
||||
bool valueExists = IsMailtoParameterExists(key);
|
||||
|
||||
value = valueExists ? MailtoParameters[key] : string.Empty;
|
||||
|
||||
return valueExists;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
23
Wino.Core.Domain/Models/MailItem/DraftPreperationRequest.cs
Normal file
23
Wino.Core.Domain/Models/MailItem/DraftPreperationRequest.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public class DraftPreperationRequest : DraftCreationOptions
|
||||
{
|
||||
public DraftPreperationRequest(MailAccount account, MailCopy createdLocalDraftCopy, MimeMessage createdLocalDraftMimeMessage)
|
||||
{
|
||||
Account = account ?? throw new ArgumentNullException(nameof(account));
|
||||
|
||||
CreatedLocalDraftCopy = createdLocalDraftCopy ?? throw new ArgumentNullException(nameof(createdLocalDraftCopy));
|
||||
CreatedLocalDraftMimeMessage = createdLocalDraftMimeMessage ?? throw new ArgumentNullException(nameof(createdLocalDraftMimeMessage));
|
||||
}
|
||||
|
||||
public MailCopy CreatedLocalDraftCopy { get; set; }
|
||||
public MimeMessage CreatedLocalDraftMimeMessage { get; set; }
|
||||
public MailAccount Account { get; }
|
||||
}
|
||||
}
|
||||
33
Wino.Core.Domain/Models/MailItem/IMailItem.cs
Normal file
33
Wino.Core.Domain/Models/MailItem/IMailItem.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface of simplest representation of a MailCopy.
|
||||
/// </summary>
|
||||
public interface IMailItem
|
||||
{
|
||||
Guid UniqueId { get; }
|
||||
string Id { get; }
|
||||
string Subject { get; }
|
||||
string ThreadId { get; }
|
||||
string MessageId { get; }
|
||||
string References { get; }
|
||||
string InReplyTo { get; }
|
||||
string PreviewText { get; }
|
||||
string FromName { get; }
|
||||
DateTime CreationDate { get; }
|
||||
string FromAddress { get; }
|
||||
bool HasAttachments { get; }
|
||||
bool IsFlagged { get; }
|
||||
bool IsFocused { get; }
|
||||
bool IsRead { get; }
|
||||
string DraftId { get; }
|
||||
bool IsDraft { get; }
|
||||
Guid FileId { get; }
|
||||
|
||||
MailItemFolder AssignedFolder { get; }
|
||||
MailAccount AssignedAccount { get; }
|
||||
}
|
||||
}
|
||||
16
Wino.Core.Domain/Models/MailItem/IMailItemThread.cs
Normal file
16
Wino.Core.Domain/Models/MailItem/IMailItemThread.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface that represents conversation threads.
|
||||
/// Even though this type has 1 single UI representation most of the time,
|
||||
/// it can contain multiple IMailItem.
|
||||
/// </summary>
|
||||
public interface IMailItemThread : IMailItem
|
||||
{
|
||||
ObservableCollection<IMailItem> ThreadItems { get; }
|
||||
IMailItem LatestMailItem { get; }
|
||||
IMailItem FirstMailItem { get; }
|
||||
}
|
||||
}
|
||||
18
Wino.Core.Domain/Models/MailItem/MailDetailInformation.cs
Normal file
18
Wino.Core.Domain/Models/MailItem/MailDetailInformation.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public class MailDetailInformation
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public Guid AccountId { get; set; }
|
||||
public Guid FolderId { get; set; }
|
||||
public string RemoteFolderId { get; set; }
|
||||
public SpecialFolderType SpecialFolderType { get; set; }
|
||||
public bool IsRead { get; set; }
|
||||
public bool IsFlagged { get; set; }
|
||||
public bool IsDraft { get; set; }
|
||||
}
|
||||
}
|
||||
25
Wino.Core.Domain/Models/MailItem/MailDragPackage.cs
Normal file
25
Wino.Core.Domain/Models/MailItem/MailDragPackage.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that holds information when the drag/drop of mails are performed.
|
||||
/// </summary>
|
||||
public class MailDragPackage
|
||||
{
|
||||
public MailDragPackage(IEnumerable<IMailItem> draggingMails)
|
||||
{
|
||||
DraggingMails = draggingMails;
|
||||
}
|
||||
|
||||
public MailDragPackage(IMailItem draggingMail)
|
||||
{
|
||||
DraggingMails =
|
||||
[
|
||||
draggingMail
|
||||
];
|
||||
}
|
||||
|
||||
public IEnumerable<IMailItem> DraggingMails { get; set; }
|
||||
}
|
||||
}
|
||||
11
Wino.Core.Domain/Models/MailItem/MailFolderPairMetadata.cs
Normal file
11
Wino.Core.Domain/Models/MailItem/MailFolderPairMetadata.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public class MailFolderPairMetadata
|
||||
{
|
||||
public Guid FolderId { get; set; }
|
||||
public string RemoteFolderId { get; set; }
|
||||
public string MailCopyId { get; set; }
|
||||
}
|
||||
}
|
||||
7
Wino.Core.Domain/Models/MailItem/MailInsertPackage.cs
Normal file
7
Wino.Core.Domain/Models/MailItem/MailInsertPackage.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public record NewMailItemPackage(MailCopy Copy, MimeMessage Mime, string AssignedRemoteFolderId);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public record MailListInitializationOptions(IEnumerable<IMailItemFolder> Folders,
|
||||
FilterOptionType FilterType,
|
||||
SortingOptionType SortingOptionType,
|
||||
bool CreateThreads,
|
||||
bool? IsFocusedOnly,
|
||||
string SearchQuery,
|
||||
IEnumerable<Guid> ExistingUniqueIds);
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates the options for preparing requests to execute mail operations for mail items like Move, Delete, MarkAsRead, etc.
|
||||
/// </summary>
|
||||
public class MailOperationPreperationRequest
|
||||
{
|
||||
public MailOperationPreperationRequest(MailOperation action,
|
||||
IEnumerable<MailCopy> mailItems,
|
||||
bool toggleExecution = false,
|
||||
IMailItemFolder moveTargetFolder = null,
|
||||
bool ignoreHardDeleteProtection = false)
|
||||
{
|
||||
Action = action;
|
||||
MailItems = mailItems ?? throw new ArgumentNullException(nameof(mailItems));
|
||||
ToggleExecution = toggleExecution;
|
||||
MoveTargetFolder = moveTargetFolder;
|
||||
IgnoreHardDeleteProtection = ignoreHardDeleteProtection;
|
||||
}
|
||||
|
||||
public MailOperationPreperationRequest(MailOperation action,
|
||||
MailCopy singleMailItem,
|
||||
bool toggleExecution = false,
|
||||
IMailItemFolder moveTargetFolder = null,
|
||||
bool ignoreHardDeleteProtection = false)
|
||||
{
|
||||
Action = action;
|
||||
MailItems = new List<MailCopy>() { singleMailItem };
|
||||
ToggleExecution = toggleExecution;
|
||||
MoveTargetFolder = moveTargetFolder;
|
||||
IgnoreHardDeleteProtection = ignoreHardDeleteProtection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Action to execute.
|
||||
/// </summary>
|
||||
public MailOperation Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Mail copies execute the action on.
|
||||
/// </summary>
|
||||
public IEnumerable<MailCopy> MailItems { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the operation can be reverted if needed.
|
||||
/// eg. MarkAsRead on already read item will set the action to MarkAsUnread.
|
||||
/// This is used in hover actions for example.
|
||||
/// </summary>
|
||||
public bool ToggleExecution { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether hard delete protection should be ignored.
|
||||
/// Discard draft requests for example should ignore hard delete protection.
|
||||
/// </summary>
|
||||
public bool IgnoreHardDeleteProtection { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Moving folder for the Move operation.
|
||||
/// If null and the action is Move, the user will be prompted to select a folder.
|
||||
/// </summary>
|
||||
public IMailItemFolder MoveTargetFolder { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using MimeKit;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates MimeMessage and the path to the file.
|
||||
/// </summary>
|
||||
public record MimeMessageInformation(MimeMessage MimeMessage, string Path);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Class that holds immutable information about special folders in Outlook.
|
||||
/// </summary>
|
||||
/// <param name="InboxId"></param>
|
||||
/// <param name="TrashId"></param>
|
||||
/// <param name="JunkId"></param>
|
||||
/// <param name="DraftId"></param>
|
||||
/// <param name="SentId"></param>
|
||||
/// <param name="ArchiveId"></param>
|
||||
public record OutlookSpecialFolderIdInformation(string InboxId, string TrashId, string JunkId, string DraftId, string SentId, string ArchiveId);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public record SendDraftPreparationRequest(MailCopy MailItem, MimeMessage Mime, MailItemFolder DraftFolder, MailItemFolder SentFolder, MailAccountPreferences AccountPreferences);
|
||||
}
|
||||
87
Wino.Core.Domain/Models/MailItem/ThreadMailItem.cs
Normal file
87
Wino.Core.Domain/Models/MailItem/ThreadMailItem.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Wino.Core.Domain.Entities;
|
||||
|
||||
namespace Wino.Core.Domain.Models.MailItem
|
||||
{
|
||||
public class ThreadMailItem : IMailItemThread
|
||||
{
|
||||
// TODO: Ideally this should be SortedList.
|
||||
public ObservableCollection<IMailItem> ThreadItems { get; } = new ObservableCollection<IMailItem>();
|
||||
|
||||
public IMailItem LatestMailItem => ThreadItems.LastOrDefault();
|
||||
public IMailItem FirstMailItem => ThreadItems.FirstOrDefault();
|
||||
|
||||
public void AddThreadItem(IMailItem item)
|
||||
{
|
||||
if (item == null) return;
|
||||
|
||||
if (ThreadItems.Any(a => a.Id == item.Id))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (item != null && item.IsDraft)
|
||||
{
|
||||
ThreadItems.Insert(0, item);
|
||||
return;
|
||||
}
|
||||
|
||||
var insertItem = ThreadItems.FirstOrDefault(a => !a.IsDraft && a.CreationDate < item.CreationDate);
|
||||
|
||||
if (insertItem == null)
|
||||
ThreadItems.Insert(ThreadItems.Count, item);
|
||||
else
|
||||
{
|
||||
var index = ThreadItems.IndexOf(insertItem);
|
||||
|
||||
ThreadItems.Insert(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
#region IMailItem
|
||||
|
||||
public Guid UniqueId => LatestMailItem?.UniqueId ?? Guid.Empty;
|
||||
public string Id => LatestMailItem?.Id ?? string.Empty;
|
||||
|
||||
// Show subject from last item.
|
||||
public string Subject => LatestMailItem?.Subject ?? string.Empty;
|
||||
|
||||
public string ThreadId => LatestMailItem?.ThreadId ?? string.Empty;
|
||||
|
||||
public string PreviewText => FirstMailItem?.PreviewText ?? string.Empty;
|
||||
|
||||
public string FromName => LatestMailItem?.FromName ?? string.Empty;
|
||||
|
||||
public string FromAddress => LatestMailItem?.FromAddress ?? string.Empty;
|
||||
|
||||
public bool HasAttachments => ThreadItems.Any(a => a.HasAttachments);
|
||||
|
||||
public bool IsFlagged => ThreadItems.Any(a => a.IsFlagged);
|
||||
|
||||
public bool IsFocused => LatestMailItem?.IsFocused ?? false;
|
||||
|
||||
public bool IsRead => ThreadItems.All(a => a.IsRead);
|
||||
|
||||
public DateTime CreationDate => FirstMailItem?.CreationDate ?? DateTime.MinValue;
|
||||
|
||||
public bool IsDraft => ThreadItems.Any(a => a.IsDraft);
|
||||
|
||||
public string DraftId => string.Empty;
|
||||
|
||||
public string MessageId => LatestMailItem?.MessageId;
|
||||
|
||||
public string References => LatestMailItem?.References ?? string.Empty;
|
||||
|
||||
public string InReplyTo => LatestMailItem?.InReplyTo ?? string.Empty;
|
||||
|
||||
public MailItemFolder AssignedFolder => LatestMailItem?.AssignedFolder;
|
||||
|
||||
public MailAccount AssignedAccount => LatestMailItem?.AssignedAccount;
|
||||
|
||||
public Guid FileId => LatestMailItem?.FileId ?? Guid.Empty;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
21
Wino.Core.Domain/Models/Menus/MailOperationMenuItem.cs
Normal file
21
Wino.Core.Domain/Models/Menus/MailOperationMenuItem.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Menus
|
||||
{
|
||||
public class MailOperationMenuItem : MenuOperationItemBase<MailOperation>, IMenuOperation
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets whether this menu item should be placed in SecondaryCommands if used in CommandBar.
|
||||
/// </summary>
|
||||
public bool IsSecondaryMenuPreferred { get; set; }
|
||||
|
||||
protected MailOperationMenuItem(MailOperation operation, bool isEnabled, bool isSecondaryMenuItem = false) : base(operation, isEnabled)
|
||||
{
|
||||
IsSecondaryMenuPreferred = isSecondaryMenuItem;
|
||||
}
|
||||
|
||||
public static MailOperationMenuItem Create(MailOperation operation, bool isEnabled = true, bool isSecondaryMenuItem = false)
|
||||
=> new MailOperationMenuItem(operation, isEnabled, isSecondaryMenuItem);
|
||||
}
|
||||
}
|
||||
18
Wino.Core.Domain/Models/Menus/MenuOperationItemBase.cs
Normal file
18
Wino.Core.Domain/Models/Menus/MenuOperationItemBase.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Menus
|
||||
{
|
||||
public class MenuOperationItemBase<TOperation> where TOperation : Enum
|
||||
{
|
||||
public MenuOperationItemBase(TOperation operation, bool isEnabled)
|
||||
{
|
||||
Operation = operation;
|
||||
IsEnabled = isEnabled;
|
||||
Identifier = operation.ToString();
|
||||
}
|
||||
|
||||
public TOperation Operation { get; set; }
|
||||
public string Identifier { get; set; }
|
||||
public bool IsEnabled { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Navigation
|
||||
{
|
||||
public class NavigateMailFolderEventArgs
|
||||
{
|
||||
public NavigateMailFolderEventArgs(IBaseFolderMenuItem baseFolderMenuItem, TaskCompletionSource<bool> folderInitLoadAwaitTask = null)
|
||||
{
|
||||
BaseFolderMenuItem = baseFolderMenuItem;
|
||||
FolderInitLoadAwaitTask = folderInitLoadAwaitTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base folder menu item.
|
||||
/// </summary>
|
||||
public IBaseFolderMenuItem BaseFolderMenuItem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Completion source for waiting folder's mail initialization.
|
||||
/// </summary>
|
||||
public TaskCompletionSource<bool> FolderInitLoadAwaitTask { get; }
|
||||
}
|
||||
}
|
||||
10
Wino.Core.Domain/Models/Navigation/NavigationMode.cs
Normal file
10
Wino.Core.Domain/Models/Navigation/NavigationMode.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Wino.Core.Domain.Models.Navigation
|
||||
{
|
||||
public enum NavigationMode
|
||||
{
|
||||
New,
|
||||
Back,
|
||||
Forward,
|
||||
Refresh
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Wino.Core.Domain.Models.Navigation
|
||||
{
|
||||
public enum NavigationTransitionType
|
||||
{
|
||||
None, // Supress
|
||||
DrillIn,
|
||||
}
|
||||
}
|
||||
29
Wino.Core.Domain/Models/Personalization/AppThemeBase.cs
Normal file
29
Wino.Core.Domain/Models/Personalization/AppThemeBase.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Personalization
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for all app themes.
|
||||
/// </summary>
|
||||
public abstract class AppThemeBase
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string ThemeName { get; set; }
|
||||
public ApplicationElementTheme ForceElementTheme { get; set; }
|
||||
public string AccentColor { get; set; }
|
||||
public bool IsAccentColorAssigned => !string.IsNullOrEmpty(AccentColor);
|
||||
public string BackgroundPreviewImage => GetBackgroundPreviewImagePath();
|
||||
public abstract AppThemeType AppThemeType { get; }
|
||||
|
||||
protected AppThemeBase(string themeName, Guid id)
|
||||
{
|
||||
ThemeName = themeName;
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public abstract Task<string> GetThemeResourceDictionaryContentAsync();
|
||||
public abstract string GetBackgroundPreviewImagePath();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Personalization
|
||||
{
|
||||
public class CustomThemeMetadata
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string AccentColorHex { get; set; }
|
||||
public bool HasCustomAccentColor => !string.IsNullOrEmpty(AccentColorHex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Personalization
|
||||
{
|
||||
public class ElementThemeContainer
|
||||
{
|
||||
public ElementThemeContainer(ApplicationElementTheme nativeTheme, string title)
|
||||
{
|
||||
NativeTheme = nativeTheme;
|
||||
Title = title;
|
||||
}
|
||||
|
||||
public ApplicationElementTheme NativeTheme { get; set; }
|
||||
public string Title { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Wino.Core.Domain.Models.Personalization
|
||||
{
|
||||
public record MailListPaneLengthPreferences(string Title, double Length);
|
||||
}
|
||||
30
Wino.Core.Domain/Models/Reader/EditorToolbarSection.cs
Normal file
30
Wino.Core.Domain/Models/Reader/EditorToolbarSection.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Reader
|
||||
{
|
||||
public class EditorToolbarSection
|
||||
{
|
||||
public EditorToolbarSectionType SectionType { get; set; }
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (SectionType)
|
||||
{
|
||||
case EditorToolbarSectionType.None:
|
||||
return Translator.EditorToolbarOption_None;
|
||||
case EditorToolbarSectionType.Format:
|
||||
return Translator.EditorToolbarOption_Format;
|
||||
case EditorToolbarSectionType.Insert:
|
||||
return Translator.EditorToolbarOption_Insert;
|
||||
case EditorToolbarSectionType.Draw:
|
||||
return Translator.EditorToolbarOption_Draw;
|
||||
case EditorToolbarSectionType.Options:
|
||||
return Translator.EditorToolbarOption_Options;
|
||||
default:
|
||||
return "Unknown Editor Option";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Wino.Core.Domain/Models/Reader/FilterOption.cs
Normal file
16
Wino.Core.Domain/Models/Reader/FilterOption.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Reader
|
||||
{
|
||||
public class FilterOption
|
||||
{
|
||||
public FilterOptionType Type { get; set; }
|
||||
public string Title { get; set; }
|
||||
|
||||
public FilterOption(string title, FilterOptionType type)
|
||||
{
|
||||
Title = title;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
Wino.Core.Domain/Models/Reader/MailRenderModel.cs
Normal file
25
Wino.Core.Domain/Models/Reader/MailRenderModel.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using MimeKit;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Reader
|
||||
{
|
||||
/// <summary>
|
||||
/// Final model to be passed to renderer page.
|
||||
/// Data here are created based on rendering settings.
|
||||
/// </summary>
|
||||
public class MailRenderModel
|
||||
{
|
||||
public string RenderHtml { get; }
|
||||
public MailRenderingOptions MailRenderingOptions { get; }
|
||||
public List<MimePart> Attachments { get; set; } = new List<MimePart>();
|
||||
|
||||
public string UnsubscribeLink { get; set; }
|
||||
public bool CanUnsubscribe => !string.IsNullOrEmpty(UnsubscribeLink);
|
||||
|
||||
public MailRenderModel(string renderHtml, MailRenderingOptions mailRenderingOptions = null)
|
||||
{
|
||||
RenderHtml = renderHtml;
|
||||
MailRenderingOptions = mailRenderingOptions;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
Wino.Core.Domain/Models/Reader/MailRenderingOptions.cs
Normal file
19
Wino.Core.Domain/Models/Reader/MailRenderingOptions.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace Wino.Core.Domain.Models.Reader
|
||||
{
|
||||
/// <summary>
|
||||
/// Rendering options for mail.
|
||||
/// </summary>
|
||||
public class MailRenderingOptions
|
||||
{
|
||||
private const bool DefaultLoadImageValue = true;
|
||||
private const bool DefaultLoadStylesValue = true;
|
||||
|
||||
public bool LoadImages { get; set; } = DefaultLoadImageValue;
|
||||
public bool LoadStyles { get; set; } = DefaultLoadStylesValue;
|
||||
|
||||
// HtmlDocument.Load call is redundant if all the settings are in default values.
|
||||
// Therefore we will purify the HTML only if needed.
|
||||
|
||||
public bool IsPurifyingNeeded() => LoadImages != DefaultLoadImageValue || LoadStyles != DefaultLoadStylesValue;
|
||||
}
|
||||
}
|
||||
6
Wino.Core.Domain/Models/Reader/ReaderFontModel.cs
Normal file
6
Wino.Core.Domain/Models/Reader/ReaderFontModel.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Reader
|
||||
{
|
||||
public record ReaderFontModel(ReaderFont Font, string FontFamilyName);
|
||||
}
|
||||
29
Wino.Core.Domain/Models/Reader/SortingOption.cs
Normal file
29
Wino.Core.Domain/Models/Reader/SortingOption.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Comparers;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Reader
|
||||
{
|
||||
public class SortingOption
|
||||
{
|
||||
public SortingOptionType Type { get; set; }
|
||||
public string Title { get; set; }
|
||||
public IComparer<IMailItem> Comparer
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Type == SortingOptionType.ReceiveDate)
|
||||
return new DateComparer();
|
||||
else
|
||||
return new NameComparer();
|
||||
}
|
||||
}
|
||||
|
||||
public SortingOption(string title, SortingOptionType type)
|
||||
{
|
||||
Title = title;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Wino.Core.Domain/Models/Requests/IUIMessage.cs
Normal file
10
Wino.Core.Domain/Models/Requests/IUIMessage.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Wino.Core.Domain.Models.Requests
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for all messages to report UI changes from synchronizers to UI.
|
||||
/// None of these messages can't run a code that manipulates database.
|
||||
/// They are sent either from processor or view models to signal some other
|
||||
/// parts of the application.
|
||||
/// </summary>
|
||||
public interface IUIMessage;
|
||||
}
|
||||
27
Wino.Core.Domain/Models/Requests/RequestBase.cs
Normal file
27
Wino.Core.Domain/Models/Requests/RequestBase.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Requests
|
||||
{
|
||||
public abstract record RequestBase<TBatchRequestType>(MailCopy Item, MailSynchronizerOperation Operation) : IRequest
|
||||
where TBatchRequestType : IBatchChangeRequest
|
||||
{
|
||||
public abstract IBatchChangeRequest CreateBatch(IEnumerable<IRequest> requests);
|
||||
public abstract void ApplyUIChanges();
|
||||
public abstract void RevertUIChanges();
|
||||
}
|
||||
|
||||
public abstract record FolderRequestBase(MailItemFolder Folder, MailSynchronizerOperation Operation) : IFolderRequest
|
||||
{
|
||||
public abstract void ApplyUIChanges();
|
||||
public abstract void RevertUIChanges();
|
||||
}
|
||||
|
||||
public abstract record BatchRequestBase(IEnumerable<IRequest> Items, MailSynchronizerOperation Operation) : IBatchChangeRequest
|
||||
{
|
||||
public abstract void ApplyUIChanges();
|
||||
public abstract void RevertUIChanges();
|
||||
}
|
||||
}
|
||||
15
Wino.Core.Domain/Models/Requests/ToggleRequestRule.cs
Normal file
15
Wino.Core.Domain/Models/Requests/ToggleRequestRule.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Requests
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a single rule for toggling user actions if needed.
|
||||
/// For example: If user wants to mark a mail as read, but it's already read, then it should be marked as unread.
|
||||
/// </summary>
|
||||
/// <param name="SourceAction"></param>
|
||||
/// <param name="TargetAction"></param>
|
||||
/// <param name="Condition"></param>
|
||||
public record ToggleRequestRule(MailOperation SourceAction, MailOperation TargetAction, Func<IMailItem, bool> Condition);
|
||||
}
|
||||
7
Wino.Core.Domain/Models/Store/StoreProductType.cs
Normal file
7
Wino.Core.Domain/Models/Store/StoreProductType.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace Wino.Core.Domain.Models.Store
|
||||
{
|
||||
public enum StoreProductType
|
||||
{
|
||||
UnlimitedAccounts
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Synchronization
|
||||
{
|
||||
public class SynchronizationOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Unique id of synchronization.
|
||||
/// </summary>
|
||||
public Guid Id { get; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>
|
||||
/// Account to execute synchronization for.
|
||||
/// </summary>
|
||||
public Guid AccountId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Type of the synchronization to be performed.
|
||||
/// </summary>
|
||||
public SynchronizationType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Collection of FolderId to perform SynchronizationType.Custom type sync.
|
||||
/// </summary>
|
||||
public List<Guid> SynchronizationFolderIds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A listener to be notified about the progress of the synchronization.
|
||||
/// </summary>
|
||||
public ISynchronizationProgress ProgressListener { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When doing a linked inbox synchronization, we must ignore reporting completion to the caller for each folder.
|
||||
/// This Id will help tracking that. Id is unique, but this one can be the same for all sync requests
|
||||
/// inside the same linked inbox sync.
|
||||
/// </summary>
|
||||
public Guid? GroupedSynchronizationTrackingId { get; set; }
|
||||
|
||||
public override string ToString() => $"Type: {Type}, Folders: {(SynchronizationFolderIds == null ? "None" : string.Join(",", SynchronizationFolderIds))}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Synchronization
|
||||
{
|
||||
public class SynchronizationResult
|
||||
{
|
||||
protected SynchronizationResult() { }
|
||||
|
||||
public IEnumerable<IMailItem> DownloadedMessages { get; set; } = new List<IMailItem>();
|
||||
public SynchronizationCompletedState CompletedState { get; set; }
|
||||
|
||||
public static SynchronizationResult Empty => new() { CompletedState = SynchronizationCompletedState.Success };
|
||||
|
||||
public static SynchronizationResult Completed(IEnumerable<IMailItem> downloadedMessages)
|
||||
=> new() { DownloadedMessages = downloadedMessages, CompletedState = SynchronizationCompletedState.Success };
|
||||
|
||||
public static SynchronizationResult Canceled => new() { CompletedState = SynchronizationCompletedState.Canceled };
|
||||
}
|
||||
}
|
||||
6
Wino.Core.Domain/Models/Translations/AppLanguageModel.cs
Normal file
6
Wino.Core.Domain/Models/Translations/AppLanguageModel.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Translations
|
||||
{
|
||||
public record AppLanguageModel(AppLanguage Language, string DisplayName);
|
||||
}
|
||||
Reference in New Issue
Block a user