Revert "File scoped namespaces"

This reverts commit d31d8f574e.
This commit is contained in:
Burak Kaan Köse
2025-02-16 11:43:30 +01:00
parent d31d8f574e
commit cf9869b71e
617 changed files with 32097 additions and 31478 deletions

View File

@@ -2,23 +2,24 @@
using SQLite;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Domain.Entities.Calendar;
public class AccountCalendar : IAccountCalendar
namespace Wino.Core.Domain.Entities.Calendar
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid AccountId { get; set; }
public string RemoteCalendarId { get; set; }
public string SynchronizationDeltaToken { get; set; }
public string Name { get; set; }
public bool IsPrimary { get; set; }
public bool IsExtended { get; set; } = true;
public class AccountCalendar : IAccountCalendar
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid AccountId { get; set; }
public string RemoteCalendarId { get; set; }
public string SynchronizationDeltaToken { get; set; }
public string Name { get; set; }
public bool IsPrimary { get; set; }
public bool IsExtended { get; set; } = true;
/// <summary>
/// Unused for now.
/// </summary>
public string TextColorHex { get; set; }
public string BackgroundColorHex { get; set; }
public string TimeZone { get; set; }
/// <summary>
/// Unused for now.
/// </summary>
public string TextColorHex { get; set; }
public string BackgroundColorHex { get; set; }
public string TimeZone { get; set; }
}
}

View File

@@ -2,18 +2,19 @@
using SQLite;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Entities.Calendar;
// TODO: Connect to Contact store with Wino People.
public class CalendarEventAttendee
namespace Wino.Core.Domain.Entities.Calendar
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid CalendarItemId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public AttendeeStatus AttendenceStatus { get; set; }
public bool IsOrganizer { get; set; }
public bool IsOptionalAttendee { get; set; }
public string Comment { get; set; }
// TODO: Connect to Contact store with Wino People.
public class CalendarEventAttendee
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid CalendarItemId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public AttendeeStatus AttendenceStatus { get; set; }
public bool IsOrganizer { get; set; }
public bool IsOptionalAttendee { get; set; }
public string Comment { get; set; }
}
}

View File

@@ -5,175 +5,176 @@ using SQLite;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
namespace Wino.Core.Domain.Entities.Calendar;
[DebuggerDisplay("{Title} ({StartDate} - {EndDate})")]
public class CalendarItem : ICalendarItem
namespace Wino.Core.Domain.Entities.Calendar
{
[PrimaryKey]
public Guid Id { get; set; }
public string RemoteEventId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Location { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate
[DebuggerDisplay("{Title} ({StartDate} - {EndDate})")]
public class CalendarItem : ICalendarItem
{
get
[PrimaryKey]
public Guid Id { get; set; }
public string RemoteEventId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Location { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate
{
return StartDate.AddSeconds(DurationInSeconds);
get
{
return StartDate.AddSeconds(DurationInSeconds);
}
}
}
public TimeSpan StartDateOffset { get; set; }
public TimeSpan EndDateOffset { get; set; }
public TimeSpan StartDateOffset { get; set; }
public TimeSpan EndDateOffset { get; set; }
private ITimePeriod _period;
public ITimePeriod Period
{
get
private ITimePeriod _period;
public ITimePeriod Period
{
_period ??= new TimeRange(StartDate, EndDate);
get
{
_period ??= new TimeRange(StartDate, EndDate);
return _period;
return _period;
}
}
}
/// <summary>
/// Events that starts at midnight and ends at midnight are considered all-day events.
/// </summary>
public bool IsAllDayEvent
{
get
/// <summary>
/// Events that starts at midnight and ends at midnight are considered all-day events.
/// </summary>
public bool IsAllDayEvent
{
return
StartDate.TimeOfDay == TimeSpan.Zero &&
EndDate.TimeOfDay == TimeSpan.Zero;
get
{
return
StartDate.TimeOfDay == TimeSpan.Zero &&
EndDate.TimeOfDay == TimeSpan.Zero;
}
}
}
/// <summary>
/// Events that are either an exceptional instance of a recurring event or occurrences.
/// IsOccurrence is used to display occurrence instances of parent recurring events.
/// IsOccurrence == false && IsRecurringChild == true => exceptional single instance.
/// </summary>
public bool IsRecurringChild
{
get
/// <summary>
/// Events that are either an exceptional instance of a recurring event or occurrences.
/// IsOccurrence is used to display occurrence instances of parent recurring events.
/// IsOccurrence == false && IsRecurringChild == true => exceptional single instance.
/// </summary>
public bool IsRecurringChild
{
return RecurringCalendarItemId != null;
get
{
return RecurringCalendarItemId != null;
}
}
}
/// <summary>
/// Events that are either an exceptional instance of a recurring event or occurrences.
/// </summary>
public bool IsRecurringEvent => IsRecurringChild || IsRecurringParent;
/// <summary>
/// Events that are either an exceptional instance of a recurring event or occurrences.
/// </summary>
public bool IsRecurringEvent => IsRecurringChild || IsRecurringParent;
/// <summary>
/// Events that are the master event definition of recurrence events.
/// </summary>
public bool IsRecurringParent
{
get
/// <summary>
/// Events that are the master event definition of recurrence events.
/// </summary>
public bool IsRecurringParent
{
return !string.IsNullOrEmpty(Recurrence) && RecurringCalendarItemId == null;
get
{
return !string.IsNullOrEmpty(Recurrence) && RecurringCalendarItemId == null;
}
}
}
/// <summary>
/// Events that are not all-day events and last more than one day are considered multi-day events.
/// </summary>
public bool IsMultiDayEvent
{
get
/// <summary>
/// Events that are not all-day events and last more than one day are considered multi-day events.
/// </summary>
public bool IsMultiDayEvent
{
return Period.Duration.TotalDays >= 1 && !IsAllDayEvent;
get
{
return Period.Duration.TotalDays >= 1 && !IsAllDayEvent;
}
}
}
public double DurationInSeconds { get; set; }
public string Recurrence { get; set; }
public double DurationInSeconds { get; set; }
public string Recurrence { get; set; }
public string OrganizerDisplayName { get; set; }
public string OrganizerEmail { get; set; }
public string OrganizerDisplayName { get; set; }
public string OrganizerEmail { get; set; }
/// <summary>
/// The id of the parent calendar item of the recurring event.
/// Exceptional instances are stored as a separate calendar item.
/// This makes the calendar item a child of the recurring event.
/// </summary>
public Guid? RecurringCalendarItemId { get; set; }
/// <summary>
/// The id of the parent calendar item of the recurring event.
/// Exceptional instances are stored as a separate calendar item.
/// This makes the calendar item a child of the recurring event.
/// </summary>
public Guid? RecurringCalendarItemId { get; set; }
/// <summary>
/// Indicates read-only events. Default is false.
/// </summary>
public bool IsLocked { get; set; }
/// <summary>
/// Indicates read-only events. Default is false.
/// </summary>
public bool IsLocked { get; set; }
/// <summary>
/// Hidden events must not be displayed to the user.
/// This usually happens when a child instance of recurring parent is cancelled after creation.
/// </summary>
public bool IsHidden { get; set; }
/// <summary>
/// Hidden events must not be displayed to the user.
/// This usually happens when a child instance of recurring parent is cancelled after creation.
/// </summary>
public bool IsHidden { get; set; }
// TODO
public string CustomEventColorHex { get; set; }
public string HtmlLink { get; set; }
public CalendarItemStatus Status { get; set; }
public CalendarItemVisibility Visibility { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
public Guid CalendarId { get; set; }
// TODO
public string CustomEventColorHex { get; set; }
public string HtmlLink { get; set; }
public CalendarItemStatus Status { get; set; }
public CalendarItemVisibility Visibility { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset UpdatedAt { get; set; }
public Guid CalendarId { get; set; }
[Ignore]
public IAccountCalendar AssignedCalendar { get; set; }
[Ignore]
public IAccountCalendar AssignedCalendar { get; set; }
/// <summary>
/// Whether this item does not really exist in the database or not.
/// These are used to display occurrence instances of parent recurring events.
/// </summary>
[Ignore]
public bool IsOccurrence { get; set; }
/// <summary>
/// Whether this item does not really exist in the database or not.
/// These are used to display occurrence instances of parent recurring events.
/// </summary>
[Ignore]
public bool IsOccurrence { get; set; }
/// <summary>
/// Id to load information related to this event.
/// Occurrences tracked by the parent recurring event if they are not exceptional instances.
/// Recurring children here are exceptional instances. They have their own info in the database including Id.
/// </summary>
public Guid EventTrackingId => IsOccurrence ? RecurringCalendarItemId.Value : Id;
/// <summary>
/// Id to load information related to this event.
/// Occurrences tracked by the parent recurring event if they are not exceptional instances.
/// Recurring children here are exceptional instances. They have their own info in the database including Id.
/// </summary>
public Guid EventTrackingId => IsOccurrence ? RecurringCalendarItemId.Value : Id;
public CalendarItem CreateRecurrence(DateTime startDate, double durationInSeconds)
{
// Create a copy with the new start date and duration
return new CalendarItem
public CalendarItem CreateRecurrence(DateTime startDate, double durationInSeconds)
{
Id = Guid.NewGuid(),
Title = Title,
Description = Description,
Location = Location,
StartDate = startDate,
DurationInSeconds = durationInSeconds,
Recurrence = Recurrence,
OrganizerDisplayName = OrganizerDisplayName,
OrganizerEmail = OrganizerEmail,
RecurringCalendarItemId = Id,
AssignedCalendar = AssignedCalendar,
CalendarId = CalendarId,
CreatedAt = CreatedAt,
UpdatedAt = UpdatedAt,
Visibility = Visibility,
Status = Status,
CustomEventColorHex = CustomEventColorHex,
HtmlLink = HtmlLink,
StartDateOffset = StartDateOffset,
EndDateOffset = EndDateOffset,
RemoteEventId = RemoteEventId,
IsHidden = IsHidden,
IsLocked = IsLocked,
IsOccurrence = true
};
// Create a copy with the new start date and duration
return new CalendarItem
{
Id = Guid.NewGuid(),
Title = Title,
Description = Description,
Location = Location,
StartDate = startDate,
DurationInSeconds = durationInSeconds,
Recurrence = Recurrence,
OrganizerDisplayName = OrganizerDisplayName,
OrganizerEmail = OrganizerEmail,
RecurringCalendarItemId = Id,
AssignedCalendar = AssignedCalendar,
CalendarId = CalendarId,
CreatedAt = CreatedAt,
UpdatedAt = UpdatedAt,
Visibility = Visibility,
Status = Status,
CustomEventColorHex = CustomEventColorHex,
HtmlLink = HtmlLink,
StartDateOffset = StartDateOffset,
EndDateOffset = EndDateOffset,
RemoteEventId = RemoteEventId,
IsHidden = IsHidden,
IsLocked = IsLocked,
IsOccurrence = true
};
}
}
}

View File

@@ -2,14 +2,15 @@
using SQLite;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Entities.Calendar;
public class Reminder
namespace Wino.Core.Domain.Entities.Calendar
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid CalendarItemId { get; set; }
public class Reminder
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid CalendarItemId { get; set; }
public DateTimeOffset ReminderTime { get; set; }
public CalendarItemReminderType ReminderType { get; set; }
public DateTimeOffset ReminderTime { get; set; }
public CalendarItemReminderType ReminderType { get; set; }
}
}

View File

@@ -1,16 +1,17 @@
using System;
using SQLite;
namespace Wino.Core.Domain.Entities.Mail;
public class AccountSignature
namespace Wino.Core.Domain.Entities.Mail
{
[PrimaryKey]
public Guid Id { get; set; }
public class AccountSignature
{
[PrimaryKey]
public Guid Id { get; set; }
public string Name { get; set; }
public string Name { get; set; }
public string HtmlBody { get; set; }
public string HtmlBody { get; set; }
public Guid MailAccountId { get; set; }
public Guid MailAccountId { get; set; }
}
}

View File

@@ -1,62 +1,63 @@
using System;
using SQLite;
namespace Wino.Core.Domain.Entities.Mail;
public class RemoteAccountAlias
namespace Wino.Core.Domain.Entities.Mail
{
/// <summary>
/// Display address of the alias.
/// </summary>
public string AliasAddress { get; set; }
public class RemoteAccountAlias
{
/// <summary>
/// Display address of the alias.
/// </summary>
public string AliasAddress { get; set; }
/// <summary>
/// Address to be included in Reply-To header when alias is used for sending messages.
/// </summary>
public string ReplyToAddress { get; set; }
/// <summary>
/// Address to be included in Reply-To header when alias is used for sending messages.
/// </summary>
public string ReplyToAddress { get; set; }
/// <summary>
/// Whether this alias is the primary alias for the account.
/// </summary>
public bool IsPrimary { get; set; }
/// <summary>
/// Whether this alias is the primary alias for the account.
/// </summary>
public bool IsPrimary { get; set; }
/// <summary>
/// Whether the alias is verified by the server.
/// Only Gmail aliases are verified for now.
/// Non-verified alias messages might be rejected by SMTP server.
/// </summary>
public bool IsVerified { get; set; }
/// <summary>
/// Whether the alias is verified by the server.
/// Only Gmail aliases are verified for now.
/// Non-verified alias messages might be rejected by SMTP server.
/// </summary>
public bool IsVerified { get; set; }
/// <summary>
/// Whether this alias is the root alias for the account.
/// Root alias means the first alias that was created for the account.
/// It can't be deleted or changed.
/// </summary>
public bool IsRootAlias { get; set; }
/// <summary>
/// Whether this alias is the root alias for the account.
/// Root alias means the first alias that was created for the account.
/// It can't be deleted or changed.
/// </summary>
public bool IsRootAlias { get; set; }
/// <summary>
/// Optional sender name for the alias.
/// Falls back to account's sender name if not set when preparing messages.
/// Used for Gmail only.
/// </summary>
public string AliasSenderName { get; set; }
}
public class MailAccountAlias : RemoteAccountAlias
{
/// <summary>
/// Unique Id for the alias.
/// </summary>
[PrimaryKey]
public Guid Id { get; set; }
/// <summary>
/// Account id that this alias is attached to.
/// </summary>
public Guid AccountId { get; set; }
/// <summary>
/// Root aliases can't be deleted.
/// </summary>
public bool CanDelete => !IsRootAlias;
/// <summary>
/// Optional sender name for the alias.
/// Falls back to account's sender name if not set when preparing messages.
/// Used for Gmail only.
/// </summary>
public string AliasSenderName { get; set; }
}
public class MailAccountAlias : RemoteAccountAlias
{
/// <summary>
/// Unique Id for the alias.
/// </summary>
[PrimaryKey]
public Guid Id { get; set; }
/// <summary>
/// Account id that this alias is attached to.
/// </summary>
public Guid AccountId { get; set; }
/// <summary>
/// Root aliases can't be deleted.
/// </summary>
public bool CanDelete => !IsRootAlias;
}
}

View File

@@ -5,152 +5,153 @@ using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.MailItem;
namespace Wino.Core.Domain.Entities.Mail;
/// <summary>
/// Summary of the parsed MIME messages.
/// Wino will do non-network operations on this table and others from the original MIME.
/// </summary>
public class MailCopy : IMailItem
namespace Wino.Core.Domain.Entities.Mail
{
/// <summary>
/// Unique Id of the mail.
/// Summary of the parsed MIME messages.
/// Wino will do non-network operations on this table and others from the original MIME.
/// </summary>
[PrimaryKey]
public Guid UniqueId { get; set; }
public class MailCopy : IMailItem
{
/// <summary>
/// Unique Id of the mail.
/// </summary>
[PrimaryKey]
public Guid UniqueId { get; set; }
/// <summary>
/// Not unique id of the item. Some operations held on this Id, some on the UniqueId.
/// Same message can be in different folder. In that case UniqueId is used.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Not unique id of the item. Some operations held on this Id, some on the UniqueId.
/// Same message can be in different folder. In that case UniqueId is used.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Folder that this mail belongs to.
/// </summary>
public Guid FolderId { get; set; }
/// <summary>
/// Folder that this mail belongs to.
/// </summary>
public Guid FolderId { get; set; }
/// <summary>
/// Conversation id for the mail.
/// </summary>
public string ThreadId { get; set; }
/// <summary>
/// Conversation id for the mail.
/// </summary>
public string ThreadId { get; set; }
/// <summary>
/// MIME MessageId if exists.
/// </summary>
public string MessageId { get; set; }
/// <summary>
/// MIME MessageId if exists.
/// </summary>
public string MessageId { get; set; }
/// <summary>
/// References header from MIME
/// </summary>
public string References { get; set; }
/// <summary>
/// References header from MIME
/// </summary>
public string References { get; set; }
/// <summary>
/// In-Reply-To header from MIME
/// </summary>
public string InReplyTo { get; set; }
/// <summary>
/// In-Reply-To header from MIME
/// </summary>
public string InReplyTo { get; set; }
/// <summary>
/// Name for the sender.
/// </summary>
public string FromName { get; set; }
/// <summary>
/// Name for the sender.
/// </summary>
public string FromName { get; set; }
/// <summary>
/// Address of the sender.
/// </summary>
public string FromAddress { get; set; }
/// <summary>
/// Address of the sender.
/// </summary>
public string FromAddress { get; set; }
/// <summary>
/// Subject of the mail.
/// </summary>
public string Subject { get; set; }
/// <summary>
/// Subject of the mail.
/// </summary>
public string Subject { get; set; }
/// <summary>
/// Short preview of the content.
/// </summary>
public string PreviewText { get; set; }
/// <summary>
/// Short preview of the content.
/// </summary>
public string PreviewText { get; set; }
/// <summary>
/// Date that represents this mail has been created in provider servers.
/// Stored always in UTC.
/// </summary>
public DateTime CreationDate { get; set; }
/// <summary>
/// Date that represents this mail has been created in provider servers.
/// Stored always in UTC.
/// </summary>
public DateTime CreationDate { get; set; }
/// <summary>
/// Importance of the mail.
/// </summary>
public MailImportance Importance { get; set; }
/// <summary>
/// Importance of the mail.
/// </summary>
public MailImportance Importance { get; set; }
/// <summary>
/// Read status for the mail.
/// </summary>
public bool IsRead { get; set; }
/// <summary>
/// Read status for the mail.
/// </summary>
public bool IsRead { get; set; }
/// <summary>
/// Flag status.
/// Flagged for Outlook.
/// Important for Gmail.
/// </summary>
public bool IsFlagged { get; set; }
/// <summary>
/// Flag status.
/// Flagged for Outlook.
/// Important for Gmail.
/// </summary>
public bool IsFlagged { get; set; }
/// <summary>
/// To support Outlook.
/// Gmail doesn't use it.
/// </summary>
public bool IsFocused { get; set; }
/// <summary>
/// To support Outlook.
/// Gmail doesn't use it.
/// </summary>
public bool IsFocused { get; set; }
/// <summary>
/// Whether mail has attachments included or not.
/// </summary>
public bool HasAttachments { get; set; }
/// <summary>
/// Whether mail has attachments included or not.
/// </summary>
public bool HasAttachments { get; set; }
/// <summary>
/// Assigned draft id.
/// </summary>
public string DraftId { get; set; }
/// <summary>
/// Assigned draft id.
/// </summary>
public string DraftId { get; set; }
/// <summary>
/// Whether this mail is only created locally.
/// </summary>
[Ignore]
public bool IsLocalDraft => !string.IsNullOrEmpty(DraftId) && DraftId.StartsWith(Constants.LocalDraftStartPrefix);
/// <summary>
/// Whether this mail is only created locally.
/// </summary>
[Ignore]
public bool IsLocalDraft => !string.IsNullOrEmpty(DraftId) && DraftId.StartsWith(Constants.LocalDraftStartPrefix);
/// <summary>
/// Whether this copy is draft or not.
/// </summary>
public bool IsDraft { get; set; }
/// <summary>
/// Whether this copy is draft or not.
/// </summary>
public bool IsDraft { get; set; }
/// <summary>
/// File id that this mail is assigned to.
/// This Id is immutable. It's used to find the file in the file system.
/// Even after mapping local draft to remote draft, it will not change.
/// </summary>
public Guid FileId { get; set; }
/// <summary>
/// File id that this mail is assigned to.
/// This Id is immutable. It's used to find the file in the file system.
/// Even after mapping local draft to remote draft, it will not change.
/// </summary>
public Guid FileId { get; set; }
/// <summary>
/// Folder that this mail is assigned to.
/// Warning: This field is not populated by queries.
/// Services or View Models are responsible for populating this field.
/// </summary>
[Ignore]
public MailItemFolder AssignedFolder { get; set; }
/// <summary>
/// Folder that this mail is assigned to.
/// Warning: This field is not populated by queries.
/// Services or View Models are responsible for populating this field.
/// </summary>
[Ignore]
public MailItemFolder AssignedFolder { get; set; }
/// <summary>
/// Account that this mail is assigned to.
/// Warning: This field is not populated by queries.
/// Services or View Models are responsible for populating this field.
/// </summary>
[Ignore]
public MailAccount AssignedAccount { get; set; }
/// <summary>
/// Account that this mail is assigned to.
/// Warning: This field is not populated by queries.
/// Services or View Models are responsible for populating this field.
/// </summary>
[Ignore]
public MailAccount AssignedAccount { get; set; }
/// <summary>
/// Contact information of the sender if exists.
/// Warning: This field is not populated by queries.
/// Services or View Models are responsible for populating this field.
/// </summary>
[Ignore]
public AccountContact SenderContact { get; set; }
/// <summary>
/// Contact information of the sender if exists.
/// Warning: This field is not populated by queries.
/// Services or View Models are responsible for populating this field.
/// </summary>
[Ignore]
public AccountContact SenderContact { get; set; }
public IEnumerable<Guid> GetContainingIds() => [UniqueId];
public override string ToString() => $"{Subject} <-> {Id}";
public IEnumerable<Guid> GetContainingIds() => [UniqueId];
public override string ToString() => $"{Subject} <-> {Id}";
}
}

View File

@@ -5,70 +5,71 @@ using SQLite;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Folders;
namespace Wino.Core.Domain.Entities.Mail;
[DebuggerDisplay("{FolderName} - {SpecialFolderType}")]
public class MailItemFolder : IMailItemFolder
namespace Wino.Core.Domain.Entities.Mail
{
[PrimaryKey]
public Guid Id { get; set; }
public string RemoteFolderId { get; set; }
public string ParentRemoteFolderId { get; set; }
public Guid MailAccountId { get; set; }
public string FolderName { get; set; }
public SpecialFolderType SpecialFolderType { get; set; }
public bool IsSystemFolder { get; set; }
public bool IsSticky { get; set; }
public bool IsSynchronizationEnabled { get; set; }
public bool IsHidden { get; set; }
public bool ShowUnreadCount { get; set; }
public DateTime? LastSynchronizedDate { get; set; }
// For IMAP
public uint UidValidity { get; set; }
public long HighestModeSeq { get; set; }
/// <summary>
/// Outlook shares delta changes per-folder. Gmail is for per-account.
/// This is only used for Outlook provider.
/// </summary>
public string DeltaToken { get; set; }
// For GMail Labels
public string TextColorHex { get; set; }
public string BackgroundColorHex { get; set; }
[Ignore]
public List<IMailItemFolder> ChildFolders { get; set; } = [];
// Category and Move type folders are not valid move targets.
// These folders are virtual. They don't exist on the server.
public bool IsMoveTarget => !(SpecialFolderType == SpecialFolderType.More || SpecialFolderType == SpecialFolderType.Category);
public bool ContainsSpecialFolderType(SpecialFolderType type)
[DebuggerDisplay("{FolderName} - {SpecialFolderType}")]
public class MailItemFolder : IMailItemFolder
{
if (SpecialFolderType == type)
return true;
[PrimaryKey]
public Guid Id { get; set; }
foreach (var child in ChildFolders)
public string RemoteFolderId { get; set; }
public string ParentRemoteFolderId { get; set; }
public Guid MailAccountId { get; set; }
public string FolderName { get; set; }
public SpecialFolderType SpecialFolderType { get; set; }
public bool IsSystemFolder { get; set; }
public bool IsSticky { get; set; }
public bool IsSynchronizationEnabled { get; set; }
public bool IsHidden { get; set; }
public bool ShowUnreadCount { get; set; }
public DateTime? LastSynchronizedDate { get; set; }
// For IMAP
public uint UidValidity { get; set; }
public long HighestModeSeq { get; set; }
/// <summary>
/// Outlook shares delta changes per-folder. Gmail is for per-account.
/// This is only used for Outlook provider.
/// </summary>
public string DeltaToken { get; set; }
// For GMail Labels
public string TextColorHex { get; set; }
public string BackgroundColorHex { get; set; }
[Ignore]
public List<IMailItemFolder> ChildFolders { get; set; } = [];
// Category and Move type folders are not valid move targets.
// These folders are virtual. They don't exist on the server.
public bool IsMoveTarget => !(SpecialFolderType == SpecialFolderType.More || SpecialFolderType == SpecialFolderType.Category);
public bool ContainsSpecialFolderType(SpecialFolderType type)
{
if (child.SpecialFolderType == type)
{
if (SpecialFolderType == type)
return true;
}
else
foreach (var child in ChildFolders)
{
return child.ContainsSpecialFolderType(type);
if (child.SpecialFolderType == type)
{
return true;
}
else
{
return child.ContainsSpecialFolderType(type);
}
}
return false;
}
return false;
public static MailItemFolder CreateMoreFolder() => new MailItemFolder() { IsSticky = true, SpecialFolderType = SpecialFolderType.More, FolderName = Translator.MoreFolderNameOverride };
public static MailItemFolder CreateCategoriesFolder() => new MailItemFolder() { IsSticky = true, SpecialFolderType = SpecialFolderType.Category, FolderName = Translator.CategoriesFolderNameOverride };
public override string ToString() => FolderName;
}
public static MailItemFolder CreateMoreFolder() => new MailItemFolder() { IsSticky = true, SpecialFolderType = SpecialFolderType.More, FolderName = Translator.MoreFolderNameOverride };
public static MailItemFolder CreateCategoriesFolder() => new MailItemFolder() { IsSticky = true, SpecialFolderType = SpecialFolderType.Category, FolderName = Translator.CategoriesFolderNameOverride };
public override string ToString() => FolderName;
}

View File

@@ -1,12 +1,13 @@
using System;
using SQLite;
namespace Wino.Core.Domain.Entities.Mail;
public class MergedInbox
namespace Wino.Core.Domain.Entities.Mail
{
[PrimaryKey]
public Guid Id { get; set; }
public class MergedInbox
{
[PrimaryKey]
public Guid Id { get; set; }
public string Name { get; set; }
public string Name { get; set; }
}
}

View File

@@ -2,75 +2,76 @@
using System.Collections.Generic;
using SQLite;
namespace Wino.Core.Domain.Entities.Shared;
/// <summary>
/// Back storage for simple name-address book.
/// These values will be inserted during MIME fetch.
/// </summary>
// TODO: This can easily evolve to Contact store, just like People app in Windows 10/11.
// Do it.
public class AccountContact : IEquatable<AccountContact>
namespace Wino.Core.Domain.Entities.Shared
{
/// <summary>
/// E-mail address of the contact.
/// Back storage for simple name-address book.
/// These values will be inserted during MIME fetch.
/// </summary>
[PrimaryKey]
public string Address { get; set; }
/// <summary>
/// Display name of the contact.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Base64 encoded profile image of the contact.
/// </summary>
public string Base64ContactPicture { get; set; }
/// <summary>
/// All registered accounts have their contacts registered as root.
/// Root contacts must not be overridden by any configuration.
/// They are created on account creation.
/// </summary>
public bool IsRootContact { get; set; }
/// <summary>
/// Short display name of the contact.
/// Eather Name or Address.
/// </summary>
public string ShortDisplayName => Address == Name || string.IsNullOrWhiteSpace(Name) ? $"{Address.ToLowerInvariant()};" : $"{Name};";
public string DisplayName => Address == Name || string.IsNullOrWhiteSpace(Name) ? Address.ToLowerInvariant() : $"{Name} <{Address.ToLowerInvariant()}>";
public override bool Equals(object obj)
// TODO: This can easily evolve to Contact store, just like People app in Windows 10/11.
// Do it.
public class AccountContact : IEquatable<AccountContact>
{
return Equals(obj as AccountContact);
}
/// <summary>
/// E-mail address of the contact.
/// </summary>
[PrimaryKey]
public string Address { get; set; }
public bool Equals(AccountContact other)
{
return other is not null &&
Address == other.Address &&
Name == other.Name;
}
/// <summary>
/// Display name of the contact.
/// </summary>
public string Name { get; set; }
public override int GetHashCode()
{
int hashCode = -1717786383;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Address);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
return hashCode;
}
/// <summary>
/// Base64 encoded profile image of the contact.
/// </summary>
public string Base64ContactPicture { get; set; }
public static bool operator ==(AccountContact left, AccountContact right)
{
return EqualityComparer<AccountContact>.Default.Equals(left, right);
}
/// <summary>
/// All registered accounts have their contacts registered as root.
/// Root contacts must not be overridden by any configuration.
/// They are created on account creation.
/// </summary>
public bool IsRootContact { get; set; }
public static bool operator !=(AccountContact left, AccountContact right)
{
return !(left == right);
/// <summary>
/// Short display name of the contact.
/// Eather Name or Address.
/// </summary>
public string ShortDisplayName => Address == Name || string.IsNullOrWhiteSpace(Name) ? $"{Address.ToLowerInvariant()};" : $"{Name};";
public string DisplayName => Address == Name || string.IsNullOrWhiteSpace(Name) ? Address.ToLowerInvariant() : $"{Name} <{Address.ToLowerInvariant()}>";
public override bool Equals(object obj)
{
return Equals(obj as AccountContact);
}
public bool Equals(AccountContact other)
{
return other is not null &&
Address == other.Address &&
Name == other.Name;
}
public override int GetHashCode()
{
int hashCode = -1717786383;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Address);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
return hashCode;
}
public static bool operator ==(AccountContact left, AccountContact right)
{
return EqualityComparer<AccountContact>.Default.Equals(left, right);
}
public static bool operator !=(AccountContact left, AccountContact right)
{
return !(left == right);
}
}
}

View File

@@ -2,51 +2,52 @@
using SQLite;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Entities.Shared;
public class CustomServerInformation
namespace Wino.Core.Domain.Entities.Shared
{
[PrimaryKey]
public Guid Id { get; set; }
public class CustomServerInformation
{
[PrimaryKey]
public Guid Id { get; set; }
public Guid AccountId { get; set; }
public Guid AccountId { get; set; }
/// <summary>
/// This field is ignored. DisplayName is stored in MailAccount as SenderName from now.
/// </summary>
[Ignore]
public string DisplayName { get; set; }
public string Address { get; set; }
public string IncomingServer { get; set; }
public string IncomingServerUsername { get; set; }
public string IncomingServerPassword { get; set; }
public string IncomingServerPort { get; set; }
/// <summary>
/// This field is ignored. DisplayName is stored in MailAccount as SenderName from now.
/// </summary>
[Ignore]
public string DisplayName { get; set; }
public string Address { get; set; }
public string IncomingServer { get; set; }
public string IncomingServerUsername { get; set; }
public string IncomingServerPassword { get; set; }
public string IncomingServerPort { get; set; }
public CustomIncomingServerType IncomingServerType { get; set; }
public CustomIncomingServerType IncomingServerType { get; set; }
public string OutgoingServer { get; set; }
public string OutgoingServerPort { get; set; }
public string OutgoingServerUsername { get; set; }
public string OutgoingServerPassword { get; set; }
public string OutgoingServer { get; set; }
public string OutgoingServerPort { get; set; }
public string OutgoingServerUsername { get; set; }
public string OutgoingServerPassword { get; set; }
/// <summary>
/// useSSL True: SslOnConnect
/// useSSL False: StartTlsWhenAvailable
/// </summary>
/// <summary>
/// useSSL True: SslOnConnect
/// useSSL False: StartTlsWhenAvailable
/// </summary>
public ImapConnectionSecurity IncomingServerSocketOption { get; set; }
public ImapAuthenticationMethod IncomingAuthenticationMethod { get; set; }
public ImapConnectionSecurity IncomingServerSocketOption { get; set; }
public ImapAuthenticationMethod IncomingAuthenticationMethod { get; set; }
public ImapConnectionSecurity OutgoingServerSocketOption { get; set; }
public ImapAuthenticationMethod OutgoingAuthenticationMethod { get; set; }
public ImapConnectionSecurity OutgoingServerSocketOption { get; set; }
public ImapAuthenticationMethod OutgoingAuthenticationMethod { get; set; }
public string ProxyServer { get; set; }
public string ProxyServerPort { get; set; }
public string ProxyServer { get; set; }
public string ProxyServerPort { get; set; }
/// <summary>
/// Number of concurrent clients that can connect to the server.
/// Default is 5.
/// </summary>
public int MaxConcurrentClients { get; set; }
/// <summary>
/// Number of concurrent clients that can connect to the server.
/// Default is 5.
/// </summary>
public int MaxConcurrentClients { get; set; }
}
}

View File

@@ -3,108 +3,109 @@ using SQLite;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
namespace Wino.Core.Domain.Entities.Shared;
public class MailAccount
namespace Wino.Core.Domain.Entities.Shared
{
[PrimaryKey]
public Guid Id { get; set; }
public class MailAccount
{
[PrimaryKey]
public Guid Id { get; set; }
/// <summary>
/// Given name of the account in Wino.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Given name of the account in Wino.
/// </summary>
public string Name { get; set; }
/// <summary>
/// TODO: Display name of the authenticated user/account.
/// API integrations will query this value from the API.
/// IMAP is populated by user on setup dialog.
/// </summary>
/// <summary>
/// TODO: Display name of the authenticated user/account.
/// API integrations will query this value from the API.
/// IMAP is populated by user on setup dialog.
/// </summary>
public string SenderName { get; set; }
public string SenderName { get; set; }
/// <summary>
/// Account e-mail address.
/// </summary>
public string Address { get; set; }
/// <summary>
/// Account e-mail address.
/// </summary>
public string Address { get; set; }
/// <summary>
/// Provider type of the account. Outlook,Gmail etc...
/// </summary>
public MailProviderType ProviderType { get; set; }
/// <summary>
/// Provider type of the account. Outlook,Gmail etc...
/// </summary>
public MailProviderType ProviderType { get; set; }
/// <summary>
/// For tracking mail change delta.
/// Gmail : historyId
/// Outlook: deltaToken
/// </summary>
public string SynchronizationDeltaIdentifier { get; set; }
/// <summary>
/// For tracking mail change delta.
/// Gmail : historyId
/// Outlook: deltaToken
/// </summary>
public string SynchronizationDeltaIdentifier { get; set; }
/// <summary>
/// For tracking calendar change delta.
/// Gmail: It's per-calendar, so unused.
/// Outlook: deltaLink
/// </summary>
public string CalendarSynchronizationDeltaIdentifier { get; set; }
/// <summary>
/// For tracking calendar change delta.
/// Gmail: It's per-calendar, so unused.
/// Outlook: deltaLink
/// </summary>
public string CalendarSynchronizationDeltaIdentifier { get; set; }
/// <summary>
/// TODO: Gets or sets the custom account identifier color in hex.
/// </summary>
public string AccountColorHex { get; set; }
/// <summary>
/// TODO: Gets or sets the custom account identifier color in hex.
/// </summary>
public string AccountColorHex { get; set; }
/// <summary>
/// Base64 encoded profile picture of the account.
/// </summary>
public string Base64ProfilePictureData { get; set; }
/// <summary>
/// Base64 encoded profile picture of the account.
/// </summary>
public string Base64ProfilePictureData { get; set; }
/// <summary>
/// Gets or sets the listing order of the account in the accounts list.
/// </summary>
public int Order { get; set; }
/// <summary>
/// Gets or sets the listing order of the account in the accounts list.
/// </summary>
public int Order { get; set; }
/// <summary>
/// Gets or sets whether the account has any reason for an interactive user action to fix continue operating.
/// </summary>
public AccountAttentionReason AttentionReason { get; set; }
/// <summary>
/// Gets or sets whether the account has any reason for an interactive user action to fix continue operating.
/// </summary>
public AccountAttentionReason AttentionReason { get; set; }
/// <summary>
/// Gets or sets the id of the merged inbox this account belongs to.
/// </summary>
public Guid? MergedInboxId { get; set; }
/// <summary>
/// Gets or sets the id of the merged inbox this account belongs to.
/// </summary>
public Guid? MergedInboxId { get; set; }
/// <summary>
/// Gets or sets the additional IMAP provider assignment for the account.
/// Providers that use IMAP as a synchronizer but have special requirements.
/// </summary>
public SpecialImapProvider SpecialImapProvider { get; set; }
/// <summary>
/// Gets or sets the additional IMAP provider assignment for the account.
/// Providers that use IMAP as a synchronizer but have special requirements.
/// </summary>
public SpecialImapProvider SpecialImapProvider { get; set; }
/// <summary>
/// Contains the merged inbox this account belongs to.
/// Ignored for all SQLite operations.
/// </summary>
[Ignore]
public MergedInbox MergedInbox { get; set; }
/// <summary>
/// Contains the merged inbox this account belongs to.
/// Ignored for all SQLite operations.
/// </summary>
[Ignore]
public MergedInbox MergedInbox { get; set; }
/// <summary>
/// Populated only when account has custom server information.
/// </summary>
/// <summary>
/// Populated only when account has custom server information.
/// </summary>
[Ignore]
public CustomServerInformation ServerInformation { get; set; }
[Ignore]
public CustomServerInformation ServerInformation { get; set; }
/// <summary>
/// Account preferences.
/// </summary>
[Ignore]
public MailAccountPreferences Preferences { get; set; }
/// <summary>
/// Account preferences.
/// </summary>
[Ignore]
public MailAccountPreferences Preferences { get; set; }
/// <summary>
/// Gets whether the account can perform ProfileInformation sync type.
/// </summary>
public bool IsProfileInfoSyncSupported => ProviderType == MailProviderType.Outlook || ProviderType == MailProviderType.Gmail;
/// <summary>
/// Gets whether the account can perform ProfileInformation sync type.
/// </summary>
public bool IsProfileInfoSyncSupported => ProviderType == MailProviderType.Outlook || ProviderType == MailProviderType.Gmail;
/// <summary>
/// Gets whether the account can perform AliasInformation sync type.
/// </summary>
public bool IsAliasSyncSupported => ProviderType == MailProviderType.Gmail;
/// <summary>
/// Gets whether the account can perform AliasInformation sync type.
/// </summary>
public bool IsAliasSyncSupported => ProviderType == MailProviderType.Gmail;
}
}

View File

@@ -1,53 +1,54 @@
using System;
using SQLite;
namespace Wino.Core.Domain.Entities.Shared;
public class MailAccountPreferences
namespace Wino.Core.Domain.Entities.Shared
{
[PrimaryKey]
public Guid Id { get; set; }
public class MailAccountPreferences
{
[PrimaryKey]
public Guid Id { get; set; }
/// <summary>
/// Id of the account in MailAccount table.
/// </summary>
public Guid AccountId { get; set; }
/// <summary>
/// Id of the account in MailAccount table.
/// </summary>
public Guid AccountId { get; set; }
/// <summary>
/// Gets or sets whether sent draft messages should be appended to the sent folder.
/// Some IMAP servers do this automatically, some don't.
/// It's disabled by default.
/// </summary>
public bool ShouldAppendMessagesToSentFolder { get; set; }
/// <summary>
/// Gets or sets whether sent draft messages should be appended to the sent folder.
/// Some IMAP servers do this automatically, some don't.
/// It's disabled by default.
/// </summary>
public bool ShouldAppendMessagesToSentFolder { get; set; }
/// <summary>
/// Gets or sets whether the notifications are enabled for the account.
/// </summary>
public bool IsNotificationsEnabled { get; set; }
/// <summary>
/// Gets or sets whether the notifications are enabled for the account.
/// </summary>
public bool IsNotificationsEnabled { get; set; }
/// <summary>
/// Gets or sets whether the account has Focused inbox support.
/// Null if the account provider type doesn't support Focused inbox.
/// </summary>
public bool? IsFocusedInboxEnabled { get; set; }
/// <summary>
/// Gets or sets whether the account has Focused inbox support.
/// Null if the account provider type doesn't support Focused inbox.
/// </summary>
public bool? IsFocusedInboxEnabled { get; set; }
/// <summary>
/// Gets or sets whether signature should be appended automatically.
/// </summary>
public bool IsSignatureEnabled { get; set; }
/// <summary>
/// Gets or sets whether signature should be appended automatically.
/// </summary>
public bool IsSignatureEnabled { get; set; }
/// <summary>
/// Gets or sets whether this account's unread items should be included in taskbar badge.
/// </summary>
public bool IsTaskbarBadgeEnabled { get; set; } = true;
/// <summary>
/// Gets or sets whether this account's unread items should be included in taskbar badge.
/// </summary>
public bool IsTaskbarBadgeEnabled { get; set; } = true;
/// <summary>
/// Gets or sets signature for new messages. Null if signature is not needed.
/// </summary>
public Guid? SignatureIdForNewMessages { get; set; }
/// <summary>
/// Gets or sets signature for new messages. Null if signature is not needed.
/// </summary>
public Guid? SignatureIdForNewMessages { get; set; }
/// <summary>
/// Gets or sets signature for following messages. Null if signature is not needed.
/// </summary>
public Guid? SignatureIdForFollowingMessages { get; set; }
/// <summary>
/// Gets or sets signature for following messages. Null if signature is not needed.
/// </summary>
public Guid? SignatureIdForFollowingMessages { get; set; }
}
}