diff --git a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs index d70dd0513f..cfa40a472d 100644 --- a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs @@ -577,6 +577,13 @@ public void LoadDefaultPage() NavigateTo(type); } + private void ReleaseWebViewPage(Control? leftPage) + { + if (leftPage is null) return; + if (ReferenceEquals(leftPage, HelpPage)) { HelpPage?.Dispose(); HelpPage = null; } + else if (ReferenceEquals(leftPage, ReleaseNotesPage)) { ReleaseNotesPage?.Dispose(); ReleaseNotesPage = null; } + } + private Control GetPageForType(PageType type) => type switch { @@ -644,6 +651,10 @@ public void NavigateTo(PageType newPage_t, bool toHistory = true) _oldPage = _currentPage; _currentPage = newPage_t; + // #5129: Help/ReleaseNotes each host a WebView2 that the control never releases on + // detach. Drop the page when leaving so its WebView2 process cluster gets freed. + ReleaseWebViewPage(oldPage); + if (toHistory && _oldPage is not PageType.Null) { NavigationHistory.Add(_oldPage); diff --git a/src/UniGetUI.Avalonia/Views/Pages/HelpPage.axaml.cs b/src/UniGetUI.Avalonia/Views/Pages/HelpPage.axaml.cs index e68467488e..c0eb7de3f7 100644 --- a/src/UniGetUI.Avalonia/Views/Pages/HelpPage.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/Pages/HelpPage.axaml.cs @@ -4,11 +4,12 @@ namespace UniGetUI.Avalonia.Views.Pages; -public partial class HelpPage : UserControl, IEnterLeaveListener +public partial class HelpPage : UserControl, IEnterLeaveListener, IDisposable { private readonly HelpPageViewModel _viewModel; private string _pendingNavigation = HelpPageViewModel.HelpBaseUrl; private bool _adapterReady; + private bool _disposed; public HelpPage() { @@ -77,4 +78,15 @@ private void HomeButton_Click(object? sender, RoutedEventArgs e) => private void ReloadButton_Click(object? sender, RoutedEventArgs e) => WebViewControl.Refresh(); + + // Detach the WebView so its WebView2 host/controller is released; the page is + // rebuilt fresh on next visit (MainWindowViewModel drops the cached instance). + public void Dispose() + { + if (_disposed) return; + _disposed = true; + if (!OperatingSystem.IsLinux()) + WebViewControl.Stop(); + WebViewBorder.Child = null; + } } diff --git a/src/UniGetUI.Avalonia/Views/Pages/ReleaseNotesPage.axaml.cs b/src/UniGetUI.Avalonia/Views/Pages/ReleaseNotesPage.axaml.cs index a0b5e5e04c..b3099cc789 100644 --- a/src/UniGetUI.Avalonia/Views/Pages/ReleaseNotesPage.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/Pages/ReleaseNotesPage.axaml.cs @@ -3,11 +3,12 @@ namespace UniGetUI.Avalonia.Views.Pages; -public partial class ReleaseNotesPage : UserControl, IEnterLeaveListener +public partial class ReleaseNotesPage : UserControl, IEnterLeaveListener, IDisposable { private readonly ReleaseNotesPageViewModel _viewModel; private bool _loaded; private bool _adapterReady; + private bool _disposed; public ReleaseNotesPage() { @@ -52,4 +53,15 @@ public void OnEnter() } public void OnLeave() { } + + // Detach the WebView so its WebView2 host/controller is released; the page is + // rebuilt fresh on next visit (MainWindowViewModel drops the cached instance). + public void Dispose() + { + if (_disposed) return; + _disposed = true; + if (!OperatingSystem.IsLinux()) + WebViewControl.Stop(); + WebViewBorder.Child = null; + } }