7d49c64a5d
Add StateChanged multicast event to IPlayerService so AudioPlayerBar and TracksView re-render themselves without relying on the IsFixed cascade re-render path. Clear _selectedTrack in TracksView when IsLoaded drops (stop, unload, end-of-track). Set IsLoaded=false in OnPlaybackEndCallback so end-of-track triggers the same clear path. Add JS-module readiness probe in AudioInteropService; delete dead TS and buffered C# path; consolidate GetPlayIcon/FormatTime helpers; fix misleading minimize dock icon.
104 lines
3.3 KiB
C#
104 lines
3.3 KiB
C#
using DeepDrftModels.DTOs;
|
|
using DeepDrftPublic.Client.Services;
|
|
using DeepDrftPublic.Client.ViewModels;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Models.Common;
|
|
|
|
namespace DeepDrftPublic.Client.Pages;
|
|
|
|
public partial class TracksView : ComponentBase, IDisposable
|
|
{
|
|
[Inject] public required TracksViewModel ViewModel { get; set; }
|
|
[CascadingParameter] public required IStreamingPlayerService PlayerService { get; set; }
|
|
|
|
private TrackDto? _selectedTrack = null;
|
|
private int _clickCount = 0;
|
|
private string _lifecycleStatus = "Not initialized";
|
|
private IStreamingPlayerService? _subscribedService;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
_lifecycleStatus = "OnInitializedAsync called";
|
|
await SetPage(1);
|
|
}
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
// The Stop/Close buttons on the player bar reset the player directly,
|
|
// bypassing PlayTrack — so the gallery's selection must follow player
|
|
// state rather than only its own clicks. Subscribe to the multicast
|
|
// side-channel (the cascade is IsFixed, so provider re-renders don't
|
|
// reach us) and clear the highlight when nothing is loaded.
|
|
if (PlayerService != null && !ReferenceEquals(PlayerService, _subscribedService))
|
|
{
|
|
if (_subscribedService != null)
|
|
_subscribedService.StateChanged -= OnPlayerStateChanged;
|
|
|
|
PlayerService.StateChanged += OnPlayerStateChanged;
|
|
_subscribedService = PlayerService;
|
|
}
|
|
}
|
|
|
|
private void OnPlayerStateChanged()
|
|
{
|
|
// Sync the gallery selection to the player. When the player is no longer
|
|
// loaded (stopped/closed/ended) drop the highlight; guard against a
|
|
// redundant re-render when nothing actually changed.
|
|
if (!PlayerService.IsLoaded && _selectedTrack != null)
|
|
{
|
|
_selectedTrack = null;
|
|
InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
_lifecycleStatus = "OnAfterRenderAsync called - WebAssembly is active!";
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
|
|
private void TestInteractivity()
|
|
{
|
|
_clickCount++;
|
|
_lifecycleStatus = $"Button clicked {_clickCount} times - Interactivity working!";
|
|
}
|
|
|
|
private async Task SetPage(int newPage)
|
|
{
|
|
var result = await ViewModel.TrackData.GetPage(newPage, ViewModel.PageSize, ViewModel.SortBy, ViewModel.IsDescending);
|
|
|
|
if (result is { Success: true, Value: PagedResult<TrackDto> pageResult })
|
|
{
|
|
ViewModel.Page = pageResult;
|
|
ViewModel.PageSize = pageResult.PageSize;
|
|
}
|
|
}
|
|
|
|
private async Task PlayTrack(TrackDto? track)
|
|
{
|
|
if (track == null && _selectedTrack == null || track?.Id == _selectedTrack?.Id) return;
|
|
|
|
if (track is null)
|
|
{
|
|
await PlayerService.Unload();
|
|
}
|
|
else
|
|
{
|
|
await PlayerService.SelectTrack(track);
|
|
}
|
|
|
|
_selectedTrack = track;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (_subscribedService != null)
|
|
{
|
|
_subscribedService.StateChanged -= OnPlayerStateChanged;
|
|
_subscribedService = null;
|
|
}
|
|
}
|
|
} |