feat(public): add /cuts/{id} album-detail page
Compose ReleaseDetailScaffold via Header + BodyContent slots for the Cut album view: left meta + Play/Share, right theme-bordered cover, TrackNumber- ordered track list with per-row play. CutDetailBase carries the multi-track prerender bridge.
This commit is contained in:
@@ -13,20 +13,30 @@
|
||||
|
||||
@TopContent
|
||||
|
||||
<MudStack Row AlignItems="AlignItems.Start" Justify="Justify.SpaceBetween" Style="margin: 2rem 0 1.5rem;">
|
||||
<div class="deepdrft-track-detail-masthead">
|
||||
<MudText Typo="Typo.h3">@Title</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">@Artist</MudText>
|
||||
</div>
|
||||
@* The header region. A composer that wants the default masthead+play row supplies nothing; one
|
||||
that needs a different arrangement (e.g. the Cut album's left-meta / right-cover split) supplies
|
||||
its own Header fragment. Layout variance rides this slot, never a boolean flag (Phase 9 §5.3). *@
|
||||
@if (Header is not null)
|
||||
{
|
||||
@Header
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Row AlignItems="AlignItems.Start" Justify="Justify.SpaceBetween" Style="margin: 2rem 0 1.5rem;">
|
||||
<div class="deepdrft-track-detail-masthead">
|
||||
<MudText Typo="Typo.h3">@Title</MudText>
|
||||
<MudText Typo="Typo.h6" Color="Color.Primary">@Artist</MudText>
|
||||
</div>
|
||||
|
||||
@* Play only makes sense once a playable track is resolved. *@
|
||||
@if (Track is not null)
|
||||
{
|
||||
<MudStack Row AlignItems="AlignItems.Center" Spacing="1">
|
||||
<PlayStateIcon Track="@Track" Size="Size.Large" Color="Color.Secondary" OnToggle="@PlayTrack" />
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
@* Play only makes sense once a playable track is resolved. *@
|
||||
@if (Track is not null)
|
||||
{
|
||||
<MudStack Row AlignItems="AlignItems.Center" Spacing="1">
|
||||
<PlayStateIcon Track="@Track" Size="Size.Large" Color="Color.Secondary" OnToggle="@PlayTrack" />
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
|
||||
@Hero
|
||||
|
||||
@@ -38,7 +48,12 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (Track is not null)
|
||||
@* Multi-track body region (the Cut album's track list). Single-track media leave it null. *@
|
||||
@BodyContent
|
||||
|
||||
@* The default share row is bound to the single resolved track. A composer that owns its own share
|
||||
affordance (the Cut header carries Play + Share inline) suppresses it via ShowShareRow. *@
|
||||
@if (Track is not null && ShowShareRow)
|
||||
{
|
||||
<div class="deepdrft-share-row">
|
||||
<SharePopover EntryKey="@Track.EntryKey" />
|
||||
|
||||
@@ -31,9 +31,24 @@ public partial class ReleaseDetailScaffold : ComponentBase
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment? TopContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional replacement for the header region (masthead + play affordance). When null, the
|
||||
/// scaffold renders its default masthead+play row wired to <see cref="PlayTrack"/>. A composer
|
||||
/// that needs a different header arrangement (e.g. the Cut album's left-meta / right-cover split
|
||||
/// with its own Play/Share buttons) supplies this — layout variance rides the slot, never a
|
||||
/// boolean flag (Phase 9 §5.3).
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment? Header { get; set; }
|
||||
|
||||
/// <summary>Medium-specific hero visual (cover art, hero image, or waveform background).</summary>
|
||||
[Parameter] public RenderFragment? Hero { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional body region rendered below the meta block — the Cut album's multi-track listing.
|
||||
/// Single-track media leave it null.
|
||||
/// </summary>
|
||||
[Parameter] public RenderFragment? BodyContent { get; set; }
|
||||
|
||||
/// <summary>Optional medium-specific metadata block, rendered under a divider when present.</summary>
|
||||
[Parameter] public RenderFragment? MetaContent { get; set; }
|
||||
|
||||
@@ -44,6 +59,13 @@ public partial class ReleaseDetailScaffold : ComponentBase
|
||||
/// </summary>
|
||||
[Parameter] public bool ShowMeta { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gate for the default track-keyed share row at the foot of the scaffold. A composer that owns
|
||||
/// its own share affordance (the Cut header carries Play + Share inline) sets this false to
|
||||
/// suppress the duplicate. Defaults to shown.
|
||||
/// </summary>
|
||||
[Parameter] public bool ShowShareRow { get; set; } = true;
|
||||
|
||||
private async Task PlayTrack()
|
||||
{
|
||||
if (Track is null || PlayerService is null) return;
|
||||
|
||||
Reference in New Issue
Block a user