@page "/sessions/{EntryKey}"
@using DeepDrftModels.DTOs
@using DeepDrftPublic.Client.Controls
@using DeepDrftPublic.Client.Services
@inherits ReleaseDetailBase
@(ViewModel.Release?.Title ?? "Session") - DeepDrft
@if (ViewModel.IsLoading)
{
← 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). *@
@* 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): the hero overlay + blurb (the session's release content) are removed
from the render so the ambient visualizer fills the surface. The top row above stays. OFF
restores this region byte-for-byte. *@
@if (!VisualizerControlState.TheaterMode)
{
@* 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";
[CascadingParameter] public IStreamingPlayerService? PlayerService { get; set; }
[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);
}
}
}