Refactor settings management in PLib video library manager. Replace dialog-based settings with a single-panel overlay for improved user experience. Update MainWindow and SettingsView to support new settings panel, and adjust ViewModels accordingly. Enhance README.md to reflect these changes.

This commit is contained in:
Leonid Pershin
2026-08-08 12:40:53 +03:00
parent 186dd900e1
commit 835937357e
12 changed files with 441 additions and 216 deletions
+17
View File
@@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:PLib.Desktop.Controls"
xmlns:icons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:views="clr-namespace:PLib.Desktop.Views"
xmlns:vm="clr-namespace:PLib.Desktop.ViewModels"
x:Class="PLib.Desktop.Views.MainWindow"
x:DataType="vm:MainWindowViewModel"
@@ -15,6 +16,10 @@
<Window.Resources>
<DataTemplate x:Key="SettingsTemplate" DataType="vm:SettingsViewModel">
<views:SettingsView />
</DataTemplate>
<!-- ======================= Video card ======================= -->
<DataTemplate x:Key="VideoCardTemplate" DataType="vm:VideoCardViewModel">
<Button Classes="card" Command="{Binding PlayCommand}" ToolTip.Tip="{Binding FullPath}">
@@ -234,5 +239,17 @@
</Grid>
</Border>
<!-- ======================= Settings panel ======================= -->
<Panel Grid.Row="0"
Grid.RowSpan="3"
Classes="settingsOverlay"
Classes.open="{Binding IsSettingsOpen}">
<Button Classes="scrim" Command="{Binding CloseSettingsCommand}" />
<Border Classes="drawer">
<ContentControl Content="{Binding SettingsPanel}"
ContentTemplate="{StaticResource SettingsTemplate}" />
</Border>
</Panel>
</Grid>
</Window>
+35 -9
View File
@@ -1,9 +1,35 @@
using ReactiveUI.Avalonia;
using PLib.Desktop.ViewModels;
namespace PLib.Desktop.Views;
public sealed partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow() => InitializeComponent();
}
using Avalonia.Input;
using Avalonia.Interactivity;
using PLib.Desktop.ViewModels;
using ReactiveUI.Avalonia;
namespace PLib.Desktop.Views;
public sealed partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow()
{
InitializeComponent();
// Handled here rather than as a KeyBinding: a KeyBinding only fires if the event
// bubbles all the way up untouched, and whichever control inside the settings panel
// happens to hold focus may well swallow Escape first. Both strategies are
// registered because a focused control can mark the event handled on the way down.
AddHandler(
KeyDownEvent,
OnPreviewKeyDown,
RoutingStrategies.Tunnel | RoutingStrategies.Bubble,
handledEventsToo: true);
}
private void OnPreviewKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key is not Key.Escape || DataContext is not MainWindowViewModel { IsSettingsOpen: true } viewModel)
{
return;
}
viewModel.CloseSettingsCommand.Execute().Subscribe();
e.Handled = true;
}
}
+24 -20
View File
@@ -1,18 +1,11 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:icons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:vm="clr-namespace:PLib.Desktop.ViewModels"
x:Class="PLib.Desktop.Views.SettingsWindow"
x:DataType="vm:SettingsViewModel"
Title="Настройки"
Width="620"
Height="700"
MinWidth="520"
MinHeight="520"
Background="{DynamicResource PageBackgroundBrush}"
WindowStartupLocation="CenterOwner">
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:icons="clr-namespace:Material.Icons.Avalonia;assembly=Material.Icons.Avalonia"
xmlns:vm="clr-namespace:PLib.Desktop.ViewModels"
x:Class="PLib.Desktop.Views.SettingsView"
x:DataType="vm:SettingsViewModel">
<Window.Styles>
<UserControl.Styles>
<!-- One settings block: a titled surface holding a few related controls. -->
<Style Selector="Border.section">
<Setter Property="Background" Value="{DynamicResource SurfaceBrush}" />
@@ -33,7 +26,7 @@
<Setter Property="FontSize" Value="11.5" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</Window.Styles>
</UserControl.Styles>
<Grid RowDefinitions="Auto,*,Auto">
@@ -43,8 +36,9 @@
BorderBrush="{DynamicResource SurfaceBorderBrush}"
BorderThickness="0,0,0,1"
Padding="20,14">
<StackPanel Orientation="Horizontal" Spacing="10">
<Border Width="32"
<Grid ColumnDefinitions="Auto,*,Auto">
<Border Grid.Column="0"
Width="32"
Height="32"
CornerRadius="9"
Background="{DynamicResource AccentSoftBrush}">
@@ -53,8 +47,18 @@
Height="18"
Foreground="{DynamicResource AccentBrush}" />
</Border>
<TextBlock Classes="sectionTitle" Text="Настройки" VerticalAlignment="Center" />
</StackPanel>
<TextBlock Grid.Column="1"
Classes="sectionTitle"
Margin="10,0,0,0"
Text="Настройки"
VerticalAlignment="Center" />
<Button Grid.Column="2"
Command="{Binding CancelCommand}"
Padding="7"
ToolTip.Tip="Закрыть без сохранения">
<icons:MaterialIcon Kind="Close" Width="15" Height="15" />
</Button>
</Grid>
</Border>
<!-- ======================= Body ======================= -->
@@ -241,4 +245,4 @@
</Border>
</Grid>
</Window>
</UserControl>
@@ -0,0 +1,8 @@
using Avalonia.Controls;
namespace PLib.Desktop.Views;
public sealed partial class SettingsView : UserControl
{
public SettingsView() => InitializeComponent();
}
@@ -1,9 +0,0 @@
using PLib.Desktop.ViewModels;
using ReactiveUI.Avalonia;
namespace PLib.Desktop.Views;
public sealed partial class SettingsWindow : ReactiveWindow<SettingsViewModel>
{
public SettingsWindow() => InitializeComponent();
}