@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; @* Ambient living waveform behind the hero overlay (Phase 12 §3e option b / §3f mode B). Session does NOT compose ReleaseDetailScaffold, so it mounts the shared engine directly with its own thin full-bleed wrapper — the engine is single-source either way, only the mount differs (§3b). The visualizer positions itself fixed/inset:0; the session-detail-foreground class lifts the content above it. The bridge follows the live playing track; TrackEntryKey is the at-rest datum. *@
← All sessions @* Theater toggle sits immediately LEFT of the lava-lamp popover (Phase 20 §3). The whole top row (back + theater + lava) stays in Theater Mode — controls, not release content (§4/OQ4). *@
@* Theater toggle only appears when this Session is the currently-playing release (Phase 20 Wave 2 §3). ShowTheaterToggle folds in the subsystem + release-playing gate. *@ @* Lava-lamp icon → popover panel (full parity, §3e/§3d-revised). Anchored top-right, clear of the hero overlay and the share/play affordances overlaid on the hero below. *@
@* Theater Mode (Phase 20 §4, Wave 2 §2): the hero overlay + blurb stay mounted and ease out via a collapsing wrapper so they do not pop — collapsed to zero height when Theater is on AND this Session is the playing release. The top row above stays. OFF eases this region back in. *@
@* 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. *@ @* Release-mode share: copies the canonical /sessions/{entryKey} URL, not a single track (§3b). *@ @if (ViewModel.Track is not null) { @* Append-only: queues the session's single track without starting playback. *@ }
} @code { protected override string PersistKey => "session-detail"; // PlayerService is cascaded by ReleaseDetailBase (used there for the Theater release-playing predicate). [CascadingParameter] public IQueueService? Queue { 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 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. 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); } } }