"use client"; import { useCallback, useEffect, useRef, useState } from "react"; interface AudioPlayerState { isPlaying: boolean; currentTime: number; duration: number; volume: number; } export function useAudioPlayer(audioUrl: string | null) { const audioRef = useRef(null); const [state, setState] = useState({ isPlaying: false, currentTime: 0, duration: 0, volume: 1, }); // Create/replace the Audio element whenever the URL changes useEffect(() => { if (!audioUrl) { if (audioRef.current) { audioRef.current.pause(); audioRef.current = null; } setState({ isPlaying: false, currentTime: 0, duration: 0, volume: 1 }); return; } const audio = new Audio(audioUrl); audioRef.current = audio; const onTimeUpdate = () => setState((prev) => ({ ...prev, currentTime: audio.currentTime })); const onDurationChange = () => setState((prev) => ({ ...prev, duration: audio.duration })); const onEnded = () => setState((prev) => ({ ...prev, isPlaying: false, currentTime: 0 })); const onPlay = () => setState((prev) => ({ ...prev, isPlaying: true })); const onPause = () => setState((prev) => ({ ...prev, isPlaying: false })); audio.addEventListener("timeupdate", onTimeUpdate); audio.addEventListener("durationchange", onDurationChange); audio.addEventListener("loadedmetadata", onDurationChange); audio.addEventListener("ended", onEnded); audio.addEventListener("play", onPlay); audio.addEventListener("pause", onPause); return () => { audio.pause(); audio.removeEventListener("timeupdate", onTimeUpdate); audio.removeEventListener("durationchange", onDurationChange); audio.removeEventListener("loadedmetadata", onDurationChange); audio.removeEventListener("ended", onEnded); audio.removeEventListener("play", onPlay); audio.removeEventListener("pause", onPause); }; }, [audioUrl]); const toggle = useCallback(() => { const audio = audioRef.current; if (!audio) return; if (audio.paused) { audio.play(); } else { audio.pause(); } }, []); const seek = useCallback((time: number) => { const audio = audioRef.current; if (!audio) return; audio.currentTime = Math.max(0, Math.min(time, audio.duration)); }, []); const setVolume = useCallback((v: number) => { const audio = audioRef.current; if (!audio) return; audio.volume = Math.max(0, Math.min(1, v)); setState((prev) => ({ ...prev, volume: v })); }, []); return { isPlaying: state.isPlaying, currentTime: state.currentTime, duration: state.duration, volume: state.volume, toggle, seek, setVolume, }; }