diff --git a/frontend/src/components/AudioPlayer.tsx b/frontend/src/components/AudioPlayer.tsx index 2c2204f..67dc981 100644 --- a/frontend/src/components/AudioPlayer.tsx +++ b/frontend/src/components/AudioPlayer.tsx @@ -5,17 +5,12 @@ import { Play, Pause, Volume2, - SkipBack, - SkipForward, + VolumeX, ChevronDown, Maximize2, - Minimize2, - List, - VolumeX, - FastForward, - Rewind, X, - Info + RotateCcw, + RotateCw, } from 'lucide-react'; interface AudioPlayerProps { @@ -30,8 +25,6 @@ export default function AudioPlayer({ episode, onClose, userId }: AudioPlayerPro const [currentTime, setCurrentTime] = useState(0); const [duration, setDuration] = useState(0); const [volume, setVolume] = useState(1); - const [playbackSpeed, setPlaybackSpeed] = useState(1); - const [isSaving, setIsSaving] = useState(false); const [isMuted, setIsMuted] = useState(false); const [isExpanded, setIsExpanded] = useState(false); @@ -40,256 +33,230 @@ export default function AudioPlayer({ episode, onClose, userId }: AudioPlayerPro // Save progress periodically useEffect(() => { if (!episode || !userId) return; - - const saveProgressInterval = setInterval(async () => { + const interval = setInterval(async () => { if (isPlaying) { try { - setIsSaving(true); - await episodeService.saveProgress( - episode._id, - Math.floor(currentTime), - false - ); - } catch (error) { - console.error('Failed to save progress:', error); - } finally { - setIsSaving(false); - } + await episodeService.saveProgress(episode._id, Math.floor(currentTime), false); + } catch {} } - }, 30000); // Save every 30 seconds - - return () => clearInterval(saveProgressInterval); + }, 30000); + return () => clearInterval(interval); }, [episode, userId, currentTime, isPlaying]); // Load previous progress useEffect(() => { if (!episode || !userId) return; - - const loadProgress = async () => { - try { - const response = await episodeService.getProgress(episode._id); - if (response.progress) { - if (audioRef.current) { - audioRef.current.currentTime = response.progress.position; - } - } - } catch (error) { - console.error('Failed to load progress:', error); + episodeService.getProgress(episode._id).then((r) => { + if (r.progress?.position && audioRef.current) { + audioRef.current.currentTime = r.progress.position; } - }; - - loadProgress(); + }).catch(() => {}); }, [episode, userId]); const handlePlayPause = () => { if (!audioRef.current) return; - - if (isPlaying) { - audioRef.current.pause(); - } else { - audioRef.current.play(); - } + if (isPlaying) audioRef.current.pause(); + else audioRef.current.play(); setIsPlaying(!isPlaying); }; - const handleTimeUpdate = () => { - if (audioRef.current) { - setCurrentTime(audioRef.current.currentTime); - } - }; - - const handleLoadedMetadata = () => { - if (audioRef.current) { - setDuration(audioRef.current.duration); - } + const handleSeek = (delta: number) => { + if (!audioRef.current) return; + audioRef.current.currentTime = Math.max(0, Math.min(duration, currentTime + delta)); }; const handleProgressChange = (e: React.ChangeEvent) => { - const newTime = parseFloat(e.target.value); - setCurrentTime(newTime); - if (audioRef.current) { - audioRef.current.currentTime = newTime; - } + const t = parseFloat(e.target.value); + setCurrentTime(t); + if (audioRef.current) audioRef.current.currentTime = t; }; const handleVolumeChange = (e: React.ChangeEvent) => { - const newVolume = parseFloat(e.target.value); - setVolume(newVolume); - if (audioRef.current) { - audioRef.current.volume = newVolume; - } + const v = parseFloat(e.target.value); + setVolume(v); + setIsMuted(v === 0); + if (audioRef.current) audioRef.current.volume = v; }; - const handleSpeedChange = (speed: number) => { - setPlaybackSpeed(speed); - if (audioRef.current) { - audioRef.current.playbackRate = speed; - } + const toggleMute = () => { + if (!audioRef.current) return; + const muted = !isMuted; + setIsMuted(muted); + audioRef.current.volume = muted ? 0 : volume; }; - const formatTime = (seconds: number) => { - if (!isFinite(seconds)) return '0:00'; - const mins = Math.floor(seconds / 60); - const secs = Math.floor(seconds % 60); - return `${mins}:${secs.toString().padStart(2, '0')}`; + const formatTime = (s: number) => { + if (!isFinite(s)) return '0:00'; + const m = Math.floor(s / 60); + const sec = Math.floor(s % 60); + return `${m}:${sec.toString().padStart(2, '0')}`; }; if (!episode) return null; + const progress = duration > 0 ? (currentTime / duration) * 100 : 0; + return ( -
+
+