From 85ef2a7fa9885c14eb2e3b5c8bcef88808aa4277 Mon Sep 17 00:00:00 2001 From: Meteoni-San <141850520+Meteony@users.noreply.github.com> Date: Sat, 19 Sep 2026 07:11:43 +0000 Subject: [PATCH 01/19] fix: restyle operation output dialog family --- .../OperationHistoryLogDialog.cs | 46 +++++++++++---- .../DialogPages/OperationFailedDialog.axaml | 56 ++++++++++++++++--- .../OperationFailedDialog.axaml.cs | 3 + .../DialogPages/OperationOutputWindow.axaml | 11 ++-- 4 files changed, 93 insertions(+), 23 deletions(-) diff --git a/src/UniGetUI.Avalonia/Infrastructure/OperationHistoryLogDialog.cs b/src/UniGetUI.Avalonia/Infrastructure/OperationHistoryLogDialog.cs index a76be453dd..33d559b408 100644 --- a/src/UniGetUI.Avalonia/Infrastructure/OperationHistoryLogDialog.cs +++ b/src/UniGetUI.Avalonia/Infrastructure/OperationHistoryLogDialog.cs @@ -4,6 +4,7 @@ using Avalonia.Layout; using Avalonia.Media; using Avalonia.Platform.Storage; +using Avalonia.Styling; using UniGetUI.Avalonia.ViewModels.Pages.LogPages; using UniGetUI.Avalonia.Views; using UniGetUI.Avalonia.Views.Controls; @@ -21,9 +22,9 @@ public static async Task ShowAsync(OperationHistoryRecord record) if (MainWindow.Instance is not { } owner) return; - bool dark = ThemeHelper.IsDark; - var defaultBrush = new SolidColorBrush(dark ? Color.FromRgb(250, 250, 250) : Color.FromRgb(0, 0, 0)); - var errorBrush = new SolidColorBrush(dark ? Color.FromRgb(255, 80, 80) : Color.FromRgb(205, 0, 0)); + ThemeVariant theme = ThemeHelper.Variant; + IBrush defaultBrush = LookupBrush("TextFillColorPrimaryBrush", theme, Brushes.White); + IBrush errorBrush = LookupBrush("StatusErrorForeground", theme, Brushes.Red); var lines = record.Output .Select(l => new LogLineItem(l.Text.Replace("\r", "").Replace("\n", ""), @@ -45,7 +46,8 @@ public static async Task ShowAsync(OperationHistoryRecord record) MinWidth = 460, MinHeight = 300, Title = CoreTools.Translate("Operation log") + (target.Length > 0 ? $" — {target}" : ""), - Background = Application.Current?.FindResource("AppDialogBackground") as IBrush, + TitleMargin = new Thickness(24, 0, 0, 0), + Background = LookupBrush("AppDialogBackground", theme, Brushes.Transparent), }; var copyButton = CreateDialogButton(CoreTools.Translate("Copy to clipboard")); @@ -69,6 +71,7 @@ public static async Task ShowAsync(OperationHistoryRecord record) }; var closeButton = CreateDialogButton(CoreTools.Translate("Close"), 100); + closeButton.Classes.Remove("secondary-action"); closeButton.Classes.Add("accent"); closeButton.Click += (_, _) => dialog.Close(); @@ -84,7 +87,7 @@ public static async Task ShowAsync(OperationHistoryRecord record) { CornerRadius = new CornerRadius(8), ClipToBounds = true, - Background = Application.Current?.FindResource("AppDialogDarkBackground") as IBrush, + Background = LookupBrush("AppWindowBackground", theme, Brushes.Transparent), Child = editor, }; Grid.SetRow(editorBorder, 1); @@ -96,19 +99,41 @@ public static async Task ShowAsync(OperationHistoryRecord record) HorizontalAlignment = HorizontalAlignment.Right, Children = { closeButton }, }; - Grid.SetRow(footer, 2); - dialog.Content = new Grid + var body = new Grid { - Margin = new Thickness(16), - RowDefinitions = new RowDefinitions("Auto,*,Auto"), + Margin = new Thickness(24, 0, 24, 24), + RowDefinitions = new RowDefinitions("Auto,*"), RowSpacing = 10, - Children = { toolbar, editorBorder, footer }, + Children = { toolbar, editorBorder }, + }; + Grid.SetRow(body, 0); + + var footerSurface = new Border + { + Background = LookupBrush("AppWindowBackground", theme, Brushes.Transparent), + Padding = new Thickness(24), + Child = footer, + }; + Grid.SetRow(footerSurface, 1); + + dialog.Content = new Grid + { + RowDefinitions = new RowDefinitions("*,Auto"), + Children = { body, footerSurface }, }; await dialog.ShowDialog(owner); } + private static IBrush LookupBrush(string key, ThemeVariant theme, IBrush fallback) + { + if (Application.Current?.TryGetResource(key, theme, out var resource) == true && + resource is IBrush brush) + return brush; + return fallback; + } + private static Button CreateDialogButton(string content, double minWidth = 0) => new() { Content = content, @@ -117,6 +142,7 @@ public static async Task ShowAsync(OperationHistoryRecord record) Padding = new Thickness(11, 5, 11, 6), CornerRadius = new CornerRadius(4), FontSize = 14, + Classes = { "secondary-action" }, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, }; diff --git a/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml b/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml index af6f1eb7fb..174e386b3a 100644 --- a/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml +++ b/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml @@ -4,16 +4,56 @@ xmlns:automation="clr-namespace:Avalonia.Automation;assembly=Avalonia.Controls" xmlns:controls="using:UniGetUI.Avalonia.Views.Controls" x:Class="UniGetUI.Avalonia.Views.DialogPages.OperationFailedDialog" - MaxWidth="800" + MaxWidth="850" MinWidth="500" - MaxHeight="550" + MaxHeight="490" MinHeight="300" + TitleMargin="24,0,0,0" Background="{DynamicResource AppDialogBackground}"> - + + + + + + + + + + + - + @@ -21,19 +61,19 @@ + Background="{DynamicResource AppWindowBackground}"> + Background="{DynamicResource AppWindowBackground}"> diff --git a/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml.cs b/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml.cs index f6bba12f6c..d5db85b6be 100644 --- a/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/DialogPages/OperationFailedDialog.axaml.cs @@ -37,6 +37,7 @@ public OperationFailedDialog(AbstractOperation operation) Content = CoreTools.Translate("Close"), HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Center, + Classes = { "operation-dialog-action" }, }; closeButton.Click += (_, _) => Close(); @@ -149,6 +150,7 @@ private Control SimpleRetryButton(AbstractOperation operation, string retryMode, Content = label, HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Center, + Classes = { "operation-dialog-action" }, }; button.Click += (_, _) => { @@ -170,6 +172,7 @@ string label Content = label, HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Center, + Classes = { "operation-dialog-action" }, }; splitButton.Click += (_, _) => { diff --git a/src/UniGetUI.Avalonia/Views/DialogPages/OperationOutputWindow.axaml b/src/UniGetUI.Avalonia/Views/DialogPages/OperationOutputWindow.axaml index 4f7399e96e..3df604d694 100644 --- a/src/UniGetUI.Avalonia/Views/DialogPages/OperationOutputWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/DialogPages/OperationOutputWindow.axaml @@ -6,17 +6,18 @@ xmlns:controls="using:UniGetUI.Avalonia.Views.Controls" x:Class="UniGetUI.Avalonia.Views.DialogPages.OperationOutputWindow" x:DataType="vm:OperationOutputViewModel" - MaxWidth="700" - MinWidth="400" - MaxHeight="500" + MaxWidth="780" + MinWidth="460" + MaxHeight="520" MinHeight="300" + TitleMargin="24,0,0,0" Background="{DynamicResource AppDialogBackground}" Title="{Binding Title}"> - + Background="{DynamicResource AppWindowBackground}"> From 9fac06bc707e5c99cfbc6a1ce98d52c4604c246f Mon Sep 17 00:00:00 2001 From: Meteoni-San <141850520+Meteony@users.noreply.github.com> Date: Sat, 19 Sep 2026 07:12:18 +0000 Subject: [PATCH 02/19] fix: refine package manager page controls --- .../SettingsPages/PackageManagerPage.axaml.cs | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/PackageManagerPage.axaml.cs b/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/PackageManagerPage.axaml.cs index 7db4aaa81f..c6aa9a7d30 100644 --- a/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/PackageManagerPage.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/PackageManagerPage.axaml.cs @@ -88,7 +88,13 @@ private void BuildPage() Grid.SetColumnSpan(execHint, 2); execGrid.Children.Add(execHint); - var execCombo = new ComboBox { HorizontalAlignment = HorizontalAlignment.Stretch }; + var execCombo = new ComboBox + { + HorizontalAlignment = HorizontalAlignment.Stretch, + MinHeight = 32, + CornerRadius = new CornerRadius(4), + Padding = new Thickness(10, 4, 8, 5), + }; AutomationProperties.SetName(execCombo, CoreTools.Translate("Select the executable to be used. The following list shows the executables found by UniGetUI")); foreach (var path in manager.FindCandidateExecutableFiles()) AddExecutablePathItem(execCombo, path); @@ -122,6 +128,8 @@ private void BuildPage() Content = CoreTools.Translate("Browse..."), IsEnabled = customPathsAllowed, Margin = new Thickness(8, 0, 0, 0), + MinWidth = 96, + Classes = { "secondary-action" }, }; browseExecutableButton.Click += async (_, _) => { @@ -258,7 +266,13 @@ private void BuildPage() (CoreTools.Translate("Custom..."), "custom"), ]; - var ageCombo = new ComboBox { MinWidth = 200 }; + var ageCombo = new ComboBox + { + MinWidth = 200, + MinHeight = 32, + CornerRadius = new CornerRadius(4), + Padding = new Thickness(10, 4, 8, 5), + }; AutomationProperties.SetName(ageCombo, CoreTools.Translate("Minimum age for updates")); foreach (var (label, _) in ageItems) ageCombo.Items.Add(label); @@ -271,6 +285,7 @@ private void BuildPage() var customAgeInput = new TextBox { MinWidth = 200, + Classes = { "search-field-standalone" }, PlaceholderText = CoreTools.Translate("e.g. 10"), [AutomationProperties.NameProperty] = CoreTools.Translate("Custom minimum age (days)"), Text = CoreSettings.GetDictionaryItem( @@ -622,6 +637,7 @@ private ButtonCard BuildVcpkgRootCard() Content = CoreTools.Translate("Reset"), IsEnabled = ViewModel.IsCustomVcpkgRootSet, Margin = new Thickness(4, 0), + Classes = { "secondary-action" }, }; AutomationProperties.SetName(resetBtn, CoreTools.Translate("Reset vcpkg root location")); var openBtn = new Button @@ -629,6 +645,7 @@ private ButtonCard BuildVcpkgRootCard() Content = CoreTools.Translate("Open"), IsEnabled = ViewModel.IsCustomVcpkgRootSet, Margin = new Thickness(4, 0), + Classes = { "secondary-action" }, }; AutomationProperties.SetName(openBtn, CoreTools.Translate("Open vcpkg root location")); From 804517cbee12db1532b48fef1acd393cd97b771b Mon Sep 17 00:00:00 2001 From: Meteoni-San <141850520+Meteony@users.noreply.github.com> Date: Sat, 19 Sep 2026 07:14:37 +0000 Subject: [PATCH 03/19] ui: restore compact WinUI operation cards --- src/UniGetUI.Avalonia/Views/MainWindow.axaml | 237 ++++++++++-------- .../Views/MainWindow.axaml.cs | 2 +- 2 files changed, 133 insertions(+), 106 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml index b0c1d91b12..7bab59ea78 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml @@ -87,6 +87,21 @@ + + + + @@ -262,61 +277,78 @@ Margin="8,4,8,4"> - + - - - - - - - - - - - - - - + + + + + @@ -324,21 +356,16 @@ - - - + + + + + + - + + diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs index b8060789c8..5dd1c1d088 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs @@ -408,7 +408,7 @@ private double ComputeOperationsAutoHeight() return 0; const double chrome = 42; - const double fallbackRow = 68; + const double fallbackRow = 58; double rows = 0; int visible = Math.Min(count, 3); From c4d5e0c0f714ee0842fb34624cae027712f8712f Mon Sep 17 00:00:00 2001 From: Meteoni-San <141850520+Meteony@users.noreply.github.com> Date: Sat, 19 Sep 2026 07:16:58 +0000 Subject: [PATCH 04/19] ui: add WinUI splitter drag tracks --- src/UniGetUI.Avalonia/Views/MainWindow.axaml | 32 +++++++++++++++++-- .../Views/MainWindow.axaml.cs | 4 +++ .../SoftwarePages/AbstractPackagesPage.axaml | 31 ++++++++++++++++-- .../AbstractPackagesPage.axaml.cs | 4 +-- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml index 7bab59ea78..958ea2094a 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml @@ -102,6 +102,30 @@ + + + + @@ -166,7 +190,7 @@ - + + automation:AutomationProperties.AccessibilityView="Raw"/> + + + + @@ -244,7 +268,7 @@ + ColumnDefinitions="220,12,*"> @@ -478,11 +502,12 @@ + ResizeDirection="Columns"/> Date: Sat, 19 Sep 2026 18:12:51 +0800 Subject: [PATCH 05/19] fix: restore targeted layouts and responsive behavior --- src/UniGetUI.Avalonia/Views/MainWindow.axaml | 245 ++++++++---------- .../Views/MainWindow.axaml.cs | 18 +- .../SettingsPages/InstallOptionsPanel.axaml | 4 + .../InstallOptionsPanel.axaml.cs | 22 +- .../Views/SidebarView.axaml.cs | 2 + .../SoftwarePages/AbstractPackagesPage.axaml | 4 +- 6 files changed, 149 insertions(+), 146 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml index 958ea2094a..8fd8604c2d 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml @@ -87,30 +87,15 @@ - - - - - + + + @@ -198,7 +205,7 @@ ViewModel.Sidebar.Mode = SidebarViewModel.ParseMode(Settings.GetValue(Settings.K.NavMenuMode)); - // Light-dismiss: clicking outside the open flyout closes it (no darkening — the layer is transparent). + // Let the splitter hover surface replace the separator visually without changing its layout thickness. private void OperationsSplitter_PointerEntered(object? sender, PointerEventArgs e) - => OperationsPanelBorder.BorderThickness = new Thickness(0); + => OperationsPanelBorder.Classes.Set("splitter-active", true); private void OperationsSplitter_PointerExited(object? sender, PointerEventArgs e) - => OperationsPanelBorder.BorderThickness = new Thickness(0, 1, 0, 0); + => OperationsPanelBorder.Classes.Set("splitter-active", false); + // Light-dismiss: clicking outside the open flyout closes it (no darkening — the layer is transparent). private void FlyoutDismiss_PointerPressed(object? sender, PointerPressedEventArgs e) => ViewModel.Sidebar.IsPaneOpen = false; diff --git a/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml b/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml index be9016d666..f91712be12 100644 --- a/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml +++ b/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml @@ -507,7 +507,7 @@ From 5e1c48890061785501410db45a92ff0206ff1924 Mon Sep 17 00:00:00 2001 From: Meteoni-San <141850520+Meteony@users.noreply.github.com> Date: Sat, 19 Sep 2026 16:05:15 +0000 Subject: [PATCH 14/19] fix: match WinUI restore-down caption glyph --- src/UniGetUI.Avalonia/Views/MainWindow.axaml | 29 ++++++++++++------- .../Views/MainWindow.axaml.cs | 14 ++++----- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml index 55e8c68942..a37a409494 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml @@ -721,22 +721,29 @@ Width="10" Height="2" HorizontalAlignment="Center" VerticalAlignment="Center"/> - + - + diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs index facc8d217d..467bce795e 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs @@ -167,6 +167,15 @@ public MainWindow() Instance = this; DataContext = new MainWindowViewModel(); InitializeComponent(); + if (OperatingSystem.IsWindows()) + { + // WinUI's caption button uses ChromeRestore (U+E923). Windows 11 supplies it + // through Segoe Fluent Icons; Windows 10 exposes the same symbol in MDL2 Assets. + RestoreIcon.FontFamily = new FontFamily( + OperatingSystem.IsWindowsVersionAtLeast(10, 0, 22000) + ? "Segoe Fluent Icons" + : "Segoe MDL2 Assets"); + } SetupTitleBar(); SetupTitleBarFocusOpacity(); SetupResponsiveRail(); @@ -974,7 +983,8 @@ private void MaximizeButton_Click(object? sender, RoutedEventArgs e) private void UpdateMaximizeButtonState(bool isMaximized) { MaximizeIcon.IsVisible = !isMaximized; - RestoreIcon.IsVisible = isMaximized; + RestoreIcon.IsVisible = isMaximized && OperatingSystem.IsWindows(); + RestoreFallbackIcon.IsVisible = isMaximized && !OperatingSystem.IsWindows(); string label = CoreTools.Translate(isMaximized ? "Restore" : "Maximize"); ToolTip.SetTip(MaximizeButton, label); From 341968657daa1c5962d56e92d27ec0bf37971dc2 Mon Sep 17 00:00:00 2001 From: Meteoni-San <141850520+Meteony@users.noreply.github.com> Date: Sat, 19 Sep 2026 16:16:59 +0000 Subject: [PATCH 16/19] fix: round and align keyboard focus visuals --- .../Assets/Styles/Styles.Common.axaml | 39 ++++++++++++++++++- .../SoftwarePages/AbstractPackagesPage.axaml | 4 ++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml index eeb8ca641d..cfa2ea3998 100644 --- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml +++ b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml @@ -1,6 +1,7 @@ + xmlns:controls="using:UniGetUI.Avalonia.Views.Controls" + xmlns:primitives="using:Avalonia.Controls.Primitives"> @@ -366,6 +367,22 @@ + + + @@ -504,6 +521,24 @@ + + + - - - + + +