diff --git a/Harmonia.Core/Player/AudioPlayer.cs b/Harmonia.Core/Player/AudioPlayer.cs index bf8e3b8..39c4312 100644 --- a/Harmonia.Core/Player/AudioPlayer.cs +++ b/Harmonia.Core/Player/AudioPlayer.cs @@ -20,9 +20,13 @@ public class AudioPlayer : IAudioPlayer } protected set { + Playlist? oldPlaylist = _playlist; _playlist = value; + NotifyPropertyChanged(nameof(Playlist)); - PlaylistChanged?.Invoke(this, new()); + + PlaylistChangedEventArgs eventArgs = new(oldPlaylist, value); + PlaylistChanged?.Invoke(this, eventArgs); } } @@ -37,9 +41,13 @@ public class AudioPlayer : IAudioPlayer } protected set { + PlaylistSong? oldSong = _playingSong; _playingSong = value; + NotifyPropertyChanged(nameof(PlayingSong)); - PlayingSongChanged?.Invoke(this, new()); + + PlayingSongChangedEventArgs eventArgs = new(oldSong, value); + PlayingSongChanged?.Invoke(this, eventArgs); } } @@ -115,8 +123,8 @@ public class AudioPlayer : IAudioPlayer protected virtual int PreviousSongSecondsThreshold => 5; - public event EventHandler? PlaylistChanged; - public event EventHandler? PlayingSongChanged; + public event EventHandler? PlaylistChanged; + public event EventHandler? PlayingSongChanged; public event PropertyChangedEventHandler? PropertyChanged; public AudioPlayer(IAudioEngine audioEngine, IPlaylistManager playlistManager) diff --git a/Harmonia.Core/Player/IAudioPlayer.cs b/Harmonia.Core/Player/IAudioPlayer.cs index f71f2be..7b97dff 100644 --- a/Harmonia.Core/Player/IAudioPlayer.cs +++ b/Harmonia.Core/Player/IAudioPlayer.cs @@ -24,7 +24,7 @@ public interface IAudioPlayer Task PreviousAsync(); Task NextAsync(); - event EventHandler PlaylistChanged; - event EventHandler PlayingSongChanged; + event EventHandler PlaylistChanged; + event EventHandler PlayingSongChanged; event PropertyChangedEventHandler PropertyChanged; } \ No newline at end of file diff --git a/Harmonia.Core/Player/PlayingSongChangedEventArgs.cs b/Harmonia.Core/Player/PlayingSongChangedEventArgs.cs new file mode 100644 index 0000000..4aad722 --- /dev/null +++ b/Harmonia.Core/Player/PlayingSongChangedEventArgs.cs @@ -0,0 +1,9 @@ +using Harmonia.Core.Playlists; + +namespace Harmonia.Core.Player; + +public class PlayingSongChangedEventArgs(PlaylistSong? oldSong, PlaylistSong? newSong) : EventArgs +{ + public PlaylistSong? OldSong { get; } = oldSong; + public PlaylistSong? NewSong { get; } = newSong; +} \ No newline at end of file diff --git a/Harmonia.Core/Player/PlaylistChangedEventArgs.cs b/Harmonia.Core/Player/PlaylistChangedEventArgs.cs new file mode 100644 index 0000000..5d6e822 --- /dev/null +++ b/Harmonia.Core/Player/PlaylistChangedEventArgs.cs @@ -0,0 +1,9 @@ +using Harmonia.Core.Playlists; + +namespace Harmonia.Core.Player; + +public class PlaylistChangedEventArgs(Playlist? oldPlaylist, Playlist? newPlaylist) : EventArgs +{ + public Playlist? OldPlaylist { get; } = oldPlaylist; + public Playlist? NewPlaylist { get; } = newPlaylist; +} \ No newline at end of file diff --git a/Harmonia.Core/Playlists/IPlaylistManager.cs b/Harmonia.Core/Playlists/IPlaylistManager.cs index 74cef68..e12457b 100644 --- a/Harmonia.Core/Playlists/IPlaylistManager.cs +++ b/Harmonia.Core/Playlists/IPlaylistManager.cs @@ -13,4 +13,5 @@ public interface IPlaylistManager event EventHandler? CurrentPlaylistChanged; event EventHandler PlaylistAdded; event EventHandler PlaylistRemoved; + event EventHandler? PlaylistSaveFailed; } \ No newline at end of file diff --git a/Harmonia.Core/Playlists/PlaylistManager.cs b/Harmonia.Core/Playlists/PlaylistManager.cs index d0f662e..2c76c38 100644 --- a/Harmonia.Core/Playlists/PlaylistManager.cs +++ b/Harmonia.Core/Playlists/PlaylistManager.cs @@ -25,6 +25,7 @@ public class PlaylistManager : IPlaylistManager public event EventHandler? CurrentPlaylistChanged; public event EventHandler? PlaylistAdded; public event EventHandler? PlaylistRemoved; + public event EventHandler? PlaylistSaveFailed; public PlaylistManager(IPlaylistRepository playlistRepository) { @@ -60,7 +61,7 @@ public class PlaylistManager : IPlaylistManager _playlistsBySongUid[song.UID] = playlist; } - await playlistRepository.SaveAsync(playlist); + await SavePlaylistAsync(playlist); PlaylistAdded?.Invoke(this, new(playlist)); @@ -108,6 +109,18 @@ public class PlaylistManager : IPlaylistManager break; } - await playlistRepository.SaveAsync(playlist); + await SavePlaylistAsync(playlist); + } + + private async Task SavePlaylistAsync(Playlist playlist) + { + try + { + await playlistRepository.SaveAsync(playlist); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) + { + PlaylistSaveFailed?.Invoke(this, new(playlist, ex)); + } } } \ No newline at end of file diff --git a/Harmonia.Core/Playlists/PlaylistSaveFailedEventArgs.cs b/Harmonia.Core/Playlists/PlaylistSaveFailedEventArgs.cs new file mode 100644 index 0000000..abce39e --- /dev/null +++ b/Harmonia.Core/Playlists/PlaylistSaveFailedEventArgs.cs @@ -0,0 +1,7 @@ +namespace Harmonia.Core.Playlists; + +public class PlaylistSaveFailedEventArgs(Playlist playlist, Exception exception) : EventArgs +{ + public Playlist Playlist { get; } = playlist; + public Exception Exception { get; } = exception; +} \ No newline at end of file diff --git a/Harmonia.WinUI/ViewModels/PlayerViewModel.cs b/Harmonia.WinUI/ViewModels/PlayerViewModel.cs index 6e88d45..6cbd599 100644 --- a/Harmonia.WinUI/ViewModels/PlayerViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlayerViewModel.cs @@ -229,9 +229,9 @@ public partial class PlayerViewModel : ViewModelBase #region Event Handlers - private void OnPlayingSongChanged(object? sender, EventArgs e) + private void OnPlayingSongChanged(object? sender, PlayingSongChangedEventArgs e) { - Song = _audioPlayer.PlayingSong?.Song; + Song = e.NewSong?.Song; Task.Run(UpdateImage); } diff --git a/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs b/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs index 653e105..62a6254 100644 --- a/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlayingSongViewModel.cs @@ -52,9 +52,9 @@ public partial class PlayingSongViewModel : ViewModelBase _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); } - private void OnAudioPlayerPlayingSongChanged(object? sender, EventArgs e) + private void OnAudioPlayerPlayingSongChanged(object? sender, PlayingSongChangedEventArgs e) { - Song = _audioPlayer.PlayingSong?.Song; + Song = e.NewSong?.Song; Task.Run(UpdateImage); } diff --git a/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs b/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs index 78fc0b7..9014b68 100644 --- a/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlaylistDetailViewModel.cs @@ -274,7 +274,6 @@ public partial class PlaylistDetailViewModel : ViewModelBase private void OnPlaylistChanged(object? sender, EventArgs e) { Playlist?.PlaylistUpdated -= OnPlaylistUpdated; - //Playlist = _audioPlayer.Playlist; Playlist = _playlistManager.CurrentPlaylist; Playlist?.PlaylistUpdated += OnPlaylistUpdated; @@ -318,9 +317,9 @@ public partial class PlaylistDetailViewModel : ViewModelBase UpdateFilteredSongs(); } - private void OnPlayingSongChanged(object? sender, EventArgs e) + private void OnPlayingSongChanged(object? sender, PlayingSongChangedEventArgs e) { - PlayingSong = _audioPlayer.PlayingSong; + PlayingSong = e.NewSong; if (_isUserInitiatingSongChange) { diff --git a/Harmonia.WinUI/ViewModels/PlaylistsViewModel.cs b/Harmonia.WinUI/ViewModels/PlaylistsViewModel.cs index 76eb5ac..a86e008 100644 --- a/Harmonia.WinUI/ViewModels/PlaylistsViewModel.cs +++ b/Harmonia.WinUI/ViewModels/PlaylistsViewModel.cs @@ -1,5 +1,6 @@ using Harmonia.Core.Player; using Harmonia.Core.Playlists; +using Microsoft.UI.Dispatching; using System; using System.Collections.ObjectModel; using System.Linq; @@ -10,6 +11,7 @@ public partial class PlaylistsViewModel : ViewModelBase { private readonly IPlaylistManager _playlistManager; private readonly IAudioPlayer _audioPlayer; + private readonly DispatcherQueue _dispatcherQueue; private ObservableCollection _playlists = []; public ObservableCollection Playlists @@ -63,6 +65,8 @@ public partial class PlaylistsViewModel : ViewModelBase _audioPlayer = audioPlayer; _audioPlayer.PlayingSongChanged += OnPlayingSongChanged; + _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + _playlists = new ObservableCollection(_playlistManager.Playlists.Select(p => new PlaylistItemViewModel(p))); _selectedPlaylist = _playlists.FirstOrDefault(pv => pv.Playlist == _playlistManager.CurrentPlaylist); } @@ -88,7 +92,12 @@ public partial class PlaylistsViewModel : ViewModelBase } } - private void OnPlayingSongChanged(object? sender, EventArgs e) + private void OnPlayingSongChanged(object? sender, PlayingSongChangedEventArgs e) + { + _dispatcherQueue.TryEnqueue(UpdateActivePlaylist); + } + + private void UpdateActivePlaylist() { ActivePlaylist = Playlists.FirstOrDefault(pv => pv.Playlist == _audioPlayer.Playlist); }