using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Media.Imaging; using Avalonia.Threading; using Harmonia.Core.Caching; using Harmonia.Core.Imaging; using Harmonia.Core.Playlists; using Harmonia.UI.ViewModels; using Microsoft.Extensions.Caching.Memory; using System; using System.Collections.Concurrent; using System.IO; using System.Threading; using System.Threading.Tasks; namespace Harmonia.UI.Views; public partial class PlaylistView : UserControl { private readonly PlaylistViewModel _viewModel; private readonly ConcurrentDictionary _imageCancellationTokens = []; public PlaylistView() { InitializeComponent(); _viewModel = (PlaylistViewModel)DataContext!; } private void ListBox_DoubleTapped(object? sender, TappedEventArgs e) { if (sender is ListBox listBox && listBox.SelectedItem is PlaylistSong playlistSong) { _viewModel.PlaySong(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(); } }