using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media.Imaging; using Avalonia.Platform.Storage; using Avalonia.Threading; using Avalonia.VisualTree; using Harmonia.Core.Engine; using Harmonia.Core.Playlists; using Harmonia.UI.ViewModels; using Microsoft.Extensions.DependencyInjection; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Harmonia.UI.Views; public partial class PlaylistView : UserControl { private readonly PlaylistViewModel _viewModel; private readonly IAudioEngine _audioEngine; private readonly ConcurrentDictionary _imageCancellationTokens = []; private IStorageProvider? _storageProvider; public PlaylistView() { InitializeComponent(); _viewModel = (PlaylistViewModel)DataContext!; _audioEngine = App.ServiceProvider.GetRequiredService(); } private void OnLoaded(object? sender, RoutedEventArgs e) { _storageProvider = TopLevel.GetTopLevel(this)?.StorageProvider; } private async void ListBox_DoubleTapped(object? sender, TappedEventArgs e) { if (sender is ListBox listBox && listBox.SelectedItem is PlaylistSong playlistSong) { await _viewModel.PlaySongAsync(playlistSong); } } private void Image_Loaded(object? sender, RoutedEventArgs e) { if (sender is not Image image) return; if (image.DataContext is not PlaylistSong playlistSong) return; Task.Run(() => DoSomethingAsync(image, playlistSong)); } private async Task DoSomethingAsync(Image image, PlaylistSong playlistSong) { int hashCode = image.GetHashCode(); _imageCancellationTokens.TryGetValue(hashCode, out CancellationTokenSource? cancellationTokenSource); cancellationTokenSource?.Cancel(); cancellationTokenSource = new(); Bitmap? bitmap = await _viewModel.GetBitmapAsync(playlistSong, cancellationTokenSource.Token); if (bitmap == null) return; await Dispatcher.UIThread.InvokeAsync(() => SetSongImageSource(image, bitmap)); } private static void SetSongImageSource(Image image, Bitmap bitmap) { image.Source = bitmap; } private void Image_Unloaded(object? sender, RoutedEventArgs e) { if (sender is not Image image) return; if (image.DataContext is not PlaylistSong playlistSong) return; if (image.Source is Bitmap bitmap) { bitmap.Dispose(); } image.Source = null; int hashCode = image.GetHashCode(); _imageCancellationTokens.TryGetValue(hashCode, out CancellationTokenSource? cancellationTokenSource); cancellationTokenSource?.Cancel(); } //private async void AddFiles_Click(object? sender, RoutedEventArgs e) //{ // if (_storageProvider == null) // return; // FilePickerOpenOptions openOptions = new() // { // FileTypeFilter = [GetAudioFileTypes()], // AllowMultiple = true // }; // IReadOnlyList result = await _storageProvider.OpenFilePickerAsync(openOptions); // string[] fileNames = [.. result.Select(file => file.TryGetLocalPath() ?? string.Empty)]; // CancellationToken cancellationToken = default; // await _viewModel.AddFilesAsync(fileNames, cancellationToken); //} //private FilePickerFileType GetAudioFileTypes() //{ // return new("Audo Files") // { // Patterns = [.. _audioEngine.SupportedFormats] // }; //} //private async void AddFolder_Click(object? sender, RoutedEventArgs e) //{ // if (_storageProvider == null) // return; // FolderPickerOpenOptions options = new() // { // AllowMultiple = true // }; // IReadOnlyList folders = await _storageProvider.OpenFolderPickerAsync(options); // if (folders.Count == 0) // return; // CancellationToken cancellationToken = default; // await _viewModel.AddFolderAsync(folders[0].TryGetLocalPath() ?? string.Empty, cancellationToken); //} }