Consolidate play/pause icon logic into PlaybackIcons mapper and PlayStateIcon component
Add Disabled parameter to PlayStateIcon; forward to MudIconButton; pass Disabled="!IsLoaded" from PlayerControls to match Stop button parity.
This commit is contained in:
@@ -13,8 +13,7 @@ else
|
||||
<MudPaper Elevation="8" Class="player-surface pa-3">
|
||||
|
||||
<div class="player-layout">
|
||||
<PlayerTransportZone IsPlaying="IsPlaying"
|
||||
IsLoaded="IsLoaded"
|
||||
<PlayerTransportZone IsLoaded="IsLoaded"
|
||||
IsLoading="IsLoading"
|
||||
IsStreaming="IsStreaming"
|
||||
LoadProgress="LoadProgress"
|
||||
|
||||
@@ -17,8 +17,6 @@ public partial class AudioPlayerBar : ComponentBase, IAsyncDisposable
|
||||
private bool IsLoading => PlayerService?.IsLoading ?? false;
|
||||
private bool IsStreaming => PlayerService?.CanStartStreaming ?? false;
|
||||
private bool IsStreamingMode => PlayerService?.IsStreamingMode ?? false;
|
||||
private bool IsPlaying => PlayerService?.IsPlaying ?? false;
|
||||
private bool IsPaused => PlayerService?.IsPaused ?? false;
|
||||
private double? Duration => PlayerService?.Duration;
|
||||
private double Volume => PlayerService?.Volume ?? 0;
|
||||
private double LoadProgress => PlayerService?.LoadProgress ?? 0;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
@namespace DeepDrftPublic.Client.Controls.AudioPlayerBar
|
||||
@using DeepDrftPublic.Client.Controls
|
||||
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
||||
<MudIconButton Icon="@GetPlayIcon()"
|
||||
<PlayStateIcon Size="Size.Large"
|
||||
Color="Color.Primary"
|
||||
Size="Size.Large"
|
||||
OnClick="@TogglePlayPause"
|
||||
Disabled="!IsLoaded"/>
|
||||
Disabled="!IsLoaded"
|
||||
OnToggle="@TogglePlayPause"/>
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Stop"
|
||||
Color="Color.Primary"
|
||||
Size="Size.Large"
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
|
||||
|
||||
public partial class PlayerControls : ComponentBase
|
||||
{
|
||||
[Parameter] public required bool IsPlaying { get; set; }
|
||||
[Parameter] public required bool IsLoaded { get; set; }
|
||||
[Parameter] public required EventCallback TogglePlayPause { get; set; }
|
||||
[Parameter] public required EventCallback Stop { get; set; }
|
||||
private string GetPlayIcon()
|
||||
{
|
||||
return IsPlaying ? Icons.Material.Filled.Pause : Icons.Material.Filled.PlayArrow;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
@namespace DeepDrftPublic.Client.Controls.AudioPlayerBar
|
||||
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1" Class="@Class">
|
||||
<PlayerControls IsPlaying="IsPlaying"
|
||||
IsLoaded="IsLoaded"
|
||||
<PlayerControls IsLoaded="IsLoaded"
|
||||
TogglePlayPause="TogglePlayPause"
|
||||
Stop="Stop"/>
|
||||
@if (IsLoading && !IsStreaming)
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
|
||||
|
||||
public partial class PlayerTransportZone : ComponentBase
|
||||
{
|
||||
[Parameter] public bool IsPlaying { get; set; }
|
||||
[Parameter] public bool IsLoaded { get; set; }
|
||||
[Parameter] public bool IsLoading { get; set; }
|
||||
[Parameter] public bool IsStreaming { get; set; }
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@namespace DeepDrftPublic.Client.Controls
|
||||
|
||||
<MudIconButton Icon="@Icon"
|
||||
Color="Color"
|
||||
Size="Size"
|
||||
Disabled="@Disabled"
|
||||
OnClick="@OnToggle"/>
|
||||
@@ -0,0 +1,62 @@
|
||||
using DeepDrftModels.DTOs;
|
||||
using DeepDrftPublic.Client.Helpers;
|
||||
using DeepDrftPublic.Client.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using MudBlazor;
|
||||
|
||||
namespace DeepDrftPublic.Client.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Renders the play/pause transport glyph for either a specific track or global playback,
|
||||
/// reading live state off the cascaded <see cref="IStreamingPlayerService"/>. The icon is
|
||||
/// always resolved through <see cref="PlaybackIcons.Resolve"/>.
|
||||
/// </summary>
|
||||
public partial class PlayStateIcon : ComponentBase, IDisposable
|
||||
{
|
||||
[CascadingParameter] public IStreamingPlayerService? PlayerService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// When non-null, the icon reflects this track's playback state (active only when it is the
|
||||
/// current track). When null, it reflects global playback state.
|
||||
/// </summary>
|
||||
[Parameter] public TrackDto? Track { get; set; }
|
||||
|
||||
[Parameter] public Size Size { get; set; } = Size.Medium;
|
||||
[Parameter] public Color Color { get; set; } = Color.Primary;
|
||||
[Parameter] public bool Disabled { get; set; } = false;
|
||||
[Parameter] public EventCallback OnToggle { get; set; }
|
||||
|
||||
private IStreamingPlayerService? _subscribedService;
|
||||
|
||||
private bool IsActive => Track is null || PlayerService?.CurrentTrack?.Id == Track.Id;
|
||||
private bool IsPlaying => IsActive && (PlayerService?.IsPlaying ?? false);
|
||||
private bool IsPaused => IsActive && (PlayerService?.IsPaused ?? false);
|
||||
|
||||
private string Icon => PlaybackIcons.Resolve(IsPlaying, IsPaused);
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
// The cascade is IsFixed, so the provider's re-render never reaches us; subscribe to the
|
||||
// multicast side-channel to re-render on every player state change. Reference-guarded so
|
||||
// re-parametering is idempotent. Mirrors AudioPlayerBar / TracksView.
|
||||
if (PlayerService != null && !ReferenceEquals(PlayerService, _subscribedService))
|
||||
{
|
||||
if (_subscribedService != null)
|
||||
_subscribedService.StateChanged -= OnPlayerStateChanged;
|
||||
|
||||
PlayerService.StateChanged += OnPlayerStateChanged;
|
||||
_subscribedService = PlayerService;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerStateChanged() => InvokeAsync(StateHasChanged);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_subscribedService != null)
|
||||
{
|
||||
_subscribedService.StateChanged -= OnPlayerStateChanged;
|
||||
_subscribedService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using MudBlazor;
|
||||
|
||||
namespace DeepDrftPublic.Client.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// Single source of truth for mapping playback state to a transport glyph across
|
||||
/// DeepDrftPublic.Client. Surfaces that render a play/pause icon call <see cref="Resolve"/>
|
||||
/// instead of inlining their own ternary.
|
||||
/// </summary>
|
||||
public static class PlaybackIcons
|
||||
{
|
||||
public static string Resolve(bool isPlaying, bool isPaused)
|
||||
=> (isPlaying && !isPaused) ? Icons.Material.Filled.Pause : Icons.Material.Filled.PlayArrow;
|
||||
}
|
||||
Reference in New Issue
Block a user