Cleaning up the solution. Separating Shared.WinRT, Services and Synchronization. Removing synchronization from app. Reducing bundle size by 45mb.
This commit is contained in:
@@ -2,9 +2,10 @@
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
@@ -71,9 +72,9 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
|
||||
private Task ShareProtocolLogAsync()
|
||||
=> SaveLogInternalAsync(ImapTestService.ProtocolLogFileName);
|
||||
=> SaveLogInternalAsync(Constants.ProtocolLogFileName);
|
||||
private Task ShareWinoLogAsync()
|
||||
=> SaveLogInternalAsync(LogInitializer.WinoLogFileName);
|
||||
=> SaveLogInternalAsync(Constants.WinoLogFileName);
|
||||
|
||||
private async Task SaveLogInternalAsync(string sourceFileName)
|
||||
{
|
||||
@@ -83,7 +84,7 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
if (!File.Exists(logFile))
|
||||
{
|
||||
DialogService.InfoBarMessage(Translator.Info_LogsNotFoundTitle, Translator.Info_LogsNotFoundMessage, Core.Domain.Enums.InfoBarMessageType.Warning);
|
||||
DialogService.InfoBarMessage(Translator.Info_LogsNotFoundTitle, Translator.Info_LogsNotFoundMessage, InfoBarMessageType.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -95,7 +96,7 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
var copiedFileName = Path.GetFileName(copiedFilePath);
|
||||
|
||||
DialogService.InfoBarMessage(Translator.Info_LogsSavedTitle, string.Format(Translator.Info_LogsSavedMessage, copiedFileName), Core.Domain.Enums.InfoBarMessageType.Success);
|
||||
DialogService.InfoBarMessage(Translator.Info_LogsSavedTitle, string.Format(Translator.Info_LogsSavedMessage, copiedFileName), InfoBarMessageType.Success);
|
||||
}
|
||||
|
||||
private async Task Navigate(object url)
|
||||
|
||||
@@ -5,12 +5,12 @@ using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
using Wino.Messaging.Server;
|
||||
|
||||
|
||||
@@ -8,13 +8,15 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Store;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Exceptions;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Exceptions;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Domain.Models.Store;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Messaging.Client.Authorization;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
|
||||
@@ -7,16 +7,15 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.MenuItems;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Domain.Models.Synchronization;
|
||||
using Wino.Mail.ViewModels.Data.MenuItems;
|
||||
using Wino.Messaging.Client.Accounts;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
@@ -432,7 +431,7 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
|
||||
var package = new MailOperationPreperationRequest(MailOperation.Move, group, false, handlingAccountFolder);
|
||||
await _winoRequestDelegator.ExecuteAsync(package);
|
||||
await _winoRequestDelegator.QueueAsync(package);
|
||||
}
|
||||
}
|
||||
else if (targetFolderMenuItem is IFolderMenuItem singleFolderMenuItem)
|
||||
@@ -442,7 +441,7 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
var package = new MailOperationPreperationRequest(MailOperation.Move, items, false, targetFolderMenuItem.HandlingFolders.First());
|
||||
|
||||
await _winoRequestDelegator.ExecuteAsync(package);
|
||||
await _winoRequestDelegator.QueueAsync(package);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +464,7 @@ namespace Wino.Mail.ViewModels
|
||||
{
|
||||
var folderPrepRequest = new FolderOperationPreperationRequest(operation, realFolder);
|
||||
|
||||
await _winoRequestDelegator.ExecuteAsync(folderPrepRequest);
|
||||
await _winoRequestDelegator.QueueAsync(folderPrepRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,7 +574,7 @@ namespace Wino.Mail.ViewModels
|
||||
});
|
||||
|
||||
// Load account folder structure and replace the visible folders.
|
||||
var folders = await _folderService.GetAccountFoldersForDisplayAsync(clickedBaseAccountMenuItem);
|
||||
var folders = await GetAccountFoldersForDisplayAsync(clickedBaseAccountMenuItem);
|
||||
|
||||
await MenuItems.ReplaceFoldersAsync(folders);
|
||||
await UpdateUnreadItemCountAsync();
|
||||
@@ -592,6 +591,154 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
#region Folder Menu Item Preperations
|
||||
|
||||
public Task<IEnumerable<IMenuItem>> GetAccountFoldersForDisplayAsync(IAccountMenuItem accountMenuItem)
|
||||
{
|
||||
if (accountMenuItem is IMergedAccountMenuItem mergedAccountFolderMenuItem)
|
||||
{
|
||||
return GetMergedAccountFolderMenuItemsAsync(mergedAccountFolderMenuItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetSingleAccountFolderMenuItemsAsync(accountMenuItem);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<FolderMenuItem> GetPreparedFolderMenuItemRecursiveAsync(MailAccount account, MailItemFolder parentFolder, IMenuItem parentMenuItem)
|
||||
{
|
||||
// Localize category folder name.
|
||||
if (parentFolder.SpecialFolderType == SpecialFolderType.Category) parentFolder.FolderName = Translator.CategoriesFolderNameOverride;
|
||||
|
||||
var preparedFolder = new FolderMenuItem(parentFolder, account, parentMenuItem);
|
||||
|
||||
var childFolders = await _folderService.GetChildFoldersAsync(account.Id, parentFolder.RemoteFolderId).ConfigureAwait(false);
|
||||
|
||||
if (childFolders.Any())
|
||||
{
|
||||
foreach (var subChildFolder in childFolders)
|
||||
{
|
||||
var preparedChild = await GetPreparedFolderMenuItemRecursiveAsync(account, subChildFolder, preparedFolder);
|
||||
|
||||
if (preparedChild == null) continue;
|
||||
|
||||
preparedFolder.SubMenuItems.Add(preparedChild);
|
||||
}
|
||||
}
|
||||
|
||||
return preparedFolder;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<IMenuItem>> GetSingleAccountFolderMenuItemsAsync(IAccountMenuItem accountMenuItem)
|
||||
{
|
||||
var accountId = accountMenuItem.EntityId.Value;
|
||||
var preparedFolderMenuItems = new List<IMenuItem>();
|
||||
|
||||
// Get all folders for the account. Excluding hidden folders.
|
||||
var folders = await _folderService.GetVisibleFoldersAsync(accountId).ConfigureAwait(false);
|
||||
|
||||
if (!folders.Any()) return new List<IMenuItem>();
|
||||
|
||||
var mailAccount = accountMenuItem.HoldingAccounts.First();
|
||||
|
||||
var listingFolders = folders.OrderBy(a => a.SpecialFolderType);
|
||||
|
||||
var moreFolder = MailItemFolder.CreateMoreFolder();
|
||||
var categoryFolder = MailItemFolder.CreateCategoriesFolder();
|
||||
|
||||
var moreFolderMenuItem = new FolderMenuItem(moreFolder, mailAccount, accountMenuItem);
|
||||
var categoryFolderMenuItem = new FolderMenuItem(categoryFolder, mailAccount, accountMenuItem);
|
||||
|
||||
foreach (var item in listingFolders)
|
||||
{
|
||||
// Category type folders should be skipped. They will be categorized under virtual category folder.
|
||||
if (Constants.SubCategoryFolderLabelIds.Contains(item.RemoteFolderId)) continue;
|
||||
|
||||
bool skipEmptyParentRemoteFolders = mailAccount.ProviderType == MailProviderType.Gmail;
|
||||
|
||||
if (skipEmptyParentRemoteFolders && !string.IsNullOrEmpty(item.ParentRemoteFolderId)) continue;
|
||||
|
||||
// Sticky items belong to account menu item directly. Rest goes to More folder.
|
||||
IMenuItem parentFolderMenuItem = item.IsSticky ? accountMenuItem : (Constants.SubCategoryFolderLabelIds.Contains(item.FolderName.ToUpper()) ? categoryFolderMenuItem : moreFolderMenuItem);
|
||||
|
||||
var preparedItem = await GetPreparedFolderMenuItemRecursiveAsync(mailAccount, item, parentFolderMenuItem).ConfigureAwait(false);
|
||||
|
||||
// Don't add menu items that are prepared for More folder. They've been included in More virtual folder already.
|
||||
// We'll add More folder later on at the end of the list.
|
||||
|
||||
if (preparedItem == null) continue;
|
||||
|
||||
if (item.IsSticky)
|
||||
{
|
||||
preparedFolderMenuItems.Add(preparedItem);
|
||||
}
|
||||
else if (parentFolderMenuItem is FolderMenuItem baseParentFolderMenuItem)
|
||||
{
|
||||
baseParentFolderMenuItem.SubMenuItems.Add(preparedItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Only add category folder if it's Gmail.
|
||||
if (mailAccount.ProviderType == MailProviderType.Gmail) preparedFolderMenuItems.Add(categoryFolderMenuItem);
|
||||
|
||||
// Only add More folder if there are any items in it.
|
||||
if (moreFolderMenuItem.SubMenuItems.Any()) preparedFolderMenuItems.Add(moreFolderMenuItem);
|
||||
|
||||
return preparedFolderMenuItems;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<IMenuItem>> GetMergedAccountFolderMenuItemsAsync(IMergedAccountMenuItem mergedAccountFolderMenuItem)
|
||||
{
|
||||
var holdingAccounts = mergedAccountFolderMenuItem.HoldingAccounts;
|
||||
|
||||
if (holdingAccounts == null || !holdingAccounts.Any()) return [];
|
||||
|
||||
var preparedFolderMenuItems = new List<IMenuItem>();
|
||||
|
||||
// First gather all account folders.
|
||||
// Prepare single menu items for both of them.
|
||||
|
||||
var allAccountFolders = new List<List<MailItemFolder>>();
|
||||
|
||||
foreach (var account in holdingAccounts)
|
||||
{
|
||||
var accountFolders = await _folderService.GetVisibleFoldersAsync(account.Id).ConfigureAwait(false);
|
||||
|
||||
allAccountFolders.Add(accountFolders);
|
||||
}
|
||||
|
||||
var commonFolders = FindCommonFolders(allAccountFolders);
|
||||
|
||||
// Prepare menu items for common folders.
|
||||
foreach (var commonFolderType in commonFolders)
|
||||
{
|
||||
var folderItems = allAccountFolders.SelectMany(a => a.Where(b => b.SpecialFolderType == commonFolderType)).Cast<IMailItemFolder>().ToList();
|
||||
var menuItem = new MergedAccountFolderMenuItem(folderItems, null, mergedAccountFolderMenuItem.Parameter);
|
||||
|
||||
preparedFolderMenuItems.Add(menuItem);
|
||||
}
|
||||
|
||||
return preparedFolderMenuItems;
|
||||
}
|
||||
|
||||
private HashSet<SpecialFolderType> FindCommonFolders(List<List<MailItemFolder>> lists)
|
||||
{
|
||||
var allSpecialTypesExceptOther = Enum.GetValues(typeof(SpecialFolderType)).Cast<SpecialFolderType>().Where(a => a != SpecialFolderType.Other).ToList();
|
||||
|
||||
// Start with all special folder types from the first list
|
||||
var commonSpecialFolderTypes = new HashSet<SpecialFolderType>(allSpecialTypesExceptOther);
|
||||
|
||||
// Intersect with special folder types from all lists
|
||||
foreach (var list in lists)
|
||||
{
|
||||
commonSpecialFolderTypes.IntersectWith(list.Select(f => f.SpecialFolderType));
|
||||
}
|
||||
|
||||
return commonSpecialFolderTypes;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task UpdateUnreadItemCountAsync()
|
||||
{
|
||||
// Get visible account menu items, ordered by merged accounts at the last.
|
||||
@@ -763,7 +910,7 @@ namespace Wino.Mail.ViewModels
|
||||
var createdDraftMailMessage = await _mailService.CreateDraftAsync(account, createdMimeMessage).ConfigureAwait(false);
|
||||
|
||||
var draftPreperationRequest = new DraftPreperationRequest(account, createdDraftMailMessage, createdMimeMessage);
|
||||
await _winoRequestDelegator.ExecuteAsync(draftPreperationRequest);
|
||||
await _winoRequestDelegator.QueueAsync(draftPreperationRequest);
|
||||
}
|
||||
|
||||
public async void Receive(NewSynchronizationRequested message)
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Messaging.Server;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
|
||||
@@ -3,11 +3,11 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Collections;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Comparers;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Comparers;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Collections
|
||||
|
||||
@@ -9,16 +9,16 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Reader;
|
||||
using Wino.Core.Extensions;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Exceptions;
|
||||
using Wino.Domain.Extensions;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Domain.Models.Reader;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
|
||||
@@ -113,6 +113,7 @@ namespace Wino.Mail.ViewModels
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly IWinoRequestDelegator _worker;
|
||||
public readonly IContactService ContactService;
|
||||
private readonly IHtmlPreviewer _htmlPreviewer;
|
||||
|
||||
public ComposePageViewModel(IDialogService dialogService,
|
||||
IMailService mailService,
|
||||
@@ -123,12 +124,13 @@ namespace Wino.Mail.ViewModels
|
||||
IFolderService folderService,
|
||||
IAccountService accountService,
|
||||
IWinoRequestDelegator worker,
|
||||
IContactService contactService) : base(dialogService)
|
||||
IContactService contactService,
|
||||
IHtmlPreviewer htmlPreviewer) : base(dialogService)
|
||||
{
|
||||
NativeAppService = nativeAppService;
|
||||
_folderService = folderService;
|
||||
ContactService = contactService;
|
||||
|
||||
_htmlPreviewer = htmlPreviewer;
|
||||
_mailService = mailService;
|
||||
_launchProtocolService = launchProtocolService;
|
||||
_mimeFileService = mimeFileService;
|
||||
@@ -170,7 +172,7 @@ namespace Wino.Mail.ViewModels
|
||||
var sentFolder = await _folderService.GetSpecialFolderByAccountIdAsync(assignedAccount.Id, SpecialFolderType.Sent);
|
||||
var draftSendPreparationRequest = new SendDraftPreparationRequest(CurrentMailDraftItem.MailCopy, CurrentMimeMessage, CurrentMailDraftItem.AssignedFolder, sentFolder, CurrentMailDraftItem.AssignedAccount.Preferences);
|
||||
|
||||
await _worker.ExecuteAsync(draftSendPreparationRequest);
|
||||
await _worker.QueueAsync(draftSendPreparationRequest);
|
||||
}
|
||||
|
||||
private async Task UpdateMimeChangesAsync()
|
||||
@@ -238,7 +240,7 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(bodyBuilder.HtmlBody))
|
||||
bodyBuilder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(bodyBuilder.HtmlBody);
|
||||
bodyBuilder.TextBody = _htmlPreviewer.GetHtmlPreview(bodyBuilder.HtmlBody);
|
||||
|
||||
if (bodyBuilder.HtmlBody != null && bodyBuilder.TextBody != null)
|
||||
CurrentMimeMessage.Body = bodyBuilder.ToMessageBody();
|
||||
@@ -269,7 +271,7 @@ namespace Wino.Mail.ViewModels
|
||||
else
|
||||
{
|
||||
var deletePackage = new MailOperationPreperationRequest(MailOperation.HardDelete, CurrentMailDraftItem.MailCopy, ignoreHardDeleteProtection: true);
|
||||
await _worker.ExecuteAsync(deletePackage).ConfigureAwait(false);
|
||||
await _worker.QueueAsync(deletePackage).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Messages.Navigation;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Domain;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.IO;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using MimeKit;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Extensions;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Extensions;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
93
Wino.Mail.ViewModels/Data/MenuItems/AccountMenuItem.cs
Normal file
93
Wino.Mail.ViewModels/Data/MenuItems/AccountMenuItem.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public partial class AccountMenuItem : MenuItemBase<MailAccount, MenuItemBase<IMailItemFolder, FolderMenuItem>>, IAccountMenuItem
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int unreadItemCount;
|
||||
|
||||
[ObservableProperty]
|
||||
[NotifyPropertyChangedFor(nameof(IsSynchronizationProgressVisible))]
|
||||
private double synchronizationProgress;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isEnabled = true;
|
||||
|
||||
public bool IsAttentionRequired => AttentionReason != AccountAttentionReason.None;
|
||||
public bool IsSynchronizationProgressVisible => SynchronizationProgress > 0 && SynchronizationProgress < 100;
|
||||
public Guid AccountId => Parameter.Id;
|
||||
|
||||
private AccountAttentionReason attentionReason;
|
||||
|
||||
public AccountAttentionReason AttentionReason
|
||||
{
|
||||
get => attentionReason;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref attentionReason, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(IsAttentionRequired));
|
||||
|
||||
UpdateFixAccountIssueMenuItem();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string AccountName
|
||||
{
|
||||
get => Parameter.Name;
|
||||
set => SetProperty(Parameter.Name, value, Parameter, (u, n) => u.Name = n);
|
||||
}
|
||||
|
||||
public IEnumerable<MailAccount> HoldingAccounts => new List<MailAccount> { Parameter };
|
||||
|
||||
public AccountMenuItem(MailAccount account, IMenuItem parent = null) : base(account, account.Id, parent)
|
||||
{
|
||||
UpdateAccount(account);
|
||||
}
|
||||
|
||||
public void UpdateAccount(MailAccount account)
|
||||
{
|
||||
Parameter = account;
|
||||
AccountName = account.Name;
|
||||
AttentionReason = account.AttentionReason;
|
||||
|
||||
if (SubMenuItems == null) return;
|
||||
|
||||
foreach (var item in SubMenuItems)
|
||||
{
|
||||
if (item is IFolderMenuItem folderMenuItem)
|
||||
{
|
||||
folderMenuItem.UpdateParentAccounnt(account);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateFixAccountIssueMenuItem()
|
||||
{
|
||||
if (AttentionReason != AccountAttentionReason.None && !SubMenuItems.Any(a => a is FixAccountIssuesMenuItem))
|
||||
{
|
||||
// Add fix issue item if not exists.
|
||||
SubMenuItems.Insert(0, new FixAccountIssuesMenuItem(Parameter, this));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove existing if issue is resolved.
|
||||
var fixAccountIssueItem = SubMenuItems.FirstOrDefault(a => a is FixAccountIssuesMenuItem);
|
||||
|
||||
if (fixAccountIssueItem != null)
|
||||
{
|
||||
SubMenuItems.Remove(fixAccountIssueItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class FixAccountIssuesMenuItem : MenuItemBase<IMailItemFolder, FolderMenuItem>
|
||||
{
|
||||
public MailAccount Account { get; }
|
||||
|
||||
public FixAccountIssuesMenuItem(MailAccount account, IMenuItem parentAccountMenuItem) : base(null, null, parentAccountMenuItem)
|
||||
{
|
||||
Account = account;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Wino.Mail.ViewModels/Data/MenuItems/FolderMenuItem.cs
Normal file
79
Wino.Mail.ViewModels/Data/MenuItems/FolderMenuItem.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public partial class FolderMenuItem : MenuItemBase<IMailItemFolder, FolderMenuItem>, IFolderMenuItem
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int unreadItemCount;
|
||||
|
||||
public bool HasTextColor => !string.IsNullOrEmpty(Parameter.TextColorHex);
|
||||
public bool IsMoveTarget => HandlingFolders.All(a => a.IsMoveTarget);
|
||||
|
||||
public SpecialFolderType SpecialFolderType => Parameter.SpecialFolderType;
|
||||
public bool IsSticky => Parameter.IsSticky;
|
||||
public bool IsSystemFolder => Parameter.IsSystemFolder;
|
||||
|
||||
/// <summary>
|
||||
/// Display name of the folder. More and Category folders have localized display names.
|
||||
/// </summary>
|
||||
public string FolderName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Parameter.SpecialFolderType == SpecialFolderType.More)
|
||||
return Translator.MoreFolderNameOverride;
|
||||
else if (Parameter.SpecialFolderType == SpecialFolderType.Category)
|
||||
return Translator.CategoriesFolderNameOverride;
|
||||
else
|
||||
return Parameter.FolderName;
|
||||
}
|
||||
set => SetProperty(Parameter.FolderName, value, Parameter, (u, n) => u.FolderName = n);
|
||||
}
|
||||
|
||||
public bool IsSynchronizationEnabled
|
||||
{
|
||||
get => Parameter.IsSynchronizationEnabled;
|
||||
set => SetProperty(Parameter.IsSynchronizationEnabled, value, Parameter, (u, n) => u.IsSynchronizationEnabled = n);
|
||||
}
|
||||
|
||||
public IEnumerable<IMailItemFolder> HandlingFolders => new List<IMailItemFolder>() { Parameter };
|
||||
|
||||
public MailAccount ParentAccount { get; private set; }
|
||||
|
||||
public string AssignedAccountName => ParentAccount?.Name;
|
||||
|
||||
public bool ShowUnreadCount => Parameter.ShowUnreadCount;
|
||||
|
||||
IEnumerable<IMenuItem> IBaseFolderMenuItem.SubMenuItems => SubMenuItems;
|
||||
|
||||
public FolderMenuItem(IMailItemFolder folderStructure, MailAccount parentAccount, IMenuItem parentMenuItem) : base(folderStructure, folderStructure.Id, parentMenuItem)
|
||||
{
|
||||
ParentAccount = parentAccount;
|
||||
}
|
||||
|
||||
public void UpdateFolder(IMailItemFolder folder)
|
||||
{
|
||||
Parameter = folder;
|
||||
|
||||
OnPropertyChanged(nameof(IsSynchronizationEnabled));
|
||||
OnPropertyChanged(nameof(ShowUnreadCount));
|
||||
OnPropertyChanged(nameof(HasTextColor));
|
||||
OnPropertyChanged(nameof(IsSystemFolder));
|
||||
OnPropertyChanged(nameof(SpecialFolderType));
|
||||
OnPropertyChanged(nameof(IsSticky));
|
||||
OnPropertyChanged(nameof(FolderName));
|
||||
}
|
||||
|
||||
public override string ToString() => FolderName;
|
||||
|
||||
public void UpdateParentAccounnt(MailAccount account) => ParentAccount = account;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class ManageAccountsMenuItem : MenuItemBase { }
|
||||
}
|
||||
63
Wino.Mail.ViewModels/Data/MenuItems/MenuItemBase.cs
Normal file
63
Wino.Mail.ViewModels/Data/MenuItems/MenuItemBase.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public partial class MenuItemBase : ObservableObject, IMenuItem
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool _isExpanded;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isSelected;
|
||||
|
||||
public IMenuItem ParentMenuItem { get; }
|
||||
|
||||
public Guid? EntityId { get; }
|
||||
|
||||
public MenuItemBase(Guid? entityId = null, IMenuItem parentMenuItem = null)
|
||||
{
|
||||
EntityId = entityId;
|
||||
ParentMenuItem = parentMenuItem;
|
||||
}
|
||||
|
||||
public void Expand()
|
||||
{
|
||||
// Recursively expand all parent menu items if parent exists, starting from parent.
|
||||
if (ParentMenuItem != null)
|
||||
{
|
||||
IMenuItem parentMenuItem = ParentMenuItem;
|
||||
|
||||
while (parentMenuItem != null)
|
||||
{
|
||||
parentMenuItem.IsExpanded = true;
|
||||
|
||||
parentMenuItem = parentMenuItem.ParentMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally expand itself.
|
||||
IsExpanded = true;
|
||||
}
|
||||
}
|
||||
|
||||
public partial class MenuItemBase<T> : MenuItemBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private T _parameter;
|
||||
|
||||
public MenuItemBase(T parameter, Guid? entityId, IMenuItem parentMenuItem = null) : base(entityId, parentMenuItem) => Parameter = parameter;
|
||||
}
|
||||
|
||||
public partial class MenuItemBase<TValue, TCollection> : MenuItemBase<TValue>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool _isChildSelected;
|
||||
|
||||
protected MenuItemBase(TValue parameter, Guid? entityId, IMenuItem parentMenuItem = null) : base(parameter, entityId, parentMenuItem) { }
|
||||
|
||||
public ObservableCollection<TCollection> SubMenuItems { get; set; } = [];
|
||||
}
|
||||
}
|
||||
202
Wino.Mail.ViewModels/Data/MenuItems/MenuItemCollection.cs
Normal file
202
Wino.Mail.ViewModels/Data/MenuItems/MenuItemCollection.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using MoreLinq.Extensions;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class MenuItemCollection : ObservableRangeCollection<IMenuItem>
|
||||
{
|
||||
// Which types to remove from the list when folders are changing due to selection of new account.
|
||||
// We don't clear the whole list since we want to keep the New Mail button and account menu items.
|
||||
private readonly Type[] _preservingTypesForFolderArea = [typeof(AccountMenuItem), typeof(NewMailMenuItem), typeof(MergedAccountMenuItem)];
|
||||
private readonly IDispatcher _dispatcher;
|
||||
|
||||
public MenuItemCollection(IDispatcher dispatcher)
|
||||
{
|
||||
_dispatcher = dispatcher;
|
||||
}
|
||||
|
||||
public IEnumerable<IAccountMenuItem> GetAllAccountMenuItems()
|
||||
{
|
||||
foreach (var item in this)
|
||||
{
|
||||
if (item is MergedAccountMenuItem mergedAccountMenuItem)
|
||||
{
|
||||
foreach (var singleItem in mergedAccountMenuItem.SubMenuItems.OfType<IAccountMenuItem>())
|
||||
{
|
||||
yield return singleItem;
|
||||
}
|
||||
|
||||
yield return mergedAccountMenuItem;
|
||||
}
|
||||
else if (item is IAccountMenuItem accountMenuItem)
|
||||
yield return accountMenuItem;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<IBaseFolderMenuItem> GetAllFolderMenuItems(Guid folderId)
|
||||
{
|
||||
foreach (var item in this)
|
||||
{
|
||||
if (item is IBaseFolderMenuItem folderMenuItem)
|
||||
{
|
||||
if (folderMenuItem.HandlingFolders.Any(a => a.Id == folderId))
|
||||
{
|
||||
yield return folderMenuItem;
|
||||
}
|
||||
else if (folderMenuItem.SubMenuItems.Any())
|
||||
{
|
||||
foreach (var subItem in folderMenuItem.SubMenuItems.OfType<IBaseFolderMenuItem>())
|
||||
{
|
||||
if (subItem.HandlingFolders.Any(a => a.Id == folderId))
|
||||
{
|
||||
yield return subItem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetAccountMenuItem(Guid accountId, out IAccountMenuItem value)
|
||||
{
|
||||
value = this.OfType<AccountMenuItem>().FirstOrDefault(a => a.AccountId == accountId);
|
||||
value ??= this.OfType<MergedAccountMenuItem>().FirstOrDefault(a => a.SubMenuItems.OfType<AccountMenuItem>().Where(b => b.AccountId == accountId) != null);
|
||||
|
||||
return value != null;
|
||||
}
|
||||
|
||||
// Pattern: Look for special folder menu item inside the loaded folders for Windows Mail style menu items.
|
||||
public bool TryGetWindowsStyleRootSpecialFolderMenuItem(Guid accountId, SpecialFolderType specialFolderType, out FolderMenuItem value)
|
||||
{
|
||||
value = this.OfType<IBaseFolderMenuItem>()
|
||||
.FirstOrDefault(a => a.HandlingFolders.Any(b => b.MailAccountId == accountId && b.SpecialFolderType == specialFolderType)) as FolderMenuItem;
|
||||
|
||||
return value != null;
|
||||
}
|
||||
|
||||
// Pattern: Find the merged account menu item and return the special folder menu item that belongs to the merged account menu item.
|
||||
// This will not look for the folders inside individual account menu items inside merged account menu item.
|
||||
public bool TryGetMergedAccountSpecialFolderMenuItem(Guid mergedInboxId, SpecialFolderType specialFolderType, out IBaseFolderMenuItem value)
|
||||
{
|
||||
value = this.OfType<MergedAccountFolderMenuItem>()
|
||||
.Where(a => a.MergedInbox.Id == mergedInboxId)
|
||||
.FirstOrDefault(a => a.SpecialFolderType == specialFolderType);
|
||||
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public bool TryGetFolderMenuItem(Guid folderId, out IBaseFolderMenuItem value)
|
||||
{
|
||||
// Root folders
|
||||
value = this.OfType<IBaseFolderMenuItem>()
|
||||
.FirstOrDefault(a => a.HandlingFolders.Any(b => b.Id == folderId));
|
||||
|
||||
value ??= this.OfType<FolderMenuItem>()
|
||||
.SelectMany(a => a.SubMenuItems)
|
||||
.OfType<IBaseFolderMenuItem>()
|
||||
.FirstOrDefault(a => a.HandlingFolders.Any(b => b.Id == folderId));
|
||||
|
||||
return value != null;
|
||||
}
|
||||
|
||||
public void UpdateUnreadItemCountsToZero()
|
||||
{
|
||||
// Handle the root folders.
|
||||
this.OfType<IBaseFolderMenuItem>().ForEach(a => RecursivelyResetUnreadItemCount(a));
|
||||
}
|
||||
|
||||
private void RecursivelyResetUnreadItemCount(IBaseFolderMenuItem baseFolderMenuItem)
|
||||
{
|
||||
baseFolderMenuItem.UnreadItemCount = 0;
|
||||
|
||||
if (baseFolderMenuItem.SubMenuItems == null) return;
|
||||
|
||||
foreach (var subMenuItem in baseFolderMenuItem.SubMenuItems.OfType<IBaseFolderMenuItem>())
|
||||
{
|
||||
RecursivelyResetUnreadItemCount(subMenuItem);
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetSpecialFolderMenuItem(Guid accountId, SpecialFolderType specialFolderType, out FolderMenuItem value)
|
||||
{
|
||||
value = this.OfType<IBaseFolderMenuItem>()
|
||||
.FirstOrDefault(a => a.HandlingFolders.Any(b => b.MailAccountId == accountId && b.SpecialFolderType == specialFolderType)) as FolderMenuItem;
|
||||
|
||||
return value != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Skips the merged account menu item, but directly returns the Account menu item inside the merged account menu item.
|
||||
/// </summary>
|
||||
/// <param name="accountId">Account id to look for.</param>
|
||||
/// <returns>Direct AccountMenuItem inside the Merged Account menu item if exists.</returns>
|
||||
public AccountMenuItem GetSpecificAccountMenuItem(Guid accountId)
|
||||
{
|
||||
AccountMenuItem accountMenuItem = null;
|
||||
|
||||
accountMenuItem = this.OfType<AccountMenuItem>().FirstOrDefault(a => a.HoldingAccounts.Any(b => b.Id == accountId));
|
||||
|
||||
// Look for the items inside the merged accounts if regular menu item is not found.
|
||||
accountMenuItem ??= this.OfType<MergedAccountMenuItem>()
|
||||
.FirstOrDefault(a => a.HoldingAccounts.Any(b => b.Id == accountId))?.SubMenuItems
|
||||
.OfType<AccountMenuItem>()
|
||||
.FirstOrDefault();
|
||||
|
||||
return accountMenuItem;
|
||||
}
|
||||
|
||||
public async Task ReplaceFoldersAsync(IEnumerable<IMenuItem> folders)
|
||||
{
|
||||
await _dispatcher.ExecuteOnUIThread(() =>
|
||||
{
|
||||
ClearFolderAreaMenuItems();
|
||||
|
||||
Items.Add(new SeperatorItem());
|
||||
AddRange(folders);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables/disables account menu items in the list.
|
||||
/// </summary>
|
||||
/// <param name="isEnabled">Whether menu items should be enabled or disabled.</param>
|
||||
public async Task SetAccountMenuItemEnabledStatusAsync(bool isEnabled)
|
||||
{
|
||||
var accountItems = this.Where(a => a is IAccountMenuItem).Cast<IAccountMenuItem>();
|
||||
|
||||
await _dispatcher.ExecuteOnUIThread(() =>
|
||||
{
|
||||
accountItems.ForEach(a => a.IsEnabled = isEnabled);
|
||||
});
|
||||
}
|
||||
|
||||
public void AddAccountMenuItem(IAccountMenuItem accountMenuItem)
|
||||
{
|
||||
var lastAccount = Items.OfType<IAccountMenuItem>().LastOrDefault();
|
||||
|
||||
// Index 0 is always the New Mail button.
|
||||
var insertIndex = lastAccount == null ? 1 : Items.IndexOf(lastAccount) + 1;
|
||||
|
||||
Insert(insertIndex, accountMenuItem);
|
||||
}
|
||||
|
||||
private void ClearFolderAreaMenuItems()
|
||||
{
|
||||
var itemsToRemove = this.Where(a => !_preservingTypesForFolderArea.Contains(a.GetType())).ToList();
|
||||
|
||||
itemsToRemove.ForEach(item =>
|
||||
{
|
||||
item.IsExpanded = false;
|
||||
item.IsSelected = false;
|
||||
});
|
||||
|
||||
RemoveRange(itemsToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
/// <summary>
|
||||
/// Menu item that holds a list of folders under the merged account menu item.
|
||||
/// </summary>
|
||||
public partial class MergedAccountFolderMenuItem : MenuItemBase<List<IMailItemFolder>, IMenuItem>, IMergedAccountFolderMenuItem
|
||||
{
|
||||
public SpecialFolderType FolderType { get; }
|
||||
|
||||
public string FolderName { get; private set; }
|
||||
|
||||
// Any of the folders is enough to determine the synchronization enable/disable state.
|
||||
public bool IsSynchronizationEnabled => HandlingFolders.Any(a => a.IsSynchronizationEnabled);
|
||||
public bool IsMoveTarget => HandlingFolders.All(a => a.IsMoveTarget);
|
||||
public IEnumerable<IMailItemFolder> HandlingFolders => Parameter;
|
||||
|
||||
// All folders in the list should have the same type.
|
||||
public SpecialFolderType SpecialFolderType => HandlingFolders.First().SpecialFolderType;
|
||||
|
||||
public bool IsSticky => true;
|
||||
|
||||
public bool IsSystemFolder => true;
|
||||
|
||||
public string AssignedAccountName => MergedInbox?.Name;
|
||||
|
||||
public MergedInbox MergedInbox { get; set; }
|
||||
|
||||
public bool ShowUnreadCount => HandlingFolders?.Any(a => a.ShowUnreadCount) ?? false;
|
||||
|
||||
public new IEnumerable<IMenuItem> SubMenuItems => base.SubMenuItems;
|
||||
|
||||
[ObservableProperty]
|
||||
private int unreadItemCount;
|
||||
|
||||
// Merged account's shared folder menu item does not have an entity id.
|
||||
// Navigations to specific folders are done by explicit folder id if needed.
|
||||
|
||||
public MergedAccountFolderMenuItem(List<IMailItemFolder> parameter, IMenuItem parentMenuItem, MergedInbox mergedInbox) : base(parameter, null, parentMenuItem)
|
||||
{
|
||||
Guard.IsNotNull(mergedInbox, nameof(mergedInbox));
|
||||
Guard.IsNotNull(parameter, nameof(parameter));
|
||||
Guard.HasSizeGreaterThan(parameter, 0, nameof(parameter));
|
||||
|
||||
MergedInbox = mergedInbox;
|
||||
|
||||
SetFolderName();
|
||||
|
||||
// All folders in the list should have the same type.
|
||||
FolderType = parameter[0].SpecialFolderType;
|
||||
}
|
||||
|
||||
private void SetFolderName()
|
||||
{
|
||||
// Folders that hold more than 1 folder belong to merged account.
|
||||
// These folders will be displayed as their localized names based on the
|
||||
// special type they have.
|
||||
|
||||
if (HandlingFolders.Count() > 1)
|
||||
{
|
||||
FolderName = GetSpecialFolderName(HandlingFolders.First());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Folder only holds 1 Id, but it's displayed as merged account folder.
|
||||
FolderName = HandlingFolders.First().FolderName;
|
||||
}
|
||||
}
|
||||
|
||||
private string GetSpecialFolderName(IMailItemFolder folder)
|
||||
{
|
||||
var specialType = folder.SpecialFolderType;
|
||||
|
||||
// We only handle 5 different types for combining folders.
|
||||
// Rest of the types are not supported.
|
||||
|
||||
return specialType switch
|
||||
{
|
||||
SpecialFolderType.Inbox => Translator.MergedAccountCommonFolderInbox,
|
||||
SpecialFolderType.Draft => Translator.MergedAccountCommonFolderDraft,
|
||||
SpecialFolderType.Sent => Translator.MergedAccountCommonFolderSent,
|
||||
SpecialFolderType.Deleted => Translator.MergedAccountCommonFolderTrash,
|
||||
SpecialFolderType.Junk => Translator.MergedAccountCommonFolderJunk,
|
||||
SpecialFolderType.Archive => Translator.MergedAccountCommonFolderArchive,
|
||||
_ => folder.FolderName,
|
||||
};
|
||||
}
|
||||
|
||||
public void UpdateFolder(IMailItemFolder folder)
|
||||
{
|
||||
var existingFolder = Parameter.FirstOrDefault(a => a.Id == folder.Id);
|
||||
|
||||
if (existingFolder == null) return;
|
||||
|
||||
Parameter.Remove(existingFolder);
|
||||
Parameter.Add(folder);
|
||||
|
||||
SetFolderName();
|
||||
OnPropertyChanged(nameof(ShowUnreadCount));
|
||||
OnPropertyChanged(nameof(IsSynchronizationEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
43
Wino.Mail.ViewModels/Data/MenuItems/MergedAccountMenuItem.cs
Normal file
43
Wino.Mail.ViewModels/Data/MenuItems/MergedAccountMenuItem.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public partial class MergedAccountMenuItem : MenuItemBase<MergedInbox, IMenuItem>, IMergedAccountMenuItem
|
||||
{
|
||||
public int MergedAccountCount => HoldingAccounts?.Count() ?? 0;
|
||||
|
||||
public IEnumerable<MailAccount> HoldingAccounts { get; }
|
||||
|
||||
[ObservableProperty]
|
||||
private int unreadItemCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private double synchronizationProgress;
|
||||
|
||||
[ObservableProperty]
|
||||
private string mergedAccountName;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isEnabled = true;
|
||||
|
||||
public MergedAccountMenuItem(MergedInbox mergedInbox, IEnumerable<MailAccount> holdingAccounts, IMenuItem parent) : base(mergedInbox, mergedInbox.Id, parent)
|
||||
{
|
||||
MergedAccountName = mergedInbox.Name;
|
||||
HoldingAccounts = holdingAccounts;
|
||||
}
|
||||
|
||||
public void RefreshFolderItemCount()
|
||||
{
|
||||
UnreadItemCount = SubMenuItems.OfType<IAccountMenuItem>().Sum(a => a.UnreadItemCount);
|
||||
}
|
||||
|
||||
public void UpdateAccount(MailAccount account)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class MergedAccountMoreFolderMenuItem : MenuItemBase<object, IMenuItem>
|
||||
{
|
||||
public MergedAccountMoreFolderMenuItem(object parameter, Guid? entityId, IMenuItem parentMenuItem = null) : base(parameter, entityId, parentMenuItem)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
4
Wino.Mail.ViewModels/Data/MenuItems/NewMailMenuItem.cs
Normal file
4
Wino.Mail.ViewModels/Data/MenuItems/NewMailMenuItem.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class NewMailMenuItem : MenuItemBase { }
|
||||
}
|
||||
164
Wino.Mail.ViewModels/Data/MenuItems/ObservableRangeCollection.cs
Normal file
164
Wino.Mail.ViewModels/Data/MenuItems/ObservableRangeCollection.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public class ObservableRangeCollection<T> : ObservableCollection<T>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class.
|
||||
/// </summary>
|
||||
public ObservableRangeCollection()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the System.Collections.ObjectModel.ObservableCollection(Of T) class that contains elements copied from the specified collection.
|
||||
/// </summary>
|
||||
/// <param name="collection">collection: The collection from which the elements are copied.</param>
|
||||
/// <exception cref="ArgumentNullException">The collection parameter cannot be null.</exception>
|
||||
public ObservableRangeCollection(IEnumerable<T> collection)
|
||||
: base(collection)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the elements of the specified collection to the end of the ObservableCollection(Of T).
|
||||
/// </summary>
|
||||
public void AddRange(IEnumerable<T> collection, NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
if (notificationMode != NotifyCollectionChangedAction.Add && notificationMode != NotifyCollectionChangedAction.Reset)
|
||||
throw new ArgumentException("Mode must be either Add or Reset for AddRange.", nameof(notificationMode));
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
|
||||
CheckReentrancy();
|
||||
|
||||
var startIndex = Count;
|
||||
|
||||
var itemsAdded = AddArrangeCore(collection);
|
||||
|
||||
if (!itemsAdded)
|
||||
return;
|
||||
|
||||
if (notificationMode == NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
RaiseChangeNotificationEvents(action: NotifyCollectionChangedAction.Reset);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var changedItems = collection is List<T> ? (List<T>)collection : new List<T>(collection);
|
||||
|
||||
RaiseChangeNotificationEvents(
|
||||
action: NotifyCollectionChangedAction.Add,
|
||||
changedItems: changedItems,
|
||||
startingIndex: startIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurence of each item in the specified collection from ObservableCollection(Of T). NOTE: with notificationMode = Remove, removed items starting index is not set because items are not guaranteed to be consecutive.
|
||||
/// </summary>
|
||||
public void RemoveRange(IEnumerable<T> collection, NotifyCollectionChangedAction notificationMode = NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
if (notificationMode != NotifyCollectionChangedAction.Remove && notificationMode != NotifyCollectionChangedAction.Reset)
|
||||
throw new ArgumentException("Mode must be either Remove or Reset for RemoveRange.", nameof(notificationMode));
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
|
||||
CheckReentrancy();
|
||||
|
||||
if (notificationMode == NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
var raiseEvents = false;
|
||||
foreach (var item in collection)
|
||||
{
|
||||
Items.Remove(item);
|
||||
raiseEvents = true;
|
||||
}
|
||||
|
||||
if (raiseEvents)
|
||||
RaiseChangeNotificationEvents(action: NotifyCollectionChangedAction.Reset);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var changedItems = new List<T>(collection);
|
||||
for (var i = 0; i < changedItems.Count; i++)
|
||||
{
|
||||
if (!Items.Remove(changedItems[i]))
|
||||
{
|
||||
changedItems.RemoveAt(i); //Can't use a foreach because changedItems is intended to be (carefully) modified
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (changedItems.Count == 0)
|
||||
return;
|
||||
|
||||
RaiseChangeNotificationEvents(
|
||||
action: NotifyCollectionChangedAction.Remove,
|
||||
changedItems: changedItems);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the current collection and replaces it with the specified item.
|
||||
/// </summary>
|
||||
public void Replace(T item) => ReplaceRange(new T[] { item });
|
||||
|
||||
/// <summary>
|
||||
/// Clears the current collection and replaces it with the specified collection.
|
||||
/// </summary>
|
||||
public void ReplaceRange(IEnumerable<T> collection)
|
||||
{
|
||||
if (collection == null)
|
||||
throw new ArgumentNullException(nameof(collection));
|
||||
|
||||
CheckReentrancy();
|
||||
|
||||
var previouslyEmpty = Items.Count == 0;
|
||||
|
||||
Items.Clear();
|
||||
|
||||
AddArrangeCore(collection);
|
||||
|
||||
var currentlyEmpty = Items.Count == 0;
|
||||
|
||||
if (previouslyEmpty && currentlyEmpty)
|
||||
return;
|
||||
|
||||
RaiseChangeNotificationEvents(action: NotifyCollectionChangedAction.Reset);
|
||||
}
|
||||
|
||||
private bool AddArrangeCore(IEnumerable<T> collection)
|
||||
{
|
||||
var itemAdded = false;
|
||||
foreach (var item in collection)
|
||||
{
|
||||
Items.Add(item);
|
||||
itemAdded = true;
|
||||
}
|
||||
return itemAdded;
|
||||
}
|
||||
|
||||
private void RaiseChangeNotificationEvents(NotifyCollectionChangedAction action, List<T> changedItems = null, int startingIndex = -1)
|
||||
{
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(Count)));
|
||||
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
|
||||
|
||||
if (changedItems is null)
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action));
|
||||
else
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, changedItems: changedItems, startingIndex: startingIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
4
Wino.Mail.ViewModels/Data/MenuItems/RateMenuItem.cs
Normal file
4
Wino.Mail.ViewModels/Data/MenuItems/RateMenuItem.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class RateMenuItem : MenuItemBase { }
|
||||
}
|
||||
4
Wino.Mail.ViewModels/Data/MenuItems/SeperatorItem.cs
Normal file
4
Wino.Mail.ViewModels/Data/MenuItems/SeperatorItem.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class SeperatorItem : MenuItemBase { }
|
||||
}
|
||||
4
Wino.Mail.ViewModels/Data/MenuItems/SettingsItem.cs
Normal file
4
Wino.Mail.ViewModels/Data/MenuItems/SettingsItem.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
namespace Wino.Mail.ViewModels.Data.MenuItems
|
||||
{
|
||||
public class SettingsItem : MenuItemBase { }
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
@@ -4,8 +4,8 @@ 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;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Data
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Translations;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Domain.Models.Translations;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -12,23 +12,24 @@ using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
using MoreLinq;
|
||||
using Nito.AsyncEx;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Menus;
|
||||
using Wino.Core.Domain.Models.Reader;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.Messages.Mails;
|
||||
using Wino.Core.Messages.Shell;
|
||||
using Wino.Core.Messages.Synchronization;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain.Models.Synchronization;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Folders;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain.Models.Menus;
|
||||
using Wino.Domain.Models.Reader;
|
||||
using Wino.Mail.ViewModels.Collections;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Messages;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
using Wino.Messaging.Client.Synchronization;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
@@ -546,7 +547,7 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
#endregion
|
||||
|
||||
public Task ExecuteMailOperationAsync(MailOperationPreperationRequest package) => _winoRequestDelegator.ExecuteAsync(package);
|
||||
public Task ExecuteMailOperationAsync(MailOperationPreperationRequest package) => _winoRequestDelegator.QueueAsync(package);
|
||||
|
||||
public IEnumerable<MailItemViewModel> GetTargetMailItemViewModels(IMailItem clickedItem)
|
||||
{
|
||||
|
||||
@@ -11,19 +11,20 @@ using MailKit;
|
||||
using Microsoft.AppCenter.Crashes;
|
||||
using MimeKit;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.MailItem;
|
||||
using Wino.Core.Domain.Models.Menus;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Reader;
|
||||
using Wino.Core.Extensions;
|
||||
using Wino.Core.Messages.Mails;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Extensions;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.MailItem;
|
||||
using Wino.Domain.Models.Menus;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Domain.Models.Reader;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Messages;
|
||||
using Wino.Messaging.Client.Mails;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
@@ -34,7 +35,7 @@ namespace Wino.Mail.ViewModels
|
||||
private readonly IUnderlyingThemeService _underlyingThemeService;
|
||||
|
||||
private readonly IMimeFileService _mimeFileService;
|
||||
private readonly Core.Domain.Interfaces.IMailService _mailService;
|
||||
private readonly Domain.Interfaces.IMailService _mailService;
|
||||
private readonly IFileService _fileService;
|
||||
private readonly IWinoRequestDelegator _requestDelegator;
|
||||
private readonly IClipboardService _clipboardService;
|
||||
@@ -120,7 +121,7 @@ namespace Wino.Mail.ViewModels
|
||||
INativeAppService nativeAppService,
|
||||
IUnderlyingThemeService underlyingThemeService,
|
||||
IMimeFileService mimeFileService,
|
||||
Core.Domain.Interfaces.IMailService mailService,
|
||||
Domain.Interfaces.IMailService mailService,
|
||||
IFileService fileService,
|
||||
IWinoRequestDelegator requestDelegator,
|
||||
IStatePersistanceService statePersistanceService,
|
||||
@@ -281,14 +282,14 @@ namespace Wino.Mail.ViewModels
|
||||
ReferenceMailCopy = initializedMailItemViewModel.MailCopy
|
||||
};
|
||||
|
||||
await _requestDelegator.ExecuteAsync(draftPreperationRequest);
|
||||
await _requestDelegator.QueueAsync(draftPreperationRequest);
|
||||
|
||||
}
|
||||
else if (initializedMailItemViewModel != null)
|
||||
{
|
||||
// All other operations require a mail item.
|
||||
var prepRequest = new MailOperationPreperationRequest(operation, initializedMailItemViewModel.MailCopy);
|
||||
await _requestDelegator.ExecuteAsync(prepRequest);
|
||||
await _requestDelegator.QueueAsync(prepRequest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +361,9 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
if (!isMimeExists)
|
||||
{
|
||||
// TODO: Prevent WinUI crash for non-existing mimes.
|
||||
return;
|
||||
|
||||
await HandleSingleItemDownloadAsync(mailItemViewModel);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@ using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Messages.Navigation;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
using Wino.Messaging.Server;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Messages
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using Wino.Core.MenuItems;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Messages
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -4,10 +4,10 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Personalization;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
|
||||
@@ -4,9 +4,9 @@ using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.Mvvm.Messaging.Messages;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Reader;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Reader;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Messages.Navigation;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
@@ -7,10 +7,10 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using MoreLinq;
|
||||
using MoreLinq.Extensions;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Entities;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
|
||||
30
Wino.Mail.ViewModels/ViewModelContainerSetup.cs
Normal file
30
Wino.Mail.ViewModels/ViewModelContainerSetup.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
public static class ViewModelContainerSetup
|
||||
{
|
||||
public static void RegisterViewModels(this IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(typeof(AppShellViewModel));
|
||||
services.AddTransient(typeof(SettingsDialogViewModel));
|
||||
services.AddTransient(typeof(PersonalizationPageViewModel));
|
||||
services.AddTransient(typeof(SettingOptionsPageViewModel));
|
||||
services.AddTransient(typeof(MailListPageViewModel));
|
||||
services.AddTransient(typeof(MailRenderingPageViewModel));
|
||||
services.AddTransient(typeof(AccountManagementViewModel));
|
||||
services.AddTransient(typeof(WelcomePageViewModel));
|
||||
services.AddTransient(typeof(AboutPageViewModel));
|
||||
services.AddTransient(typeof(ComposePageViewModel));
|
||||
services.AddTransient(typeof(IdlePageViewModel));
|
||||
services.AddTransient(typeof(SettingsPageViewModel));
|
||||
services.AddTransient(typeof(NewAccountManagementPageViewModel));
|
||||
services.AddTransient(typeof(AccountDetailsPageViewModel));
|
||||
services.AddTransient(typeof(SignatureManagementPageViewModel));
|
||||
services.AddTransient(typeof(MessageListPageViewModel));
|
||||
services.AddTransient(typeof(ReadingPanePageViewModel));
|
||||
services.AddTransient(typeof(MergedAccountDetailsPageViewModel));
|
||||
services.AddTransient(typeof(LanguageTimePageViewModel));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Domain;
|
||||
using Wino.Domain.Enums;
|
||||
using Wino.Domain.Interfaces;
|
||||
using Wino.Domain.Models.Navigation;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
@@ -30,7 +31,7 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
DialogService.InfoBarMessage(Translator.GeneralTitle_Error, "Can't find the patch notes.", Core.Domain.Enums.InfoBarMessageType.Information);
|
||||
DialogService.InfoBarMessage(Translator.GeneralTitle_Error, "Can't find the patch notes.", InfoBarMessageType.Information);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,16 +8,18 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.Diagnostics" Version="8.2.2" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
|
||||
<PackageReference Include="Microsoft.AppCenter.Crashes" Version="5.0.5" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
<PackageReference Include="morelinq" Version="4.3.0" />
|
||||
<PackageReference Include="Serilog" Version="4.0.0" />
|
||||
<PackageReference Include="System.Reactive" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
||||
<ProjectReference Include="..\Wino.Core\Wino.Core.csproj" />
|
||||
<ProjectReference Include="..\Wino.Messages\Wino.Messaging.csproj" />
|
||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Domain.csproj" />
|
||||
<ProjectReference Include="..\Wino.Messaging\Wino.Messaging.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user