From 741007322480b108753648d101768650eb9d5230 Mon Sep 17 00:00:00 2001 From: Alexander Shabarshov Date: Sat, 25 Jul 2026 14:39:57 +0100 Subject: [PATCH] UI fixes: combined play/pause button, tooltips. --- .../Converters/PlayPauseGeometryConverter .cs | 23 ++++++++ ABStemPlayer/ViewModels/PlaybackViewModel.cs | 20 ++++++- ABStemPlayer/Views/PlaybackControls.axaml | 57 ++++++++----------- AudioCore/Impl/StemPlaybackEngine.cs | 2 +- 4 files changed, 64 insertions(+), 38 deletions(-) create mode 100644 ABStemPlayer/Converters/PlayPauseGeometryConverter .cs diff --git a/ABStemPlayer/Converters/PlayPauseGeometryConverter .cs b/ABStemPlayer/Converters/PlayPauseGeometryConverter .cs new file mode 100644 index 0000000..67dc6a9 --- /dev/null +++ b/ABStemPlayer/Converters/PlayPauseGeometryConverter .cs @@ -0,0 +1,23 @@ +using System.Globalization; +using Avalonia.Data.Converters; +using Avalonia.Media; + +namespace ABStemPlayer.Converters; + +public class PlayPauseGeometryConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + bool isPlaying = value is bool b && b; + + // Pause icon + if (isPlaying) + return Geometry.Parse("M 12 8 L 18 8 L 18 32 L 12 32 Z M 22 8 L 28 8 L 28 32 L 22 32 Z"); + + // Play icon + return Geometry.Parse("M 10 8 L 32 20 L 10 32 Z"); + } + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + => throw new NotSupportedException(); +} + diff --git a/ABStemPlayer/ViewModels/PlaybackViewModel.cs b/ABStemPlayer/ViewModels/PlaybackViewModel.cs index 2881030..6679b06 100644 --- a/ABStemPlayer/ViewModels/PlaybackViewModel.cs +++ b/ABStemPlayer/ViewModels/PlaybackViewModel.cs @@ -36,7 +36,6 @@ public sealed partial class PlaybackViewModel : ObservableObject public ICommand OpenFileCommand { get; } public ICommand PlayCommand { get; } - public ICommand PauseCommand { get; } public ICommand StopCommand { get; } public ICommand RewindCommand { get; } public ICommand FastForwardCommand { get; } @@ -48,6 +47,7 @@ public sealed partial class PlaybackViewModel : ObservableObject // Playback properties // ----------------------------- + [ObservableProperty] private bool _isPlaying; [ObservableProperty] private bool _loopEnabled; [ObservableProperty] private float _playbackSpeed = 1f; [ObservableProperty] private TimeSpan _currentTime; @@ -83,8 +83,7 @@ public sealed partial class PlaybackViewModel : ObservableObject OpenFileCommand = new AsyncRelayCommand(OpenFileAsync); PlayCommand = new AsyncRelayCommand(OnPlay); - PauseCommand = new AsyncRelayCommand(() => _engine.PauseAsync()); - StopCommand = new AsyncRelayCommand(async () => { await _engine.StopAsync(); await _engine.SeekAsync(TimeSpan.Zero); }); + StopCommand = new AsyncRelayCommand(OnStop); RewindCommand = new AsyncRelayCommand(() => _engine.SeekAsync(CurrentTime - TimeSpan.FromSeconds(5))); FastForwardCommand = new AsyncRelayCommand(() => _engine.SeekAsync(CurrentTime + TimeSpan.FromSeconds(5))); @@ -123,6 +122,13 @@ public sealed partial class PlaybackViewModel : ObservableObject private async Task OnPlay() { + if (IsPlaying) + { + await _engine.PauseAsync(); + IsPlaying = false; + return; + } + if (_engine.CurrentSession == null) return; @@ -135,6 +141,14 @@ public sealed partial class PlaybackViewModel : ObservableObject await _engine.UpdatePlaybackSpeedAsync(new PlaybackSpeedSettings { Speed = PlaybackSpeed }); await _engine.PlayAsync(); + IsPlaying = true; + } + + private async Task OnStop() + { + await _engine.StopAsync(); + IsPlaying = false; + CurrentTime = TimeSpan.Zero; } partial void OnMixerChanged(MixerViewModel? oldValue, MixerViewModel newValue) diff --git a/ABStemPlayer/Views/PlaybackControls.axaml b/ABStemPlayer/Views/PlaybackControls.axaml index cf8fa64..9cc6427 100644 --- a/ABStemPlayer/Views/PlaybackControls.axaml +++ b/ABStemPlayer/Views/PlaybackControls.axaml @@ -3,10 +3,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="using:ABStemPlayer.ViewModels" xmlns:conv="using:ABStemPlayer.Converters" + xmlns:av="clr-namespace:Avalonia;assembly=Avalonia.Base" x:DataType="vm:PlaybackViewModel" x:Class="ABStemPlayer.Views.PlaybackControls"> + + Margin="0,0,6,0" + ToolTip.Tip="Open File"> @@ -57,7 +60,8 @@ Width="40" Height="40" Grid.Column="1" - Margin="0,0,6,0"> + Margin="0,0,6,0" + ToolTip.Tip="Rewind"> @@ -72,50 +76,30 @@ - - - -