Various updates.
This commit is contained in:
@@ -11,17 +11,26 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<SolidColorBrush x:Key="SongItemTitleBrush" Color="#dddddd"/>
|
||||
<SolidColorBrush x:Key="SongItemSubtitleBrush" Color="#aaaaaa"/>
|
||||
|
||||
<Style x:Key="PlayerGrid" TargetType="Grid">
|
||||
<Setter Property="Background" Value="#1a1a1a"/>
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
</Style>
|
||||
<Style x:Key="SongTitleTextBlock" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
|
||||
<Setter Property="Foreground" Value="{StaticResource SongItemTitleBrush}"/>
|
||||
</Style>
|
||||
<Style x:Key="SongImage" TargetType="Image">
|
||||
<Setter Property="Width" Value="80"/>
|
||||
<Setter Property="Height" Value="80"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
|
||||
<Grid Style="{StaticResource PlayerGrid}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition></ColumnDefinition>
|
||||
@@ -43,15 +52,16 @@
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
Foreground="#aaaaaa"
|
||||
Text="{Binding Position, Converter={StaticResource SecondsToString}}"
|
||||
FontSize="13"
|
||||
Margin="0 0 6 0"
|
||||
VerticalAlignment="Center"
|
||||
LineHeight="0">
|
||||
</TextBlock>
|
||||
<Border Grid.Column="0" Background="Transparent" Padding="0 8" Width="60" CornerRadius="4" VerticalAlignment="Center" Margin="0 0 6 0">
|
||||
<TextBlock
|
||||
Foreground="#aaaaaa"
|
||||
Text="{Binding Position, Converter={StaticResource SecondsToString}}"
|
||||
FontSize="13"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Center">
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
<Slider
|
||||
Name="PositionSlider"
|
||||
Loaded="PositionSlider_Loaded"
|
||||
@@ -59,19 +69,22 @@
|
||||
Value="{Binding CurrentPosition, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
|
||||
Minimum="0"
|
||||
Maximum="{Binding MaxPosition, Mode=OneWay}"
|
||||
IsEnabled="{Binding CanUpdatePosition, Mode=OneWay}"
|
||||
ThumbToolTipValueConverter="{StaticResource SecondsToString}"
|
||||
VerticalAlignment="Center"
|
||||
VerticalContentAlignment="Center" />
|
||||
<TextBlock
|
||||
Grid.Column="2"
|
||||
Foreground="#aaaaaa"
|
||||
Text="{Binding MaxPosition, Converter={StaticResource SecondsToString}}"
|
||||
FontSize="13"
|
||||
Margin="6 0 0 0"
|
||||
VerticalAlignment="Center">
|
||||
</TextBlock>
|
||||
|
||||
<Border Grid.Column="2" Background="Transparent" Padding="0 8" Width="60" CornerRadius="4" VerticalAlignment="Center" Margin="6 0 0 0">
|
||||
<TextBlock
|
||||
Foreground="#aaaaaa"
|
||||
Text="{Binding MaxPosition, Converter={StaticResource SecondsToString}}"
|
||||
FontSize="13"
|
||||
VerticalAlignment="Center">
|
||||
</TextBlock>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<!-- Song Info -->
|
||||
<Grid Grid.Row="1" Grid.Column="0" Name="PlayingSongGrid">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -80,10 +93,10 @@
|
||||
<Canvas Background="#19000000"></Canvas>
|
||||
</Grid>
|
||||
<StackPanel VerticalAlignment="Center">
|
||||
<TextBlock Foreground="#dddddd" FontWeight="SemiBold" FontSize="16" LineHeight="20" Text="{Binding Song, Converter={StaticResource SongTitle}}"></TextBlock>
|
||||
<TextBlock Foreground="#aaaaaa" FontSize="14" LineHeight="20" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}"></TextBlock>
|
||||
<TextBlock Foreground="#aaaaaa" FontSize="14" LineHeight="20" Text="{Binding Song.Album}"></TextBlock>
|
||||
<TextBlock Foreground="#777" FontSize="12" Visibility="{Binding Song, Converter={StaticResource NullVisibility}}" FontWeight="Normal" Opacity="1.0">
|
||||
<TextBlock Foreground="#dddddd" FontWeight="SemiBold" FontSize="16" Text="{Binding Song, Converter={StaticResource SongTitle}}"></TextBlock>
|
||||
<TextBlock Foreground="#aaaaaa" FontSize="14" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}"></TextBlock>
|
||||
<TextBlock Foreground="#aaaaaa" FontSize="14" Text="{Binding Song.Album}"></TextBlock>
|
||||
<TextBlock Foreground="#777" FontSize="12" Visibility="{Binding Song, Converter={StaticResource NullVisibility}}">
|
||||
<Run Text="{Binding Song.FileType}"></Run><Run Text=" - "></Run><Run Text="{Binding Song.BitRate}"></Run><Run Text=" kbps - "></Run><Run Text="{Binding Song.SampleRate}"></Run><Run Text=" Hz"></Run>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
|
||||
<!-- Image Border -->
|
||||
<Style x:Key="PlaylistSongImageBorder" TargetType="Border">
|
||||
<Setter Property="Width" Value="75"/>
|
||||
<Setter Property="Height" Value="75"/>
|
||||
<Setter Property="Width" Value="60"/> <!-- as 75 -->
|
||||
<Setter Property="Height" Value="60"/> <!-- as 75 -->
|
||||
<Setter Property="CornerRadius" Value="8"/>
|
||||
</Style>
|
||||
|
||||
<DataTemplate x:Key="SongTemplate" x:DataType="playlists:PlaylistSong">
|
||||
<!-- Background was formerly transparent -->
|
||||
<Border DoubleTapped="PlaylistListViewItem_DoubleTapped" Background="Transparent">
|
||||
<Border DoubleTapped="PlaylistListViewItem_DoubleTapped" RightTapped="PlaylistListViewItem_RightTapped" Background="Transparent">
|
||||
<Grid Padding="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"></ColumnDefinition>
|
||||
@@ -55,11 +55,11 @@
|
||||
<RowDefinition></RowDefinition>
|
||||
<RowDefinition></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Column="0" Grid.Row="0" Foreground="{StaticResource SongItemTitleBrush}" Text="{x:Bind Song, Converter={StaticResource SongTitle}, Mode=OneWay}" FontSize="15" FontWeight="SemiBold" LineStackingStrategy="BlockLineHeight" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" LineHeight="0">
|
||||
<TextBlock Grid.Column="0" Grid.Row="0" Foreground="{StaticResource SongItemTitleBrush}" Text="{x:Bind Song, Converter={StaticResource SongTitle}, Mode=OneWay}" FontSize="15" FontWeight="Medium" LineStackingStrategy="BlockLineHeight" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" LineHeight="0">
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Row="1" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="14" Margin="0 0 0 0">
|
||||
<TextBlock Grid.Row="1" Text="{Binding Song.Artists, Converter={StaticResource ArtistsToString}}" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="13" Margin="0 0 0 0">
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Row="2" Text="{Binding Song.Album}" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="14" Margin="0 0 0 0">
|
||||
<TextBlock Grid.Row="2" Text="{Binding Song.Album}" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="13" Margin="0 0 0 0">
|
||||
</TextBlock>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" TextAlignment="Right" HorizontalTextAlignment="Right" Foreground="{StaticResource SongItemSubtitleBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="13" Text="{Binding Song.Length.TotalSeconds, Converter={StaticResource SecondsToString}}"></TextBlock>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="{StaticResource SongItemFooterBrush}" TextTrimming="CharacterEllipsis" LineStackingStrategy="BlockLineHeight" LineHeight="0" FontSize="12" Text="{Binding Song.FileType}"></TextBlock>
|
||||
@@ -128,7 +128,66 @@
|
||||
Name="PlaylistListView"
|
||||
ItemsSource="{Binding FilteredPlaylistSongs}"
|
||||
ItemTemplate="{StaticResource SongTemplate}"
|
||||
SelectionMode="Extended">
|
||||
SelectionMode="Extended"
|
||||
SelectionChanged="PlaylistListView_SelectionChanged">
|
||||
<ListView.ContextFlyout>
|
||||
<MenuFlyout x:Name="PlaylistListViewMenuFlyout" Opening="MenuFlyout_Opening" ShouldConstrainToRootBounds="False" SystemBackdrop="{StaticResource AcrylicBackgroundFillColorDefaultBackdrop}">
|
||||
<MenuFlyout.MenuFlyoutPresenterStyle>
|
||||
<Style TargetType="MenuFlyoutPresenter">
|
||||
<Setter Property="Padding" Value="10"></Setter>
|
||||
<Setter Property="Background" Value="Transparent"></Setter>
|
||||
</Style>
|
||||
</MenuFlyout.MenuFlyoutPresenterStyle>
|
||||
<MenuFlyoutItem Text="Play" FontWeight="SemiBold" Command="{Binding PlaySongCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource PlayIcon}"></PathIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Enter"/>
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator></MenuFlyoutSeparator>
|
||||
<MenuFlyoutItem Text="Remove" Command="{Binding RemoveSongsCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource DeleteIcon}"></PathIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="Delete"/>
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator></MenuFlyoutSeparator>
|
||||
<MenuFlyoutItem Text="Cut" Command="{Binding CutSongsCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource CutIcon}"></PathIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="X" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Text="Copy" Command="{Binding CopySongsCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource CopyIcon}"></PathIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="C" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutItem Text="Paste" Command="{Binding PasteSongsCommand}">
|
||||
<MenuFlyoutItem.Icon>
|
||||
<PathIcon Data="{StaticResource PasteIcon}"></PathIcon>
|
||||
</MenuFlyoutItem.Icon>
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="V" Modifiers="Control" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
<MenuFlyoutSeparator></MenuFlyoutSeparator>
|
||||
<MenuFlyoutItem Text="Open File Location" Command="{Binding OpenFileLocationCommand}">
|
||||
<MenuFlyoutItem.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Key="O" Modifiers="Menu" />
|
||||
</MenuFlyoutItem.KeyboardAccelerators>
|
||||
</MenuFlyoutItem>
|
||||
</MenuFlyout>
|
||||
</ListView.ContextFlyout>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
using Harmonia.Core.Playlists;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Harmonia.Core.Playlists;
|
||||
using Harmonia.WinUI.ViewModels;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Harmonia.WinUI.Views;
|
||||
|
||||
@@ -14,34 +19,97 @@ public sealed partial class PlaylistView : UserControl
|
||||
public PlaylistView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_viewModel = (PlaylistViewModel)DataContext;
|
||||
_viewModel.PlayingSongChangedAutomatically += OnPlayingSongChangedAutomatically;
|
||||
|
||||
foreach (MenuFlyoutItemBase item in PlaylistListViewMenuFlyout.Items)
|
||||
{
|
||||
item.DataContextChanged += Item_DataContextChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayingSongChangedAutomatically(object? sender, EventArgs e)
|
||||
{
|
||||
BringPlayingSongIntoView();
|
||||
}
|
||||
|
||||
private void BringPlayingSongIntoView()
|
||||
{
|
||||
PlaylistSong? playingSong = _viewModel.PlayingSong;
|
||||
|
||||
if (playingSong == null)
|
||||
return;
|
||||
|
||||
ListViewItem listViewItem = (ListViewItem)PlaylistListView.ContainerFromItem(playingSong);
|
||||
|
||||
if (listViewItem != null)
|
||||
{
|
||||
listViewItem.UpdateLayout();
|
||||
listViewItem.StartBringIntoView(new BringIntoViewOptions() { VerticalAlignmentRatio = .5, AnimationDesired = true });
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaylistListView.UpdateLayout();
|
||||
PlaylistListView.ScrollIntoView(playingSong);
|
||||
}
|
||||
}
|
||||
|
||||
private void Item_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
|
||||
{
|
||||
if (sender is not MenuFlyoutItemBase item)
|
||||
return;
|
||||
|
||||
if (args.NewValue == _viewModel)
|
||||
return;
|
||||
|
||||
item.DataContext = _viewModel;
|
||||
}
|
||||
|
||||
private void Image_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//Image? image = sender as Image;
|
||||
if (sender is not Image image)
|
||||
return;
|
||||
|
||||
//if (image == null)
|
||||
// return;
|
||||
image.DataContextChanged += Image_DataContextChanged;
|
||||
|
||||
//image.DataContextChanged += Image_DataContextChanged;
|
||||
if (image.DataContext is not PlaylistSong playlistSong)
|
||||
return;
|
||||
|
||||
//var song = (PlaylistSong)image.DataContext;
|
||||
|
||||
//if (song == null)
|
||||
// return;
|
||||
|
||||
//Task.Run(async () => await FetchImage(song.Song, image));
|
||||
//Task.Run(async () => await UpdateImage(image, playlistSong));
|
||||
UpdateImage(image, playlistSong);
|
||||
}
|
||||
|
||||
private void Image_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//Image? image = sender as Image;
|
||||
if (sender is not Image image)
|
||||
return;
|
||||
|
||||
//if (image == null)
|
||||
// return;
|
||||
image.DataContextChanged -= Image_DataContextChanged;
|
||||
}
|
||||
|
||||
//image.DataContextChanged -= Image_DataContextChanged;
|
||||
private void Image_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
|
||||
{
|
||||
if (sender is not Image image)
|
||||
return;
|
||||
|
||||
if (args.NewValue is not PlaylistSong playlistSong)
|
||||
return;
|
||||
|
||||
//Task.Run(async () => await UpdateImage(image, playlistSong));
|
||||
UpdateImage(image, playlistSong);
|
||||
}
|
||||
|
||||
private void UpdateImage(Image image, PlaylistSong playlistSong)
|
||||
{
|
||||
int hashCode = image.GetHashCode();
|
||||
//BitmapImage? bitmapImage = await _viewModel.GetBitmapImageAsync(hashCode, playlistSong);
|
||||
|
||||
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||
{
|
||||
BitmapImage? bitmapImage = await _viewModel.GetBitmapImageAsync(hashCode, playlistSong);
|
||||
image.Source = bitmapImage;
|
||||
});
|
||||
}
|
||||
|
||||
private async void PlaylistListViewItem_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
|
||||
@@ -54,4 +122,45 @@ public sealed partial class PlaylistView : UserControl
|
||||
|
||||
await _viewModel.PlaySongAsync(playlistSong);
|
||||
}
|
||||
|
||||
private void PlaylistListViewItem_RightTapped(object sender, RightTappedRoutedEventArgs e)
|
||||
{
|
||||
if (sender is not FrameworkElement element)
|
||||
return;
|
||||
|
||||
if (element == null || element.DataContext is not PlaylistSong playlistSong)
|
||||
return;
|
||||
|
||||
if (PlaylistListView.SelectedItems.Contains(playlistSong))
|
||||
return;
|
||||
|
||||
int index = PlaylistListView.Items.IndexOf(playlistSong);
|
||||
|
||||
PlaylistListView.DeselectAll();
|
||||
PlaylistListView.SelectRange(new ItemIndexRange(index, 1));
|
||||
}
|
||||
|
||||
private void PlaylistListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is not ListView listView)
|
||||
return;
|
||||
|
||||
PlaylistSong[] selectedPlaylistSongs = [.. listView.SelectedItems.Cast<PlaylistSong>()];
|
||||
|
||||
_viewModel.SelectedPlaylistSongs = [.. selectedPlaylistSongs];
|
||||
}
|
||||
|
||||
private void MenuFlyout_Opening(object sender, object e)
|
||||
{
|
||||
if (sender is not MenuFlyout menuFlyout)
|
||||
return;
|
||||
|
||||
foreach (MenuFlyoutItemBase item in menuFlyout.Items)
|
||||
{
|
||||
if (item.DataContext != _viewModel)
|
||||
{
|
||||
item.DataContext = _viewModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user