Update README.md with project details, features, requirements, architecture, and data management for PLib video library manager.
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
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:vm="clr-namespace:PLib.Desktop.ViewModels"
|
||||
x:Class="PLib.Desktop.Views.MainWindow"
|
||||
x:DataType="vm:MainWindowViewModel"
|
||||
Title="PLib — видеотека"
|
||||
Width="1180"
|
||||
Height="760"
|
||||
MinWidth="640"
|
||||
MinHeight="420"
|
||||
Background="{DynamicResource PageBackgroundBrush}"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
<Window.Resources>
|
||||
|
||||
<!-- ======================= Video card ======================= -->
|
||||
<DataTemplate x:Key="VideoCardTemplate" DataType="vm:VideoCardViewModel">
|
||||
<Button Classes="card" Command="{Binding PlayCommand}" ToolTip.Tip="{Binding FullPath}">
|
||||
|
||||
<Button.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Header="Воспроизвести" Command="{Binding PlayCommand}" />
|
||||
<MenuItem Header="Показать в папке" Command="{Binding RevealCommand}" />
|
||||
</ContextMenu>
|
||||
</Button.ContextMenu>
|
||||
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
|
||||
<!-- Poster frame -->
|
||||
<Border Grid.Row="0"
|
||||
CornerRadius="9"
|
||||
ClipToBounds="True"
|
||||
Background="{DynamicResource ThumbnailPlaceholderBrush}">
|
||||
<Panel>
|
||||
<controls:AsyncImage Source="{Binding ThumbnailPath}"
|
||||
DecodeWidth="480"
|
||||
PlaceholderBrush="{DynamicResource ThumbnailPlaceholderBrush}" />
|
||||
|
||||
<!-- Shown until ffmpeg has produced a frame for this file. -->
|
||||
<icons:MaterialIcon Kind="FilmstripBoxMultiple"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Opacity="0.35"
|
||||
Foreground="{DynamicResource TextTertiaryBrush}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
IsVisible="{Binding IsPending}" />
|
||||
|
||||
<Border Classes="badge"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top"
|
||||
IsVisible="{Binding QualityText, Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<TextBlock Text="{Binding QualityText}" />
|
||||
</Border>
|
||||
|
||||
<Border Classes="badge"
|
||||
Margin="8"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom">
|
||||
<TextBlock Text="{Binding DurationText}" />
|
||||
</Border>
|
||||
|
||||
<Border Classes="playOverlay" Background="{DynamicResource OverlayBrush}">
|
||||
<Border Width="46"
|
||||
Height="46"
|
||||
CornerRadius="23"
|
||||
Background="{DynamicResource AccentBrush}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<icons:MaterialIcon Kind="Play" Width="24" Height="24" Foreground="White" />
|
||||
</Border>
|
||||
</Border>
|
||||
</Panel>
|
||||
</Border>
|
||||
|
||||
<!-- Caption -->
|
||||
<StackPanel Grid.Row="1" Margin="4,10,4,2" Spacing="3">
|
||||
<TextBlock Classes="cardTitle" Text="{Binding Title}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBlock Classes="cardMeta" Text="{Binding SizeText}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</Button>
|
||||
</DataTemplate>
|
||||
|
||||
</Window.Resources>
|
||||
|
||||
<Grid RowDefinitions="Auto,*,Auto">
|
||||
|
||||
<!-- ======================= Header ======================= -->
|
||||
<Border Grid.Row="0"
|
||||
Background="{DynamicResource SurfaceBrush}"
|
||||
BorderBrush="{DynamicResource SurfaceBorderBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Padding="20,14">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="20">
|
||||
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="10" VerticalAlignment="Center">
|
||||
<Border Width="34"
|
||||
Height="34"
|
||||
CornerRadius="9"
|
||||
Background="{DynamicResource AccentSoftBrush}">
|
||||
<icons:MaterialIcon Kind="VideoVintage"
|
||||
Width="19"
|
||||
Height="19"
|
||||
Foreground="{DynamicResource AccentBrush}" />
|
||||
</Border>
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Classes="sectionTitle" Text="Видеотека" />
|
||||
<TextBlock Classes="cardMeta" Text="{Binding Videos.Count, StringFormat='{}{0} видео'}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<TextBox Grid.Column="1"
|
||||
MaxWidth="420"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
PlaceholderText="Поиск по названию…"
|
||||
Text="{Binding SearchText}" />
|
||||
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
|
||||
|
||||
<ComboBox MinWidth="180"
|
||||
ItemsSource="{Binding SortOptions}"
|
||||
SelectedItem="{Binding SelectedSort}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:SortOption">
|
||||
<TextBlock Text="{Binding Label}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
|
||||
<Button Command="{Binding ScanCommand}"
|
||||
IsEnabled="{Binding !IsScanning}"
|
||||
ToolTip.Tip="Пересканировать библиотеку">
|
||||
<icons:MaterialIcon Kind="Refresh" Width="17" Height="17" />
|
||||
</Button>
|
||||
|
||||
<Button Command="{Binding ToggleThemeCommand}" ToolTip.Tip="Сменить тему">
|
||||
<icons:MaterialIcon Kind="ThemeLightDark" Width="17" Height="17" />
|
||||
</Button>
|
||||
|
||||
<Button Classes="Primary" Command="{Binding AddFolderCommand}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="7">
|
||||
<icons:MaterialIcon Kind="FolderPlusOutline" Width="17" Height="17" />
|
||||
<TextBlock Text="Добавить папку" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- ======================= Grid ======================= -->
|
||||
<Panel Grid.Row="1">
|
||||
|
||||
<ScrollViewer Padding="20,18" HorizontalScrollBarVisibility="Disabled">
|
||||
<ItemsRepeater ItemsSource="{Binding Videos}" ItemTemplate="{StaticResource VideoCardTemplate}">
|
||||
<ItemsRepeater.Layout>
|
||||
<UniformGridLayout ItemsStretch="Fill"
|
||||
MinItemWidth="230"
|
||||
MinItemHeight="212"
|
||||
MinColumnSpacing="16"
|
||||
MinRowSpacing="16" />
|
||||
</ItemsRepeater.Layout>
|
||||
</ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Empty state -->
|
||||
<StackPanel HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Spacing="14"
|
||||
MaxWidth="420"
|
||||
IsVisible="{Binding IsEmpty}">
|
||||
<icons:MaterialIcon Kind="VideoBoxOff"
|
||||
Width="52"
|
||||
Height="52"
|
||||
Opacity="0.35"
|
||||
Foreground="{DynamicResource TextTertiaryBrush}"
|
||||
HorizontalAlignment="Center" />
|
||||
<TextBlock Classes="sectionTitle"
|
||||
HorizontalAlignment="Center"
|
||||
Text="Здесь пока пусто" />
|
||||
<TextBlock Classes="subtle"
|
||||
HorizontalAlignment="Center"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap"
|
||||
Text="Укажите папку с видеофайлами — PLib пройдётся по ней, соберёт превью и покажет всё карточками." />
|
||||
<Button Classes="Primary"
|
||||
HorizontalAlignment="Center"
|
||||
Command="{Binding AddFolderCommand}"
|
||||
Content="Выбрать папку" />
|
||||
</StackPanel>
|
||||
|
||||
</Panel>
|
||||
|
||||
<!-- ======================= Status bar ======================= -->
|
||||
<Border Grid.Row="2"
|
||||
Background="{DynamicResource SurfaceBrush}"
|
||||
BorderBrush="{DynamicResource SurfaceBorderBrush}"
|
||||
BorderThickness="0,1,0,0"
|
||||
Padding="20,9">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto" ColumnSpacing="14">
|
||||
|
||||
<ProgressBar Grid.Column="0"
|
||||
Width="160"
|
||||
VerticalAlignment="Center"
|
||||
Minimum="0"
|
||||
Maximum="100"
|
||||
Value="{Binding ScanProgress}"
|
||||
IsIndeterminate="{Binding IsProgressIndeterminate}"
|
||||
IsVisible="{Binding IsScanning}" />
|
||||
|
||||
<TextBlock Grid.Column="1"
|
||||
Classes="subtle"
|
||||
VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Text="{Binding StatusText}" />
|
||||
|
||||
<Button Grid.Column="2"
|
||||
Content="Отмена"
|
||||
Command="{Binding ScanCancelCommand}"
|
||||
IsVisible="{Binding IsScanning}" />
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@@ -0,0 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace PLib.Desktop.Views;
|
||||
|
||||
public sealed partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow() => InitializeComponent();
|
||||
}
|
||||
Reference in New Issue
Block a user