/** * PlayerPage — 2-pane yazi depth view of the now-playing episode. * * depth 0 (parent) — tab list (muted, read-only). * depth 0 (current) — the single now-playing pane (rich view + controls). * * No preview pane (PaneRow `panes={2}`). Audio transport (play/pause, * next/prev, seek) is handled globally by the Shell router (P/N/B/); this * page only renders the now-playing surface. `h` at depth 0 returns to the * tab root. */ import { Show } from "solid-js"; import { PlaybackControls } from "./PlaybackControls"; import { ProgressBar } from "./ProgressBar"; import { RealtimeWaveform } from "./RealtimeWaveform"; import { useAudio } from "@/hooks/useAudio"; import { useAppStore } from "@/stores/app"; import { useTheme } from "@/context/ThemeContext"; import { useNavigation, DEPTH_CENTER_PANE } from "@/context/NavigationContext"; import { PaneRow } from "@/components/PaneRow"; import { TabListPane } from "@/components/TabPanel"; export const PlayerPaneCount = 1; export function PlayerPage() { const audio = useAudio(); const { theme } = useTheme(); const nav = useNavigation(); const muted = () => theme.muted || theme.text; const isActive = () => nav.activePane() === DEPTH_CENTER_PANE; const progressPercent = () => { const d = audio.duration(); if (d <= 0) return 0; return Math.min(100, Math.round((audio.position() / d) * 100)); }; const formatTime = (seconds: number) => { const m = Math.floor(seconds / 60); const s = Math.floor(seconds % 60); return `${m}:${String(s).padStart(2, "0")}`; }; // ── parent pane: the tab list (muted) ────────────────────────────────────── const parentContent = () => ; // ── current pane: now playing ─────────────────────────────────────────────── const currentContent = () => ( Now Playing {formatTime(audio.position())} / {formatTime(audio.duration())} ( {progressPercent()}%) {(err) => {err()}} No episode loaded. } > {(ep) => ( {ep().title} {ep().description?.slice(0, 500) ?? "No description available."} { const viz = useAppStore().state().settings.visualizer; // bars is width-derived in RealtimeWaveform; pass only the // audio-processing params here. return { noiseReduction: viz.noiseReduction, lowCutOff: viz.lowCutOff, highCutOff: viz.highCutOff, }; })()} /> )} audio.seek(0)} onNext={() => audio.seek(audio.currentEpisode()?.duration ?? 0)} onSpeedChange={(s: number) => audio.setSpeed(s)} onVolumeChange={(v: number) => audio.setVolume(v)} /> {"P play/pause N next B prev < > seek h back"} ); return ( ); }