Show total songs and total duration for each playlist.

This commit is contained in:
2026-07-31 09:04:14 -04:00
parent ea5b428a65
commit 16b87d255e
3 changed files with 93 additions and 18 deletions

View File

@@ -0,0 +1,47 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Harmonia.Core.Playlists;
using System;
using System.Linq;
namespace Harmonia.WinUI.ViewModels;
public partial class PlaylistItemViewModel : ObservableObject
{
public Playlist Playlist { get; private set; }
private string _summary = string.Empty;
public string Summary
{
get
{
return _summary;
}
set
{
SetProperty(ref _summary, value);
}
}
public PlaylistItemViewModel(Playlist playlist)
{
Playlist = playlist;
Playlist.PlaylistUpdated += OnPlaylistUpdated;
UpdateMetaData();
}
public void Unsubscribe()
{
Playlist.PlaylistUpdated -= OnPlaylistUpdated;
}
private void OnPlaylistUpdated(object? sender, EventArgs e)
{
UpdateMetaData();
}
private void UpdateMetaData()
{
TimeSpan total = TimeSpan.FromSeconds(Playlist.Songs.Sum(s => s.Song.Length.TotalSeconds));
Summary = $"{Playlist.Songs.Count} songs / {total:h\\:mm\\:ss}";
}
}

View File

@@ -1,6 +1,8 @@
using Harmonia.Core.Playlists; using CommunityToolkit.Mvvm.ComponentModel;
using Harmonia.Core.Playlists;
using System; using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq;
namespace Harmonia.WinUI.ViewModels; namespace Harmonia.WinUI.ViewModels;
@@ -8,8 +10,8 @@ public partial class PlaylistsViewModel : ViewModelBase
{ {
private readonly IPlaylistManager _playlistManager; private readonly IPlaylistManager _playlistManager;
private ObservableCollection<Playlist> _playlists = []; private ObservableCollection<PlaylistItemViewModel> _playlists = [];
public ObservableCollection<Playlist> Playlists public ObservableCollection<PlaylistItemViewModel> Playlists
{ {
get get
{ {
@@ -21,8 +23,8 @@ public partial class PlaylistsViewModel : ViewModelBase
} }
} }
private Playlist? _selectedPlaylist = null; private PlaylistItemViewModel? _selectedPlaylist = null;
public Playlist? SelectedPlaylist public PlaylistItemViewModel? SelectedPlaylist
{ {
get get
{ {
@@ -32,7 +34,7 @@ public partial class PlaylistsViewModel : ViewModelBase
{ {
if (SetProperty(ref _selectedPlaylist, value)) if (SetProperty(ref _selectedPlaylist, value))
{ {
_playlistManager.CurrentPlaylist = value; _playlistManager.CurrentPlaylist = value?.Playlist;
} }
} }
} }
@@ -44,22 +46,28 @@ public partial class PlaylistsViewModel : ViewModelBase
_playlistManager.PlaylistRemoved += OnPlaylistRemoved; _playlistManager.PlaylistRemoved += OnPlaylistRemoved;
_playlistManager.CurrentPlaylistChanged += OnCurrentPlaylistChanged; _playlistManager.CurrentPlaylistChanged += OnCurrentPlaylistChanged;
_playlists = new(_playlistManager.Playlists); _playlists = new ObservableCollection<PlaylistItemViewModel>(_playlistManager.Playlists.Select(p => new PlaylistItemViewModel(p)));
_selectedPlaylist = _playlistManager.CurrentPlaylist; _selectedPlaylist = _playlists.FirstOrDefault(pv => pv.Playlist == _playlistManager.CurrentPlaylist);
} }
private void OnCurrentPlaylistChanged(object? sender, EventArgs e) private void OnCurrentPlaylistChanged(object? sender, EventArgs e)
{ {
SelectedPlaylist = _playlistManager.CurrentPlaylist; SelectedPlaylist = _playlists.FirstOrDefault(pv => pv.Playlist == _playlistManager.CurrentPlaylist);
} }
private void OnPlaylistAdded(object? sender, PlaylistAddedEventArgs e) private void OnPlaylistAdded(object? sender, PlaylistAddedEventArgs e)
{ {
Playlists.Add(e.Playlist); Playlists.Add(new PlaylistItemViewModel(e.Playlist));
} }
private void OnPlaylistRemoved(object? sender, PlaylistRemovedEventArgs e) private void OnPlaylistRemoved(object? sender, PlaylistRemovedEventArgs e)
{ {
Playlists.Remove(e.Playlist); var playlistView = Playlists.FirstOrDefault(pv => pv.Playlist == e.Playlist);
if (playlistView != null)
{
playlistView.Unsubscribe();
Playlists.Remove(playlistView);
}
} }
} }

View File

@@ -12,13 +12,33 @@
d:DataContext="{d:DesignInstance Type=vm:PlaylistsViewModel, IsDesignTimeCreatable=True}" d:DataContext="{d:DesignInstance Type=vm:PlaylistsViewModel, IsDesignTimeCreatable=True}"
mc:Ignorable="d"> mc:Ignorable="d">
<UserControl.Resources> <UserControl.Resources>
<DataTemplate x:Key="PlaylistTemplate" x:DataType="playlists:Playlist"> <SolidColorBrush x:Key="PlaylistItemSubtitleBrush" Color="#aaaaaa"/>
<StackPanel Orientation="Horizontal" Spacing="8" VerticalAlignment="Bottom">
<Viewbox Height="24" Width="24"> <!-- Playlist Item Subtitle Text Block -->
<PathIcon Data="{StaticResource MusicNoteList}" /> <Style x:Key="PlaylistSubtitleTextBlock" TargetType="TextBlock">
</Viewbox> <Setter Property="Foreground" Value="{StaticResource PlaylistItemSubtitleBrush}"/>
<TextBlock Text="{x:Bind Name}" FontSize="16" VerticalAlignment="Center" /> <Setter Property="FontSize" Value="13"/>
</StackPanel> <Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="LineHeight" Value="0"/>
</Style>
<DataTemplate x:Key="PlaylistTemplate" x:DataType="vm:PlaylistItemViewModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
<Viewbox Height="24" Width="24">
<PathIcon Data="{StaticResource MusicNoteList}" />
</Viewbox>
<TextBlock Text="{x:Bind Playlist.Name}" FontSize="16" VerticalAlignment="Center" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center" Spacing="8">
<TextBlock Text="{x:Bind Summary, Mode=OneWay}" Style="{StaticResource PlaylistSubtitleTextBlock}" />
</StackPanel>
</Grid>
</DataTemplate> </DataTemplate>
</UserControl.Resources> </UserControl.Resources>
<Grid Margin="10"> <Grid Margin="10">