From d534e0dae3fc4d5d9b93b0d10a9cd041d144e627 Mon Sep 17 00:00:00 2001 From: GabrielDuf Date: Thu, 23 Jul 2026 16:02:24 -0400 Subject: [PATCH 1/2] improve ignored-updates dialog sizing and theming --- .../ManageIgnoredUpdatesWindow.axaml | 55 ++++--------------- .../ManageIgnoredUpdatesWindow.axaml.cs | 52 +++++++++++++++--- .../Views/MainWindow.axaml.cs | 6 +- .../AbstractPackagesPage.axaml.cs | 2 +- .../SettingsEngine_Names.cs | 2 + 5 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml b/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml index c1cf31e938..2b8204bc6b 100644 --- a/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml @@ -3,36 +3,16 @@ xmlns:automation="clr-namespace:Avalonia.Automation;assembly=Avalonia.Controls" xmlns:vm="using:UniGetUI.Avalonia.ViewModels" xmlns:controls="using:UniGetUI.Avalonia.Views.Controls" - xmlns:chrome="using:Avalonia.Controls.Chrome" xmlns:t="using:UniGetUI.Avalonia.MarkupExtensions" x:Class="UniGetUI.Avalonia.Views.ManageIgnoredUpdatesWindow" x:DataType="vm:ManageIgnoredUpdatesViewModel" - Width="1100" MinWidth="520" + Width="850" MinWidth="520" Height="500" MinHeight="280" CanResize="True" ShowInTaskbar="False" - Background="{DynamicResource IgnoredDialogBackground}" + Background="{DynamicResource AppDialogBackground}" WindowStartupLocation="CenterOwner" - Title=""> - - - - - - - - - - - - - - - - - - + Title="{Binding Title}"> - - - - - - - + + - + diff --git a/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml.cs index ec23a3c172..bbac588cbc 100644 --- a/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/DialogPages/ManageIgnoredUpdatesWindow.axaml.cs @@ -2,27 +2,65 @@ using Avalonia.Interactivity; using Avalonia.Threading; using UniGetUI.Avalonia.ViewModels; +using UniGetUI.Core.Logging; +using UniGetUI.Core.SettingsEngine; namespace UniGetUI.Avalonia.Views; public partial class ManageIgnoredUpdatesWindow : Window { - public ManageIgnoredUpdatesWindow() + public ManageIgnoredUpdatesWindow(Window? owner = null) { var vm = new ManageIgnoredUpdatesViewModel(); DataContext = vm; InitializeComponent(); + UniGetUI.Avalonia.Infrastructure.MicaWindowHelper.Apply(this); - // Drop the OS title-bar strip (its background clashed with the dialog) but keep - // the system min/max/close buttons floating over the extended client area. Default - // WindowDecorations (Full) keeps the system buttons; extending the client area - // merges the title-bar region into the content. - ExtendClientAreaToDecorationsHint = true; - ExtendClientAreaTitleBarHeightHint = -1; + // Set the size before the window opens so CenterOwner positions it correctly. + ApplyInitialSize(owner); vm.CloseRequested += (_, _) => Close(); } + // Restore the user's last size, falling back to the XAML default, and never open larger + // than the owner window (recovers the adaptive sizing of the pre-Avalonia overlay). + private void ApplyInitialSize(Window? owner) + { + double width = Width; + double height = Height; + + string saved = Settings.GetValue(Settings.K.IgnoredUpdatesWindowSize); + if (!string.IsNullOrEmpty(saved)) + { + string[] parts = saved.Split(','); + if (parts.Length == 2 && int.TryParse(parts[0], out int w) && int.TryParse(parts[1], out int h)) + { + width = w; + height = h; + } + } + + if (owner is not null) + { + width = Math.Min(width, owner.Width - 40); + height = Math.Min(height, owner.Height - 40); + } + + Width = Math.Max(MinWidth, width); + Height = Math.Max(MinHeight, height); + } + + protected override void OnClosing(WindowClosingEventArgs e) + { + // Persist only the normal (non-maximized) size so the dialog reopens as the user left it. + if (WindowState == WindowState.Normal) + { + try { Settings.SetValue(Settings.K.IgnoredUpdatesWindowSize, $"{(int)Width},{(int)Height}"); } + catch (Exception ex) { Logger.Error(ex); } + } + base.OnClosing(e); + } + protected override void OnOpened(EventArgs e) { base.OnOpened(e); diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs index acffd36d58..3ed1fcbf07 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs @@ -452,7 +452,11 @@ private void SetupTitleBarFocusOpacity() // Match WinUI's inactive Mica appearance without invoking the permanent, global // NotifyMicaUnavailable() fallback used when composition actually fails (#5111). - InactiveMicaFallback.Opacity = MicaWindowHelper.IsMicaEnabled() && !active ? 1.0 : 0.0; + // A partial (not full) overlay so the inactive window still keeps some of the Mica + // tint instead of flattening to solid grey. Skip it entirely while a modal dialog is + // open: the window deactivates but shouldn't grey out behind its own dialog. + InactiveMicaFallback.Opacity = + MicaWindowHelper.IsMicaEnabled() && !active && OwnedWindows.Count == 0 ? 0.4 : 0.0; }); private void SetupTitleBar() diff --git a/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml.cs b/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml.cs index 8fb99b27a4..e7b3936fea 100644 --- a/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml.cs @@ -49,7 +49,7 @@ protected AbstractPackagesPage(PackagesPageData data) ViewModel.ManageIgnoredRequested += async () => { if (GetMainWindow() is { } win) - await new ManageIgnoredUpdatesWindow().ShowDialog(win); + await new ManageIgnoredUpdatesWindow(win).ShowDialog(win); }; // "New version" sort option is only relevant on the updates page diff --git a/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs b/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs index 4affb62113..cb52486f04 100644 --- a/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs +++ b/src/UniGetUI.Core.Settings/SettingsEngine_Names.cs @@ -59,6 +59,7 @@ public enum K OperationHistory, StartupPage, WindowGeometry, + IgnoredUpdatesWindowSize, ChangeBackupFileName, CurrentSessionToken, IgnoredPackageUpdates, @@ -178,6 +179,7 @@ public static string ResolveKey(K key) K.OperationHistory => "OperationHistory", K.StartupPage => "StartupPage", K.WindowGeometry => "WindowGeometry", + K.IgnoredUpdatesWindowSize => "IgnoredUpdatesWindowSize", K.ChangeBackupFileName => "ChangeBackupFileName", K.CurrentSessionToken => "CurrentSessionToken", K.IgnoredPackageUpdates => "IgnoredPackageUpdates", From ca3ce31b8a0218f66535977d29e8f3600c738d80 Mon Sep 17 00:00:00 2001 From: GabrielDuf Date: Thu, 23 Jul 2026 16:18:25 -0400 Subject: [PATCH 2/2] Only skip inactive overlay for modal dialogs, not modeless children --- src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs index 3ed1fcbf07..d70fd266d5 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs @@ -453,12 +453,23 @@ private void SetupTitleBarFocusOpacity() // Match WinUI's inactive Mica appearance without invoking the permanent, global // NotifyMicaUnavailable() fallback used when composition actually fails (#5111). // A partial (not full) overlay so the inactive window still keeps some of the Mica - // tint instead of flattening to solid grey. Skip it entirely while a modal dialog is - // open: the window deactivates but shouldn't grey out behind its own dialog. + // tint instead of flattening to solid grey. Skip it while a modal dialog is open: the + // window deactivates but shouldn't grey out behind its own dialog. Modeless owned + // windows (operation output/failure) don't count — the main window should still grey + // when the user switches to another application. InactiveMicaFallback.Opacity = - MicaWindowHelper.IsMicaEnabled() && !active && OwnedWindows.Count == 0 ? 0.4 : 0.0; + MicaWindowHelper.IsMicaEnabled() && !active && !HasOpenModalDialog() ? 0.4 : 0.0; }); + // True when a window opened modally (ShowDialog) over this one is currently open. + private bool HasOpenModalDialog() + { + foreach (var owned in OwnedWindows) + if (owned.IsDialog) + return true; + return false; + } + private void SetupTitleBar() { if (OperatingSystem.IsMacOS())