Front End Work

- Redesign component wiring for audio playback
 - Removed playback logic from the player control and moved it to injectable audio player engine service
 - Chunked/buffered stream loading from Content API passed to Web Audio API playback in 8K blocks
This commit is contained in:
daniel-c-harvey
2025-09-06 13:39:26 -04:00
parent 3766d4e010
commit 66d800bd26
21 changed files with 519 additions and 907 deletions
+12 -11
View File
@@ -9,29 +9,30 @@
@if (ViewModel.Page != null)
{
<div class="tracks-content">
<TracksGallery Tracks="@ViewModel.Page.Items"/>
<TracksGallery Tracks="@ViewModel.Page.Items"
SelectedTrack="_selectedTrack"
SelectedTrackChanged="@PlayTrack"/>
</div>
<div class="tracks-pagination">
<MudContainer Class="d-flex justify-center py-2">
<div class="tracks-footer">
<div class="py-4">
<MudPagination Count="@ViewModel.Page.TotalPages"
Selected="@ViewModel.Page.Page"
SelectedChanged="i => SetPage(i)"
SelectedChanged="@SetPage"
BoundaryCount="2"
MiddleCount="3"/>
</MudContainer>
</div>
<AudioPlayerBar AudioPlaybackEngine="AudioPlaybackEngine" />
</div>
}
else
{
<div class="tracks-content">
<MudSkeleton Height="100%" Class="pa-2 ma-2"/>
<MudSkeleton Height="95%" Class="pa-2 ma-6"/>
</div>
<div class="tracks-pagination">
<MudSkeleton Height="60px"/>
<div class="tracks-footer">
<MudSkeleton Height="60px" Width="240px" Class="justify-center"/>
<MudSkeleton Height="120px" Width="460px"/>
</div>
}
</div>
<AudioPlayerBar AudioUrl=""></AudioPlayerBar>
</div>
+16 -3
View File
@@ -1,5 +1,6 @@
using DeepDrftModels.Entities;
using DeepDrftModels.Models;
using DeepDrftWeb.Client.Services;
using DeepDrftWeb.Client.ViewModels;
using Microsoft.AspNetCore.Components;
@@ -7,13 +8,17 @@ namespace DeepDrftWeb.Client.Pages;
public partial class TracksView : ComponentBase
{
[Inject]
public required TracksViewModel ViewModel { get; set; }
[Inject] public required TracksViewModel ViewModel { get; set; }
[Inject] public required AudioPlaybackEngine AudioPlaybackEngine { get; set; }
private TrackEntity? _selectedTrack = null;
protected override async Task OnInitializedAsync()
{
await SetPage(1);
if (!RendererInfo.IsInteractive) return;
await AudioPlaybackEngine.InitializeAudioPlayer();
}
private async Task SetPage(int newPage)
@@ -26,4 +31,12 @@ public partial class TracksView : ComponentBase
ViewModel.PageSize = pageResult.PageSize;
}
}
private async Task PlayTrack(TrackEntity? track)
{
if (track == null) return;
await AudioPlaybackEngine.LoadTrack(track);
StateHasChanged();
}
}
@@ -1,8 +1,8 @@
.tracks-page-wrapper {
display: flex;
flex-direction: column;
height: calc(100dvh - 64px); /* Subtract app bar height (pt-16 = 4rem = 64px) */
margin: -16px; /* Counteract MudMainContent padding */
height: calc(100dvh - 80px); /* Subtract app bar height (pt-16 = 4rem = 64px) */
/*margin: -16px; !* Counteract MudMainContent padding *!*/
padding-top: 16px; /* Restore top padding for spacing */
}
@@ -17,12 +17,12 @@
.tracks-content {
flex: 1 1 auto;
overflow-y: scroll;
min-height: 0;
padding-top: 16px;
}
.tracks-pagination {
.tracks-footer {
flex: 0 0 auto;
padding: 8px 0;
justify-items: center;
}