@page "/sessions/{EntryKey}" @using DeepDrftModels.DTOs @using DeepDrftPublic.Client.Controls @using DeepDrftPublic.Client.Services @inherits ReleaseDetailBase @(ViewModel.Release?.Title ?? "Session") - DeepDrft @if (ViewModel.IsLoading) {
} else if (ViewModel.NotFound || ViewModel.Release is null) {
Session not found.
All sessions
} else { var release = ViewModel.Release; 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; ← All sessions @* 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. *@
@if (!string.IsNullOrEmpty(heroImage)) { } else { } @* Darkening shim so overlaid text/controls stay legible over any image. *@
@* Top overlay: secondary details (genre, release date) and the share affordance. *@
@if (hasGenre) { @release.Genre } @if (hasDate) {
Released @release.ReleaseDate!.Value.ToString("MMMM yyyy")
}
@if (ViewModel.Track is not null) {
}
@* Bottom overlay: cover thumbnail, title/artist, and the play affordance in one row. *@
@if (showCover) {
}
@release.Title
@release.Artist
@if (ViewModel.Track is not null) {
}
} @code { protected override string PersistKey => "session-detail"; [CascadingParameter] public IStreamingPlayerService? PlayerService { get; set; } // Mirrors the play-toggle wiring the shared scaffold owns. Session detail composes the player // affordance directly (it diverges from ReleaseDetailScaffold for the overlay layout), so the // toggle logic lives here: 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); } } }