2026-05-24 16:36:32 -05:00
|
|
|
<UserControl xmlns="https://github.com/avaloniaui"
|
|
|
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
2026-06-06 05:49:24 -05:00
|
|
|
xmlns:vm="using:LANCommander.Launcher.ViewModels"
|
|
|
|
|
xmlns:vmComponents="using:LANCommander.Launcher.ViewModels.Components"
|
|
|
|
|
xmlns:components="using:LANCommander.Launcher.Views.Components"
|
|
|
|
|
xmlns:controls="using:LANCommander.Launcher.Controls"
|
|
|
|
|
xmlns:converters="using:LANCommander.Launcher.Converters"
|
|
|
|
|
xmlns:local="using:LANCommander.Launcher.Views"
|
|
|
|
|
x:Class="LANCommander.Launcher.Views.LibraryRowView"
|
2026-05-24 16:36:32 -05:00
|
|
|
x:DataType="vm:LibraryViewModel">
|
|
|
|
|
|
|
|
|
|
<UserControl.Styles>
|
|
|
|
|
<Style Selector="ListBox.CompactGamesList">
|
|
|
|
|
<Setter Property="Background" Value="Transparent" />
|
|
|
|
|
<Setter Property="BorderThickness" Value="0" />
|
|
|
|
|
<Setter Property="Padding" Value="0" />
|
|
|
|
|
</Style>
|
|
|
|
|
<Style Selector="ListBox.CompactGamesList ListBoxItem">
|
|
|
|
|
<Setter Property="Padding" Value="0" />
|
|
|
|
|
<Setter Property="Margin" Value="0" />
|
|
|
|
|
<Setter Property="Background" Value="Transparent" />
|
|
|
|
|
<Setter Property="Cursor" Value="Hand" />
|
|
|
|
|
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
2026-06-11 00:12:09 -05:00
|
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
2026-06-25 19:46:19 -05:00
|
|
|
<Setter Property="controls:GameContextMenu.IsEnabled" Value="True" />
|
2026-05-24 16:36:32 -05:00
|
|
|
<Setter Property="Template">
|
|
|
|
|
<ControlTemplate>
|
|
|
|
|
<ContentPresenter Name="PART_ContentPresenter"
|
|
|
|
|
Content="{TemplateBinding Content}"
|
|
|
|
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
|
|
|
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
|
|
|
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
|
|
|
|
Padding="{TemplateBinding Padding}" />
|
|
|
|
|
</ControlTemplate>
|
|
|
|
|
</Setter>
|
|
|
|
|
</Style>
|
2026-06-25 21:41:05 -05:00
|
|
|
<Style Selector="ListBox.CompactGamesList Border.CompactListRow">
|
|
|
|
|
<Setter Property="Background" Value="Transparent" />
|
|
|
|
|
</Style>
|
2026-05-24 16:36:32 -05:00
|
|
|
<Style Selector="ListBox.CompactGamesList ListBoxItem:pointerover Border.CompactListRow">
|
|
|
|
|
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundChromeMediumBrush}" />
|
|
|
|
|
</Style>
|
|
|
|
|
<Style Selector="ListBox.CompactGamesList ListBoxItem:selected Border.CompactListRow">
|
|
|
|
|
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundChromeMediumBrush}" />
|
|
|
|
|
<Setter Property="BorderBrush" Value="{DynamicResource SystemAccentColor}" />
|
|
|
|
|
<Setter Property="BorderThickness" Value="2,0,0,0" />
|
|
|
|
|
</Style>
|
|
|
|
|
</UserControl.Styles>
|
|
|
|
|
|
|
|
|
|
<Grid ColumnDefinitions="250,*">
|
|
|
|
|
|
|
|
|
|
<!-- ═══ LEFT PANEL: Compact Game List ═══ -->
|
|
|
|
|
<Border Grid.Column="0"
|
|
|
|
|
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
|
|
|
|
BorderThickness="0,0,1,0"
|
|
|
|
|
Margin="0,48,0,0">
|
2026-05-26 00:14:13 -05:00
|
|
|
<ListBox x:Name="GameListBox"
|
2026-06-14 23:50:31 -05:00
|
|
|
Classes="CompactGamesList"
|
2026-05-24 16:36:32 -05:00
|
|
|
ItemsSource="{Binding Games}"
|
|
|
|
|
SelectedItem="{Binding SelectedGame}"
|
|
|
|
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
|
|
|
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
2026-05-26 00:14:13 -05:00
|
|
|
Tapped="GameList_Tapped"
|
|
|
|
|
KeyDown="GameList_KeyDown">
|
2026-05-24 16:36:32 -05:00
|
|
|
<ListBox.ItemsPanel>
|
|
|
|
|
<ItemsPanelTemplate>
|
|
|
|
|
<VirtualizingStackPanel />
|
|
|
|
|
</ItemsPanelTemplate>
|
|
|
|
|
</ListBox.ItemsPanel>
|
|
|
|
|
<ListBox.ItemTemplate>
|
|
|
|
|
<DataTemplate DataType="vmComponents:GameItemViewModel">
|
|
|
|
|
<Border Classes="CompactListRow" Padding="8,4" CornerRadius="0">
|
|
|
|
|
<DockPanel>
|
2026-07-04 03:33:13 -05:00
|
|
|
<Image controls:AsyncImage.Source="{Binding IconPath}"
|
|
|
|
|
controls:AsyncImage.DecodeWidth="48"
|
2026-05-24 16:36:32 -05:00
|
|
|
Width="24" Height="24"
|
|
|
|
|
Stretch="Uniform"
|
|
|
|
|
Margin="0,0,8,0"
|
|
|
|
|
VerticalAlignment="Center" />
|
2026-06-08 19:36:37 -05:00
|
|
|
<StackPanel VerticalAlignment="Center" MinWidth="0">
|
|
|
|
|
<TextBlock Text="{Binding Title}"
|
|
|
|
|
FontSize="13"
|
|
|
|
|
TextTrimming="CharacterEllipsis"
|
|
|
|
|
Opacity="{Binding IsInstalled, Converter={x:Static converters:BoolToDoubleConverter.Instance}}" />
|
|
|
|
|
<TextBlock Text="Update Available"
|
|
|
|
|
FontSize="10"
|
|
|
|
|
Foreground="{DynamicResource SystemAccentColor}"
|
|
|
|
|
IsVisible="{Binding IsUpdateAvailable}" />
|
|
|
|
|
</StackPanel>
|
2026-05-24 16:36:32 -05:00
|
|
|
</DockPanel>
|
|
|
|
|
</Border>
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</ListBox.ItemTemplate>
|
|
|
|
|
</ListBox>
|
|
|
|
|
</Border>
|
|
|
|
|
|
|
|
|
|
<!-- ═══ RIGHT PANEL: Carousels + Grid ═══ -->
|
|
|
|
|
<ScrollViewer x:Name="RightPanelScrollViewer"
|
2026-05-28 00:14:22 -05:00
|
|
|
Classes="TitlebarOffset"
|
2026-05-24 16:36:32 -05:00
|
|
|
Grid.Column="1"
|
|
|
|
|
HorizontalScrollBarVisibility="Disabled"
|
|
|
|
|
VerticalScrollBarVisibility="Auto"
|
|
|
|
|
SizeChanged="RightPanelScrollViewer_SizeChanged">
|
|
|
|
|
<StackPanel Margin="10,48,10,24" Spacing="32" Grid.IsSharedSizeScope="True">
|
|
|
|
|
|
|
|
|
|
<!-- ══ RECENTLY PLAYED ═══════════════════════════════════════════════ -->
|
2026-05-26 00:49:30 -05:00
|
|
|
<CarouselControl x:Name="RecentlyPlayedCarousel"
|
|
|
|
|
Title="Recently Played"
|
2026-05-24 16:36:32 -05:00
|
|
|
ItemsSource="{Binding RecentlyPlayedGames}"
|
|
|
|
|
ItemWidth="160"
|
|
|
|
|
VisibleItems="5"
|
2026-05-25 01:42:49 -05:00
|
|
|
Gap="16"
|
|
|
|
|
ItemOverflow="14">
|
2026-05-24 16:36:32 -05:00
|
|
|
<CarouselControl.IsVisible>
|
|
|
|
|
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
|
|
|
|
<Binding Path="HasRecentlyPlayed" />
|
|
|
|
|
<Binding Path="!IsCollectionFiltered" />
|
|
|
|
|
</MultiBinding>
|
|
|
|
|
</CarouselControl.IsVisible>
|
|
|
|
|
<CarouselControl.ItemTemplate>
|
|
|
|
|
<DataTemplate x:DataType="vmComponents:GameItemViewModel">
|
|
|
|
|
<components:CoverButton Width="160" Height="240"
|
2026-06-25 19:46:19 -05:00
|
|
|
controls:GameContextMenu.IsEnabled="True"
|
2026-05-24 16:36:32 -05:00
|
|
|
Command="{Binding $parent[local:LibraryRowView].((vm:LibraryViewModel)DataContext).ViewGameDetailsCommand}"
|
|
|
|
|
CommandParameter="{Binding}" />
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</CarouselControl.ItemTemplate>
|
|
|
|
|
</CarouselControl>
|
|
|
|
|
|
|
|
|
|
<!-- ══ COLLECTIONS ═══════════════════════════════════════════════════ -->
|
2026-05-26 00:49:30 -05:00
|
|
|
<CarouselControl x:Name="CollectionsCarousel"
|
|
|
|
|
Title="Collections"
|
2026-05-24 16:36:32 -05:00
|
|
|
WrapItems="True"
|
|
|
|
|
ItemsSource="{Binding LibraryCollections}"
|
|
|
|
|
ItemWidth="200"
|
|
|
|
|
VisibleItems="4">
|
|
|
|
|
<CarouselControl.IsVisible>
|
|
|
|
|
<MultiBinding Converter="{x:Static BoolConverters.And}">
|
|
|
|
|
<Binding Path="HasCollections" />
|
|
|
|
|
<Binding Path="!IsCollectionFiltered" />
|
|
|
|
|
</MultiBinding>
|
|
|
|
|
</CarouselControl.IsVisible>
|
|
|
|
|
<CarouselControl.ItemTemplate>
|
|
|
|
|
<DataTemplate x:DataType="vmComponents:GenreCarouselButtomViewModel">
|
|
|
|
|
<components:GenreCarouselButton Width="200" Height="150"
|
|
|
|
|
Command="{Binding $parent[local:LibraryRowView].((vm:LibraryViewModel)DataContext).FilterByCollectionCommand}"
|
|
|
|
|
CommandParameter="{Binding Name}" />
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</CarouselControl.ItemTemplate>
|
|
|
|
|
</CarouselControl>
|
|
|
|
|
|
|
|
|
|
<!-- ══ ALL GAMES GRID (75% size) ═════════════════════════════════════ -->
|
|
|
|
|
<StackPanel Margin="32,0,32,0" Spacing="4">
|
|
|
|
|
<DockPanel>
|
|
|
|
|
<Button DockPanel.Dock="Right"
|
|
|
|
|
Command="{Binding ClearCollectionFilterCommand}"
|
|
|
|
|
Content="✕"
|
|
|
|
|
Classes="Text Error"
|
|
|
|
|
Padding="8,4"
|
2026-05-26 00:49:30 -05:00
|
|
|
Focusable="False"
|
2026-05-24 16:36:32 -05:00
|
|
|
IsVisible="{Binding IsCollectionFiltered}" />
|
|
|
|
|
<TextBlock Text="All Games" FontSize="18" FontWeight="SemiBold"
|
|
|
|
|
IsVisible="{Binding !IsCollectionFiltered}" />
|
|
|
|
|
<TextBlock Text="{Binding FilteredCollectionName}" FontSize="18" FontWeight="SemiBold"
|
|
|
|
|
IsVisible="{Binding IsCollectionFiltered}" />
|
|
|
|
|
</DockPanel>
|
|
|
|
|
<ItemsRepeater x:Name="LibraryGridItemsRepeater"
|
|
|
|
|
ItemsSource="{Binding Games}"
|
2026-05-26 00:14:13 -05:00
|
|
|
ClipToBounds="False"
|
|
|
|
|
controls:DirectionalNavigation.IsEnabled="True">
|
2026-05-24 16:36:32 -05:00
|
|
|
<ItemsRepeater.Layout>
|
|
|
|
|
<UniformGridLayout MinItemWidth="105" MinItemHeight="158"
|
|
|
|
|
MinColumnSpacing="12" MinRowSpacing="12"
|
|
|
|
|
ItemsStretch="None"
|
|
|
|
|
ItemsJustification="Start" />
|
|
|
|
|
</ItemsRepeater.Layout>
|
|
|
|
|
<ItemsRepeater.ItemTemplate>
|
|
|
|
|
<DataTemplate DataType="vmComponents:GameItemViewModel">
|
|
|
|
|
<components:CoverButton
|
|
|
|
|
Width="{Binding $parent[local:LibraryRowView].SmallCoverWidth}"
|
|
|
|
|
Height="{Binding $parent[local:LibraryRowView].SmallCoverHeight}"
|
2026-06-25 19:46:19 -05:00
|
|
|
controls:GameContextMenu.IsEnabled="True"
|
2026-05-24 16:36:32 -05:00
|
|
|
Command="{Binding $parent[ItemsRepeater].((vm:LibraryViewModel)DataContext).ViewGameDetailsCommand}"
|
|
|
|
|
CommandParameter="{Binding}" />
|
|
|
|
|
</DataTemplate>
|
|
|
|
|
</ItemsRepeater.ItemTemplate>
|
|
|
|
|
</ItemsRepeater>
|
|
|
|
|
</StackPanel>
|
|
|
|
|
|
|
|
|
|
</StackPanel>
|
|
|
|
|
</ScrollViewer>
|
|
|
|
|
|
|
|
|
|
</Grid>
|
|
|
|
|
</UserControl>
|