@page "/mixes/{EntryKey}" @using DeepDrftPublic.Client.Controls @using DeepDrftPublic.Client.Services @inherits ReleaseDetailBase @(ViewModel.Release?.Title ?? "Mix") - DeepDrft @if (ViewModel.IsLoading) {
} else if (ViewModel.NotFound || ViewModel.Release is null) {
Mix not found.
All mixes
} else { var release = ViewModel.Release; @* 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 playback only when the player is on this mix's track; TrackEntryKey is the datum to render at rest (before playback) — the mix's single track, so the lava shows immediately on page load (§4). *@
@* 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). *@ @* Theater toggle sits immediately LEFT of the lava-lamp popover (Phase 20 §3). Both stay visible in Theater Mode — controls over the experience, not release content (§4/OQ4). Wrapped so they cluster on the right rather than spreading across the SpaceBetween row. *@
@* Theater toggle only appears when this Mix is the currently-playing release (Phase 20 Wave 2 §3). ShowTheaterToggle folds in the subsystem + release-playing gate. *@ @* Lava-lamp icon → popover panel, top-right across from the back link (Phase 12 §3d-revised). Replaces the former inline TopContent knob-bar: the icon IS the toggle and the popover IS the panel. Mix takes the cleanest anchor case (§8e) — the popover's default bottom-right anchor opens down over the full-bleed field. *@
@* Theater Mode (Phase 20 §4, Wave 2 §2): the hero overlay stays mounted and eases out via a collapsing wrapper so it does not pop — collapsed to zero height when Theater is on AND this Mix is the playing release. OFF eases the full-bleed visualizer back behind the hero. *@
@* 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. *@ @* Release-mode share: copies the canonical /mixes/{entryKey} URL, not a single track (§3b). *@ @if (ViewModel.Track is not null) { @* Append-only: queues the mix's single track without starting playback. *@ }
@* Theater Mode (Wave 2 §2): eased collapse, mirroring the Hero region. *@
@* Blurb sits below the hero, inside the scaffold's foreground stacking context. *@
} @code { protected override string PersistKey => "mix-detail"; // PlayerService is cascaded by ReleaseDetailBase (used there for the Theater release-playing predicate). [CascadingParameter] public IQueueService? Queue { 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 PLAY it: prepend to the queue's front (deque PLAY semantics) so it becomes // current and the existing queue stays intact behind it. Falls back to a direct stream when the // queue cascade is absent (prerender / non-interactive). 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 if (Queue is not null) { await Queue.PlayTrack(track); } else { await PlayerService.SelectTrackStreaming(track); } } }