mirror of
https://github.com/JezzWTF/vibepod.git
synced 2026-06-13 03:58:07 +00:00
feat: add studio roadmap and streaming cleanup
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
"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<HTMLAudioElement | null>(null);
|
||||
const [state, setState] = useState<AudioPlayerState>({
|
||||
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,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user