Added ContextMenu/Flyout animations. Added platform services. Use bitmap cache for all views.

This commit is contained in:
2025-03-18 09:31:32 -04:00
parent 7c70eb3814
commit 9214e97100
17 changed files with 649 additions and 169 deletions

View File

@@ -1,15 +1,13 @@
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.Input;
using Harmonia.Core.Caching;
using Harmonia.Core.Imaging;
using Harmonia.Core.Models;
using Harmonia.Core.Player;
using Harmonia.Core.Playlists;
using Harmonia.Core.Scanner;
using Harmonia.UI.Caching;
using Harmonia.UI.Models;
using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -20,7 +18,7 @@ namespace Harmonia.UI.ViewModels;
public partial class PlaybackBarViewModel : ViewModelBase, IDisposable
{
private readonly IAudioPlayer _audioPlayer;
private readonly IAudioImageCache _audioImageCache;
private readonly IAudioBitmapCache _audioBitmapCache;
private readonly DispatcherTimer _timer;
private CancellationTokenSource? _audioImageCancellationTokenSource;
@@ -53,7 +51,6 @@ public partial class PlaybackBarViewModel : ViewModelBase, IDisposable
}
private set
{
_songImageSource?.Dispose();
_songImageSource = value;
OnPropertyChanged();
}
@@ -205,14 +202,29 @@ public partial class PlaybackBarViewModel : ViewModelBase, IDisposable
public ICommand ToggleRandomizerCommand => new RelayCommand(ToggleRandomizer);
public ICommand ToggleRepeatCommand => new RelayCommand(ToggleRepeat);
public PlaybackBarViewModel(IAudioPlayer audioPlayer, IAudioImageCache audioImageCache, IPlaylistRepository playlistRepository, IAudioFileScanner audioFileScanner)
public PlaybackBarViewModel(IAudioPlayer audioPlayer, IAudioBitmapCache audioBitmapCache, IPlaylistRepository playlistRepository, IAudioFileScanner audioFileScanner)
{
_audioPlayer = audioPlayer;
_audioPlayer.PlayingSongChanged += OnAudioPlayerPlayingSongChanged;
_audioImageCache = audioImageCache;
_audioBitmapCache = audioBitmapCache;
_timer = new(TimeSpan.FromMilliseconds(100), DispatcherPriority.Default, TickTock);
Task.Run(() => PlayDemoSong(playlistRepository));
}
private async Task PlayDemoSong(IPlaylistRepository playlistRepository)
{
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 OnAudioPlayerPlayingSongChanged(object? sender, EventArgs e)
@@ -233,21 +245,14 @@ public partial class PlaybackBarViewModel : ViewModelBase, IDisposable
_audioImageCancellationTokenSource = new();
CancellationToken cancellationToken = _audioImageCancellationTokenSource.Token;
SongPictureInfo? songPictureInfo = await _audioImageCache.GetAsync(Song, cancellationToken);
Bitmap? bitmap = await _audioBitmapCache.GetAsync(Song, cancellationToken);
if (songPictureInfo == null)
return;
await Dispatcher.UIThread.InvokeAsync(() => SetSongImageSource(songPictureInfo));
await Dispatcher.UIThread.InvokeAsync(() => SetSongImageSource(bitmap));
}
private void SetSongImageSource(SongPictureInfo songPictureInfo)
private void SetSongImageSource(Bitmap? bitmap)
{
if (songPictureInfo.Data.Length == 0)
return;
using MemoryStream stream = new(songPictureInfo.Data);
SongImageSource = new(stream);
SongImageSource = bitmap;
}
private void TickTock(object? sender, object e)