diff --git a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml
index 00e7acbae2..b001dc1cc8 100644
--- a/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml
+++ b/src/UniGetUI.Avalonia/Assets/Styles/Styles.Common.axaml
@@ -495,6 +495,39 @@
+
+
+
+
+
-
-
-
diff --git a/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml b/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml
index 73579cf2e3..4187f29c79 100644
--- a/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml
+++ b/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml
@@ -25,16 +25,61 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
-
+
@@ -93,19 +162,22 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
+
+
+
+
+
@@ -338,11 +423,16 @@
+
-
-
-
+
diff --git a/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml.cs b/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml.cs
index 3b26bef9f8..c5049ad177 100644
--- a/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml.cs
+++ b/src/UniGetUI.Avalonia/Views/SoftwarePages/SoftwareCatalogPage.axaml.cs
@@ -1,6 +1,10 @@
+using System.ComponentModel;
+using Avalonia;
using Avalonia.Controls;
using Avalonia.Threading;
+using UniGetUI.Avalonia.Extensions;
using UniGetUI.Avalonia.ViewModels.Pages;
+using UniGetUI.Core.SettingsEngine;
using UniGetUI.Core.Tools;
using UniGetUI.PackageEngine.PackageLoader;
@@ -8,9 +12,12 @@ namespace UniGetUI.Avalonia.Views.Pages;
public partial class SoftwareCatalogPage : UserControl, IEnterLeaveListener, ISearchBoxPage
{
+ private const string FilterPaneWidthKey = "SoftwareCatalog";
+ private const double DefaultFilterPaneWidth = 220;
private readonly SoftwareCatalogViewModel _viewModel = new();
private readonly DispatcherTimer _stateTimer = new() { Interval = TimeSpan.FromSeconds(2) };
private InstalledPackagesLoader? _loader;
+ private double _savedFilterPaneWidth = DefaultFilterPaneWidth;
public string QueryBackup
{
@@ -27,6 +34,47 @@ public SoftwareCatalogPage()
InitializeComponent();
DataContext = _viewModel;
_stateTimer.Tick += (_, _) => _viewModel.UpdateStates();
+
+ // Restore the per-page filter pane width from settings.
+ var savedWidth = Settings.GetDictionaryItem(Settings.K.SidepanelWidths, FilterPaneWidthKey);
+ if (savedWidth >= 100) _savedFilterPaneWidth = savedWidth;
+ _viewModel.TrackedFilterPaneWidth = _savedFilterPaneWidth;
+
+ // Persist the dragged width and snap the pane closed when it is dragged below the minimum.
+ FilteringPanel.ColumnDefinitions[0]
+ .GetObservable(ColumnDefinition.WidthProperty)
+ .SubscribeValue(width =>
+ {
+ if (!_viewModel.IsFilterPaneOpen) return;
+ if (width.IsAbsolute && width.Value >= 100)
+ {
+ _savedFilterPaneWidth = width.Value;
+ _viewModel.TrackedFilterPaneWidth = width.Value;
+ Settings.SetDictionaryItem(Settings.K.SidepanelWidths, FilterPaneWidthKey, (int)width.Value);
+ }
+ else if (width.IsAbsolute && width.Value < 100)
+ {
+ _savedFilterPaneWidth = DefaultFilterPaneWidth;
+ _viewModel.TrackedFilterPaneWidth = DefaultFilterPaneWidth;
+ _viewModel.IsFilterPaneOpen = false;
+ }
+ });
+
+ _viewModel.PropertyChanged += OnViewModelPropertyChanged;
+ UpdateFilterPaneColumn(_viewModel.IsFilterPaneOpen);
+ }
+
+ private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == nameof(SoftwareCatalogViewModel.IsFilterPaneOpen))
+ UpdateFilterPaneColumn(_viewModel.IsFilterPaneOpen);
+ }
+
+ private void UpdateFilterPaneColumn(bool open)
+ {
+ if (FilteringPanel.ColumnDefinitions.Count < 2) return;
+ FilteringPanel.ColumnDefinitions[0].Width = open ? new GridLength(_savedFilterPaneWidth) : new GridLength(0);
+ FilteringPanel.ColumnDefinitions[1].Width = open ? new GridLength(12) : new GridLength(0);
}
public void OnEnter()