feat(mix-detail): extract shared ReleaseHeroOverlay; Mix cover becomes overlaid 600px square hero (Direction B)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
@page "/mixes/{EntryKey}"
|
||||
@using DeepDrftPublic.Client.Controls
|
||||
@using DeepDrftPublic.Client.Services
|
||||
@inherits ReleaseDetailBase
|
||||
|
||||
<PageTitle>@(ViewModel.Release?.Title ?? "Mix") - DeepDrft</PageTitle>
|
||||
@@ -31,8 +32,6 @@ else if (ViewModel.NotFound || ViewModel.Release is null)
|
||||
else
|
||||
{
|
||||
var release = ViewModel.Release;
|
||||
var hasGenre = release.Genre is not null;
|
||||
var hasDate = release.ReleaseDate is not null;
|
||||
|
||||
@* Full-page waveform sits behind the scaffold content. The scaffold's container is positioned
|
||||
above it via the mix-detail-foreground stacking context. TrackId lets the visualizer couple to
|
||||
@@ -41,12 +40,17 @@ else
|
||||
|
||||
<div class="mix-detail-foreground">
|
||||
<MudContainer MaxWidth="MaxWidth.Large" Class="mix-detail-container">
|
||||
@* Mix keeps the scaffold solely for the Phase 10 top row (back link | controls | lava-lamp).
|
||||
Title/artist/genre/date/share/play all move into the overlaid hero, so the scaffold's
|
||||
default header and meta regions are suppressed (ShowHeader/ShowMeta=false) and the share
|
||||
row stays off (ShowShareRow=false). *@
|
||||
<ReleaseDetailScaffold Title="@release.Title"
|
||||
Artist="@release.Artist"
|
||||
Track="@ViewModel.Track"
|
||||
BackHref="/mixes"
|
||||
BackLabel="All mixes"
|
||||
ShowMeta="@(hasGenre || hasDate)"
|
||||
ShowHeader="false"
|
||||
ShowMeta="false"
|
||||
ShowShareRow="false">
|
||||
<TopContent>
|
||||
@* The seven-knob band lives in its own full-width area below the back/lamp top row.
|
||||
@@ -73,43 +77,28 @@ else
|
||||
</MudTooltip>
|
||||
</TopRightAction>
|
||||
<Hero>
|
||||
<div class="mix-detail-cover">
|
||||
@if (!string.IsNullOrEmpty(release.ImagePath))
|
||||
{
|
||||
<MudPaper Elevation="2" Class="deepdrft-track-detail-cover-art"
|
||||
Style="@($"background-image: url('api/image/{Uri.EscapeDataString(release.ImagePath)}');")" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudPaper Elevation="2" Class="deepdrft-track-detail-cover-placeholder deepdrft-gradient-soft-secondary">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Album" Color="Color.Primary" />
|
||||
</MudPaper>
|
||||
}
|
||||
</div>
|
||||
@* Cover-as-background hero with all metadata overlaid, square `mix-hero` sizing. The
|
||||
cover art IS the background, so no separate cover thumbnail (CoverThumbKey defaults
|
||||
to null). Share and play ride in as slots, matching Sessions. *@
|
||||
<ReleaseHeroOverlay Class="mix-hero"
|
||||
HeroImageKey="@release.ImagePath"
|
||||
PlaceholderIcon="@Icons.Material.Filled.Album"
|
||||
Title="@release.Title"
|
||||
Artist="@release.Artist"
|
||||
Genre="@release.Genre"
|
||||
ReleaseDate="@release.ReleaseDate">
|
||||
<ShareContent>
|
||||
@* Release-mode share: copies the canonical /mixes/{entryKey} URL, not a single track (§3b). *@
|
||||
<SharePopover ReleaseEntryKey="@release.EntryKey" ReleaseMedium="@release.Medium" />
|
||||
</ShareContent>
|
||||
<PlayContent>
|
||||
@if (ViewModel.Track is not null)
|
||||
{
|
||||
<PlayStateIcon Track="@ViewModel.Track" Size="Size.Large" Color="Color.Secondary" OnToggle="@PlayTrack" />
|
||||
}
|
||||
</PlayContent>
|
||||
</ReleaseHeroOverlay>
|
||||
</Hero>
|
||||
<MetaContent>
|
||||
@if (hasGenre)
|
||||
{
|
||||
<div>
|
||||
<MudChip T="string" Variant="Variant.Outlined" Color="Color.Tertiary" Class="deepdrft-genre-chip">
|
||||
@release.Genre
|
||||
</MudChip>
|
||||
</div>
|
||||
}
|
||||
@if (hasDate)
|
||||
{
|
||||
<div>
|
||||
<MudText Typo="Typo.overline">Released</MudText>
|
||||
<MudText Typo="Typo.body1">@release.ReleaseDate!.Value.ToString("MMMM yyyy")</MudText>
|
||||
</div>
|
||||
}
|
||||
</MetaContent>
|
||||
<BodyContent>
|
||||
@* Release-mode share: copies the canonical /mixes/{entryKey} URL, not a single track (§3b). *@
|
||||
<div class="deepdrft-share-row">
|
||||
<SharePopover ReleaseEntryKey="@release.EntryKey" ReleaseMedium="@release.Medium" />
|
||||
</div>
|
||||
</BodyContent>
|
||||
</ReleaseDetailScaffold>
|
||||
</MudContainer>
|
||||
</div>
|
||||
@@ -118,6 +107,27 @@ else
|
||||
@code {
|
||||
protected override string PersistKey => "mix-detail";
|
||||
|
||||
[CascadingParameter] public IStreamingPlayerService? PlayerService { get; set; }
|
||||
|
||||
// The hero now carries the play affordance (the scaffold's header is suppressed), so the
|
||||
// play-toggle is wired here directly — mirroring SessionDetail. Toggle if this track is already
|
||||
// active, otherwise start a fresh stream.
|
||||
private async Task PlayTrack()
|
||||
{
|
||||
var track = ViewModel.Track;
|
||||
if (track is null || PlayerService is null) return;
|
||||
|
||||
var isThisTrack = PlayerService.CurrentTrack?.Id == track.Id;
|
||||
if (isThisTrack && (PlayerService.IsPlaying || PlayerService.IsPaused))
|
||||
{
|
||||
await PlayerService.TogglePlayPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
await PlayerService.SelectTrackStreaming(track);
|
||||
}
|
||||
}
|
||||
|
||||
// Lava-lamp knob-band visibility. Pure presentation over MixVisualizerControlState — gates whether
|
||||
// the seven-knob MixVisualizerControls is rendered into the TopContent band; toggling it touches no
|
||||
// control value or bridge push. The lava-lamp button's filled/outline glyph is driven off this flag.
|
||||
|
||||
Reference in New Issue
Block a user