diff --git a/index.html b/index.html index d1ab187..adc9906 100644 --- a/index.html +++ b/index.html @@ -875,14 +875,18 @@ const [showPlaylist, setShowPlaylist] = useState(false); const [showSideDrawer, setShowSideDrawer] = useState(false); - const audioRef = useRef(new Audio()); - + const audioRef = useRef(null); + const autoAdvanceLockRef = useRef(false); const currentSongRef = useRef(null); useEffect(() => { currentSongRef.current = currentSong; }, [currentSong]); + useEffect(() => { + autoAdvanceLockRef.current = false; + }, [currentSong]); + // Media Session Refs const playNextRef = useRef(null); const playPrevRef = useRef(null); @@ -997,12 +1001,27 @@ useEffect(() => { const audio = audioRef.current; + if (!audio) return; audio.volume = volume; + + const triggerAutoNext = () => { + if (autoAdvanceLockRef.current) return; + autoAdvanceLockRef.current = true; + playNext(true, { immediate: true }); + }; + const updateTime = () => { setCurrentTime(audio.currentTime); + if (autoAdvanceLockRef.current) return; + const durationSeconds = resolveDurationSeconds(audio, currentSongRef.current); + if (Number.isFinite(durationSeconds) && durationSeconds > 0) { + if (audio.currentTime >= durationSeconds - 0.35) { + triggerAutoNext(); + } + } }; const updateDuration = () => setDuration(resolveDurationSeconds(audio, currentSongRef.current)); - const onEnded = () => playNext(true); + const onEnded = () => triggerAutoNext(); audio.addEventListener('timeupdate', updateTime); audio.addEventListener('loadedmetadata', updateDuration); @@ -1013,23 +1032,25 @@ audio.removeEventListener('loadedmetadata', updateDuration); audio.removeEventListener('ended', onEnded); }; - }, [playlist, currentSong, mode]); + }, [playlist, currentSong, mode, volume, quality]); useEffect(() => { if (currentSong) { + const audio = audioRef.current; + if (!audio) return; // Update URL when quality changes or song changes const url = api.getSongUrl(currentSong.id, currentSong.platform || currentSong.source, quality); // Only update src if it's different to avoid reloading same song on re-render (unless quality changed) // Note: audioRef.current.src returns full absolute URL - const currentSrc = audioRef.current.src; + const currentSrc = audio.src; // Simple check if src changed significantly (avoiding minor encoding diffs if possible, but exact match is safer) if (currentSrc !== url) { const wasPlaying = isPlaying; - audioRef.current.src = url; + audio.src = url; if (wasPlaying) { - audioRef.current.play() + audio.play() .then(() => setIsPlaying(true)) .catch(e => { console.warn("Auto-play prevented:", e); @@ -1042,8 +1063,10 @@ useEffect(() => { if (currentSong) { - if (isPlaying) audioRef.current.play().catch(() => setIsPlaying(false)); - else audioRef.current.pause(); + const audio = audioRef.current; + if (!audio) return; + if (isPlaying) audio.play().catch(() => setIsPlaying(false)); + else audio.pause(); } }, [isPlaying]); @@ -1117,12 +1140,15 @@ const togglePlay = () => setIsPlaying(!isPlaying); - const playNext = (auto = false) => { + const playNext = (auto = false, options = {}) => { if (playlist.length === 0) return; if (auto && mode === 'one') { - audioRef.current.currentTime = 0; - audioRef.current.play(); + const audio = audioRef.current; + if (!audio) return; + audio.currentTime = 0; + audio.play().catch(() => setIsPlaying(false)); + autoAdvanceLockRef.current = false; return; } @@ -1135,8 +1161,24 @@ nextIdx = (currIdx + 1) % playlist.length; } - setCurrentSong(playlist[nextIdx]); + const nextSong = playlist[nextIdx]; + setCurrentSong(nextSong); setIsPlaying(true); + + if (options.immediate) { + const audio = audioRef.current; + if (!audio || !nextSong) return; + const url = api.getSongUrl(nextSong.id, nextSong.platform || nextSong.source, quality); + if (audio.src !== url) { + audio.src = url; + } + audio.play() + .then(() => setIsPlaying(true)) + .catch(e => { + console.warn("Auto-play prevented:", e); + setIsPlaying(false); + }); + } }; const playPrev = () => { @@ -1172,7 +1214,9 @@ const handleSeek = (time) => { if (Number.isFinite(time)) { - audioRef.current.currentTime = time; + const audio = audioRef.current; + if (!audio) return; + audio.currentTime = time; setCurrentTime(time); updateMediaSessionPosition(); } @@ -1263,6 +1307,7 @@ if (!('mediaSession' in navigator)) return; const audio = audioRef.current; + if (!audio) return; const updateState = () => { if (!audio) return; @@ -1317,6 +1362,14 @@ return (
+