Some more cleanup.
This commit is contained in:
@@ -231,6 +231,7 @@ public partial class App : WinoApplication,
|
||||
if (windowManager.GetWindow(WinoWindowKind.Welcome) is not WelcomeWindow welcomeWindow)
|
||||
return;
|
||||
|
||||
welcomeWindow.PrepareForClose();
|
||||
welcomeWindow.AllowClose();
|
||||
welcomeWindow.Close();
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
{
|
||||
"sections": [
|
||||
{
|
||||
"title": "# Wino Calendar is here!",
|
||||
"title": "Wino Calendar is here!",
|
||||
"description": "You can now create local or remote CalDAV-compatible calendars, manage recurring events, and respond to invitations — all from within Wino.",
|
||||
"imageUrl": "ms-appx:///Assets/UpdateNotes/Images/Calendar.svg",
|
||||
"imageWidth": 128,
|
||||
"imageHeight": 128
|
||||
},
|
||||
{
|
||||
"title": "# S/MIME Signing & Encryption",
|
||||
"title": "S/MIME Signing & Encryption",
|
||||
"description": "Wino now supports signing and encrypting your emails with personal certificates. Keep your communications secure and verifiable.",
|
||||
"imageUrl": "ms-appx:///Assets/UpdateNotes/Images/Security.svg",
|
||||
"imageWidth": 128,
|
||||
"imageHeight": 128
|
||||
},
|
||||
{
|
||||
"title": "# Threaded Mail View",
|
||||
"title": "Threaded Mail View",
|
||||
"description": "Emails are now grouped by conversation, making it easier to follow long discussions without losing context.",
|
||||
"imageUrl": "ms-appx:///Assets/UpdateNotes/Images/Thread.svg",
|
||||
"imageWidth": 128,
|
||||
"imageHeight": 128
|
||||
},
|
||||
{
|
||||
"title": "# Smarter Notifications",
|
||||
"title": "Smarter Notifications",
|
||||
"description": "Act on your emails directly from toast notifications — mark as read, delete, or archive without opening the app.",
|
||||
"imageUrl": "ms-appx:///Assets/UpdateNotes/Images/Notification.svg",
|
||||
"imageWidth": 128,
|
||||
"imageHeight": 128
|
||||
},
|
||||
{
|
||||
"title": "# And much more...",
|
||||
"title": "And much more...",
|
||||
"description": "Folder management, swipe actions, keyboard shortcuts, a custom print dialog, and significant performance improvements are all included in this release.\n\nThank you for using Wino Mail!",
|
||||
"imageUrl": "ms-appx:///Assets/UpdateNotes/Images/More.svg",
|
||||
"imageWidth": 128,
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Wino.Mail.WinUI;
|
||||
|
||||
public partial class BasePage : Page, IRecipient<LanguageChanged>
|
||||
{
|
||||
private bool _isPreparedForClose;
|
||||
|
||||
public void Receive(LanguageChanged message)
|
||||
{
|
||||
OnLanguageChanged();
|
||||
@@ -31,6 +33,24 @@ public partial class BasePage : Page, IRecipient<LanguageChanged>
|
||||
protected virtual void UnregisterRecipients() { }
|
||||
|
||||
public virtual CoreBaseViewModel? AssociatedViewModel => null;
|
||||
|
||||
public virtual void PrepareForClose()
|
||||
{
|
||||
if (_isPreparedForClose)
|
||||
return;
|
||||
|
||||
_isPreparedForClose = true;
|
||||
|
||||
WeakReferenceMessenger.Default.Unregister<LanguageChanged>(this);
|
||||
UnregisterRecipients();
|
||||
}
|
||||
|
||||
protected void ResetPreparedForCloseState()
|
||||
{
|
||||
_isPreparedForClose = false;
|
||||
}
|
||||
|
||||
protected bool IsPreparedForClose => _isPreparedForClose;
|
||||
}
|
||||
|
||||
public abstract class BasePage<T> : BasePage where T : CoreBaseViewModel
|
||||
@@ -63,6 +83,7 @@ public abstract class BasePage<T> : BasePage where T : CoreBaseViewModel
|
||||
var mode = GetNavigationMode(e.NavigationMode);
|
||||
var parameter = e.Parameter;
|
||||
|
||||
ResetPreparedForCloseState();
|
||||
WeakReferenceMessenger.Default.Register<LanguageChanged>(this);
|
||||
RegisterRecipients();
|
||||
|
||||
@@ -76,14 +97,25 @@ public abstract class BasePage<T> : BasePage where T : CoreBaseViewModel
|
||||
var mode = GetNavigationMode(e.NavigationMode);
|
||||
var parameter = e.Parameter;
|
||||
|
||||
WeakReferenceMessenger.Default.Unregister<LanguageChanged>(this);
|
||||
UnregisterRecipients();
|
||||
|
||||
ViewModel.OnNavigatedFrom(mode, parameter);
|
||||
PrepareForClose(mode, parameter);
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
public override void PrepareForClose()
|
||||
{
|
||||
PrepareForClose(WinoNavigationMode.New, null);
|
||||
}
|
||||
|
||||
private void PrepareForClose(WinoNavigationMode mode, object? parameter)
|
||||
{
|
||||
if (IsPreparedForClose)
|
||||
return;
|
||||
|
||||
base.PrepareForClose();
|
||||
ViewModel.OnNavigatedFrom(mode, parameter!);
|
||||
}
|
||||
|
||||
private WinoNavigationMode GetNavigationMode(NavigationMode mode)
|
||||
{
|
||||
return (WinoNavigationMode)mode;
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
|
||||
namespace Wino.Mail.WinUI.Helpers;
|
||||
|
||||
internal static class WindowCleanupHelper
|
||||
{
|
||||
public static void CleanupFrame(Frame? frame)
|
||||
{
|
||||
if (frame == null)
|
||||
return;
|
||||
|
||||
CleanupObject(frame.Content);
|
||||
frame.BackStack.Clear();
|
||||
frame.ForwardStack.Clear();
|
||||
frame.Content = null;
|
||||
}
|
||||
|
||||
public static void CleanupObject(object? instance)
|
||||
{
|
||||
if (instance == null)
|
||||
return;
|
||||
|
||||
var visited = new HashSet<object>(ReferenceEqualityComparer.Instance);
|
||||
CleanupObject(instance, visited);
|
||||
}
|
||||
|
||||
private static void CleanupObject(object? instance, HashSet<object> visited)
|
||||
{
|
||||
if (instance == null || !visited.Add(instance))
|
||||
return;
|
||||
|
||||
switch (instance)
|
||||
{
|
||||
case Views.WinoAppShell shell:
|
||||
shell.PrepareForWindowClose();
|
||||
break;
|
||||
case Frame frame:
|
||||
CleanupFrame(frame);
|
||||
break;
|
||||
case BasePage page:
|
||||
page.PrepareForClose();
|
||||
break;
|
||||
}
|
||||
|
||||
if (instance is DependencyObject dependencyObject)
|
||||
{
|
||||
var childCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
CleanupObject(VisualTreeHelper.GetChild(dependencyObject, i), visited);
|
||||
}
|
||||
}
|
||||
|
||||
if (instance is IDisposable disposable)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class ReferenceEqualityComparer : IEqualityComparer<object>
|
||||
{
|
||||
public static ReferenceEqualityComparer Instance { get; } = new();
|
||||
|
||||
public new bool Equals(object? x, object? y) => ReferenceEquals(x, y);
|
||||
|
||||
public int GetHashCode(object obj) => System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(obj);
|
||||
}
|
||||
}
|
||||
@@ -221,12 +221,6 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
|
||||
set => SetPropertyAndSave(nameof(IsLoggingEnabled), value);
|
||||
}
|
||||
|
||||
public bool IsMailkitProtocolLoggerEnabled
|
||||
{
|
||||
get => _configurationService.Get(nameof(IsMailkitProtocolLoggerEnabled), false);
|
||||
set => SetPropertyAndSave(nameof(IsMailkitProtocolLoggerEnabled), value);
|
||||
}
|
||||
|
||||
public bool IsGravatarEnabled
|
||||
{
|
||||
get => _configurationService.Get(nameof(IsGravatarEnabled), true);
|
||||
|
||||
@@ -16,6 +16,7 @@ using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Extensions;
|
||||
using Wino.Mail.WinUI.Activation;
|
||||
using Wino.Mail.WinUI.Extensions;
|
||||
using Wino.Mail.WinUI.Helpers;
|
||||
using Wino.Mail.WinUI.Interfaces;
|
||||
using Wino.Mail.WinUI.Models;
|
||||
using Wino.Mail.WinUI.Views;
|
||||
@@ -46,6 +47,7 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
private ITitleBarSearchHost? _activeTitleBarSearchHost;
|
||||
private bool _isBackButtonVisibilityReady;
|
||||
private bool _isSynchronizingTitleBarSearch;
|
||||
private bool _isPreparedForClose;
|
||||
|
||||
public ShellWindow()
|
||||
{
|
||||
@@ -365,11 +367,18 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
|
||||
public void PrepareForClose()
|
||||
{
|
||||
if (_isPreparedForClose)
|
||||
return;
|
||||
|
||||
_isPreparedForClose = true;
|
||||
|
||||
if (MainShellFrame.Content is WinoAppShell shellPage)
|
||||
{
|
||||
shellPage.PrepareForWindowClose();
|
||||
}
|
||||
|
||||
WindowCleanupHelper.CleanupFrame(MainShellFrame);
|
||||
|
||||
_allowClose = true;
|
||||
}
|
||||
|
||||
@@ -384,6 +393,7 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
shellPage.PrepareForWindowClose();
|
||||
}
|
||||
|
||||
WindowCleanupHelper.CleanupFrame(MainShellFrame);
|
||||
UnregisterRecipients();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,19 +25,21 @@ public sealed partial class WelcomeHostPage : WelcomeHostPageAbstract,
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
WeakReferenceMessenger.Default.Register<BreadcrumbNavigationRequested>(this);
|
||||
WeakReferenceMessenger.Default.Register<BackBreadcrumNavigationRequested>(this);
|
||||
|
||||
ResetWizard();
|
||||
}
|
||||
|
||||
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
|
||||
protected override void RegisterRecipients()
|
||||
{
|
||||
base.RegisterRecipients();
|
||||
WeakReferenceMessenger.Default.Register<BreadcrumbNavigationRequested>(this);
|
||||
WeakReferenceMessenger.Default.Register<BackBreadcrumNavigationRequested>(this);
|
||||
}
|
||||
|
||||
protected override void UnregisterRecipients()
|
||||
{
|
||||
base.UnregisterRecipients();
|
||||
WeakReferenceMessenger.Default.Unregister<BreadcrumbNavigationRequested>(this);
|
||||
WeakReferenceMessenger.Default.Unregister<BackBreadcrumNavigationRequested>(this);
|
||||
|
||||
base.OnNavigatingFrom(e);
|
||||
}
|
||||
|
||||
public void Receive(BreadcrumbNavigationRequested message)
|
||||
|
||||
@@ -28,6 +28,7 @@ using Wino.Mail.ViewModels;
|
||||
using Wino.Mail.ViewModels.Data;
|
||||
using Wino.Mail.WinUI.ViewModels;
|
||||
using Wino.Mail.WinUI.Controls;
|
||||
using Wino.Mail.WinUI.Helpers;
|
||||
using Wino.MenuFlyouts;
|
||||
using Wino.MenuFlyouts.Context;
|
||||
using Wino.Messaging.Client.Accounts;
|
||||
@@ -127,6 +128,7 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
||||
|
||||
navigationView.MenuItemsSource = null;
|
||||
CalendarHostListView.ItemsSource = null;
|
||||
WindowCleanupHelper.CleanupFrame(InnerShellFrame);
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -3,6 +3,7 @@ using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Mail.WinUI.Helpers;
|
||||
using Wino.Mail.WinUI.Interfaces;
|
||||
using WinUIEx;
|
||||
|
||||
@@ -11,6 +12,7 @@ namespace Wino.Mail.WinUI;
|
||||
public sealed partial class WelcomeWindow : WindowEx
|
||||
{
|
||||
private bool _allowClose;
|
||||
private bool _isPreparedForClose;
|
||||
|
||||
public Frame GetRootFrame() => RootFrame;
|
||||
|
||||
@@ -25,6 +27,7 @@ public sealed partial class WelcomeWindow : WindowEx
|
||||
|
||||
ConfigureWindowChrome();
|
||||
AppWindow.Closing += OnAppWindowClosing;
|
||||
Closed += OnWindowClosed;
|
||||
}
|
||||
|
||||
private void ConfigureWindowChrome()
|
||||
@@ -55,4 +58,20 @@ public sealed partial class WelcomeWindow : WindowEx
|
||||
{
|
||||
_allowClose = true;
|
||||
}
|
||||
|
||||
public void PrepareForClose()
|
||||
{
|
||||
if (_isPreparedForClose)
|
||||
return;
|
||||
|
||||
_isPreparedForClose = true;
|
||||
WindowCleanupHelper.CleanupFrame(RootFrame);
|
||||
}
|
||||
|
||||
private void OnWindowClosed(object sender, WindowEventArgs e)
|
||||
{
|
||||
Closed -= OnWindowClosed;
|
||||
AppWindow.Closing -= OnAppWindowClosing;
|
||||
PrepareForClose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user