import "./PlayerControls.css"; import { type AppOptions, getItemName, type PlayerState } from "../types"; import { type Accessor, createEffect, createSignal, type Setter } from "solid-js"; import { NextTrackSVG, PauseSVG, PlaySVG, PreviousTrackSVG, RepeatSVG, ShuffleSVG, VolumeSVG } from "./SVG"; import { formatTime } from "../utils"; import type { SetStoreFunction } from "solid-js/store"; import { LoadingSpinner } from "./LoadingScreen"; interface PlayerControlsProps { playerState: PlayerState; setPlayerState: SetStoreFunction; togglePlay: () => void; playPrevious: () => void; playNext: () => void; isShuffled: Accessor; setShuffled: Setter; isRepeated: Accessor; setRepeated: Setter; options: AppOptions; audioElement: HTMLAudioElement; } export default function PlayerControls(props: PlayerControlsProps) { const [controlsDisabled, setControlsDisabled] = createSignal(false); createEffect(() => { setControlsDisabled(!props.playerState.currentTrack); }); function setVolume(e: Event) { const input = e.target as HTMLInputElement; const volume = Number.parseFloat(input.value); props.setPlayerState("volume", volume); if (props.audioElement) { props.audioElement.volume = volume; } } // Seek to position function seekTo(e: MouseEvent) { const playerState = props.playerState; if (!props.audioElement || !playerState.currentTrack) return; const progressBar = e.currentTarget as HTMLDivElement; const rect = progressBar.getBoundingClientRect(); const pos = (e.clientX - rect.left) / rect.width; const duration = playerState.currentTrack.metadata.duration; props.audioElement.currentTime = Math.min(pos * duration, playerState.buffered - 1); props.setPlayerState("currentTime", pos * duration); } return (
{getItemName(props.playerState.currentTrack) || "No track selected"} {props.playerState.waitingForStart ? (
) : ( "" )}
{formatTime(props.playerState.currentTime)}/ {formatTime(props.playerState.currentTrack?.metadata.duration || 0)}
); }