feat(mix-detail): extract shared ReleaseHeroOverlay; Mix cover becomes overlaid 600px square hero (Direction B)

This commit is contained in:
daniel-c-harvey
2026-06-16 20:53:25 -04:00
parent 9cf6bb4cf2
commit a6d25344b4
8 changed files with 399 additions and 301 deletions
+20 -69
View File
@@ -39,12 +39,6 @@ else
var heroKey = release.SessionMetadata?.HeroImageEntryKey;
// Hero image precedence: the session's dedicated hero, then the release cover, then a placeholder.
var heroImage = !string.IsNullOrEmpty(heroKey) ? heroKey : release.ImagePath;
// Show the cover thumbnail only when it differs from what the hero displays. When there is no
// dedicated hero, the hero already falls back to release.ImagePath — rendering the cover too
// would duplicate the same image.
var showCover = !string.IsNullOrEmpty(release.ImagePath) && release.ImagePath != heroImage;
var hasGenre = release.Genre is not null;
var hasDate = release.ReleaseDate is not null;
<MudContainer MaxWidth="MaxWidth.Large" Class="session-detail-page">
@@ -52,70 +46,27 @@ else
&larr; All sessions
</MudLink>
@* The hero is the positioning context for every overlay row; the gradient shim and the
top/bottom overlays are absolutely positioned children of this wrapper. *@
<div class="session-hero">
@if (!string.IsNullOrEmpty(heroImage))
{
<MudPaper Elevation="0" Square="true" Class="session-hero-img"
Style="@($"background-image: url('api/image/{Uri.EscapeDataString(heroImage)}');")" />
}
else
{
<MudPaper Elevation="0" Square="true" Class="session-hero-placeholder deepdrft-gradient-soft-secondary">
<MudIcon Icon="@Icons.Material.Filled.Piano" Color="Color.Primary" />
</MudPaper>
}
@* Darkening shim so overlaid text/controls stay legible over any image. *@
<div class="session-hero-shim"></div>
@* Top overlay: secondary details (genre, release date) and the share affordance. *@
<div class="session-hero-top">
<MudStack Row AlignItems="AlignItems.Center" Spacing="3" Class="session-hero-meta">
@if (hasGenre)
{
<MudChip T="string" Variant="Variant.Outlined" Class="session-overlay-chip">
@release.Genre
</MudChip>
}
@if (hasDate)
{
<div class="session-overlay-date">
<span class="session-overlay-label">Released</span>
<span class="session-overlay-value">@release.ReleaseDate!.Value.ToString("MMMM yyyy")</span>
</div>
}
</MudStack>
@* The overlay shows the cover thumbnail only when it differs from the resolved hero image —
when there is no dedicated hero, heroImage already falls back to release.ImagePath, so the
thumb would duplicate the background. That logic lives in ReleaseHeroOverlay. *@
<ReleaseHeroOverlay HeroImageKey="@heroImage"
CoverThumbKey="@release.ImagePath"
PlaceholderIcon="@Icons.Material.Filled.Piano"
Title="@release.Title"
Artist="@release.Artist"
Genre="@release.Genre"
ReleaseDate="@release.ReleaseDate">
<ShareContent>
@* Release-mode share: copies the canonical /sessions/{entryKey} URL, not a single track (§3b). *@
<div class="session-hero-share">
<SharePopover ReleaseEntryKey="@release.EntryKey" ReleaseMedium="@release.Medium" />
</div>
</div>
@* Bottom overlay: cover thumbnail, title/artist, and the play affordance in one row. *@
<div class="session-hero-bottom">
<MudStack Row AlignItems="AlignItems.Center" Spacing="4" Class="session-hero-bottom-row">
@if (showCover)
{
<div class="session-cover-thumb">
<MudPaper Elevation="0" Square="true" Class="deepdrft-track-detail-cover-art"
Style="@($"background-image: url('api/image/{Uri.EscapeDataString(release.ImagePath!)}');")" />
</div>
}
<div class="session-hero-titles">
<div class="session-overlay-title">@release.Title</div>
<div class="session-overlay-artist">@release.Artist</div>
</div>
@if (ViewModel.Track is not null)
{
<div class="session-hero-play">
<PlayStateIcon Track="@ViewModel.Track" Size="Size.Large" Color="Color.Secondary" OnToggle="@PlayTrack" />
</div>
}
</MudStack>
</div>
</div>
<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>
</MudContainer>
}