Dispose mail webviews when closing the shell
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
namespace Wino.Core.Domain.Enums;
|
||||||
|
|
||||||
|
public enum ThreeButtonDialogResult
|
||||||
|
{
|
||||||
|
Primary,
|
||||||
|
Secondary,
|
||||||
|
Cancel
|
||||||
|
}
|
||||||
@@ -19,6 +19,12 @@ public interface IMailDialogService : IDialogServiceBase
|
|||||||
{
|
{
|
||||||
void ShowReadOnlyCalendarMessage();
|
void ShowReadOnlyCalendarMessage();
|
||||||
Task<bool> ShowHardDeleteConfirmationAsync();
|
Task<bool> ShowHardDeleteConfirmationAsync();
|
||||||
|
Task<ThreeButtonDialogResult> ShowThreeButtonDialogAsync(string title,
|
||||||
|
string description,
|
||||||
|
string primaryButtonText,
|
||||||
|
string secondaryButtonText,
|
||||||
|
string cancelButtonText,
|
||||||
|
WinoCustomMessageDialogIcon? icon = null);
|
||||||
Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService);
|
Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService);
|
||||||
|
|
||||||
// Custom dialogs
|
// Custom dialogs
|
||||||
|
|||||||
@@ -305,6 +305,8 @@
|
|||||||
"DialogMessage_DeleteRecurringSeriesTitle": "Delete Recurring Series",
|
"DialogMessage_DeleteRecurringSeriesTitle": "Delete Recurring Series",
|
||||||
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
|
"DialogMessage_DiscardDraftConfirmationMessage": "This draft will be discarded. Do you want to continue?",
|
||||||
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
|
"DialogMessage_DiscardDraftConfirmationTitle": "Discard Draft",
|
||||||
|
"DialogMessage_CloseDraftWindowConfirmationMessage": "A draft is still open. Save it before closing the window?",
|
||||||
|
"DialogMessage_CloseDraftWindowConfirmationTitle": "Close Window",
|
||||||
"DialogMessage_EmptySubjectConfirmation": "Missing Subject",
|
"DialogMessage_EmptySubjectConfirmation": "Missing Subject",
|
||||||
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
|
"DialogMessage_EmptySubjectConfirmationMessage": "Message has no subject. Do you want to continue?",
|
||||||
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
|
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
|
||||||
|
|||||||
@@ -488,6 +488,12 @@ public partial class ComposePageViewModel : MailBaseViewModel,
|
|||||||
|
|
||||||
[RelayCommand(CanExecute = nameof(canSendMail))]
|
[RelayCommand(CanExecute = nameof(canSendMail))]
|
||||||
private async Task DiscardAsync()
|
private async Task DiscardAsync()
|
||||||
|
=> await DiscardDraftAsync();
|
||||||
|
|
||||||
|
public Task SaveDraftAsync()
|
||||||
|
=> UpdateMimeChangesAsync();
|
||||||
|
|
||||||
|
public async Task DiscardDraftAsync(bool requireConfirmation = true)
|
||||||
{
|
{
|
||||||
if (ComposingAccount == null)
|
if (ComposingAccount == null)
|
||||||
{
|
{
|
||||||
@@ -495,14 +501,19 @@ public partial class ComposePageViewModel : MailBaseViewModel,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var confirmation = await _dialogService.ShowConfirmationDialogAsync(Translator.DialogMessage_DiscardDraftConfirmationMessage,
|
var confirmation = !requireConfirmation || await _dialogService.ShowConfirmationDialogAsync(Translator.DialogMessage_DiscardDraftConfirmationMessage,
|
||||||
Translator.DialogMessage_DiscardDraftConfirmationTitle,
|
Translator.DialogMessage_DiscardDraftConfirmationTitle,
|
||||||
Translator.Buttons_Yes);
|
Translator.Buttons_Yes);
|
||||||
|
|
||||||
if (confirmation)
|
if (!confirmation)
|
||||||
{
|
{
|
||||||
isUpdatingMimeBlocked = true;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
isUpdatingMimeBlocked = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
// Don't send delete request for local drafts. Just delete the record and mime locally.
|
// Don't send delete request for local drafts. Just delete the record and mime locally.
|
||||||
if (CurrentMailDraftItem.MailCopy.IsLocalDraft)
|
if (CurrentMailDraftItem.MailCopy.IsLocalDraft)
|
||||||
{
|
{
|
||||||
@@ -514,6 +525,11 @@ public partial class ComposePageViewModel : MailBaseViewModel,
|
|||||||
await _worker.ExecuteAsync(deletePackage).ConfigureAwait(false);
|
await _worker.ExecuteAsync(deletePackage).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
isUpdatingMimeBlocked = false;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//public override void OnNavigatedFrom(NavigationMode mode, object parameters)
|
//public override void OnNavigatedFrom(NavigationMode mode, object parameters)
|
||||||
|
|||||||
@@ -137,6 +137,41 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
|||||||
WinoCustomMessageDialogIcon.Warning,
|
WinoCustomMessageDialogIcon.Warning,
|
||||||
Translator.Buttons_No);
|
Translator.Buttons_No);
|
||||||
|
|
||||||
|
public async Task<ThreeButtonDialogResult> ShowThreeButtonDialogAsync(string title,
|
||||||
|
string description,
|
||||||
|
string primaryButtonText,
|
||||||
|
string secondaryButtonText,
|
||||||
|
string cancelButtonText,
|
||||||
|
WinoCustomMessageDialogIcon? icon = null)
|
||||||
|
{
|
||||||
|
var informationContainer = new CustomMessageDialogInformationContainer(
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
icon ?? WinoCustomMessageDialogIcon.Information,
|
||||||
|
false);
|
||||||
|
|
||||||
|
var dialog = new ContentDialog
|
||||||
|
{
|
||||||
|
Style = ApplicationResourceManager.GetResource<Style>("WinoDialogStyle"),
|
||||||
|
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme(),
|
||||||
|
DefaultButton = ContentDialogButton.Primary,
|
||||||
|
PrimaryButtonText = primaryButtonText,
|
||||||
|
SecondaryButtonText = secondaryButtonText,
|
||||||
|
CloseButtonText = cancelButtonText,
|
||||||
|
ContentTemplate = ApplicationResourceManager.GetResource<DataTemplate>("CustomWinoContentDialogContentTemplate"),
|
||||||
|
Content = informationContainer
|
||||||
|
};
|
||||||
|
|
||||||
|
var dialogResult = await HandleDialogPresentationAsync(dialog);
|
||||||
|
|
||||||
|
return dialogResult switch
|
||||||
|
{
|
||||||
|
ContentDialogResult.Primary => ThreeButtonDialogResult.Primary,
|
||||||
|
ContentDialogResult.Secondary => ThreeButtonDialogResult.Secondary,
|
||||||
|
_ => ThreeButtonDialogResult.Cancel
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts)
|
public async Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts)
|
||||||
{
|
{
|
||||||
var accountPicker = new AccountPickerDialog(availableAccounts)
|
var accountPicker = new AccountPickerDialog(availableAccounts)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
|
|||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.UI.Windowing;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
@@ -20,8 +21,10 @@ using Wino.Mail.WinUI.Helpers;
|
|||||||
using Wino.Mail.WinUI.Interfaces;
|
using Wino.Mail.WinUI.Interfaces;
|
||||||
using Wino.Mail.WinUI.Models;
|
using Wino.Mail.WinUI.Models;
|
||||||
using Wino.Mail.WinUI.Views;
|
using Wino.Mail.WinUI.Views;
|
||||||
|
using Wino.Messaging.Client.Mails;
|
||||||
using Wino.Messaging.Client.Shell;
|
using Wino.Messaging.Client.Shell;
|
||||||
using Wino.Messaging.UI;
|
using Wino.Messaging.UI;
|
||||||
|
using Wino.Views.Mail;
|
||||||
using WinUIEx;
|
using WinUIEx;
|
||||||
|
|
||||||
namespace Wino.Mail.WinUI;
|
namespace Wino.Mail.WinUI;
|
||||||
@@ -356,12 +359,16 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
|||||||
SynchronizeTitleBarSearchBox();
|
SynchronizeTitleBarSearchBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnAppWindowClosing(object sender, Microsoft.UI.Windowing.AppWindowClosingEventArgs e)
|
private async void OnAppWindowClosing(object sender, AppWindowClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (_allowClose || (Application.Current as App)?.IsExiting == true)
|
if (_allowClose || (Application.Current as App)?.IsExiting == true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
e.Cancel = true;
|
e.Cancel = true;
|
||||||
|
|
||||||
|
if (!await PrepareMailModeForHideAsync())
|
||||||
|
return;
|
||||||
|
|
||||||
var windowManager = WinoApplication.Current.Services.GetService<IWinoWindowManager>();
|
var windowManager = WinoApplication.Current.Services.GetService<IWinoWindowManager>();
|
||||||
windowManager?.HideWindow(this);
|
windowManager?.HideWindow(this);
|
||||||
}
|
}
|
||||||
@@ -398,6 +405,55 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
|||||||
UnregisterRecipients();
|
UnregisterRecipients();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task<bool> PrepareMailModeForHideAsync()
|
||||||
|
{
|
||||||
|
if (MainShellFrame.Content is not WinoAppShell shellPage)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (shellPage.GetShellFrame().Content is not MailListPage mailListPage)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var renderingFrame = mailListPage.FindName("RenderingFrame") as Frame;
|
||||||
|
|
||||||
|
if (renderingFrame?.Content is ComposePage composePage)
|
||||||
|
{
|
||||||
|
var closeResult = await MailDialogService.ShowThreeButtonDialogAsync(
|
||||||
|
Translator.DialogMessage_CloseDraftWindowConfirmationTitle,
|
||||||
|
Translator.DialogMessage_CloseDraftWindowConfirmationMessage,
|
||||||
|
Translator.Buttons_Save,
|
||||||
|
Translator.Buttons_Discard,
|
||||||
|
Translator.Buttons_Cancel,
|
||||||
|
WinoCustomMessageDialogIcon.Warning);
|
||||||
|
|
||||||
|
if (closeResult == ThreeButtonDialogResult.Cancel)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (closeResult == ThreeButtonDialogResult.Primary)
|
||||||
|
{
|
||||||
|
await composePage.ViewModel.SaveDraftAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await composePage.ViewModel.DiscardDraftAsync(requireConfirmation: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MailDialogService.InfoBarMessage(Translator.GeneralTitle_Error, ex.Message, InfoBarMessageType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await mailListPage.ViewModel.MailCollection.UnselectAllAsync();
|
||||||
|
WeakReferenceMessenger.Default.Send(new DisposeRenderingFrameRequested());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private void RegisterRecipients()
|
private void RegisterRecipients()
|
||||||
{
|
{
|
||||||
WeakReferenceMessenger.Default.Register<TitleBarShellContentUpdated>(this);
|
WeakReferenceMessenger.Default.Register<TitleBarShellContentUpdated>(this);
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
|||||||
{
|
{
|
||||||
private const double RENDERING_COLUMN_MIN_WIDTH = 375;
|
private const double RENDERING_COLUMN_MIN_WIDTH = 375;
|
||||||
private const int SELECTION_SETTLE_DELAY_MS = 120;
|
private const int SELECTION_SETTLE_DELAY_MS = 120;
|
||||||
private const int RENDERING_FRAME_RELEASE_DELAY_MS = 2000;
|
|
||||||
private int _idleNavigationRequestVersion = 0;
|
private int _idleNavigationRequestVersion = 0;
|
||||||
private int _mailActivationRequestVersion = 0;
|
private int _mailActivationRequestVersion = 0;
|
||||||
private IPopoutClient? _activePopoutClient;
|
private IPopoutClient? _activePopoutClient;
|
||||||
@@ -546,11 +545,6 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(RENDERING_FRAME_RELEASE_DELAY_MS);
|
|
||||||
|
|
||||||
if (requestVersion != _idleNavigationRequestVersion) return;
|
|
||||||
if (ViewModel.MailCollection.SelectedItemsCount != 0) return;
|
|
||||||
|
|
||||||
// Ensure rendering frame actually navigates away from Compose/Rendering pages.
|
// Ensure rendering frame actually navigates away from Compose/Rendering pages.
|
||||||
// Otherwise those pages keep their messenger registrations alive.
|
// Otherwise those pages keep their messenger registrations alive.
|
||||||
ViewModel.NavigationService.Navigate(WinoPage.IdlePage, null, NavigationReferenceFrame.RenderingFrame, NavigationTransitionType.DrillIn);
|
ViewModel.NavigationService.Navigate(WinoPage.IdlePage, null, NavigationReferenceFrame.RenderingFrame, NavigationTransitionType.DrillIn);
|
||||||
|
|||||||
Reference in New Issue
Block a user