Removed "PlaylistSongs" field, in order to maintain one source of truth (Playlist.Songs). No not allow reordering when a filter is present on the playlist.
This commit is contained in:
@@ -56,19 +56,6 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObservableCollection<PlaylistSong> _playlistSongs = [];
|
|
||||||
public ObservableCollection<PlaylistSong> PlaylistSongs
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _playlistSongs;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetProperty(ref _playlistSongs, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string? _filter;
|
private string? _filter;
|
||||||
public string? Filter
|
public string? Filter
|
||||||
{
|
{
|
||||||
@@ -79,10 +66,13 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
SetProperty(ref _filter, value);
|
SetProperty(ref _filter, value);
|
||||||
|
OnPropertyChanged(nameof(CanReorderSongs));
|
||||||
RestartFilterTimer();
|
RestartFilterTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanReorderSongs => string.IsNullOrWhiteSpace(Filter);
|
||||||
|
|
||||||
private ObservableCollection<PlaylistSong> _filteredPlaylistSongs = [];
|
private ObservableCollection<PlaylistSong> _filteredPlaylistSongs = [];
|
||||||
public ObservableCollection<PlaylistSong> FilteredPlaylistSongs
|
public ObservableCollection<PlaylistSong> FilteredPlaylistSongs
|
||||||
{
|
{
|
||||||
@@ -123,6 +113,8 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
|||||||
|
|
||||||
public bool IsUserUpdating { get; set; }
|
public bool IsUserUpdating { get; set; }
|
||||||
private bool _isUserInitiatingSongChange;
|
private bool _isUserInitiatingSongChange;
|
||||||
|
private PlaylistSong? _pendingMovedSong;
|
||||||
|
private int _pendingMovedSongIndex = -1;
|
||||||
|
|
||||||
public event EventHandler? PlayingSongChangedAutomatically;
|
public event EventHandler? PlayingSongChangedAutomatically;
|
||||||
|
|
||||||
@@ -152,10 +144,7 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
|||||||
FilteredPlaylistSongs.CollectionChanged += OnFilteredPlaylistSongsCollectionChanged;
|
FilteredPlaylistSongs.CollectionChanged += OnFilteredPlaylistSongsCollectionChanged;
|
||||||
|
|
||||||
Playlist = _playlistManager.CurrentPlaylist; // Testing
|
Playlist = _playlistManager.CurrentPlaylist; // Testing
|
||||||
UpdatePlaylistSongs(Playlist);
|
UpdateFilteredSongs();
|
||||||
|
|
||||||
// Testing
|
|
||||||
//Task.Run(() => PlayDemoSong(playlistRepository));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnFilteredPlaylistSongsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
private void OnFilteredPlaylistSongsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
@@ -163,47 +152,42 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
|||||||
if (IsUserUpdating == false)
|
if (IsUserUpdating == false)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int x = 1;
|
// A drag-reorder in the ListView raises a Remove followed by an Add for the same item.
|
||||||
|
// Reordering is only enabled while unfiltered, so view indices map 1:1 to Playlist.Songs.
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
_pendingMovedSong = e.OldItems?.Cast<PlaylistSong>().FirstOrDefault();
|
||||||
|
_pendingMovedSongIndex = e.OldStartingIndex;
|
||||||
|
break;
|
||||||
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
PlaylistSong? addedSong = e.NewItems?.Cast<PlaylistSong>().FirstOrDefault();
|
||||||
|
|
||||||
|
if (addedSong != null && addedSong == _pendingMovedSong)
|
||||||
|
{
|
||||||
|
MoveSongInPlaylist(_pendingMovedSongIndex, e.NewStartingIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
_pendingMovedSong = null;
|
||||||
|
_pendingMovedSongIndex = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//private async Task PlayDemoSong(IPlaylistRepository playlistRepository)
|
private void MoveSongInPlaylist(int oldIndex, int newIndex)
|
||||||
//{
|
|
||||||
// if (playlistRepository.Get().Count == 0)
|
|
||||||
// {
|
|
||||||
// playlistRepository.AddPlaylist();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Playlist playlist = playlistRepository.Get().First();
|
|
||||||
|
|
||||||
// if (playlist.Songs.Count > 0)
|
|
||||||
// await _audioPlayer.LoadAsync(playlist.Songs[0], PlaybackMode.LoadOnly);
|
|
||||||
//}
|
|
||||||
|
|
||||||
private void UpdatePlaylistSongs(Playlist? playlist)
|
|
||||||
{
|
{
|
||||||
PlaylistSong[] playlistSongs = playlist?.Songs.ToArray() ?? [];
|
if (Playlist == null || oldIndex < 0 || oldIndex == newIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
PlaylistSongs = [.. playlistSongs];
|
Playlist.MoveSong(oldIndex, newIndex);
|
||||||
UpdateFilteredSongs();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPlaylistChanged(object? sender, EventArgs e)
|
private void OnPlaylistChanged(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (Playlist != null)
|
Playlist?.PlaylistUpdated -= OnPlaylistUpdated;
|
||||||
{
|
|
||||||
Playlist.PlaylistUpdated -= OnPlaylistUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
Playlist = _audioPlayer.Playlist;
|
Playlist = _audioPlayer.Playlist;
|
||||||
|
Playlist?.PlaylistUpdated += OnPlaylistUpdated;
|
||||||
|
|
||||||
if (Playlist != null)
|
|
||||||
{
|
|
||||||
Playlist.PlaylistUpdated += OnPlaylistUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlaylistSong[] playlistSongs = _audioPlayer.Playlist?.Songs.ToArray() ?? [];
|
|
||||||
|
|
||||||
PlaylistSongs = [.. playlistSongs];
|
|
||||||
UpdateFilteredSongs();
|
UpdateFilteredSongs();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,32 +199,23 @@ public partial class PlaylistDetailViewModel : ViewModelBase
|
|||||||
switch (e.Action)
|
switch (e.Action)
|
||||||
{
|
{
|
||||||
case PlaylistUpdateAction.Add:
|
case PlaylistUpdateAction.Add:
|
||||||
_dispatcherQueue.TryEnqueue(() => AddSongs(e.Songs, e.Index));
|
|
||||||
break;
|
|
||||||
case PlaylistUpdateAction.Remove:
|
case PlaylistUpdateAction.Remove:
|
||||||
_dispatcherQueue.TryEnqueue(() => RemoveSongsFromCollection(e.Songs));
|
_dispatcherQueue.TryEnqueue(UpdateFilteredSongs);
|
||||||
|
break;
|
||||||
|
case PlaylistUpdateAction.Move:
|
||||||
|
case PlaylistUpdateAction.Reset:
|
||||||
|
_dispatcherQueue.TryEnqueue(() => ApplyReorderedSongs(e.Songs));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSongs(PlaylistSong[] playlistSongs, int index = 0)
|
private void ApplyReorderedSongs(PlaylistSong[] playlistSongs)
|
||||||
{
|
{
|
||||||
// TODO: Performance improvements
|
// UpdateFilteredSongs assumes the projection order matches Playlist.Songs order,
|
||||||
int currentIndex = index;
|
// so remove reordered songs first to let them be reinserted at their new positions.
|
||||||
|
|
||||||
foreach (PlaylistSong playlistSong in playlistSongs)
|
foreach (PlaylistSong playlistSong in playlistSongs)
|
||||||
{
|
{
|
||||||
PlaylistSongs.Insert(currentIndex++, playlistSong);
|
FilteredPlaylistSongs.Remove(playlistSong);
|
||||||
}
|
|
||||||
|
|
||||||
UpdateFilteredSongs();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RemoveSongsFromCollection(PlaylistSong[] playlistSongs)
|
|
||||||
{
|
|
||||||
foreach (PlaylistSong playlistSong in playlistSongs)
|
|
||||||
{
|
|
||||||
PlaylistSongs.Remove(playlistSong);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateFilteredSongs();
|
UpdateFilteredSongs();
|
||||||
|
|||||||
@@ -184,11 +184,11 @@
|
|||||||
Name="PlaylistListView"
|
Name="PlaylistListView"
|
||||||
ItemsSource="{Binding FilteredPlaylistSongs}"
|
ItemsSource="{Binding FilteredPlaylistSongs}"
|
||||||
ItemTemplate="{StaticResource SongTemplate}"
|
ItemTemplate="{StaticResource SongTemplate}"
|
||||||
CanReorderItems="True"
|
CanReorderItems="{Binding CanReorderSongs, Mode=OneWay}"
|
||||||
CanDragItems="True"
|
CanDragItems="{Binding CanReorderSongs, Mode=OneWay}"
|
||||||
DragItemsStarting="PlaylistListView_DragItemsStarting"
|
DragItemsStarting="PlaylistListView_DragItemsStarting"
|
||||||
DragItemsCompleted="PlaylistListView_DragItemsCompleted"
|
DragItemsCompleted="PlaylistListView_DragItemsCompleted"
|
||||||
AllowDrop="True"
|
AllowDrop="{Binding CanReorderSongs, Mode=OneWay}"
|
||||||
SelectionMode="Extended"
|
SelectionMode="Extended"
|
||||||
SelectionChanged="PlaylistListView_SelectionChanged">
|
SelectionChanged="PlaylistListView_SelectionChanged">
|
||||||
<ListView.ContextFlyout>
|
<ListView.ContextFlyout>
|
||||||
|
|||||||
Reference in New Issue
Block a user