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:
@@ -89,7 +89,7 @@ namespace Wino.Mail.ViewModels
|
||||
[RelayCommand]
|
||||
private async Task CreateMergedAccountAsync()
|
||||
{
|
||||
var linkName = await DialogService.ShowTextInputDialogAsync(string.Empty, Translator.DialogMessage_CreateLinkedAccountTitle, Translator.DialogMessage_CreateLinkedAccountMessage);
|
||||
var linkName = await DialogService.ShowTextInputDialogAsync(string.Empty, Translator.DialogMessage_CreateLinkedAccountTitle, Translator.DialogMessage_CreateLinkedAccountMessage, Translator.Buttons_Create);
|
||||
|
||||
if (string.IsNullOrEmpty(linkName)) return;
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ 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.Extensions;
|
||||
using Wino.Core.MenuItems;
|
||||
using Wino.Core.Messages.Accounts;
|
||||
using Wino.Core.Messages.Mails;
|
||||
@@ -49,8 +48,8 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
private IAccountMenuItem latestSelectedAccountMenuItem;
|
||||
|
||||
public MenuItemCollection FooterItems { get; set; } = [];
|
||||
public MenuItemCollection MenuItems { get; set; } = [];
|
||||
public MenuItemCollection FooterItems { get; set; }
|
||||
public MenuItemCollection MenuItems { get; set; }
|
||||
|
||||
private readonly SettingsItem SettingsItem = new SettingsItem();
|
||||
|
||||
@@ -118,6 +117,14 @@ namespace Wino.Mail.ViewModels
|
||||
_winoRequestDelegator = winoRequestDelegator;
|
||||
}
|
||||
|
||||
protected override void OnDispatcherAssigned()
|
||||
{
|
||||
base.OnDispatcherAssigned();
|
||||
|
||||
MenuItems = new MenuItemCollection(Dispatcher);
|
||||
FooterItems = new MenuItemCollection(Dispatcher);
|
||||
}
|
||||
|
||||
public IEnumerable<FolderOperationMenuItem> GetFolderContextMenuActions(IBaseFolderMenuItem folder)
|
||||
{
|
||||
if (folder == null || folder.SpecialFolderType == SpecialFolderType.Category || folder.SpecialFolderType == SpecialFolderType.More)
|
||||
@@ -148,183 +155,63 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
private async Task LoadAccountsAsync()
|
||||
{
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
// First clear all account menu items.
|
||||
MenuItems.RemoveRange(MenuItems.Where(a => a is IAccountMenuItem));
|
||||
|
||||
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false);
|
||||
|
||||
// Group accounts by merged account.
|
||||
var groupedAccounts = accounts.GroupBy(a => a.MergedInboxId);
|
||||
var groupedAccounts = accounts.GroupBy(a => a.MergedInboxId).OrderBy(a => a.Key != null);
|
||||
|
||||
foreach (var accountGroup in groupedAccounts)
|
||||
foreach (var group in groupedAccounts)
|
||||
{
|
||||
var mergedInbox = accountGroup.Key;
|
||||
var mergedInboxId = group.Key;
|
||||
|
||||
if (mergedInbox == null)
|
||||
if (mergedInboxId == null)
|
||||
{
|
||||
// This account is not merged. Create menu item for each account.
|
||||
foreach (var account in accountGroup)
|
||||
// Single accounts.
|
||||
// Preserve the order while listing.
|
||||
|
||||
var orderedGroup = group.OrderBy(a => a.Order);
|
||||
|
||||
foreach (var account in orderedGroup)
|
||||
{
|
||||
await CreateNestedAccountMenuItem(account);
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
MenuItems.Add(new AccountMenuItem(account, null));
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Accounts are merged. Create menu item for merged inbox.
|
||||
await CreateMergedInboxMenuItemAsync(accountGroup);
|
||||
// Merged accounts.
|
||||
var mergedInbox = group.First().MergedInbox;
|
||||
var mergedAccountMenuItem = new MergedAccountMenuItem(mergedInbox, group, null);
|
||||
|
||||
foreach (var accountItem in group)
|
||||
{
|
||||
mergedAccountMenuItem.SubMenuItems.Add(new AccountMenuItem(accountItem, mergedAccountMenuItem));
|
||||
}
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
MenuItems.Add(mergedAccountMenuItem);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Re-assign latest selected account menu item for containers to reflect changes better.
|
||||
// Also , this will ensure that the latest selected account is still selected after re-creation.
|
||||
|
||||
if (latestSelectedAccountMenuItem != null)
|
||||
{
|
||||
latestSelectedAccountMenuItem = MenuItems.GetAccountMenuItem(latestSelectedAccountMenuItem.EntityId.GetValueOrDefault());
|
||||
|
||||
if (latestSelectedAccountMenuItem != null)
|
||||
{
|
||||
latestSelectedAccountMenuItem.IsSelected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override async void OnFolderUpdated(MailItemFolder updatedFolder, MailAccount account)
|
||||
{
|
||||
base.OnFolderUpdated(updatedFolder, account);
|
||||
|
||||
if (updatedFolder == null) return;
|
||||
|
||||
var folderMenuItemsToUpdate = MenuItems.GetFolderItems(updatedFolder.Id);
|
||||
|
||||
foreach (var item in folderMenuItemsToUpdate)
|
||||
if (latestSelectedAccountMenuItem != null && MenuItems.TryGetAccountMenuItem(latestSelectedAccountMenuItem.EntityId.GetValueOrDefault(), out IAccountMenuItem foundLatestSelectedAccountMenuItem))
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
item.UpdateFolder(updatedFolder);
|
||||
foundLatestSelectedAccountMenuItem.IsSelected = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CreateMergedInboxMenuItemAsync(IEnumerable<MailAccount> accounts)
|
||||
{
|
||||
var mergedInbox = accounts.First().MergedInbox;
|
||||
var mergedInboxMenuItem = new MergedAccountMenuItem(mergedInbox, null); // Merged accounts are parentless.
|
||||
|
||||
// Store common special type folders.
|
||||
var commonFolderList = new Dictionary<MailAccount, IMailItemFolder>();
|
||||
|
||||
// Map special folder types for each account.
|
||||
var accountTreeList = new List<AccountFolderTree>();
|
||||
|
||||
foreach (var account in accounts)
|
||||
{
|
||||
var accountStructure = await _folderService.GetFolderStructureForAccountAsync(account.Id, includeHiddenFolders: true);
|
||||
accountTreeList.Add(accountStructure);
|
||||
}
|
||||
|
||||
var allFolders = accountTreeList.SelectMany(a => a.Folders);
|
||||
|
||||
// 1. Group sticky folders by special folder type.
|
||||
// 2. Merge all folders that are sticky and have the same special folder type.
|
||||
// 3. Add merged folder menu items to the merged inbox menu item.
|
||||
// 4. Add remaining sticky folders that doesn't exist in all accounts as plain folder menu items.
|
||||
|
||||
var stickyFolders = allFolders.Where(a => a.IsSticky);
|
||||
|
||||
var grouped = stickyFolders
|
||||
.GroupBy(a => a.SpecialFolderType)
|
||||
.Where(a => accountTreeList.All(b => b.HasSpecialTypeFolder(a.Key)));
|
||||
|
||||
var mergedInboxItems = grouped.Select(a => new MergedAccountFolderMenuItem(a.ToList(), mergedInboxMenuItem, mergedInbox));
|
||||
|
||||
// Shared common folders.
|
||||
foreach (var mergedInboxFolder in mergedInboxItems)
|
||||
{
|
||||
mergedInboxMenuItem.SubMenuItems.Add(mergedInboxFolder);
|
||||
}
|
||||
|
||||
var usedFolderIds = mergedInboxItems.SelectMany(a => a.Parameter.Select(a => a.Id));
|
||||
var remainingStickyFolders = stickyFolders.Where(a => !usedFolderIds.Contains(a.Id));
|
||||
|
||||
// Marked as sticky, but doesn't exist in all accounts. Add as plain folder menu item.
|
||||
foreach (var remainingStickyFolder in remainingStickyFolders)
|
||||
{
|
||||
var account = accounts.FirstOrDefault(a => a.Id == remainingStickyFolder.MailAccountId);
|
||||
mergedInboxMenuItem.SubMenuItems.Add(new FolderMenuItem(remainingStickyFolder, account, mergedInboxMenuItem));
|
||||
}
|
||||
|
||||
|
||||
var mergedMoreItem = new MergedAccountMoreFolderMenuItem(null, null, mergedInboxMenuItem);
|
||||
|
||||
// 2. Sticky folder preparation is done. Continue with regular account menu items.
|
||||
|
||||
foreach (var accountTree in accountTreeList)
|
||||
{
|
||||
var tree = accountTree.GetAccountMenuTree(mergedInboxMenuItem);
|
||||
|
||||
mergedMoreItem.SubMenuItems.Add(tree);
|
||||
}
|
||||
|
||||
mergedInboxMenuItem.SubMenuItems.Add(mergedMoreItem);
|
||||
|
||||
MenuItems.Add(mergedInboxMenuItem);
|
||||
|
||||
// Instead of refreshing all accounts, refresh the merged account only.
|
||||
// Receiver will handle it.
|
||||
|
||||
Messenger.Send(new RefreshUnreadCountsMessage(mergedInbox.Id));
|
||||
}
|
||||
|
||||
private async Task<IAccountMenuItem> CreateNestedAccountMenuItem(MailAccount account)
|
||||
{
|
||||
try
|
||||
{
|
||||
await accountInitFolderUpdateSlim.WaitAsync();
|
||||
|
||||
// Don't remove but replace existing record.
|
||||
int existingIndex = -1;
|
||||
|
||||
var existingAccountMenuItem = MenuItems.FirstOrDefault(a => a is AccountMenuItem accountMenuItem && accountMenuItem.Parameter.Id == account.Id);
|
||||
|
||||
if (existingAccountMenuItem != null)
|
||||
{
|
||||
existingIndex = MenuItems.IndexOf(existingAccountMenuItem);
|
||||
}
|
||||
|
||||
// Create account structure with integrator for this menu item.
|
||||
var accountStructure = await _folderService.GetFolderStructureForAccountAsync(account.Id, includeHiddenFolders: false);
|
||||
|
||||
var createdMenuItem = accountStructure.GetAccountMenuTree();
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
if (existingIndex >= 0)
|
||||
{
|
||||
createdMenuItem.IsExpanded = existingAccountMenuItem.IsExpanded;
|
||||
|
||||
MenuItems.RemoveAt(existingIndex);
|
||||
MenuItems.Insert(existingIndex, createdMenuItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
MenuItems.AddAccountMenuItem(createdMenuItem);
|
||||
}
|
||||
});
|
||||
|
||||
Messenger.Send(new RefreshUnreadCountsMessage(account.Id));
|
||||
|
||||
return createdMenuItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, WinoErrors.AccountStructureRender);
|
||||
}
|
||||
finally
|
||||
{
|
||||
accountInitFolderUpdateSlim.Release();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnNavigatedTo(mode, parameters);
|
||||
@@ -371,7 +258,6 @@ namespace Wino.Mail.ViewModels
|
||||
Type = SynchronizationType.Inbox
|
||||
};
|
||||
|
||||
|
||||
Messenger.Send(new NewSynchronizationRequested(options));
|
||||
}
|
||||
}
|
||||
@@ -392,9 +278,9 @@ namespace Wino.Mail.ViewModels
|
||||
// Find the account that this folder and mail belongs to.
|
||||
var account = await _mailService.GetMailAccountByUniqueIdAsync(accountExtendedMessage.NavigateMailItem.UniqueId).ConfigureAwait(false);
|
||||
|
||||
if (account != null && MenuItems.GetAccountMenuItem(account.Id) is IAccountMenuItem accountMenuItem)
|
||||
if (account != null && MenuItems.TryGetAccountMenuItem(account.Id, out IAccountMenuItem accountMenuItem))
|
||||
{
|
||||
ChangeLoadedAccount(accountMenuItem);
|
||||
await ChangeLoadedAccountAsync(accountMenuItem);
|
||||
|
||||
WeakReferenceMessenger.Default.Send(accountExtendedMessage);
|
||||
|
||||
@@ -402,7 +288,7 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessLaunchDefault();
|
||||
await ProcessLaunchDefaultAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,7 +305,7 @@ namespace Wino.Mail.ViewModels
|
||||
else
|
||||
{
|
||||
// Use default startup extending.
|
||||
ProcessLaunchDefault();
|
||||
await ProcessLaunchDefaultAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,7 +315,7 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessLaunchDefault()
|
||||
private async Task ProcessLaunchDefaultAsync()
|
||||
{
|
||||
if (PreferencesService.StartupEntityId == null)
|
||||
{
|
||||
@@ -452,7 +338,7 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
if (startupEntityMenuItem is IAccountMenuItem startupAccountMenuItem)
|
||||
{
|
||||
ChangeLoadedAccount(startupAccountMenuItem);
|
||||
await ChangeLoadedAccountAsync(startupAccountMenuItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,30 +356,49 @@ namespace Wino.Mail.ViewModels
|
||||
var args = new NavigateMailFolderEventArgs(baseFolderMenuItem, mailInitCompletionSource);
|
||||
|
||||
NavigationService.NavigateFolder(args);
|
||||
StatePersistenceService.CoreWindowTitle = $"{baseFolderMenuItem.AssignedAccountName} - {baseFolderMenuItem.FolderName}";
|
||||
|
||||
UpdateWindowTitleForFolder(baseFolderMenuItem);
|
||||
|
||||
// Wait until mail list page picks up the event and finish initialization of the mails.
|
||||
await mailInitCompletionSource.Task;
|
||||
}
|
||||
|
||||
private void UpdateWindowTitleForFolder(IBaseFolderMenuItem folder)
|
||||
{
|
||||
StatePersistenceService.CoreWindowTitle = $"{folder.AssignedAccountName} - {folder.FolderName}";
|
||||
}
|
||||
|
||||
private async Task NavigateSpecialFolderAsync(MailAccount account, SpecialFolderType specialFolderType, bool extendAccountMenu)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (account == null) return;
|
||||
|
||||
// If the account is inside a merged account, expand the merged account and navigate to shared folder.
|
||||
if (MenuItems.TryGetMergedAccountRootFolderMenuItemByAccountId(account.Id, specialFolderType, out MergedAccountFolderMenuItem mergedFolderItem))
|
||||
{
|
||||
mergedFolderItem.Expand();
|
||||
await NavigateFolderAsync(mergedFolderItem);
|
||||
}
|
||||
else if (MenuItems.TryGetRootSpecialFolderMenuItem(account.Id, specialFolderType, out FolderMenuItem rootFolderMenuItem))
|
||||
{
|
||||
// Account is not in merged account. Navigate to root folder.
|
||||
if (!MenuItems.TryGetAccountMenuItem(account.Id, out IAccountMenuItem accountMenuItem)) return;
|
||||
|
||||
rootFolderMenuItem.Expand();
|
||||
await NavigateFolderAsync(rootFolderMenuItem);
|
||||
// First make sure to navigate to the given accounnt.
|
||||
|
||||
if (latestSelectedAccountMenuItem != accountMenuItem)
|
||||
{
|
||||
await ChangeLoadedAccountAsync(accountMenuItem, false);
|
||||
}
|
||||
|
||||
// Account folders are already initialized.
|
||||
// Try to find the special folder menu item and navigate to it.
|
||||
|
||||
if (latestSelectedAccountMenuItem is IMergedAccountMenuItem latestMergedAccountMenuItem)
|
||||
{
|
||||
if (MenuItems.TryGetMergedAccountSpecialFolderMenuItem(latestSelectedAccountMenuItem.EntityId.Value, specialFolderType, out IBaseFolderMenuItem mergedFolderMenuItem))
|
||||
{
|
||||
await NavigateFolderAsync(mergedFolderMenuItem);
|
||||
}
|
||||
}
|
||||
else if (latestSelectedAccountMenuItem is IAccountMenuItem latestAccountMenuItem)
|
||||
{
|
||||
if (MenuItems.TryGetSpecialFolderMenuItem(account.Id, specialFolderType, out FolderMenuItem rootFolderMenuItem))
|
||||
{
|
||||
await NavigateFolderAsync(rootFolderMenuItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -566,7 +471,12 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
foreach (var folder in folderMenuItem.HandlingFolders)
|
||||
{
|
||||
await _winoRequestDelegator.ExecuteAsync(operation, folder);
|
||||
if (folder is MailItemFolder realFolder)
|
||||
{
|
||||
var folderPrepRequest = new FolderOperationPreperationRequest(operation, realFolder);
|
||||
|
||||
await _winoRequestDelegator.ExecuteAsync(folderPrepRequest);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh the pins.
|
||||
@@ -632,6 +542,11 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
await NavigateFolderAsync(baseFolderMenuItem);
|
||||
}
|
||||
else if (clickedMenuItem is MergedAccountMenuItem clickedMergedAccountMenuItem && latestSelectedAccountMenuItem != clickedMenuItem)
|
||||
{
|
||||
// Don't navigate to merged account if it's already selected. Preserve user's already selected folder.
|
||||
await ChangeLoadedAccountAsync(clickedMergedAccountMenuItem, true);
|
||||
}
|
||||
else if (clickedMenuItem is SettingsItem)
|
||||
{
|
||||
NavigationService.Navigate(WinoPage.SettingsPage);
|
||||
@@ -642,19 +557,23 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
else if (clickedMenuItem is IAccountMenuItem clickedAccountMenuItem && latestSelectedAccountMenuItem != clickedAccountMenuItem)
|
||||
{
|
||||
ChangeLoadedAccount(clickedAccountMenuItem);
|
||||
await ChangeLoadedAccountAsync(clickedAccountMenuItem);
|
||||
}
|
||||
}
|
||||
|
||||
private async void ChangeLoadedAccount(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true)
|
||||
private async Task ChangeLoadedAccountAsync(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true)
|
||||
{
|
||||
if (clickedBaseAccountMenuItem == null) return;
|
||||
|
||||
// User clicked an account in Windows Mail style menu.
|
||||
// List folders for this account and select Inbox.
|
||||
|
||||
await MenuItems.SetAccountMenuItemEnabledStatusAsync(false);
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
clickedBaseAccountMenuItem.IsEnabled = false;
|
||||
|
||||
if (latestSelectedAccountMenuItem != null)
|
||||
{
|
||||
latestSelectedAccountMenuItem.IsSelected = false;
|
||||
@@ -662,20 +581,18 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
clickedBaseAccountMenuItem.IsSelected = true;
|
||||
|
||||
|
||||
latestSelectedAccountMenuItem = clickedBaseAccountMenuItem;
|
||||
|
||||
|
||||
if (clickedBaseAccountMenuItem is AccountMenuItem accountMenuItem)
|
||||
{
|
||||
MenuItems.ReplaceFolders(accountMenuItem.SubMenuItems);
|
||||
}
|
||||
else if (clickedBaseAccountMenuItem is MergedAccountMenuItem mergedAccountMenuItem)
|
||||
{
|
||||
MenuItems.ReplaceFolders(mergedAccountMenuItem.SubMenuItems);
|
||||
}
|
||||
});
|
||||
|
||||
// Load account folder structure and replace the visible folders.
|
||||
var folders = await _folderService.GetAccountFoldersForDisplayAsync(clickedBaseAccountMenuItem);
|
||||
|
||||
// var unreadCountResult = await _folderService.GetUnreadItemCountResultsAsync(clickedBaseAccountMenuItem.HoldingAccounts.Select(a => a.Id)).ConfigureAwait(false);
|
||||
|
||||
await MenuItems.ReplaceFoldersAsync(folders);
|
||||
await UpdateUnreadItemCountAsync();
|
||||
await MenuItems.SetAccountMenuItemEnabledStatusAsync(true);
|
||||
|
||||
if (navigateInbox)
|
||||
{
|
||||
await Task.Yield();
|
||||
@@ -687,6 +604,67 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private async Task UpdateUnreadItemCountAsync()
|
||||
{
|
||||
// Get visible account menu items, ordered by merged accounts at the last.
|
||||
// We will update the unread counts for all single accounts and trigger UI refresh for merged menu items.
|
||||
var accountMenuItems = MenuItems.GetAllAccountMenuItems().OrderBy(a => a.HoldingAccounts.Count());
|
||||
|
||||
// Individually get all single accounts' unread counts.
|
||||
var accountIds = accountMenuItems.OfType<AccountMenuItem>().Select(a => a.AccountId);
|
||||
var unreadCountResult = await _folderService.GetUnreadItemCountResultsAsync(accountIds).ConfigureAwait(false);
|
||||
|
||||
// Recursively update all folders' unread counts to 0.
|
||||
// Query above only returns unread counts that exists. We need to reset the rest to 0 first.
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
MenuItems.UpdateUnreadItemCountsToZero();
|
||||
});
|
||||
|
||||
foreach (var accountMenuItem in accountMenuItems)
|
||||
{
|
||||
if (accountMenuItem is MergedAccountMenuItem mergedAccountMenuItem)
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
mergedAccountMenuItem.RefreshFolderItemCount();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
accountMenuItem.UnreadItemCount = unreadCountResult
|
||||
.Where(a => a.AccountId == accountMenuItem.HoldingAccounts.First().Id && a.SpecialFolderType == SpecialFolderType.Inbox)
|
||||
.Sum(a => a.UnreadItemCount);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Try to update unread counts for all folders.
|
||||
foreach (var unreadCount in unreadCountResult)
|
||||
{
|
||||
if (MenuItems.TryGetFolderMenuItem(unreadCount.FolderId, out IBaseFolderMenuItem folderMenuItem))
|
||||
{
|
||||
if (folderMenuItem is IMergedAccountFolderMenuItem mergedAccountFolderMenuItem)
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
folderMenuItem.UnreadItemCount = unreadCountResult.Where(a => a.SpecialFolderType == unreadCount.SpecialFolderType && mergedAccountFolderMenuItem.HandlingFolders.Select(b => b.Id).Contains(a.FolderId)).Sum(a => a.UnreadItemCount);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
folderMenuItem.UnreadItemCount = unreadCount.UnreadItemCount;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void NavigateInbox(IAccountMenuItem clickedBaseAccountMenuItem)
|
||||
{
|
||||
if (clickedBaseAccountMenuItem is AccountMenuItem accountMenuItem)
|
||||
@@ -741,7 +719,16 @@ namespace Wino.Mail.ViewModels
|
||||
else
|
||||
{
|
||||
// There are multiple accounts and there is no selection.
|
||||
Messenger.Send(new CreateNewMailWithMultipleAccountsRequested(accounts));
|
||||
// Don't list all accounts, but only accounts that belong to Merged Inbox.
|
||||
|
||||
if (latestSelectedAccountMenuItem is MergedAccountMenuItem selectedMergedAccountMenuItem)
|
||||
{
|
||||
var mergedAccounts = accounts.Where(a => a.MergedInboxId == selectedMergedAccountMenuItem.EntityId);
|
||||
|
||||
if (!mergedAccounts.Any()) return;
|
||||
|
||||
Messenger.Send(new CreateNewMailWithMultipleAccountsRequested(mergedAccounts.ToList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,18 +838,26 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
|
||||
protected override async void OnAccountUpdated(MailAccount updatedAccount)
|
||||
=> await ExecuteUIThread(() => { MenuItems.GetAccountMenuItem(updatedAccount.Id)?.UpdateAccount(updatedAccount); });
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
if (MenuItems.TryGetAccountMenuItem(updatedAccount.Id, out IAccountMenuItem foundAccountMenuItem))
|
||||
{
|
||||
foundAccountMenuItem.UpdateAccount(updatedAccount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnAccountRemoved(MailAccount removedAccount)
|
||||
=> Messenger.Send(new AccountsMenuRefreshRequested(true));
|
||||
|
||||
protected override async void OnAccountCreated(MailAccount createdAccount)
|
||||
{
|
||||
var createdMenuItem = await CreateNestedAccountMenuItem(createdAccount);
|
||||
await RecreateMenuItemsAsync();
|
||||
|
||||
if (createdMenuItem == null) return;
|
||||
if (!MenuItems.TryGetAccountMenuItem(createdAccount.Id, out IAccountMenuItem createdMenuItem)) return;
|
||||
|
||||
ChangeLoadedAccount(createdMenuItem);
|
||||
await ChangeLoadedAccountAsync(createdMenuItem);
|
||||
|
||||
// Each created account should start a new synchronization automatically.
|
||||
var options = new SynchronizationOptions()
|
||||
@@ -876,96 +871,9 @@ namespace Wino.Mail.ViewModels
|
||||
await _nativeAppService.PinAppToTaskbarAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates given single account menu item's unread count for all folders.
|
||||
/// </summary>
|
||||
/// <param name="accountMenuItem">Menu item to update unread count for.</param>
|
||||
/// <returns>Unread item count for Inbox only.</returns>
|
||||
private async Task<int> UpdateSingleAccountMenuItemUnreadCountAsync(AccountMenuItem accountMenuItem)
|
||||
{
|
||||
var accountId = accountMenuItem.AccountId;
|
||||
int inboxItemCount = 0;
|
||||
|
||||
// Get the folders needed to be refreshed.
|
||||
var allFolders = await _folderService.GetUnreadUpdateFoldersAsync(accountId);
|
||||
|
||||
foreach (var folder in allFolders)
|
||||
{
|
||||
var unreadItemCount = await UpdateAccountFolderUnreadItemCountAsync(accountMenuItem, folder.Id);
|
||||
|
||||
if (folder.SpecialFolderType == SpecialFolderType.Inbox)
|
||||
{
|
||||
inboxItemCount = unreadItemCount;
|
||||
|
||||
await ExecuteUIThread(() => { accountMenuItem.UnreadItemCount = unreadItemCount; });
|
||||
}
|
||||
}
|
||||
|
||||
return inboxItemCount;
|
||||
}
|
||||
|
||||
private async Task RefreshUnreadCountsForAccountAsync(Guid accountId)
|
||||
{
|
||||
// TODO: Merged accounts unread item count.
|
||||
|
||||
var accountMenuItem = MenuItems.GetAccountMenuItem(accountId);
|
||||
|
||||
if (accountMenuItem == null) return;
|
||||
|
||||
if (accountMenuItem is AccountMenuItem singleAccountMenuItem)
|
||||
{
|
||||
await UpdateSingleAccountMenuItemUnreadCountAsync(singleAccountMenuItem);
|
||||
|
||||
}
|
||||
else if (accountMenuItem is MergedAccountMenuItem mergedAccountMenuItem)
|
||||
{
|
||||
// Merged account.
|
||||
// Root account should include all parent accounts' unread item count.
|
||||
|
||||
int totalUnreadCount = 0;
|
||||
|
||||
var individualAccountMenuItems = mergedAccountMenuItem.GetAccountMenuItems();
|
||||
|
||||
foreach (var singleMenuItem in individualAccountMenuItems)
|
||||
{
|
||||
totalUnreadCount += await UpdateSingleAccountMenuItemUnreadCountAsync(singleMenuItem);
|
||||
}
|
||||
|
||||
// At this point all single accounts are calculated.
|
||||
// Merge account folder's menu items can be calculated from those values for precision.
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
mergedAccountMenuItem.RefreshFolderItemCount();
|
||||
mergedAccountMenuItem.UnreadItemCount = totalUnreadCount;
|
||||
});
|
||||
}
|
||||
|
||||
await ExecuteUIThread(async () => { await _notificationBuilder.UpdateTaskbarIconBadgeAsync(); });
|
||||
}
|
||||
|
||||
private async Task<int> UpdateAccountFolderUnreadItemCountAsync(AccountMenuItem accountMenuItem, Guid folderId)
|
||||
{
|
||||
if (accountMenuItem == null) return 0;
|
||||
|
||||
var folder = accountMenuItem.FlattenedFolderHierarchy.Find(a => a.Parameter?.Id == folderId);
|
||||
|
||||
if (folder == null) return 0;
|
||||
|
||||
int folderUnreadItemCount = 0;
|
||||
|
||||
folderUnreadItemCount = await _folderService.GetFolderNotificationBadgeAsync(folder.Parameter.Id).ConfigureAwait(false);
|
||||
|
||||
await ExecuteUIThread(() => { folder.UnreadItemCount = folderUnreadItemCount; });
|
||||
|
||||
return folderUnreadItemCount;
|
||||
}
|
||||
|
||||
private async Task SetAccountAttentionAsync(Guid accountId, AccountAttentionReason reason)
|
||||
{
|
||||
var accountMenuItem = MenuItems.GetAccountMenuItem(accountId);
|
||||
|
||||
if (accountMenuItem == null) return;
|
||||
if (!MenuItems.TryGetAccountMenuItem(accountId, out IAccountMenuItem accountMenuItem)) return;
|
||||
|
||||
var accountModel = accountMenuItem.HoldingAccounts.First(a => a.Id == accountId);
|
||||
|
||||
@@ -1025,7 +933,7 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
|
||||
public async void Receive(RefreshUnreadCountsMessage message)
|
||||
=> await RefreshUnreadCountsForAccountAsync(message.AccountId);
|
||||
=> await UpdateUnreadItemCountAsync();
|
||||
|
||||
public async void Receive(AccountsMenuRefreshRequested message)
|
||||
{
|
||||
@@ -1035,7 +943,7 @@ namespace Wino.Mail.ViewModels
|
||||
{
|
||||
if (MenuItems.FirstOrDefault(a => a is IAccountMenuItem) is IAccountMenuItem firstAccount)
|
||||
{
|
||||
ChangeLoadedAccount(firstAccount);
|
||||
await ChangeLoadedAccountAsync(firstAccount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1057,21 +965,48 @@ namespace Wino.Mail.ViewModels
|
||||
await CreateFooterItemsAsync();
|
||||
await RecreateMenuItemsAsync();
|
||||
|
||||
ChangeLoadedAccount(latestSelectedAccountMenuItem, navigateInbox: false);
|
||||
await ChangeLoadedAccountAsync(latestSelectedAccountMenuItem, navigateInbox: false);
|
||||
}
|
||||
|
||||
private void ReorderAccountMenuItems(Dictionary<Guid, int> newAccountOrder)
|
||||
{
|
||||
foreach (var item in newAccountOrder)
|
||||
{
|
||||
var menuItem = MenuItems.GetAccountMenuItem(item.Key);
|
||||
|
||||
if (menuItem == null) continue;
|
||||
if (!MenuItems.TryGetAccountMenuItem(item.Key, out IAccountMenuItem menuItem)) return;
|
||||
|
||||
MenuItems.Move(MenuItems.IndexOf(menuItem), item.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(AccountMenuItemsReordered message) => ReorderAccountMenuItems(message.newOrderDictionary);
|
||||
|
||||
private async void UpdateFolderCollection(IMailItemFolder updatedMailItemFolder)
|
||||
{
|
||||
var menuItem = MenuItems.GetAllFolderMenuItems(updatedMailItemFolder.Id);
|
||||
|
||||
if (!menuItem.Any()) return;
|
||||
|
||||
foreach (var item in menuItem)
|
||||
{
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
item.UpdateFolder(updatedMailItemFolder);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnFolderRenamed(IMailItemFolder mailItemFolder)
|
||||
{
|
||||
base.OnFolderRenamed(mailItemFolder);
|
||||
|
||||
UpdateFolderCollection(mailItemFolder);
|
||||
}
|
||||
|
||||
protected override void OnFolderSynchronizationEnabled(IMailItemFolder mailItemFolder)
|
||||
{
|
||||
base.OnFolderSynchronizationEnabled(mailItemFolder);
|
||||
|
||||
UpdateFolderCollection(mailItemFolder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ 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.Core.Domain.Models.Requests;
|
||||
using Wino.Core.Requests;
|
||||
@@ -15,16 +16,15 @@ namespace Wino.Mail.ViewModels
|
||||
IRecipient<AccountCreatedMessage>,
|
||||
IRecipient<AccountRemovedMessage>,
|
||||
IRecipient<AccountUpdatedMessage>,
|
||||
IRecipient<FolderAddedMessage>,
|
||||
IRecipient<FolderUpdatedMessage>,
|
||||
IRecipient<FolderRemovedMessage>,
|
||||
IRecipient<MailAddedMessage>,
|
||||
IRecipient<MailRemovedMessage>,
|
||||
IRecipient<MailUpdatedMessage>,
|
||||
IRecipient<MailDownloadedMessage>,
|
||||
IRecipient<DraftCreated>,
|
||||
IRecipient<DraftFailed>,
|
||||
IRecipient<DraftMapped>
|
||||
IRecipient<DraftMapped>,
|
||||
IRecipient<FolderRenamed>,
|
||||
IRecipient<FolderSynchronizationEnabled>
|
||||
{
|
||||
private IDispatcher _dispatcher;
|
||||
public IDispatcher Dispatcher
|
||||
@@ -65,13 +65,12 @@ namespace Wino.Mail.ViewModels
|
||||
protected virtual void OnAccountRemoved(MailAccount removedAccount) { }
|
||||
protected virtual void OnAccountUpdated(MailAccount updatedAccount) { }
|
||||
|
||||
protected virtual void OnFolderAdded(MailItemFolder addedFolder, MailAccount account) { }
|
||||
protected virtual void OnFolderRemoved(MailItemFolder removedFolder, MailAccount account) { }
|
||||
protected virtual void OnFolderUpdated(MailItemFolder updatedFolder, MailAccount account) { }
|
||||
|
||||
protected virtual void OnDraftCreated(MailCopy draftMail, MailAccount account) { }
|
||||
protected virtual void OnDraftFailed(MailCopy draftMail, MailAccount account) { }
|
||||
protected virtual void OnDraftMapped(string localDraftCopyId, string remoteDraftCopyId) { }
|
||||
protected virtual void OnFolderRenamed(IMailItemFolder mailItemFolder) { }
|
||||
protected virtual void OnFolderSynchronizationEnabled(IMailItemFolder mailItemFolder) { }
|
||||
|
||||
public void ReportUIChange<TMessage>(TMessage message) where TMessage : class, IUIMessage
|
||||
=> Messenger.Send(message);
|
||||
@@ -80,16 +79,17 @@ namespace Wino.Mail.ViewModels
|
||||
void IRecipient<AccountRemovedMessage>.Receive(AccountRemovedMessage message) => OnAccountRemoved(message.Account);
|
||||
void IRecipient<AccountUpdatedMessage>.Receive(AccountUpdatedMessage message) => OnAccountUpdated(message.Account);
|
||||
|
||||
void IRecipient<FolderAddedMessage>.Receive(FolderAddedMessage message) => OnFolderAdded(message.AddedFolder, message.Account);
|
||||
void IRecipient<FolderUpdatedMessage>.Receive(FolderUpdatedMessage message) => OnFolderUpdated(message.UpdatedFolder, message.Account);
|
||||
void IRecipient<FolderRemovedMessage>.Receive(FolderRemovedMessage message) => OnFolderAdded(message.RemovedFolder, message.Account);
|
||||
|
||||
void IRecipient<MailAddedMessage>.Receive(MailAddedMessage message) => OnMailAdded(message.AddedMail);
|
||||
void IRecipient<MailRemovedMessage>.Receive(MailRemovedMessage message) => OnMailRemoved(message.RemovedMail);
|
||||
void IRecipient<MailUpdatedMessage>.Receive(MailUpdatedMessage message) => OnMailUpdated(message.UpdatedMail);
|
||||
void IRecipient<MailDownloadedMessage>.Receive(MailDownloadedMessage message) => OnMailDownloaded(message.DownloadedMail);
|
||||
|
||||
void IRecipient<DraftMapped>.Receive(DraftMapped message) => OnDraftMapped(message.LocalDraftCopyId, message.RemoteDraftCopyId);
|
||||
void IRecipient<DraftFailed>.Receive(DraftFailed message) => OnDraftFailed(message.DraftMail, message.Account);
|
||||
void IRecipient<DraftCreated>.Receive(DraftCreated message) => OnDraftCreated(message.DraftMail, message.Account);
|
||||
|
||||
void IRecipient<FolderRenamed>.Receive(FolderRenamed message) => OnFolderRenamed(message.MailItemFolder);
|
||||
void IRecipient<FolderSynchronizationEnabled>.Receive(FolderSynchronizationEnabled message) => OnFolderSynchronizationEnabled(message.MailItemFolder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ 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;
|
||||
@@ -309,24 +310,24 @@ namespace Wino.Mail.ViewModels
|
||||
MailCollection.CoreDispatcher = Dispatcher;
|
||||
}
|
||||
|
||||
protected override async void OnFolderUpdated(MailItemFolder updatedFolder, MailAccount account)
|
||||
{
|
||||
base.OnFolderUpdated(updatedFolder, account);
|
||||
//protected override async void OnFolderUpdated(MailItemFolder updatedFolder, MailAccount account)
|
||||
//{
|
||||
// base.OnFolderUpdated(updatedFolder, account);
|
||||
|
||||
// Don't need to update if the folder update does not belong to the current folder menu item.
|
||||
if (ActiveFolder == null || updatedFolder == null || !ActiveFolder.HandlingFolders.Any(a => a.Id == updatedFolder.Id)) return;
|
||||
// // Don't need to update if the folder update does not belong to the current folder menu item.
|
||||
// if (ActiveFolder == null || updatedFolder == null || !ActiveFolder.HandlingFolders.Any(a => a.Id == updatedFolder.Id)) return;
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
ActiveFolder.UpdateFolder(updatedFolder);
|
||||
// await ExecuteUIThread(() =>
|
||||
// {
|
||||
// ActiveFolder.UpdateFolder(updatedFolder);
|
||||
|
||||
OnPropertyChanged(nameof(CanSynchronize));
|
||||
OnPropertyChanged(nameof(IsFolderSynchronizationEnabled));
|
||||
});
|
||||
// OnPropertyChanged(nameof(CanSynchronize));
|
||||
// OnPropertyChanged(nameof(IsFolderSynchronizationEnabled));
|
||||
// });
|
||||
|
||||
// Force synchronization after enabling the folder.
|
||||
SyncFolder();
|
||||
}
|
||||
// // Force synchronization after enabling the folder.
|
||||
// SyncFolder();
|
||||
//}
|
||||
|
||||
private async void UpdateBarMessage(InfoBarMessageType severity, string title, string message)
|
||||
{
|
||||
@@ -523,14 +524,6 @@ namespace Wino.Mail.ViewModels
|
||||
{
|
||||
await _folderService.ChangeFolderSynchronizationStateAsync(folder.Id, true);
|
||||
}
|
||||
|
||||
// TODO
|
||||
//ActiveFolder.IsSynchronizationEnabled = true;
|
||||
|
||||
//OnPropertyChanged(nameof(IsFolderSynchronizationEnabled));
|
||||
//OnPropertyChanged(nameof(CanSynchronize));
|
||||
|
||||
//SyncFolderCommand?.Execute(null);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
@@ -652,6 +645,8 @@ namespace Wino.Mail.ViewModels
|
||||
{
|
||||
base.OnMailRemoved(removedMail);
|
||||
|
||||
if (removedMail.AssignedAccount == null || removedMail.AssignedFolder == null) return;
|
||||
|
||||
// We should delete the items only if:
|
||||
// 1. They are deleted from the active folder.
|
||||
// 2. Deleted from draft or sent folder.
|
||||
@@ -954,6 +949,21 @@ namespace Wino.Mail.ViewModels
|
||||
public async void Receive(NewSynchronizationRequested message)
|
||||
=> await ExecuteUIThread(() => { OnPropertyChanged(nameof(CanSynchronize)); });
|
||||
|
||||
protected override async void OnFolderSynchronizationEnabled(IMailItemFolder mailItemFolder)
|
||||
{
|
||||
if (ActiveFolder?.EntityId != mailItemFolder.Id) return;
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
ActiveFolder.UpdateFolder(mailItemFolder);
|
||||
|
||||
OnPropertyChanged(nameof(CanSynchronize));
|
||||
OnPropertyChanged(nameof(IsFolderSynchronizationEnabled));
|
||||
});
|
||||
|
||||
SyncFolderCommand?.Execute(null);
|
||||
}
|
||||
|
||||
public async void Receive(AccountSynchronizerStateChanged message)
|
||||
=> await CheckIfAccountIsSynchronizingAsync();
|
||||
|
||||
|
||||
@@ -24,10 +24,12 @@ using Wino.Core.Extensions;
|
||||
using Wino.Core.Messages.Mails;
|
||||
using Wino.Core.Services;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.ViewModels.Messages;
|
||||
|
||||
namespace Wino.Mail.ViewModels
|
||||
{
|
||||
public partial class MailRenderingPageViewModel : BaseViewModel,
|
||||
IRecipient<NewMailItemRenderingRequestedEvent>,
|
||||
ITransferProgress // For listening IMAP message download progress.
|
||||
{
|
||||
private readonly IUnderlyingThemeService _underlyingThemeService;
|
||||
@@ -340,10 +342,6 @@ namespace Wino.Mail.ViewModels
|
||||
Crashes.TrackError(ex);
|
||||
Log.Error(ex, "Render Failed");
|
||||
}
|
||||
finally
|
||||
{
|
||||
StatePersistanceService.IsReadingMail = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -384,8 +382,7 @@ namespace Wino.Mail.ViewModels
|
||||
// Find the MIME for this item and render it.
|
||||
var mimeMessageInformation = await _mimeFileService.GetMimeMessageInformationAsync(mailItemViewModel.MailCopy.FileId,
|
||||
mailItemViewModel.AssignedAccount.Id,
|
||||
cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (mimeMessageInformation == null)
|
||||
{
|
||||
@@ -411,6 +408,8 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
Attachments.Clear();
|
||||
|
||||
Subject = message.Subject;
|
||||
|
||||
// TODO: FromName and FromAddress is probably not correct here for mail lists.
|
||||
@@ -447,6 +446,8 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(IsImageRenderingDisabled));
|
||||
|
||||
StatePersistanceService.IsReadingMail = true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -467,10 +468,14 @@ namespace Wino.Mail.ViewModels
|
||||
BCCItems.Clear();
|
||||
Attachments.Clear();
|
||||
MenuItems.Clear();
|
||||
|
||||
StatePersistanceService.IsReadingMail = false;
|
||||
}
|
||||
|
||||
private void LoadAddressInfo(InternetAddressList list, ObservableCollection<AddressInformation> collection)
|
||||
{
|
||||
collection.Clear();
|
||||
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item is MailboxAddress mailboxAddress)
|
||||
@@ -660,5 +665,7 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
// For upload.
|
||||
void ITransferProgress.Report(long bytesTransferred) { }
|
||||
|
||||
public async void Receive(NewMailItemRenderingRequestedEvent message) => await RenderAsync(message.MailItemViewModel, renderCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,8 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
var newName = await DialogService.ShowTextInputDialogAsync(EditingMergedAccount.MergedInbox.Name,
|
||||
Translator.DialogMessage_RenameLinkedAccountsTitle,
|
||||
Translator.DialogMessage_RenameLinkedAccountsMessage);
|
||||
Translator.DialogMessage_RenameLinkedAccountsMessage,
|
||||
Translator.FolderOperation_Rename);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(newName)) return;
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
|
||||
namespace Wino.Mail.ViewModels.Messages
|
||||
{
|
||||
/// <summary>
|
||||
/// When the rendering page is active, but new item is requested to be rendered.
|
||||
/// To not trigger navigation again and re-use existing Chromium.
|
||||
/// </summary>
|
||||
public class NewMailItemRenderingRequestedEvent
|
||||
{
|
||||
public NewMailItemRenderingRequestedEvent(MailItemViewModel mailItemViewModel)
|
||||
{
|
||||
MailItemViewModel = mailItemViewModel;
|
||||
}
|
||||
|
||||
public MailItemViewModel MailItemViewModel { get; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user