import { Music2, SkipForward, Square, Volume2, VolumeX } from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; import { Button, Input } from "../../../shared/ui"; interface MusicSubPanelProps { volume: number; onVolumeChange: (v: number) => void; onQueue: (source: string) => void; onSkip: () => void; onStop: () => void; loading: boolean; } export function MusicSubPanel({ volume, onVolumeChange, onQueue, onSkip, onStop, loading, }: MusicSubPanelProps) { const [source, setSource] = useState(""); const safeVolume = Number.isFinite(volume) ? Math.max(0, Math.min(1, volume)) : 1; const [draftVolume, setDraftVolume] = useState(Math.round(safeVolume * 100)); const [muted, setMuted] = useState(false); const prevVolumeRef = useRef(safeVolume); const debounceRef = useRef | null>(null); // Proper debounce: setTimeout instead of setInterval polling useEffect(() => { if (debounceRef.current) clearTimeout(debounceRef.current); debounceRef.current = setTimeout(() => { const normalized = draftVolume / 100; if (Math.abs(normalized - safeVolume) >= 0.001) onVolumeChange(normalized); }, 200); return () => { if (debounceRef.current) clearTimeout(debounceRef.current); }; }, [draftVolume, safeVolume, onVolumeChange]); const handleMute = useCallback(() => { if (muted) { // Unmute: restore previous volume const restore = prevVolumeRef.current; setDraftVolume(Math.round(restore * 100)); onVolumeChange(restore); setMuted(false); } else { // Mute: save current, set to 0 prevVolumeRef.current = safeVolume; setDraftVolume(0); onVolumeChange(0); setMuted(true); } }, [muted, safeVolume, onVolumeChange]); const submit = () => { const t = source.trim(); if (!t) return; onQueue(t); setSource(""); }; return (
setSource(e.target.value)} onKeyDown={(e) => e.key === "Enter" && submit()} placeholder="YouTube URL, Spotify track, or search terms" />
{ setDraftVolume(Number(e.target.value)); if (muted) setMuted(false); }} className="h-2 w-full cursor-pointer accent-primary" /> {draftVolume}%
); }