Folder operations, Gmail folder sync improvements and rework of menu items. (#273)

* New rename folder dialog keys.

* Insfra work for folder operations and rename folder code.

* RenameFolder for Gmail.

* Fixed input dialog to take custom take for primary button.

* Missing rename for DS call.

* Outlook to throw exception in case of error.

* Implemented rename folder functionality for Outlook.

* Remove default primary text from input dialog.

* Fixed an issue where outlook folder rename does not work.

* Disable vertical scroll for composing page editor items.

* Fixing some issues with imap folder sync.

* fix copy pasta

* TODO folder update/removed overrides for shell.

* New rename folder dialog keys.

* Insfra work for folder operations and rename folder code.

* RenameFolder for Gmail.

* Fixed input dialog to take custom take for primary button.

* Missing rename for DS call.

* Outlook to throw exception in case of error.

* Implemented rename folder functionality for Outlook.

* Remove default primary text from input dialog.

* Fixed an issue where outlook folder rename does not work.

* Disable vertical scroll for composing page editor items.

* Fixing some issues with imap folder sync.

* fix copy pasta

* TODO folder update/removed overrides for shell.

* New rename folder dialog keys.

* Insfra work for folder operations and rename folder code.

* RenameFolder for Gmail.

* Fixed input dialog to take custom take for primary button.

* Missing rename for DS call.

* Outlook to throw exception in case of error.

* Implemented rename folder functionality for Outlook.

* Remove default primary text from input dialog.

* Fixed an issue where outlook folder rename does not work.

* Disable vertical scroll for composing page editor items.

* Fixing some issues with imap folder sync.

* fix copy pasta

* TODO folder update/removed overrides for shell.

* New rename folder dialog keys.

* Fixed an issue where redundant older updates causing pivots to be re-created.

* New empty folder request

* New rename folder dialog keys.

* Insfra work for folder operations and rename folder code.

* RenameFolder for Gmail.

* Fixed input dialog to take custom take for primary button.

* Missing rename for DS call.

* Outlook to throw exception in case of error.

* Implemented rename folder functionality for Outlook.

* Remove default primary text from input dialog.

* Fixed an issue where outlook folder rename does not work.

* Fixing some issues with imap folder sync.

* fix copy pasta

* TODO folder update/removed overrides for shell.

* New rename folder dialog keys.

* New rename folder dialog keys.

* New rename folder dialog keys.

* Fixed an issue where redundant older updates causing pivots to be re-created.

* New empty folder request

* Enable empty folder on base sync.

* Move updates on event listeners.

* Remove folder UI messages.

* Reworked folder synchronization for gmail.

* Loading folders on the fly as the selected account changed instead of relying on cached menu items.

* Merged account folder items, re-navigating to existing rendering page.

* - Reworked merged account menu system.
- Reworked unread item count loadings.
- Fixed back button visibility.
- Instant rendering of mails if renderer is active.
- Animation fixes.
- Menu item re-load crash/hang fixes.

* Handle folder renaming on the UI.

* Empty folder for all synchronizers.

* New execution delay mechanism and handling folder mark as read for all synchronizers.

* Revert UI changes on failure for IMAP.

* Remove duplicate translation keys.

* Cleanup.
This commit is contained in:
Burak Kaan Köse
2024-07-09 01:05:16 +02:00
committed by GitHub
parent ac01006398
commit 536fbb23a1
67 changed files with 1396 additions and 1585 deletions

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Serilog;
using SqlKata;
@@ -9,10 +10,12 @@ using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Extensions;
using Wino.Core.MenuItems;
using Wino.Core.Requests;
namespace Wino.Core.Services
@@ -168,6 +171,155 @@ namespace Wino.Core.Services
return accountTree;
}
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 query = new Query(nameof(MailItemFolder))
.Where(nameof(MailItemFolder.ParentRemoteFolderId), parentFolder.RemoteFolderId)
.Where(nameof(MailItemFolder.MailAccountId), parentFolder.MailAccountId);
var preparedFolder = new FolderMenuItem(parentFolder, account, parentMenuItem);
var childFolders = await Connection.QueryAsync<MailItemFolder>(query.GetRawQuery()).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 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 (GoogleIntegratorExtensions.SubCategoryFolderLabelIds.Contains(item.RemoteFolderId)) continue;
bool skipEmptyParentRemoteFolders = mailAccount.ProviderType == MailProviderType.Gmail;
if (skipEmptyParentRemoteFolders && !string.IsNullOrEmpty(item.ParentRemoteFolderId)) continue;
// Sticky items belong to account menu item directly. Rest goes to More folder.
IMenuItem parentFolderMenuItem = item.IsSticky ? accountMenuItem : (GoogleIntegratorExtensions.SubCategoryFolderLabelIds.Contains(item.FolderName.ToUpper()) ? categoryFolderMenuItem : moreFolderMenuItem);
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 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;
}
private async Task<MailItemFolder> GetChildFolderItemsRecursiveAsync(Guid folderId, Guid accountId)
{
var folder = await Connection.Table<MailItemFolder>().Where(a => a.Id == folderId && a.MailAccountId == accountId).FirstOrDefaultAsync();
@@ -198,49 +350,22 @@ namespace Wino.Core.Services
=> Connection.Table<MailCopy>().Where(a => a.FolderId == folderId).CountAsync();
public Task<List<MailItemFolder>> GetFoldersAsync(Guid accountId)
=> Connection.Table<MailItemFolder>().Where(a => a.MailAccountId == accountId).ToListAsync();
public async Task UpdateCustomServerMailListAsync(Guid accountId, List<MailItemFolder> folders)
{
var account = await Connection.Table<MailAccount>().FirstOrDefaultAsync(a => a.Id == accountId);
var query = new Query(nameof(MailItemFolder))
.Where(nameof(MailItemFolder.MailAccountId), accountId)
.OrderBy(nameof(MailItemFolder.SpecialFolderType));
if (account == null)
return;
return Connection.QueryAsync<MailItemFolder>(query.GetRawQuery());
}
// IMAP servers don't have unique identifier for folders all the time.
// We'll map them with parent-name relation.
public Task<List<MailItemFolder>> GetVisibleFoldersAsync(Guid accountId)
{
var query = new Query(nameof(MailItemFolder))
.Where(nameof(MailItemFolder.MailAccountId), accountId)
.Where(nameof(MailItemFolder.IsHidden), false)
.OrderBy(nameof(MailItemFolder.SpecialFolderType));
var currentFolders = await GetFoldersAsync(accountId);
// These folders don't exist anymore. Remove them.
var localRemoveFolders = currentFolders.ExceptBy(folders, a => a.RemoteFolderId);
foreach (var currentFolder in currentFolders)
{
// Check if we have this folder locally.
var remotelyExistFolder = folders.FirstOrDefault(a => a.RemoteFolderId == currentFolder.RemoteFolderId
&& a.ParentRemoteFolderId == currentFolder.ParentRemoteFolderId);
if (remotelyExistFolder == null)
{
// This folder is removed.
// Remove everything for this folder.
}
}
foreach (var folder in folders)
{
var currentFolder = await Connection.Table<MailItemFolder>().FirstOrDefaultAsync(a => a.MailAccountId == accountId && a.RemoteFolderId == folder.RemoteFolderId);
// Nothing is changed, it's still the same folder.
// Just update Id of the folder.
if (currentFolder != null)
folder.Id = currentFolder.Id;
await Connection.InsertOrReplaceAsync(folder);
}
return Connection.QueryAsync<MailItemFolder>(query.GetRawQuery());
}
public async Task<IList<uint>> GetKnownUidsForFolderAsync(Guid folderId)
@@ -301,6 +426,8 @@ namespace Wino.Core.Services
localFolder.IsSynchronizationEnabled = isSynchronizationEnabled;
await UpdateFolderAsync(localFolder).ConfigureAwait(false);
Messenger.Send(new FolderSynchronizationEnabled(localFolder));
}
}
@@ -337,11 +464,19 @@ namespace Wino.Core.Services
_logger.Debug("Inserting folder {Id} - {FolderName}", folder.Id, folder.FolderName, folder.MailAccountId);
await Connection.InsertAsync(folder).ConfigureAwait(false);
ReportUIChange(new FolderAddedMessage(folder, account));
}
else
{
// TODO: This is not alright. We should've updated the folder instead of inserting.
// Now we need to match the properties that user might've set locally.
folder.Id = existingFolder.Id;
folder.IsSticky = existingFolder.IsSticky;
folder.SpecialFolderType = existingFolder.SpecialFolderType;
folder.ShowUnreadCount = existingFolder.ShowUnreadCount;
folder.TextColorHex = existingFolder.TextColorHex;
folder.BackgroundColorHex = existingFolder.BackgroundColorHex;
_logger.Debug("Folder {Id} - {FolderName} already exists. Updating.", folder.Id, folder.FolderName);
await UpdateFolderAsync(folder).ConfigureAwait(false);
@@ -364,13 +499,9 @@ namespace Wino.Core.Services
return;
}
#if !DEBUG // Annoying
_logger.Debug("Updating folder {FolderName}", folder.Id, folder.FolderName);
#endif
await Connection.UpdateAsync(folder).ConfigureAwait(false);
ReportUIChange(new FolderUpdatedMessage(folder, account));
}
private async Task DeleteFolderAsync(MailItemFolder folder)
@@ -393,9 +524,10 @@ namespace Wino.Core.Services
await Connection.DeleteAsync(folder).ConfigureAwait(false);
// TODO: Delete all mail copies for this folder.
// Delete all existing mails from this folder.
await Connection.ExecuteAsync("DELETE FROM MailCopy WHERE FolderId = ?", folder.Id);
ReportUIChange(new FolderRemovedMessage(folder, account));
// TODO: Delete MIME messages from the disk.
}
#endregion
@@ -426,8 +558,6 @@ namespace Wino.Core.Services
public Task<List<MailFolderPairMetadata>> GetMailFolderPairMetadatasAsync(string mailCopyId)
=> GetMailFolderPairMetadatasAsync(new List<string>() { mailCopyId });
public async Task SetSpecialFolderAsync(Guid folderId, SpecialFolderType type)
=> await Connection.ExecuteAsync("UPDATE MailItemFolder SET SpecialFolderType = ? WHERE Id = ?", type, folderId);
public async Task<List<MailItemFolder>> GetSynchronizationFoldersAsync(SynchronizationOptions options)
{
@@ -489,38 +619,6 @@ namespace Wino.Core.Services
public Task<MailItemFolder> GetFolderAsync(Guid accountId, string remoteFolderId)
=> Connection.Table<MailItemFolder>().FirstOrDefaultAsync(a => a.MailAccountId == accountId && a.RemoteFolderId == remoteFolderId);
// v2
public async Task BulkUpdateFolderStructureAsync(Guid accountId, List<MailItemFolder> allFolders)
{
var existingFolders = await GetFoldersAsync(accountId).ConfigureAwait(false);
var foldersToInsert = allFolders.ExceptBy(existingFolders, a => a.RemoteFolderId);
var foldersToDelete = existingFolders.ExceptBy(allFolders, a => a.RemoteFolderId);
var foldersToUpdate = allFolders.Except(foldersToInsert).Except(foldersToDelete);
_logger.Debug("Found {0} folders to insert, {1} folders to update and {2} folders to delete.",
foldersToInsert.Count(),
foldersToUpdate.Count(),
foldersToDelete.Count());
foreach (var folder in foldersToInsert)
{
await InsertFolderAsync(folder).ConfigureAwait(false);
}
foreach (var folder in foldersToUpdate)
{
await UpdateFolderAsync(folder).ConfigureAwait(false);
}
foreach (var folder in foldersToDelete)
{
await DeleteFolderAsync(folder).ConfigureAwait(false);
}
}
public async Task DeleteFolderAsync(Guid accountId, string remoteFolderId)
{
var folder = await GetFolderAsync(accountId, remoteFolderId);
@@ -547,33 +645,6 @@ namespace Wino.Core.Services
}
}
// Inbox folder is always included for account menu item unread count.
public Task<List<MailItemFolder>> GetUnreadUpdateFoldersAsync(Guid accountId)
=> Connection.Table<MailItemFolder>().Where(a => a.MailAccountId == accountId && (a.ShowUnreadCount || a.SpecialFolderType == SpecialFolderType.Inbox)).ToListAsync();
public async Task TestAsync()
{
var account = new MailAccount()
{
Address = "test@test.com",
ProviderType = MailProviderType.Gmail,
Name = "Test Account",
Id = Guid.NewGuid()
};
await Connection.InsertAsync(account);
var pref = new MailAccountPreferences
{
Id = Guid.NewGuid(),
AccountId = account.Id
};
await Connection.InsertAsync(pref);
ReportUIChange(new AccountCreatedMessage(account));
}
public async Task<bool> IsInboxAvailableForAccountAsync(Guid accountId)
=> (await Connection.Table<MailItemFolder>()
.Where(a => a.SpecialFolderType == SpecialFolderType.Inbox && a.MailAccountId == accountId)
@@ -581,5 +652,18 @@ namespace Wino.Core.Services
public Task UpdateFolderLastSyncDateAsync(Guid folderId)
=> Connection.ExecuteAsync("UPDATE MailItemFolder SET LastSynchronizedDate = ? WHERE Id = ?", DateTime.UtcNow, folderId);
public Task<List<UnreadItemCountResult>> GetUnreadItemCountResultsAsync(IEnumerable<Guid> accountIds)
{
var query = new Query(nameof(MailCopy))
.Join(nameof(MailItemFolder), $"{nameof(MailCopy)}.FolderId", $"{nameof(MailItemFolder)}.Id")
.WhereIn($"{nameof(MailItemFolder)}.MailAccountId", accountIds)
.Where($"{nameof(MailCopy)}.IsRead", 0)
.Where($"{nameof(MailItemFolder)}.ShowUnreadCount", 1)
.SelectRaw($"{nameof(MailItemFolder)}.Id as FolderId, {nameof(MailItemFolder)}.SpecialFolderType as SpecialFolderType, count (DISTINCT {nameof(MailCopy)}.Id) as UnreadItemCount, {nameof(MailItemFolder)}.MailAccountId as AccountId")
.GroupBy($"{nameof(MailItemFolder)}.Id");
return Connection.QueryAsync<UnreadItemCountResult>(query.GetRawQuery());
}
}
}

View File

@@ -4,7 +4,6 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.Kiota.Abstractions.Extensions;
using MimeKit;
using MimeKit.Text;
using MoreLinq;
using Serilog;
using SqlKata;
@@ -111,9 +110,29 @@ namespace Wino.Core.Services
return copy;
}
public Task<List<string>> GetMailIdsByFolderIdAsync(Guid folderId)
=> Connection.QueryScalarsAsync<string>("SELECT Id FROM MailCopy WHERE FolderId = ?", folderId);
public async Task<List<MailCopy>> GetMailsByFolderIdAsync(Guid folderId)
{
var mails = await Connection.QueryAsync<MailCopy>("SELECT * FROM MailCopy WHERE FolderId = ?", folderId);
foreach (var mail in mails)
{
await LoadAssignedPropertiesAsync(mail).ConfigureAwait(false);
}
return mails;
}
public async Task<List<MailCopy>> GetUnreadMailsByFolderIdAsync(Guid folderId)
{
var unreadMails = await Connection.QueryAsync<MailCopy>("SELECT * FROM MailCopy WHERE FolderId = ? AND IsRead = 0", folderId);
foreach (var mail in unreadMails)
{
await LoadAssignedPropertiesAsync(mail).ConfigureAwait(false);
}
return unreadMails;
}
private string BuildMailFetchQuery(MailListInitializationOptions options)
{

View File

@@ -10,7 +10,6 @@ using Wino.Core.Domain.Exceptions;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Requests;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Messages.Synchronization;
using Wino.Core.Requests;
@@ -85,13 +84,17 @@ namespace Wino.Core.Services
}
}
public async Task ExecuteAsync(FolderOperation operation, IMailItemFolder folderStructure)
public async Task ExecuteAsync(FolderOperationPreperationRequest folderRequest)
{
IRequest request = null;
if (folderRequest == null || folderRequest.Folder == null) return;
IRequestBase request = null;
var accountId = folderRequest.Folder.MailAccountId;
try
{
request = await _winoRequestProcessor.PrepareFolderRequestAsync(operation, folderStructure);
request = await _winoRequestProcessor.PrepareFolderRequestAsync(folderRequest);
}
catch (NotImplementedException)
{
@@ -102,7 +105,10 @@ namespace Wino.Core.Services
Log.Error(ex, "Folder operation execution failed.");
}
// _synchronizationWorker.Queue(request);
if (request == null) return;
QueueRequest(request, accountId);
QueueSynchronization(accountId);
}
public Task ExecuteAsync(DraftPreperationRequest draftPreperationRequest)
@@ -125,7 +131,7 @@ namespace Wino.Core.Services
return Task.CompletedTask;
}
private void QueueRequest(IRequest request, Guid accountId)
private void QueueRequest(IRequestBase request, Guid accountId)
{
var synchronizer = _winoSynchronizerFactory.GetAccountSynchronizer(accountId);

View File

@@ -215,45 +215,45 @@ namespace Wino.Core.Services
return null;
}
public async Task<IRequest> PrepareFolderRequestAsync(FolderOperation operation, IMailItemFolder mailItemFolder)
public async Task<IRequestBase> PrepareFolderRequestAsync(FolderOperationPreperationRequest request)
{
if (mailItemFolder == null) return default;
if (request == null || request.Folder == null) return default;
var accountId = mailItemFolder.MailAccountId;
IRequestBase change = null;
IRequest change = null;
var folder = request.Folder;
var operation = request.Action;
switch (operation)
switch (request.Action)
{
case FolderOperation.Pin:
case FolderOperation.Unpin:
await _folderService.ChangeStickyStatusAsync(mailItemFolder.Id, operation == FolderOperation.Pin);
await _folderService.ChangeStickyStatusAsync(folder.Id, operation == FolderOperation.Pin);
break;
//case FolderOperation.MarkAllAsRead:
// // Get all mails in the folder.
// var mailItems = await _folderService.GetAllUnreadItemsByFolderIdAsync(accountId, folderStructure.RemoteFolderId).ConfigureAwait(false);
case FolderOperation.Rename:
var newFolderName = await _dialogService.ShowTextInputDialogAsync(folder.FolderName, Translator.DialogMessage_RenameFolderTitle, Translator.DialogMessage_RenameFolderMessage, Translator.FolderOperation_Rename);
// if (mailItems.Any())
// change = new FolderMarkAsReadRequest(accountId, mailItems.Select(a => a.Id).Distinct(), folderStructure.RemoteFolderId, folderStructure.FolderId);
if (!string.IsNullOrEmpty(newFolderName))
{
change = new RenameFolderRequest(folder, folder.FolderName, newFolderName);
}
// break;
//case FolderOperation.Empty:
// // Get all mails in the folder.
break;
case FolderOperation.Empty:
var mailsToDelete = await _mailService.GetMailsByFolderIdAsync(folder.Id).ConfigureAwait(false);
// var mailsToDelete = await _folderService.GetMailByFolderIdAsync(folderStructure.FolderId).ConfigureAwait(false);
change = new EmptyFolderRequest(folder, mailsToDelete);
// if (mailsToDelete.Any())
// change = new FolderEmptyRequest(accountId, mailsToDelete.Select(a => a.Id).Distinct(), folderStructure.RemoteFolderId, folderStructure.FolderId);
break;
case FolderOperation.MarkAllAsRead:
// break;
//case FolderOperation.Rename:
// var newFolderName = await _dialogService.ShowRenameFolderDialogAsync(folderStructure.FolderName);
var unreadItems = await _mailService.GetUnreadMailsByFolderIdAsync(folder.Id).ConfigureAwait(false);
// if (!string.IsNullOrEmpty(newFolderName))
// change = new RenameFolderRequest(accountId, folderStructure.RemoteFolderId, folderStructure.FolderId, newFolderName, folderStructure.FolderName);
if (unreadItems.Any())
change = new MarkFolderAsReadRequest(folder, unreadItems);
// break;
break;
//case FolderOperation.Delete:
// var isConfirmed = await _dialogService.ShowConfirmationDialogAsync($"'{folderStructure.FolderName}' is going to be deleted. Do you want to continue?", "Are you sure?", "Yes delete.");