// Copyright (c) Arlo Godfrey. All Rights Reserved. // Licensed under the GNU Lesser General Public License, Version 3.0 with additional terms. // See the LICENSE, LICENSE.LESSER and LICENSE.ADDITIONAL files in the project root for more information. using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using CommunityToolkit.Diagnostics; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using OwlCore; using OwlCore.Events; using OwlCore.Extensions; using StrixMusic.Sdk.AdapterModels; using StrixMusic.Sdk.AppModels; using StrixMusic.Sdk.BaseModels; using StrixMusic.Sdk.CoreModels; using StrixMusic.Sdk.Extensions; using StrixMusic.Sdk.MediaPlayback; using StrixMusic.Sdk.ViewModels.Helpers; namespace StrixMusic.Sdk.ViewModels { /// /// A ViewModel for . /// public class PlayableCollectionGroupViewModel : ObservableObject, ISdkViewModel, IPlayableCollectionGroup, IPlayableCollectionGroupChildrenViewModel, IAlbumCollectionViewModel, IArtistCollectionViewModel, ITrackCollectionViewModel, IPlaylistCollectionViewModel, IImageCollectionViewModel, IUrlCollectionViewModel { private readonly IPlayableCollectionGroup _collectionGroup; private readonly SemaphoreSlim _populateTracksMutex = new(1, 1); private readonly SemaphoreSlim _populateAlbumsMutex = new(1, 1); private readonly SemaphoreSlim _populateArtistsMutex = new(1, 1); private readonly SemaphoreSlim _populatePlaylistsMutex = new(1, 1); private readonly SemaphoreSlim _populateChildrenMutex = new(1, 1); private readonly SemaphoreSlim _populateImagesMutex = new(1, 1); private readonly SemaphoreSlim _populateUrlsMutex = new(1, 1); private readonly SynchronizationContext _syncContext; /// /// Initializes a new instance of the class. /// /// The base containing properties about this class. public PlayableCollectionGroupViewModel(IPlayableCollectionGroup collectionGroup) { _syncContext = SynchronizationContext.Current; _collectionGroup = collectionGroup; PauseAlbumCollectionAsyncCommand = new AsyncRelayCommand(PauseAlbumCollectionAsync); PlayAlbumCollectionAsyncCommand = new AsyncRelayCommand(PlayAlbumCollectionAsync); PauseArtistCollectionAsyncCommand = new AsyncRelayCommand(PauseArtistCollectionAsync); PlayArtistCollectionAsyncCommand = new AsyncRelayCommand(PlayArtistCollectionAsync); PausePlaylistCollectionAsyncCommand = new AsyncRelayCommand(PausePlaylistCollectionAsync); PlayPlaylistCollectionAsyncCommand = new AsyncRelayCommand(PlayPlaylistCollectionAsync); PauseTrackCollectionAsyncCommand = new AsyncRelayCommand(PauseTrackCollectionAsync); PlayTrackCollectionAsyncCommand = new AsyncRelayCommand(PlayTrackCollectionAsync); PlayTrackAsyncCommand = new AsyncRelayCommand((x, y) => _collectionGroup.PlayTrackCollectionAsync(x ?? ThrowHelper.ThrowArgumentNullException(nameof(x)), y)); PlayAlbumAsyncCommand = new AsyncRelayCommand((x, y) => _collectionGroup.PlayAlbumCollectionAsync(x ?? ThrowHelper.ThrowArgumentNullException(nameof(x)), y)); PlayPlaylistAsyncCommand = new AsyncRelayCommand((x, y) => _collectionGroup.PlayPlaylistCollectionAsync(x ?? ThrowHelper.ThrowArgumentNullException(nameof(x)), y)); PlayArtistAsyncCommand = new AsyncRelayCommand((x, y) => _collectionGroup.PlayArtistCollectionAsync(x ?? ThrowHelper.ThrowArgumentNullException(nameof(x)), y)); ChangeNameAsyncCommand = new AsyncRelayCommand(ChangeNameInternalAsync); ChangeDescriptionAsyncCommand = new AsyncRelayCommand(ChangeDescriptionAsync); ChangeDurationAsyncCommand = new AsyncRelayCommand(ChangeDurationAsync); PopulateMoreTracksCommand = new AsyncRelayCommand(PopulateMoreTracksAsync); PopulateMorePlaylistsCommand = new AsyncRelayCommand(PopulateMorePlaylistsAsync); PopulateMoreAlbumsCommand = new AsyncRelayCommand(PopulateMoreAlbumsAsync); PopulateMoreArtistsCommand = new AsyncRelayCommand(PopulateMoreArtistsAsync); PopulateMoreChildrenCommand = new AsyncRelayCommand(PopulateMoreChildrenAsync); PopulateMoreImagesCommand = new AsyncRelayCommand(PopulateMoreImagesAsync); PopulateMoreUrlsCommand = new AsyncRelayCommand(PopulateMoreUrlsAsync); InitImageCollectionAsyncCommand = new AsyncRelayCommand(InitImageCollectionAsync); InitTrackCollectionAsyncCommand = new AsyncRelayCommand(InitTrackCollectionAsync); InitArtistCollectionAsyncCommand = new AsyncRelayCommand(InitArtistCollectionAsync); InitAlbumCollectionAsyncCommand = new AsyncRelayCommand(InitAlbumCollectionAsync); InitPlaylistCollectionAsyncCommand = new AsyncRelayCommand(InitPlaylistCollectionAsync); ChangeTrackCollectionSortingTypeCommand = new RelayCommand(x => SortTrackCollection(x, CurrentTracksSortingDirection)); ChangeTrackCollectionSortingDirectionCommand = new RelayCommand(x => SortTrackCollection(CurrentTracksSortingType, x)); ChangeArtistCollectionSortingTypeCommand = new RelayCommand(x => SortArtistCollection(x, CurrentArtistSortingDirection)); ChangeArtistCollectionSortingDirectionCommand = new RelayCommand(x => SortArtistCollection(CurrentArtistSortingType, x)); ChangeAlbumCollectionSortingTypeCommand = new RelayCommand(x => SortAlbumCollection(x, CurrentAlbumSortingDirection)); ChangeAlbumCollectionSortingDirectionCommand = new RelayCommand(x => SortAlbumCollection(CurrentAlbumSortingType, x)); ChangePlaylistCollectionSortingTypeCommand = new RelayCommand(x => SortPlaylistCollection(x, CurrentPlaylistSortingDirection)); ChangePlaylistCollectionSortingDirectionCommand = new RelayCommand(x => SortPlaylistCollection(CurrentPlaylistSortingType, x)); Albums = new ObservableCollection(); Artists = new ObservableCollection(); Children = new ObservableCollection(); Playlists = new ObservableCollection(); Tracks = new ObservableCollection(); Images = new ObservableCollection(); Urls = new ObservableCollection(); UnsortedAlbums = new ObservableCollection(); UnsortedArtists = new ObservableCollection(); UnsortedPlaylists = new ObservableCollection(); UnsortedTracks = new ObservableCollection(); AttachPropertyEvents(); } private void AttachPropertyEvents() { PlaybackStateChanged += CollectionGroupPlaybackStateChanged; DescriptionChanged += CollectionGroupDescriptionChanged; NameChanged += CollectionGroupNameChanged; LastPlayedChanged += CollectionGroupLastPlayedChanged; DownloadInfoChanged += OnDownloadInfoChanged; AlbumItemsCountChanged += CollectionGroupOnAlbumItemsCountChanged; TracksCountChanged += CollectionGroupOnTrackItemsCountChanged; ArtistItemsCountChanged += CollectionGroupOnArtistItemsCountChanged; PlaylistItemsCountChanged += CollectionGroupOnPlaylistItemsCountChanged; ChildrenCountChanged += CollectionGroupOnTotalChildrenCountChanged; ImagesCountChanged += PlayableCollectionGroupViewModel_ImagesCountChanged; UrlsCountChanged += PlayableCollectionGroupViewModel_UrlsCountChanged; IsPlayAlbumCollectionAsyncAvailableChanged += OnIsPlayAlbumCollectionAsyncAvailableChanged; IsPauseAlbumCollectionAsyncAvailableChanged += OnIsPauseAlbumCollectionAsyncAvailableChanged; IsPlayArtistCollectionAsyncAvailableChanged += OnIsPlayArtistCollectionAsyncAvailableChanged; IsPauseArtistCollectionAsyncAvailableChanged += OnIsPauseArtistCollectionAsyncAvailableChanged; IsPlayPlaylistCollectionAsyncAvailableChanged += OnIsPlayPlaylistCollectionAsyncAvailableChanged; IsPausePlaylistCollectionAsyncAvailableChanged += OnIsPausePlaylistCollectionAsyncAvailableChanged; IsPlayTrackCollectionAsyncAvailableChanged += OnIsPlayTrackCollectionAsyncAvailableChanged; IsPauseTrackCollectionAsyncAvailableChanged += OnIsPauseTrackCollectionAsyncAvailableChanged; IsChangeNameAsyncAvailableChanged += OnIsChangeNameAsyncAvailableChanged; IsChangeDurationAsyncAvailableChanged += OnIsChangeDurationAsyncAvailableChanged; IsChangeDescriptionAsyncAvailableChanged += OnIsChangeDescriptionAsyncAvailableChanged; AlbumItemsChanged += PlayableCollectionGroupViewModel_AlbumItemsChanged; TracksChanged += PlayableCollectionGroupViewModel_TrackItemsChanged; ArtistItemsChanged += PlayableCollectionGroupViewModel_ArtistItemsChanged; PlaylistItemsChanged += PlayableCollectionGroupViewModel_PlaylistItemsChanged; ChildItemsChanged += PlayableCollectionGroupViewModel_ChildItemsChanged; ImagesChanged += PlayableCollectionGroupViewModel_ImagesChanged; UrlsChanged += PlayableCollectionGroupViewModel_UrlsChanged; } private void DetachPropertyEvents() { PlaybackStateChanged -= CollectionGroupPlaybackStateChanged; DescriptionChanged -= CollectionGroupDescriptionChanged; NameChanged -= CollectionGroupNameChanged; LastPlayedChanged -= CollectionGroupLastPlayedChanged; DownloadInfoChanged -= OnDownloadInfoChanged; AlbumItemsCountChanged -= CollectionGroupOnAlbumItemsCountChanged; TracksCountChanged -= CollectionGroupOnTrackItemsCountChanged; ArtistItemsCountChanged -= CollectionGroupOnArtistItemsCountChanged; PlaylistItemsCountChanged -= CollectionGroupOnPlaylistItemsCountChanged; ChildrenCountChanged -= CollectionGroupOnTotalChildrenCountChanged; ImagesCountChanged += PlayableCollectionGroupViewModel_ImagesCountChanged; IsPlayAlbumCollectionAsyncAvailableChanged -= OnIsPlayAlbumCollectionAsyncAvailableChanged; IsPauseAlbumCollectionAsyncAvailableChanged -= OnIsPauseAlbumCollectionAsyncAvailableChanged; IsPlayArtistCollectionAsyncAvailableChanged -= OnIsPlayArtistCollectionAsyncAvailableChanged; IsPauseArtistCollectionAsyncAvailableChanged -= OnIsPauseArtistCollectionAsyncAvailableChanged; IsPlayPlaylistCollectionAsyncAvailableChanged -= OnIsPlayPlaylistCollectionAsyncAvailableChanged; IsPausePlaylistCollectionAsyncAvailableChanged -= OnIsPausePlaylistCollectionAsyncAvailableChanged; IsPlayTrackCollectionAsyncAvailableChanged -= OnIsPlayTrackCollectionAsyncAvailableChanged; IsPauseTrackCollectionAsyncAvailableChanged -= OnIsPauseTrackCollectionAsyncAvailableChanged; IsChangeNameAsyncAvailableChanged -= OnIsChangeNameAsyncAvailableChanged; IsChangeDurationAsyncAvailableChanged -= OnIsChangeDurationAsyncAvailableChanged; IsChangeDescriptionAsyncAvailableChanged -= OnIsChangeDescriptionAsyncAvailableChanged; AlbumItemsChanged -= PlayableCollectionGroupViewModel_AlbumItemsChanged; TracksChanged -= PlayableCollectionGroupViewModel_TrackItemsChanged; ArtistItemsChanged -= PlayableCollectionGroupViewModel_ArtistItemsChanged; PlaylistItemsChanged -= PlayableCollectionGroupViewModel_PlaylistItemsChanged; ChildItemsChanged -= PlayableCollectionGroupViewModel_ChildItemsChanged; ImagesChanged -= PlayableCollectionGroupViewModel_ImagesChanged; } /// public event EventHandler? SourcesChanged { add => _collectionGroup.SourcesChanged += value; remove => _collectionGroup.SourcesChanged -= value; } /// public event EventHandler? NameChanged { add => _collectionGroup.NameChanged += value; remove => _collectionGroup.NameChanged -= value; } /// public event EventHandler? DescriptionChanged { add => _collectionGroup.DescriptionChanged += value; remove => _collectionGroup.DescriptionChanged -= value; } /// public event EventHandler? PlaybackStateChanged { add => _collectionGroup.PlaybackStateChanged += value; remove => _collectionGroup.PlaybackStateChanged -= value; } /// public event EventHandler? DownloadInfoChanged { add => _collectionGroup.DownloadInfoChanged += value; remove => _collectionGroup.DownloadInfoChanged -= value; } /// public event EventHandler? DurationChanged { add => _collectionGroup.DurationChanged += value; remove => _collectionGroup.DurationChanged -= value; } /// public event EventHandler? LastPlayedChanged { add => _collectionGroup.LastPlayedChanged += value; remove => _collectionGroup.LastPlayedChanged -= value; } /// public event EventHandler? IsChangeNameAsyncAvailableChanged { add => _collectionGroup.IsChangeNameAsyncAvailableChanged += value; remove => _collectionGroup.IsChangeNameAsyncAvailableChanged -= value; } /// public event EventHandler? IsChangeDescriptionAsyncAvailableChanged { add => _collectionGroup.IsChangeDescriptionAsyncAvailableChanged += value; remove => _collectionGroup.IsChangeDescriptionAsyncAvailableChanged -= value; } /// public event EventHandler? IsChangeDurationAsyncAvailableChanged { add => _collectionGroup.IsChangeDurationAsyncAvailableChanged += value; remove => _collectionGroup.IsChangeDurationAsyncAvailableChanged -= value; } /// public event EventHandler? IsPlayAlbumCollectionAsyncAvailableChanged { add => _collectionGroup.IsPlayAlbumCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPlayAlbumCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPlayArtistCollectionAsyncAvailableChanged { add => _collectionGroup.IsPlayArtistCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPlayArtistCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPlayPlaylistCollectionAsyncAvailableChanged { add => _collectionGroup.IsPlayPlaylistCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPlayPlaylistCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPlayTrackCollectionAsyncAvailableChanged { add => _collectionGroup.IsPlayTrackCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPlayTrackCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPauseArtistCollectionAsyncAvailableChanged { add => _collectionGroup.IsPauseArtistCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPauseArtistCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPauseAlbumCollectionAsyncAvailableChanged { add => _collectionGroup.IsPauseAlbumCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPauseAlbumCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPausePlaylistCollectionAsyncAvailableChanged { add => _collectionGroup.IsPausePlaylistCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPausePlaylistCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? IsPauseTrackCollectionAsyncAvailableChanged { add => _collectionGroup.IsPauseTrackCollectionAsyncAvailableChanged += value; remove => _collectionGroup.IsPauseTrackCollectionAsyncAvailableChanged -= value; } /// public event EventHandler? TracksCountChanged { add => _collectionGroup.TracksCountChanged += value; remove => _collectionGroup.TracksCountChanged -= value; } /// public event EventHandler? ArtistItemsCountChanged { add => _collectionGroup.ArtistItemsCountChanged += value; remove => _collectionGroup.ArtistItemsCountChanged -= value; } /// public event EventHandler? AlbumItemsCountChanged { add => _collectionGroup.AlbumItemsCountChanged += value; remove => _collectionGroup.AlbumItemsCountChanged -= value; } /// public event EventHandler? PlaylistItemsCountChanged { add => _collectionGroup.PlaylistItemsCountChanged += value; remove => _collectionGroup.PlaylistItemsCountChanged -= value; } /// public event EventHandler? ImagesCountChanged { add => _collectionGroup.ImagesCountChanged += value; remove => _collectionGroup.ImagesCountChanged -= value; } /// public event EventHandler? UrlsCountChanged { add => _collectionGroup.UrlsCountChanged += value; remove => _collectionGroup.UrlsCountChanged -= value; } /// public event CollectionChangedEventHandler? ImagesChanged { add => _collectionGroup.ImagesChanged += value; remove => _collectionGroup.ImagesChanged -= value; } /// public event CollectionChangedEventHandler? PlaylistItemsChanged { add => _collectionGroup.PlaylistItemsChanged += value; remove => _collectionGroup.PlaylistItemsChanged -= value; } /// public event CollectionChangedEventHandler? TracksChanged { add => _collectionGroup.TracksChanged += value; remove => _collectionGroup.TracksChanged -= value; } /// public event CollectionChangedEventHandler? AlbumItemsChanged { add => _collectionGroup.AlbumItemsChanged += value; remove => _collectionGroup.AlbumItemsChanged -= value; } /// public event CollectionChangedEventHandler? ArtistItemsChanged { add => _collectionGroup.ArtistItemsChanged += value; remove => _collectionGroup.ArtistItemsChanged -= value; } /// public event CollectionChangedEventHandler? ChildItemsChanged { add => _collectionGroup.ChildItemsChanged += value; remove => _collectionGroup.ChildItemsChanged -= value; } /// public event EventHandler? ChildrenCountChanged { add => _collectionGroup.ChildrenCountChanged += value; remove => _collectionGroup.ChildrenCountChanged -= value; } /// public event CollectionChangedEventHandler? UrlsChanged { add => _collectionGroup.UrlsChanged += value; remove => _collectionGroup.UrlsChanged -= value; } private void CollectionGroupNameChanged(object sender, string e) => _syncContext.Post(_ => OnPropertyChanged(nameof(Name)), null); private void CollectionGroupDescriptionChanged(object sender, string? e) => _syncContext.Post(_ => OnPropertyChanged(nameof(Description)), null); private void CollectionGroupPlaybackStateChanged(object sender, PlaybackState e) => _syncContext.Post(_ => OnPropertyChanged(nameof(PlaybackState)), null); private void OnDownloadInfoChanged(object sender, DownloadInfo e) => _syncContext.Post(_ => OnPropertyChanged(nameof(DownloadInfo)), null); private void CollectionGroupOnTotalChildrenCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalChildrenCount)), null); private void CollectionGroupOnPlaylistItemsCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalPlaylistItemsCount)), null); private void CollectionGroupOnArtistItemsCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalArtistItemsCount)), null); private void CollectionGroupOnTrackItemsCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalTrackCount)), null); private void CollectionGroupOnAlbumItemsCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalAlbumItemsCount)), null); private void PlayableCollectionGroupViewModel_ImagesCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalImageCount)), null); private void PlayableCollectionGroupViewModel_UrlsCountChanged(object sender, int e) => _syncContext.Post(_ => OnPropertyChanged(nameof(TotalUrlCount)), null); private void CollectionGroupLastPlayedChanged(object sender, DateTime? e) => _syncContext.Post(_ => OnPropertyChanged(nameof(LastPlayed)), null); private void OnIsChangeDescriptionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsChangeDescriptionAsyncAvailable)), null); private void OnIsChangeDurationAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsChangeDurationAsyncAvailable)), null); private void OnIsChangeNameAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsChangeNameAsyncAvailable)), null); private void OnIsPauseAlbumCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPauseAlbumCollectionAsyncAvailable)), null); private void OnIsPlayAlbumCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPlayAlbumCollectionAsyncAvailable)), null); private void OnIsPauseArtistCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPauseArtistCollectionAsyncAvailable)), null); private void OnIsPlayArtistCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPlayArtistCollectionAsyncAvailable)), null); private void OnIsPausePlaylistCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPausePlaylistCollectionAsyncAvailable)), null); private void OnIsPlayPlaylistCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPlayPlaylistCollectionAsyncAvailable)), null); private void OnIsPauseTrackCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPauseTrackCollectionAsyncAvailable)), null); private void OnIsPlayTrackCollectionAsyncAvailableChanged(object sender, bool e) => _syncContext.Post(_ => OnPropertyChanged(nameof(IsPlayTrackCollectionAsyncAvailable)), null); private void PlayableCollectionGroupViewModel_AlbumItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { if (CurrentAlbumSortingType == AlbumSortingType.Unsorted) { Albums.ChangeCollection(addedItems, removedItems, item => item.Data switch { IAlbum album => new AlbumViewModel(album), IAlbumCollection collection => new AlbumCollectionViewModel(collection), _ => ThrowHelper.ThrowNotSupportedException( $"{item.Data.GetType()} not supported for adding to {GetType()}") }); } else { // Make sure both ordered and unordered album are updated. UnsortedAlbums.ChangeCollection(addedItems, removedItems, item => item.Data switch { IAlbum album => new AlbumViewModel(album), IAlbumCollection collection => new AlbumCollectionViewModel(collection), _ => ThrowHelper.ThrowNotSupportedException( $"{item.Data.GetType()} not supported for adding to {GetType()}") }); foreach (var item in UnsortedAlbums) { if (!Albums.Contains(item)) Albums.Add(item); } foreach (var item in Albums.ToArray()) { if (!UnsortedAlbums.Contains(item)) Albums.Remove(item); } SortAlbumCollection(CurrentAlbumSortingType, CurrentAlbumSortingDirection); } }, null); private void PlayableCollectionGroupViewModel_ArtistItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { Artists.ChangeCollection(addedItems, removedItems, item => item.Data switch { IArtist artist => new ArtistViewModel(artist), IArtistCollection collection => new ArtistCollectionViewModel(collection), _ => ThrowHelper.ThrowNotSupportedException($"{item.Data.GetType()} not supported for adding to {GetType()}") }); }, null); private void PlayableCollectionGroupViewModel_ChildItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { Children.ChangeCollection(addedItems, removedItems, item => new PlayableCollectionGroupViewModel(item.Data)); }, null); private void PlayableCollectionGroupViewModel_PlaylistItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { if (CurrentPlaylistSortingType == PlaylistSortingType.Unsorted) { Playlists.ChangeCollection(addedItems, removedItems, item => item.Data switch { IPlaylist playlist => new PlaylistViewModel(playlist), IPlaylistCollection collection => new PlaylistCollectionViewModel(collection), _ => ThrowHelper.ThrowNotSupportedException( $"{item.Data.GetType()} not supported for adding to {GetType()}") }); } else { // Make sure both ordered and unordered playlists are updated. UnsortedPlaylists.ChangeCollection(addedItems, removedItems, item => item.Data switch { IPlaylist playlist => new PlaylistViewModel(playlist), IPlaylistCollection collection => new PlaylistCollectionViewModel(collection), _ => ThrowHelper.ThrowNotSupportedException( $"{item.Data.GetType()} not supported for adding to {GetType()}") }); foreach (var item in UnsortedPlaylists) { if (!Playlists.Contains(item)) Playlists.Add(item); } foreach (var item in Playlists.ToArray()) { if (!UnsortedPlaylists.Contains(item)) Playlists.Remove(item); } SortPlaylistCollection(CurrentPlaylistSortingType, CurrentPlaylistSortingDirection); } }, null); private void PlayableCollectionGroupViewModel_TrackItemsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { if (this.CurrentTracksSortingType == TrackSortingType.Unsorted) { Tracks.ChangeCollection(addedItems, removedItems, x => new TrackViewModel(x.Data)); } else { // Make sure both ordered and unordered track are updated. UnsortedTracks.ChangeCollection(addedItems, removedItems, x => new TrackViewModel(x.Data)); foreach (var item in UnsortedTracks) { if (!Tracks.Contains(item)) Tracks.Add(item); } foreach (var item in Tracks.ToArray()) { if (!UnsortedTracks.Contains(item)) Tracks.Remove(item); } SortTrackCollection(CurrentTracksSortingType, CurrentTracksSortingDirection); } }, null); private void PlayableCollectionGroupViewModel_ImagesChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { Images.ChangeCollection(addedItems, removedItems); }, null); private void PlayableCollectionGroupViewModel_UrlsChanged(object sender, IReadOnlyList> addedItems, IReadOnlyList> removedItems) => _syncContext.Post(_ => { Urls.ChangeCollection(addedItems, removedItems); }, null); /// public string Id => _collectionGroup.Id; /// /// The merged sources for this item. /// public IReadOnlyList Sources => _collectionGroup.GetSources(); /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// IReadOnlyList IMerged.Sources => Sources; /// public TimeSpan Duration => _collectionGroup.Duration; /// public DateTime? LastPlayed => _collectionGroup.LastPlayed; /// public DateTime? AddedAt => _collectionGroup.AddedAt; /// public ObservableCollection UnsortedTracks { get; } /// public ObservableCollection UnsortedArtists { get; } /// public ObservableCollection UnsortedAlbums { get; } /// public ObservableCollection UnsortedPlaylists { get; } /// /// The albums in this collection. /// public ObservableCollection Albums { get; } /// public ObservableCollection Artists { get; } /// /// The nested items in this collection. /// public ObservableCollection Children { get; } /// public ObservableCollection Playlists { get; } /// public ObservableCollection Tracks { get; set; } /// public ObservableCollection Images { get; } /// public ObservableCollection Urls { get; } /// public TrackSortingType CurrentTracksSortingType { get; private set; } /// public SortDirection CurrentTracksSortingDirection { get; private set; } /// public PlaylistSortingType CurrentPlaylistSortingType { get; private set; } /// public SortDirection CurrentPlaylistSortingDirection { get; private set; } /// public ArtistSortingType CurrentArtistSortingType { get; private set; } /// public SortDirection CurrentArtistSortingDirection { get; private set; } /// public AlbumSortingType CurrentAlbumSortingType { get; private set; } /// public SortDirection CurrentAlbumSortingDirection { get; private set; } /// public string Name => _collectionGroup.Name; /// public int TotalTrackCount => _collectionGroup.TotalTrackCount; /// public int TotalAlbumItemsCount => _collectionGroup.TotalAlbumItemsCount; /// public int TotalArtistItemsCount => _collectionGroup.TotalArtistItemsCount; /// public int TotalChildrenCount => _collectionGroup.TotalChildrenCount; /// public int TotalPlaylistItemsCount => _collectionGroup.TotalPlaylistItemsCount; /// public int TotalImageCount => _collectionGroup.TotalImageCount; /// public int TotalUrlCount => _collectionGroup.TotalUrlCount; /// public string? Description => _collectionGroup.Description; /// public PlaybackState PlaybackState => _collectionGroup.PlaybackState; /// public DownloadInfo DownloadInfo => _collectionGroup.DownloadInfo; /// public bool IsPlayPlaylistCollectionAsyncAvailable => _collectionGroup.IsPlayPlaylistCollectionAsyncAvailable; /// public bool IsPausePlaylistCollectionAsyncAvailable => _collectionGroup.IsPausePlaylistCollectionAsyncAvailable; /// public bool IsPlayTrackCollectionAsyncAvailable => _collectionGroup.IsPlayTrackCollectionAsyncAvailable; /// public bool IsPauseTrackCollectionAsyncAvailable => _collectionGroup.IsPauseTrackCollectionAsyncAvailable; /// public bool IsPlayAlbumCollectionAsyncAvailable => _collectionGroup.IsPlayAlbumCollectionAsyncAvailable; /// public bool IsPauseAlbumCollectionAsyncAvailable => _collectionGroup.IsPauseAlbumCollectionAsyncAvailable; /// public bool IsPlayArtistCollectionAsyncAvailable => _collectionGroup.IsPlayArtistCollectionAsyncAvailable; /// public bool IsPauseArtistCollectionAsyncAvailable => _collectionGroup.IsPauseArtistCollectionAsyncAvailable; /// public bool IsChangeNameAsyncAvailable => _collectionGroup.IsChangeNameAsyncAvailable; /// public bool IsChangeDescriptionAsyncAvailable => _collectionGroup.IsChangeDescriptionAsyncAvailable; /// public bool IsChangeDurationAsyncAvailable => _collectionGroup.IsChangeDurationAsyncAvailable; /// public Task IsAddAlbumItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddAlbumItemAvailableAsync(index, cancellationToken); /// public Task IsAddArtistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddArtistItemAvailableAsync(index, cancellationToken); /// public Task IsAddChildAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddChildAvailableAsync(index, cancellationToken); /// public Task IsAddPlaylistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddPlaylistItemAvailableAsync(index, cancellationToken); /// public Task IsAddTrackAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddTrackAvailableAsync(index, cancellationToken); /// public Task IsAddImageAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddImageAvailableAsync(index, cancellationToken); /// public Task IsAddUrlAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsAddUrlAvailableAsync(index, cancellationToken); /// public Task IsRemoveAlbumItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemoveAlbumItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveArtistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemoveArtistItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveChildAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemoveChildAvailableAsync(index, cancellationToken); /// public Task IsRemovePlaylistItemAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemovePlaylistItemAvailableAsync(index, cancellationToken); /// public Task IsRemoveTrackAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemoveTrackAvailableAsync(index, cancellationToken); /// public Task IsRemoveImageAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemoveImageAvailableAsync(index, cancellationToken); /// public Task IsRemoveUrlAvailableAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.IsRemoveUrlAvailableAsync(index, cancellationToken); /// public Task StartDownloadOperationAsync(DownloadOperation operation, CancellationToken cancellationToken = default) => _collectionGroup.StartDownloadOperationAsync(operation, cancellationToken); /// public Task ChangeNameAsync(string name, CancellationToken cancellationToken = default) => ChangeNameInternalAsync(name, cancellationToken); /// public Task ChangeDescriptionAsync(string? description, CancellationToken cancellationToken = default) => _collectionGroup.ChangeDescriptionAsync(description, cancellationToken); /// public Task ChangeDurationAsync(TimeSpan duration, CancellationToken cancellationToken = default) => _collectionGroup.ChangeDurationAsync(duration, cancellationToken); /// public Task AddAlbumItemAsync(IAlbumCollectionItem album, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddAlbumItemAsync(album, index, cancellationToken); /// public Task AddArtistItemAsync(IArtistCollectionItem artistItem, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddArtistItemAsync(artistItem, index, cancellationToken); /// public Task AddChildAsync(IPlayableCollectionGroup child, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddChildAsync(child, index, cancellationToken); /// public Task AddPlaylistItemAsync(IPlaylistCollectionItem playlistItem, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddPlaylistItemAsync(playlistItem, index, cancellationToken); /// public Task AddTrackAsync(ITrack track, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddTrackAsync(track, index, cancellationToken); /// public Task AddUrlAsync(IUrl url, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddUrlAsync(url, index, cancellationToken); /// public Task RemoveAlbumItemAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemoveAlbumItemAsync(index, cancellationToken); /// public Task RemoveArtistItemAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemoveArtistItemAsync(index, cancellationToken); /// public Task RemoveChildAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemoveChildAsync(index, cancellationToken); /// public Task RemovePlaylistItemAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemovePlaylistItemAsync(index, cancellationToken); /// public Task RemoveTrackAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemoveTrackAsync(index, cancellationToken); /// public Task RemoveImageAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemoveImageAsync(index, cancellationToken); /// public Task RemoveUrlAsync(int index, CancellationToken cancellationToken = default) => _collectionGroup.RemoveUrlAsync(index, cancellationToken); /// public IAsyncEnumerable GetChildrenAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetChildrenAsync(limit, offset, cancellationToken); /// public IAsyncEnumerable GetPlaylistItemsAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetPlaylistItemsAsync(limit, offset, cancellationToken); /// public IAsyncEnumerable GetTracksAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetTracksAsync(limit, offset, cancellationToken); /// public IAsyncEnumerable GetAlbumItemsAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetAlbumItemsAsync(limit, offset, cancellationToken); /// public IAsyncEnumerable GetArtistItemsAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetArtistItemsAsync(limit, offset, cancellationToken); /// public Task AddImageAsync(IImage image, int index, CancellationToken cancellationToken = default) => _collectionGroup.AddImageAsync(image, index, cancellationToken); /// public IAsyncEnumerable GetImagesAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetImagesAsync(limit, offset, cancellationToken); /// public IAsyncEnumerable GetUrlsAsync(int limit, int offset, CancellationToken cancellationToken = default) => _collectionGroup.GetUrlsAsync(limit, offset, cancellationToken); /// public async Task PopulateMorePlaylistsAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populatePlaylistsMutex)) { using var releaseReg = cancellationToken.Register(() => _populatePlaylistsMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetPlaylistItemsAsync(limit, Playlists.Count, cancellationToken)) { switch (item) { case IPlaylist playlist: var pvm = new PlaylistViewModel(playlist); Playlists.Add(pvm); UnsortedPlaylists.Add(pvm); break; case IPlaylistCollection collection: var pcvm = new PlaylistCollectionViewModel(collection); Playlists.Add(pcvm); UnsortedPlaylists.Add(pcvm); break; } } }, null); } } /// public async Task PopulateMoreTracksAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populateTracksMutex)) { using var releaseReg = cancellationToken.Register(() => _populateTracksMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetTracksAsync(limit, Tracks.Count, cancellationToken)) { var tvm = new TrackViewModel(item); Tracks.Add(tvm); UnsortedTracks.Add(tvm); } }, null); } } /// public async Task PopulateMoreAlbumsAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populateAlbumsMutex)) { using var releaseReg = cancellationToken.Register(() => _populateAlbumsMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetAlbumItemsAsync(limit, Albums.Count, cancellationToken)) { switch (item) { case IAlbum album: var avm = new AlbumViewModel(album); Albums.Add(avm); UnsortedAlbums.Add(avm); break; case IAlbumCollection collection: var acvm = new AlbumCollectionViewModel(collection); Albums.Add(acvm); UnsortedAlbums.Add(acvm); break; } } }, null); } } /// public async Task PopulateMoreArtistsAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populateArtistsMutex)) { using var releaseReg = cancellationToken.Register(() => _populateArtistsMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetArtistItemsAsync(limit, Artists.Count, cancellationToken)) { switch (item) { case IArtist artist: var avm = new ArtistViewModel(artist); Artists.Add(avm); UnsortedArtists.Add(avm); break; case IArtistCollection collection: var acvm = new ArtistCollectionViewModel(collection); Artists.Add(acvm); UnsortedArtists.Add(acvm); break; } } }, null); } } /// public async Task PopulateMoreChildrenAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populateChildrenMutex)) { using var releaseReg = cancellationToken.Register(() => _populateChildrenMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetChildrenAsync(limit, Albums.Count, cancellationToken)) { Children.Add(new PlayableCollectionGroupViewModel(item)); } }, null); } } /// public async Task PopulateMoreImagesAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populateImagesMutex)) { using var releaseReg = cancellationToken.Register(() => _populateImagesMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetImagesAsync(limit, Images.Count, cancellationToken)) { Images.Add(item); } }, null); } } /// public async Task PopulateMoreUrlsAsync(int limit, CancellationToken cancellationToken = default) { using (await Flow.EasySemaphore(_populateUrlsMutex)) { using var releaseReg = cancellationToken.Register(() => _populateUrlsMutex.Release()); _syncContext.Post(async _ => { await foreach (var item in _collectionGroup.GetUrlsAsync(limit, Urls.Count, cancellationToken)) { Urls.Add(item); } }, null); } } /// public Task PlayAlbumCollectionAsync(IAlbumCollectionItem albumItem, CancellationToken cancellationToken = default) => _collectionGroup.PlayAlbumCollectionAsync(albumItem, cancellationToken); /// public Task PlayAlbumCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PlayAlbumCollectionAsync(cancellationToken); /// public Task PauseAlbumCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PauseAlbumCollectionAsync(cancellationToken); /// public Task PlayArtistCollectionAsync(IArtistCollectionItem artistItem, CancellationToken cancellationToken = default) => _collectionGroup.PlayArtistCollectionAsync(artistItem, cancellationToken); /// public Task PlayArtistCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PlayArtistCollectionAsync(cancellationToken); /// public Task PauseArtistCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PauseArtistCollectionAsync(cancellationToken); /// public Task PlayPlayableCollectionGroupAsync(IPlayableCollectionGroup collectionGroup, CancellationToken cancellationToken = default) => _collectionGroup.PlayPlaylistCollectionAsync(collectionGroup, cancellationToken); /// public Task PlayPlayableCollectionGroupAsync(CancellationToken cancellationToken = default) => _collectionGroup.PlayPlayableCollectionGroupAsync(cancellationToken); /// public Task PausePlayableCollectionGroupAsync(CancellationToken cancellationToken = default) => _collectionGroup.PausePlayableCollectionGroupAsync(cancellationToken); /// public Task PlayPlaylistCollectionAsync(IPlaylistCollectionItem playlistItem, CancellationToken cancellationToken = default) => _collectionGroup.PlayPlaylistCollectionAsync(playlistItem, cancellationToken); /// public Task PlayPlaylistCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PlayPlaylistCollectionAsync(cancellationToken); /// public Task PausePlaylistCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PausePlaylistCollectionAsync(cancellationToken); /// public Task PlayTrackCollectionAsync(ITrack track, CancellationToken cancellationToken = default) => _collectionGroup.PlayTrackCollectionAsync(track, cancellationToken); /// public Task PlayTrackCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PlayTrackCollectionAsync(cancellationToken); /// public Task PauseTrackCollectionAsync(CancellationToken cancellationToken = default) => _collectionGroup.PauseTrackCollectionAsync(cancellationToken); /// public void SortAlbumCollection(AlbumSortingType albumSorting, SortDirection sortDirection) { CurrentAlbumSortingType = albumSorting; CurrentAlbumSortingDirection = sortDirection; CollectionSorting.SortAlbums(Albums, albumSorting, sortDirection, UnsortedAlbums); } /// public void SortArtistCollection(ArtistSortingType artistSorting, SortDirection sortDirection) { CurrentArtistSortingType = artistSorting; CurrentArtistSortingDirection = sortDirection; CollectionSorting.SortArtists(Artists, artistSorting, sortDirection, UnsortedArtists); } /// public void SortPlaylistCollection(PlaylistSortingType playlistSorting, SortDirection sortDirection) { CurrentPlaylistSortingType = playlistSorting; CurrentPlaylistSortingDirection = sortDirection; CollectionSorting.SortPlaylists(Playlists, playlistSorting, sortDirection, UnsortedPlaylists); } /// public void SortTrackCollection(TrackSortingType trackSorting, SortDirection sortDirection) { CurrentTracksSortingType = trackSorting; CurrentTracksSortingDirection = sortDirection; CollectionSorting.SortTracks(Tracks, trackSorting, sortDirection, UnsortedTracks); } /// public Task InitAlbumCollectionAsync(CancellationToken cancellationToken = default) => CollectionInit.AlbumCollection(this, cancellationToken); /// public Task InitImageCollectionAsync(CancellationToken cancellationToken = default) => CollectionInit.ImageCollection(this, cancellationToken); /// public Task InitArtistCollectionAsync(CancellationToken cancellationToken = default) => CollectionInit.ArtistCollection(this, cancellationToken); /// public Task InitTrackCollectionAsync(CancellationToken cancellationToken = default) => CollectionInit.TrackCollection(this, cancellationToken); /// public Task InitPlaylistCollectionAsync(CancellationToken cancellationToken = default) => CollectionInit.PlaylistCollection(this, cancellationToken); /// /// Command to change the name. It triggers . /// public IAsyncRelayCommand ChangeNameAsyncCommand { get; } /// /// Command to change the description. It triggers . /// public IAsyncRelayCommand ChangeDescriptionAsyncCommand { get; } /// /// Command to change the duration. It triggers . /// public IAsyncRelayCommand ChangeDurationAsyncCommand { get; } /// public IAsyncRelayCommand PopulateMoreTracksCommand { get; } /// public IAsyncRelayCommand PopulateMorePlaylistsCommand { get; } /// public IAsyncRelayCommand PopulateMoreAlbumsCommand { get; } /// public IAsyncRelayCommand PopulateMoreArtistsCommand { get; } /// public IAsyncRelayCommand PopulateMoreChildrenCommand { get; } /// public IAsyncRelayCommand PopulateMoreImagesCommand { get; } /// public IAsyncRelayCommand PopulateMoreUrlsCommand { get; } /// public IAsyncRelayCommand PlayAlbumAsyncCommand { get; } /// public IAsyncRelayCommand PlayAlbumCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PauseAlbumCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PlayArtistAsyncCommand { get; } /// public IAsyncRelayCommand PlayArtistCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PauseArtistCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PlayPlaylistAsyncCommand { get; } /// public IAsyncRelayCommand PlayPlaylistCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PausePlaylistCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PlayTrackAsyncCommand { get; } /// public IAsyncRelayCommand PlayTrackCollectionAsyncCommand { get; } /// public IAsyncRelayCommand PauseTrackCollectionAsyncCommand { get; } /// public IRelayCommand ChangeAlbumCollectionSortingTypeCommand { get; } /// public IRelayCommand ChangeAlbumCollectionSortingDirectionCommand { get; } /// public IRelayCommand ChangeArtistCollectionSortingTypeCommand { get; } /// public IRelayCommand ChangeArtistCollectionSortingDirectionCommand { get; } /// public IRelayCommand ChangePlaylistCollectionSortingTypeCommand { get; } /// public IRelayCommand ChangePlaylistCollectionSortingDirectionCommand { get; } /// public IRelayCommand ChangeTrackCollectionSortingTypeCommand { get; } /// public IRelayCommand ChangeTrackCollectionSortingDirectionCommand { get; } /// public IAsyncRelayCommand InitAlbumCollectionAsyncCommand { get; } /// public IAsyncRelayCommand InitImageCollectionAsyncCommand { get; } /// public IAsyncRelayCommand InitArtistCollectionAsyncCommand { get; } /// public IAsyncRelayCommand InitTrackCollectionAsyncCommand { get; } /// public IAsyncRelayCommand InitPlaylistCollectionAsyncCommand { get; } /// public bool Equals(ICoreAlbumCollectionItem other) => _collectionGroup.Equals(other); /// public bool Equals(ICoreAlbumCollection other) => _collectionGroup.Equals(other); /// public bool Equals(ICoreArtistCollectionItem other) => _collectionGroup.Equals(other); /// public bool Equals(ICoreArtistCollection other) => _collectionGroup.Equals(other); /// public bool Equals(ICorePlayableCollectionGroupChildren other) => _collectionGroup.Equals(other); /// public bool Equals(ICorePlayableCollectionGroup other) => _collectionGroup.Equals(other); /// public bool Equals(ICorePlaylistCollectionItem other) => _collectionGroup.Equals(other); /// public bool Equals(ICorePlaylistCollection other) => _collectionGroup.Equals(other); /// public bool Equals(ICoreTrackCollection other) => _collectionGroup.Equals(other); /// public bool Equals(ICoreImageCollection other) => _collectionGroup.Equals(other); /// public bool Equals(ICoreUrlCollection other) => _collectionGroup.Equals(other); /// public virtual Task InitAsync(CancellationToken cancellationToken = default) { if (IsInitialized) return Task.CompletedTask; IsInitialized = true; return Task.WhenAll(InitImageCollectionAsync(cancellationToken), InitPlaylistCollectionAsync(cancellationToken), InitTrackCollectionAsync(cancellationToken), InitAlbumCollectionAsync(cancellationToken), InitArtistCollectionAsync(cancellationToken)); } private Task ChangeNameInternalAsync(string? name, CancellationToken cancellationToken = default) { Guard.IsNotNull(name, nameof(name)); return _collectionGroup.ChangeNameAsync(name, cancellationToken); } /// public bool IsInitialized { get; protected set; } /// public ValueTask DisposeAsync() { DetachPropertyEvents(); return _collectionGroup.DisposeAsync(); } } }