diff --git a/src/UniGetUI.Avalonia.slnx b/src/UniGetUI.Avalonia.slnx index f56b39c19..dfd391425 100644 --- a/src/UniGetUI.Avalonia.slnx +++ b/src/UniGetUI.Avalonia.slnx @@ -165,6 +165,12 @@ + + + + + + diff --git a/src/UniGetUI.Avalonia/Views/Controls/Settings/SettingsPageButton.cs b/src/UniGetUI.Avalonia/Views/Controls/Settings/SettingsPageButton.cs index 0f7345e01..fa65be12d 100644 --- a/src/UniGetUI.Avalonia/Views/Controls/Settings/SettingsPageButton.cs +++ b/src/UniGetUI.Avalonia/Views/Controls/Settings/SettingsPageButton.cs @@ -46,6 +46,7 @@ public SettingsPageButton() IconType.SaveAs => "save_as", IconType.OpenFolder => "open_folder", IconType.Experimental => "experimental", + IconType.ClipboardList => "clipboard_list", _ => icon.ToString().ToLower(), }; } diff --git a/src/UniGetUI.Avalonia/Views/Controls/SvgIcon.cs b/src/UniGetUI.Avalonia/Views/Controls/SvgIcon.cs index a225cc6c2..001b3bc0d 100644 --- a/src/UniGetUI.Avalonia/Views/Controls/SvgIcon.cs +++ b/src/UniGetUI.Avalonia/Views/Controls/SvgIcon.cs @@ -104,6 +104,20 @@ private void LoadSvg(string? uri) catch { /* skip malformed path data */ } } } + foreach (XElement el in doc.Descendants(ns + "ellipse")) + { + if (double.TryParse(el.Attribute("cx")?.Value, System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture, out double cx) && + double.TryParse(el.Attribute("cy")?.Value, System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture, out double cy) && + double.TryParse(el.Attribute("rx")?.Value, System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture, out double rx) && + double.TryParse(el.Attribute("ry")?.Value, System.Globalization.NumberStyles.Any, + System.Globalization.CultureInfo.InvariantCulture, out double ry)) + { + _geometries.Add(new EllipseGeometry(new Rect(cx - rx, cy - ry, rx * 2, ry * 2))); + } + } } catch { diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml b/src/UniGetUI.Avalonia/Views/MainWindow.axaml index 7cefffcd1..9d8e2f9ee 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml @@ -9,14 +9,14 @@ mc:Ignorable="d" d:DesignWidth="1200" d:DesignHeight="750" x:Class="UniGetUI.Avalonia.Views.MainWindow" x:DataType="vm:MainWindowViewModel" + Title="UniGetUI" Width="1450" MinWidth="700" - MinHeight="500" - ExtendClientAreaToDecorationsHint="True" - ExtendClientAreaTitleBarHeightHint="-1"> + MinHeight="500"> - @@ -204,17 +204,20 @@ - - + - - + - + - - + + + + + + + + + + + + + + diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs index 9bc2da9b9..7a0e8eb9c 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs @@ -1,10 +1,14 @@ +using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Media; using UniGetUI.Avalonia.ViewModels; using UniGetUI.Avalonia.Views.Pages; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; +using UniGetUI.Core.Tools; namespace UniGetUI.Avalonia.Views; @@ -44,6 +48,7 @@ public MainWindow() Instance = this; DataContext = new MainWindowViewModel(); InitializeComponent(); + SetupTitleBar(); KeyDown += Window_KeyDown; } @@ -81,6 +86,54 @@ private void Window_KeyDown(object? sender, KeyEventArgs e) } } + private void SetupTitleBar() + { + if (OperatingSystem.IsMacOS()) + { + // macOS: extend into the native title bar area. + // WindowDecorationMargin.Top drives TitleBarGrid.Height via binding. + // Traffic lights sit on the left → keep the 65 px HamburgerPanel margin. + // Avatar can be a bit taller to fill the deeper title bar. + ExtendClientAreaToDecorationsHint = true; + ExtendClientAreaTitleBarHeightHint = -1; + AvatarControl.Height = 36; + } + else if (OperatingSystem.IsLinux()) + { + // Linux: remove the native title bar entirely; our toolbar is the + // only chrome. Custom min/max/close buttons appear on the right. + WindowDecorations = WindowDecorations.None; + TitleBarGrid.ClearValue(HeightProperty); + TitleBarGrid.Height = 44; + HamburgerPanel.Margin = new Thickness(10, 0, 8, 0); + AvatarControl.Height = 32; + LinuxWindowButtons.IsVisible = true; + MainContentGrid.Margin = new Thickness(0, 44, 0, 0); + // Keep maximize icon in sync with window state + this.GetObservable(WindowStateProperty).Subscribe(state => + { + MaximizeIcon.Data = Geometry.Parse( + state == WindowState.Maximized + ? "M2,0 H10 V8 H2 Z M0,2 H8 V10 H0 Z" // restore: two overlapping squares + : "M0,0 H10 V10 H0 Z"); // maximise: single square + ToolTip.SetTip( + MaximizeButton, + CoreTools.Translate(state == WindowState.Maximized ? "Restore" : "Maximize")); + }); + } + } + + private void MinimizeButton_Click(object? sender, RoutedEventArgs e) + => WindowState = WindowState.Minimized; + + private void MaximizeButton_Click(object? sender, RoutedEventArgs e) + => WindowState = WindowState == WindowState.Maximized + ? WindowState.Normal + : WindowState.Maximized; + + private void CloseButton_Click(object? sender, RoutedEventArgs e) + => Close(); + private void TitleBar_PointerPressed(object? sender, PointerPressedEventArgs e) { if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) diff --git a/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/SettingsHomepage.axaml b/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/SettingsHomepage.axaml index bb1fd43b5..a389c504a 100644 --- a/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/SettingsHomepage.axaml +++ b/src/UniGetUI.Avalonia/Views/Pages/SettingsPages/SettingsHomepage.axaml @@ -71,7 +71,7 @@ diff --git a/src/UniGetUI.Avalonia/Views/SidebarView.axaml b/src/UniGetUI.Avalonia/Views/SidebarView.axaml index 5c7dba381..899c1af73 100644 --- a/src/UniGetUI.Avalonia/Views/SidebarView.axaml +++ b/src/UniGetUI.Avalonia/Views/SidebarView.axaml @@ -26,7 +26,7 @@ ToolTip.Tip="{t:Translate Discover Packages}"> - + - + - + - + diff --git a/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml b/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml index 22ae3eefd..fd222103e 100644 --- a/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml +++ b/src/UniGetUI.Avalonia/Views/SoftwarePages/AbstractPackagesPage.axaml @@ -186,7 +186,7 @@ CornerRadius="4" IsChecked="{Binding IsFilterPaneOpen, Mode=TwoWay}"> - + @@ -258,7 +258,7 @@ Background="{DynamicResource SettingsCardBackground}"> - + @@ -325,7 +325,7 @@ Background="{DynamicResource SettingsCardBackground}"> - + @@ -632,7 +632,8 @@ + + + + + + + \ No newline at end of file diff --git a/src/UniGetUI/Assets/Symbols/Filter.svg b/src/UniGetUI/Assets/Symbols/Filter.svg new file mode 100644 index 000000000..149af0245 --- /dev/null +++ b/src/UniGetUI/Assets/Symbols/Filter.svg @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/UniGetUI/Assets/Symbols/InstalledPackages.svg b/src/UniGetUI/Assets/Symbols/InstalledPackages.svg new file mode 100644 index 000000000..cdae590c0 --- /dev/null +++ b/src/UniGetUI/Assets/Symbols/InstalledPackages.svg @@ -0,0 +1,10 @@ + + + + + + diff --git a/src/UniGetUI/Assets/Symbols/PackagesBundle.svg b/src/UniGetUI/Assets/Symbols/PackagesBundle.svg new file mode 100644 index 000000000..d43e65961 --- /dev/null +++ b/src/UniGetUI/Assets/Symbols/PackagesBundle.svg @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/src/UniGetUI/Assets/Symbols/Sources.svg b/src/UniGetUI/Assets/Symbols/Sources.svg new file mode 100644 index 000000000..ba3717395 --- /dev/null +++ b/src/UniGetUI/Assets/Symbols/Sources.svg @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file