Initial commit.
This commit is contained in:
26
Wino.Mail.ViewModels/Data/AccountProviderDetailViewModel.cs
Normal file
26
Wino.Mail.ViewModels/Data/AccountProviderDetailViewModel.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
public partial class AccountProviderDetailViewModel : ObservableObject, IAccountProviderDetailViewModel
|
||||
{
|
||||
|
||||
[ObservableProperty]
|
||||
private MailAccount account;
|
||||
|
||||
public IProviderDetail ProviderDetail { get; set; }
|
||||
|
||||
public Guid StartupEntityId => Account.Id;
|
||||
|
||||
public string StartupEntityTitle => Account.Name;
|
||||
|
||||
public AccountProviderDetailViewModel(IProviderDetail providerDetail, MailAccount account)
|
||||
{
|
||||
ProviderDetail = providerDetail;
|
||||
Account = account;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Wino.Mail.ViewModels/Data/AppColorViewModel.cs
Normal file
23
Wino.Mail.ViewModels/Data/AppColorViewModel.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
public class AppColorViewModel : ObservableObject
|
||||
{
|
||||
private string _hex;
|
||||
|
||||
public string Hex
|
||||
{
|
||||
get => _hex;
|
||||
set => SetProperty(ref _hex, value);
|
||||
}
|
||||
|
||||
public bool IsAccentColor { get; }
|
||||
|
||||
public AppColorViewModel(string hex, bool isAccentColor = false)
|
||||
{
|
||||
IsAccentColor = isAccentColor;
|
||||
Hex = hex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Messages.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
public class BreadcrumbNavigationItemViewModel : ObservableObject
|
||||
{
|
||||
public BreadcrumbNavigationRequested Request { get; set; }
|
||||
|
||||
public BreadcrumbNavigationItemViewModel(BreadcrumbNavigationRequested request, bool isActive)
|
||||
{
|
||||
Request = request;
|
||||
Title = request.PageTitle;
|
||||
|
||||
this.isActive = isActive;
|
||||
}
|
||||
|
||||
private string title;
|
||||
public string Title
|
||||
{
|
||||
get => title;
|
||||
set => SetProperty(ref title, value);
|
||||
}
|
||||
|
||||
private bool isActive;
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => isActive;
|
||||
set => SetProperty(ref isActive, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Wino.Mail.ViewModels/Data/FolderPivotViewModel.cs
Normal file
33
Wino.Mail.ViewModels/Data/FolderPivotViewModel.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
[DebuggerDisplay("{FolderTitle}")]
|
||||
public partial class FolderPivotViewModel : ObservableObject
|
||||
{
|
||||
public bool? IsFocused { get; set; }
|
||||
public string FolderTitle { get; }
|
||||
|
||||
public bool ShouldDisplaySelectedItemCount => IsExtendedMode ? SelectedItemCount > 1 : SelectedItemCount > 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isSelected;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShouldDisplaySelectedItemCount))]
|
||||
private int selectedItemCount;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(ShouldDisplaySelectedItemCount))]
|
||||
private bool isExtendedMode = true;
|
||||
|
||||
public FolderPivotViewModel(string folderName, bool? isFocused)
|
||||
{
|
||||
IsFocused = isFocused;
|
||||
|
||||
FolderTitle = IsFocused == null ? folderName : (IsFocused == true ? Translator.Focused : Translator.Other);
|
||||
}
|
||||
}
|
||||
}
|
||||
100
Wino.Mail.ViewModels/Data/MailAttachmentViewModel.cs
Normal file
100
Wino.Mail.ViewModels/Data/MailAttachmentViewModel.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System.IO;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Extensions;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
public class MailAttachmentViewModel : ObservableObject
|
||||
{
|
||||
private bool isBusy;
|
||||
private readonly MimePart _mimePart;
|
||||
|
||||
public MailAttachmentType AttachmentType { get; }
|
||||
public string FileName { get; }
|
||||
public string FilePath { get; set; }
|
||||
public string ReadableSize { get; }
|
||||
public byte[] Content { get; set; }
|
||||
|
||||
public IMimeContent MimeContent => _mimePart.Content;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether attachment is busy with opening or saving etc.
|
||||
/// </summary>
|
||||
public bool IsBusy
|
||||
{
|
||||
get => isBusy;
|
||||
set => SetProperty(ref isBusy, value);
|
||||
}
|
||||
|
||||
public MailAttachmentViewModel(MimePart mimePart)
|
||||
{
|
||||
_mimePart = mimePart;
|
||||
|
||||
var array = new byte[_mimePart.Content.Stream.Length];
|
||||
_mimePart.Content.Stream.Read(array, 0, (int)_mimePart.Content.Stream.Length);
|
||||
|
||||
Content = array;
|
||||
|
||||
FileName = mimePart.FileName;
|
||||
ReadableSize = mimePart.Content.Stream.Length.GetBytesReadable();
|
||||
|
||||
var extension = Path.GetExtension(FileName);
|
||||
AttachmentType = GetAttachmentType(extension);
|
||||
}
|
||||
|
||||
public MailAttachmentViewModel(string fullFilePath, byte[] content)
|
||||
{
|
||||
Content = content;
|
||||
|
||||
FileName = Path.GetFileName(fullFilePath);
|
||||
FilePath = fullFilePath;
|
||||
|
||||
ReadableSize = ((long)content.Length).GetBytesReadable();
|
||||
|
||||
var extension = Path.GetExtension(FileName);
|
||||
AttachmentType = GetAttachmentType(extension);
|
||||
}
|
||||
|
||||
public MailAttachmentType GetAttachmentType(string mediaSubtype)
|
||||
{
|
||||
if (string.IsNullOrEmpty(mediaSubtype))
|
||||
return MailAttachmentType.None;
|
||||
|
||||
switch (mediaSubtype.ToLower())
|
||||
{
|
||||
case ".exe":
|
||||
return MailAttachmentType.Executable;
|
||||
case ".rar":
|
||||
return MailAttachmentType.RarArchive;
|
||||
case ".zip":
|
||||
return MailAttachmentType.Archive;
|
||||
case ".ogg":
|
||||
case ".mp3":
|
||||
case ".wav":
|
||||
case ".aac":
|
||||
case ".alac":
|
||||
return MailAttachmentType.Audio;
|
||||
case ".mp4":
|
||||
case ".wmv":
|
||||
case ".avi":
|
||||
case ".flv":
|
||||
return MailAttachmentType.Video;
|
||||
case ".pdf":
|
||||
return MailAttachmentType.PDF;
|
||||
case ".htm":
|
||||
case ".html":
|
||||
return MailAttachmentType.HTML;
|
||||
case ".png":
|
||||
case ".jpg":
|
||||
case ".jpeg":
|
||||
case ".gif":
|
||||
case ".jiff":
|
||||
return MailAttachmentType.Image;
|
||||
default:
|
||||
return MailAttachmentType.Other;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Wino.Mail.ViewModels/Data/MailItemContainer.cs
Normal file
20
Wino.Mail.ViewModels/Data/MailItemContainer.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
public class MailItemContainer
|
||||
{
|
||||
public MailItemViewModel ItemViewModel { get; set; }
|
||||
public ThreadMailItemViewModel ThreadViewModel { get; set; }
|
||||
|
||||
public MailItemContainer(MailItemViewModel itemViewModel, ThreadMailItemViewModel threadViewModel) : this(itemViewModel)
|
||||
{
|
||||
ThreadViewModel = threadViewModel ?? throw new ArgumentNullException(nameof(threadViewModel));
|
||||
}
|
||||
|
||||
public MailItemContainer(MailItemViewModel itemViewModel)
|
||||
{
|
||||
ItemViewModel = itemViewModel ?? throw new ArgumentNullException(nameof(itemViewModel));
|
||||
}
|
||||
}
|
||||
}
|
||||
106
Wino.Mail.ViewModels/Data/MailItemViewModel.cs
Normal file
106
Wino.Mail.ViewModels/Data/MailItemViewModel.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Single view model for IMailItem representation.
|
||||
/// </summary>
|
||||
public partial class MailItemViewModel(MailCopy mailCopy) : ObservableObject, IMailItem
|
||||
{
|
||||
public MailCopy MailCopy { get; private set; } = mailCopy;
|
||||
|
||||
public bool IsLocalDraft => !string.IsNullOrEmpty(DraftId) && DraftId.StartsWith(Constants.LocalDraftStartPrefix);
|
||||
|
||||
public Guid UniqueId => ((IMailItem)MailCopy).UniqueId;
|
||||
public string ThreadId => ((IMailItem)MailCopy).ThreadId;
|
||||
public string MessageId => ((IMailItem)MailCopy).MessageId;
|
||||
public string FromName => ((IMailItem)MailCopy).FromName ?? FromAddress;
|
||||
public DateTime CreationDate => ((IMailItem)MailCopy).CreationDate;
|
||||
public string FromAddress => ((IMailItem)MailCopy).FromAddress;
|
||||
public bool HasAttachments => ((IMailItem)MailCopy).HasAttachments;
|
||||
public string References => ((IMailItem)MailCopy).References;
|
||||
public string InReplyTo => ((IMailItem)MailCopy).InReplyTo;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isCustomFocused;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool isSelected;
|
||||
|
||||
public bool IsFlagged
|
||||
{
|
||||
get => MailCopy.IsFlagged;
|
||||
set => SetProperty(MailCopy.IsFlagged, value, MailCopy, (u, n) => u.IsFlagged = n);
|
||||
}
|
||||
|
||||
public bool IsFocused
|
||||
{
|
||||
get => MailCopy.IsFocused;
|
||||
set => SetProperty(MailCopy.IsFocused, value, MailCopy, (u, n) => u.IsFocused = n);
|
||||
}
|
||||
|
||||
public bool IsRead
|
||||
{
|
||||
get => MailCopy.IsRead;
|
||||
set => SetProperty(MailCopy.IsRead, value, MailCopy, (u, n) => u.IsRead = n);
|
||||
}
|
||||
|
||||
public bool IsDraft
|
||||
{
|
||||
get => MailCopy.IsDraft;
|
||||
set => SetProperty(MailCopy.IsDraft, value, MailCopy, (u, n) => u.IsDraft = n);
|
||||
}
|
||||
|
||||
public string DraftId
|
||||
{
|
||||
get => MailCopy.DraftId;
|
||||
set => SetProperty(MailCopy.DraftId, value, MailCopy, (u, n) => u.DraftId = n);
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get => MailCopy.Id;
|
||||
set => SetProperty(MailCopy.Id, value, MailCopy, (u, n) => u.Id = n);
|
||||
}
|
||||
|
||||
public string Subject
|
||||
{
|
||||
get => MailCopy.Subject;
|
||||
set => SetProperty(MailCopy.Subject, value, MailCopy, (u, n) => u.Subject = n);
|
||||
}
|
||||
|
||||
public string PreviewText
|
||||
{
|
||||
get => MailCopy.PreviewText;
|
||||
set => SetProperty(MailCopy.PreviewText, value, MailCopy, (u, n) => u.PreviewText = n);
|
||||
}
|
||||
|
||||
public MailItemFolder AssignedFolder => ((IMailItem)MailCopy).AssignedFolder;
|
||||
|
||||
public MailAccount AssignedAccount => ((IMailItem)MailCopy).AssignedAccount;
|
||||
|
||||
public Guid FileId => ((IMailItem)MailCopy).FileId;
|
||||
|
||||
public void Update(MailCopy updatedMailItem)
|
||||
{
|
||||
MailCopy = updatedMailItem;
|
||||
|
||||
// DEBUG
|
||||
//if (updatedMailItem.AssignedAccount == null || updatedMailItem.AssignedFolder == null)
|
||||
// throw new Exception("Assigned account or folder is null.");
|
||||
|
||||
OnPropertyChanged(nameof(IsRead));
|
||||
OnPropertyChanged(nameof(IsFocused));
|
||||
OnPropertyChanged(nameof(IsFlagged));
|
||||
OnPropertyChanged(nameof(IsDraft));
|
||||
OnPropertyChanged(nameof(DraftId));
|
||||
OnPropertyChanged(nameof(Subject));
|
||||
OnPropertyChanged(nameof(PreviewText));
|
||||
OnPropertyChanged(nameof(IsLocalDraft));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
public partial class MergedAccountProviderDetailViewModel : ObservableObject, IAccountProviderDetailViewModel
|
||||
{
|
||||
public List<AccountProviderDetailViewModel> HoldingAccounts { get; }
|
||||
public MergedInbox MergedInbox { get; }
|
||||
|
||||
public string AccountAddresses => string.Join(", ", HoldingAccounts.Select(a => a.Account.Address));
|
||||
|
||||
public Guid StartupEntityId => MergedInbox.Id;
|
||||
|
||||
public string StartupEntityTitle => MergedInbox.Name;
|
||||
|
||||
public MergedAccountProviderDetailViewModel(MergedInbox mergedInbox, List<AccountProviderDetailViewModel> holdingAccounts)
|
||||
{
|
||||
MergedInbox = mergedInbox;
|
||||
HoldingAccounts = holdingAccounts;
|
||||
}
|
||||
}
|
||||
}
|
||||
127
Wino.Mail.ViewModels/Data/ThreadMailItemViewModel.cs
Normal file
127
Wino.Mail.ViewModels/Data/ThreadMailItemViewModel.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Thread mail item (multiple IMailItem) view model representation.
|
||||
/// </summary>
|
||||
public class ThreadMailItemViewModel : ObservableObject, IMailItemThread, IComparable<string>, IComparable<DateTime>
|
||||
{
|
||||
public ObservableCollection<IMailItem> ThreadItems => ((IMailItemThread)_threadMailItem).ThreadItems;
|
||||
|
||||
private readonly ThreadMailItem _threadMailItem;
|
||||
|
||||
private bool isThreadExpanded;
|
||||
public bool IsThreadExpanded
|
||||
{
|
||||
get => isThreadExpanded;
|
||||
set => SetProperty(ref isThreadExpanded, value);
|
||||
}
|
||||
|
||||
public ThreadMailItemViewModel(ThreadMailItem threadMailItem)
|
||||
{
|
||||
_threadMailItem = new ThreadMailItem();
|
||||
|
||||
// Local copies
|
||||
foreach (var item in threadMailItem.ThreadItems)
|
||||
{
|
||||
AddMailItemViewModel(item);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<MailCopy> GetMailCopies()
|
||||
=> ThreadItems.OfType<MailItemViewModel>().Select(a => a.MailCopy);
|
||||
|
||||
public void AddMailItemViewModel(IMailItem mailItem)
|
||||
{
|
||||
if (mailItem == null) return;
|
||||
|
||||
if (mailItem is MailCopy mailCopy)
|
||||
_threadMailItem.AddThreadItem(new MailItemViewModel(mailCopy));
|
||||
else if (mailItem is MailItemViewModel mailItemViewModel)
|
||||
_threadMailItem.AddThreadItem(mailItemViewModel);
|
||||
else
|
||||
Debugger.Break();
|
||||
}
|
||||
|
||||
public bool HasUniqueId(Guid uniqueMailId)
|
||||
=> ThreadItems.Any(a => a.UniqueId == uniqueMailId);
|
||||
|
||||
public IMailItem GetItemById(Guid uniqueMailId)
|
||||
=> ThreadItems.FirstOrDefault(a => a.UniqueId == uniqueMailId);
|
||||
|
||||
public void RemoveCopyItem(IMailItem item)
|
||||
{
|
||||
MailCopy copyToRemove = null;
|
||||
|
||||
if (item is MailItemViewModel mailItemViewModel)
|
||||
copyToRemove = mailItemViewModel.MailCopy;
|
||||
else if (item is MailCopy copyItem)
|
||||
copyToRemove = copyItem;
|
||||
|
||||
var existedItem = ThreadItems.FirstOrDefault(a => a.Id == copyToRemove.Id);
|
||||
|
||||
if (existedItem == null) return;
|
||||
|
||||
ThreadItems.Remove(existedItem);
|
||||
|
||||
NotifyPropertyChanges();
|
||||
}
|
||||
|
||||
public void NotifyPropertyChanges()
|
||||
{
|
||||
OnPropertyChanged(nameof(Subject));
|
||||
OnPropertyChanged(nameof(PreviewText));
|
||||
OnPropertyChanged(nameof(FromName));
|
||||
OnPropertyChanged(nameof(FromAddress));
|
||||
OnPropertyChanged(nameof(HasAttachments));
|
||||
|
||||
OnPropertyChanged(nameof(IsFlagged));
|
||||
OnPropertyChanged(nameof(IsDraft));
|
||||
OnPropertyChanged(nameof(IsRead));
|
||||
OnPropertyChanged(nameof(IsFocused));
|
||||
OnPropertyChanged(nameof(CreationDate));
|
||||
}
|
||||
|
||||
public IMailItem LatestMailItem => ((IMailItemThread)_threadMailItem).LatestMailItem;
|
||||
public IMailItem FirstMailItem => ((IMailItemThread)_threadMailItem).FirstMailItem;
|
||||
|
||||
public string Id => ((IMailItem)_threadMailItem).Id;
|
||||
public string Subject => ((IMailItem)_threadMailItem).Subject;
|
||||
public string ThreadId => ((IMailItem)_threadMailItem).ThreadId;
|
||||
public string MessageId => ((IMailItem)_threadMailItem).MessageId;
|
||||
public string References => ((IMailItem)_threadMailItem).References;
|
||||
public string PreviewText => ((IMailItem)_threadMailItem).PreviewText;
|
||||
public string FromName => ((IMailItem)_threadMailItem).FromName;
|
||||
public DateTime CreationDate => ((IMailItem)_threadMailItem).CreationDate;
|
||||
public string FromAddress => ((IMailItem)_threadMailItem).FromAddress;
|
||||
public bool HasAttachments => ((IMailItem)_threadMailItem).HasAttachments;
|
||||
public bool IsFlagged => ((IMailItem)_threadMailItem).IsFlagged;
|
||||
public bool IsFocused => ((IMailItem)_threadMailItem).IsFocused;
|
||||
public bool IsRead => ((IMailItem)_threadMailItem).IsRead;
|
||||
public bool IsDraft => ((IMailItem)_threadMailItem).IsDraft;
|
||||
public string DraftId => string.Empty;
|
||||
public string InReplyTo => ((IMailItem)_threadMailItem).InReplyTo;
|
||||
|
||||
public MailItemFolder AssignedFolder => ((IMailItem)_threadMailItem).AssignedFolder;
|
||||
|
||||
public MailAccount AssignedAccount => ((IMailItem)_threadMailItem).AssignedAccount;
|
||||
|
||||
public Guid UniqueId => ((IMailItem)_threadMailItem).UniqueId;
|
||||
|
||||
public Guid FileId => ((IMailItem)_threadMailItem).FileId;
|
||||
|
||||
public int CompareTo(DateTime other) => CreationDate.CompareTo(other);
|
||||
public int CompareTo(string other) => FromName.CompareTo(other);
|
||||
|
||||
// Get single mail item view model out of the only item in thread items.
|
||||
public MailItemViewModel GetSingleItemViewModel() => ThreadItems.First() as MailItemViewModel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user