1- import React , { useState , useEffect , useRef , useCallback } from ' react' ;
2- import { Episode , Podcast } from ' ../../types' ;
3- import { storageService } from ' ../../services/storageService' ;
4- import { PlayerPresentation } from ' ./PlayerPresentation' ;
1+ import React , { useState , useEffect , useRef , useCallback } from " react" ;
2+ import { Episode , Podcast } from " ../../types" ;
3+ import { storageService } from " ../../services/storageService" ;
4+ import { PlayerPresentation } from " ./PlayerPresentation" ;
55
66export interface PlayerContainerProps {
77 episode : Episode ;
@@ -12,7 +12,11 @@ export interface PlayerContainerProps {
1212 onClearQueue : ( ) => void ;
1313 onClose : ( ) => void ;
1414 onShare : ( ) => void ;
15- onProgress ?: ( episodeId : string , currentTime : number , duration : number ) => void ;
15+ onProgress ?: (
16+ episodeId : string ,
17+ currentTime : number ,
18+ duration : number
19+ ) => void ;
1620 onReady ?: ( ) => void ;
1721 autoPlay ?: boolean ;
1822}
@@ -40,7 +44,9 @@ export const PlayerContainer: React.FC<PlayerContainerProps> = ({
4044 // UI state
4145 const [ showQueue , setShowQueue ] = useState ( false ) ;
4246 const [ showSpeedMenu , setShowSpeedMenu ] = useState ( false ) ;
43- const [ errorMessage , setErrorMessage ] = useState < string | undefined > ( undefined ) ;
47+ const [ errorMessage , setErrorMessage ] = useState < string | undefined > (
48+ undefined
49+ ) ;
4450
4551 // Refs
4652 const audioRef = useRef < HTMLAudioElement | null > ( null ) ;
@@ -49,7 +55,7 @@ export const PlayerContainer: React.FC<PlayerContainerProps> = ({
4955 // Initialize audio element
5056 useEffect ( ( ) => {
5157 if ( ! episode . audioUrl ) {
52- setErrorMessage ( ' No audio URL available' ) ;
58+ setErrorMessage ( " No audio URL available" ) ;
5359 setIsBuffering ( false ) ;
5460 return ;
5561 }
@@ -100,44 +106,44 @@ export const PlayerContainer: React.FC<PlayerContainerProps> = ({
100106 } ;
101107
102108 const handleError = ( ) => {
103- setErrorMessage ( ' Failed to load audio' ) ;
109+ setErrorMessage ( " Failed to load audio" ) ;
104110 setIsBuffering ( false ) ;
105111 setIsPlaying ( false ) ;
106112 } ;
107113
108- audio . addEventListener ( ' loadedmetadata' , handleLoadedMetadata ) ;
109- audio . addEventListener ( ' timeupdate' , handleTimeUpdate ) ;
110- audio . addEventListener ( ' ended' , handleEnded ) ;
111- audio . addEventListener ( ' play' , handlePlay ) ;
112- audio . addEventListener ( ' pause' , handlePause ) ;
113- audio . addEventListener ( ' waiting' , handleWaiting ) ;
114- audio . addEventListener ( ' canplay' , handleCanPlay ) ;
115- audio . addEventListener ( ' error' , handleError ) ;
114+ audio . addEventListener ( " loadedmetadata" , handleLoadedMetadata ) ;
115+ audio . addEventListener ( " timeupdate" , handleTimeUpdate ) ;
116+ audio . addEventListener ( " ended" , handleEnded ) ;
117+ audio . addEventListener ( " play" , handlePlay ) ;
118+ audio . addEventListener ( " pause" , handlePause ) ;
119+ audio . addEventListener ( " waiting" , handleWaiting ) ;
120+ audio . addEventListener ( " canplay" , handleCanPlay ) ;
121+ audio . addEventListener ( " error" , handleError ) ;
116122
117123 // Auto-play if requested
118124 if ( autoPlay ) {
119125 audio . play ( ) . catch ( ( ) => {
120- setErrorMessage ( ' Auto-play prevented by browser' ) ;
126+ setErrorMessage ( " Auto-play prevented by browser" ) ;
121127 setIsPlaying ( false ) ;
122128 } ) ;
123129 }
124130
125131 return ( ) => {
126- audio . removeEventListener ( ' loadedmetadata' , handleLoadedMetadata ) ;
127- audio . removeEventListener ( ' timeupdate' , handleTimeUpdate ) ;
128- audio . removeEventListener ( ' ended' , handleEnded ) ;
129- audio . removeEventListener ( ' play' , handlePlay ) ;
130- audio . removeEventListener ( ' pause' , handlePause ) ;
131- audio . removeEventListener ( ' waiting' , handleWaiting ) ;
132- audio . removeEventListener ( ' canplay' , handleCanPlay ) ;
133- audio . removeEventListener ( ' error' , handleError ) ;
134-
132+ audio . removeEventListener ( " loadedmetadata" , handleLoadedMetadata ) ;
133+ audio . removeEventListener ( " timeupdate" , handleTimeUpdate ) ;
134+ audio . removeEventListener ( " ended" , handleEnded ) ;
135+ audio . removeEventListener ( " play" , handlePlay ) ;
136+ audio . removeEventListener ( " pause" , handlePause ) ;
137+ audio . removeEventListener ( " waiting" , handleWaiting ) ;
138+ audio . removeEventListener ( " canplay" , handleCanPlay ) ;
139+ audio . removeEventListener ( " error" , handleError ) ;
140+
135141 if ( saveIntervalRef . current ) {
136142 clearInterval ( saveIntervalRef . current ) ;
137143 }
138-
144+
139145 audio . pause ( ) ;
140- audio . src = '' ;
146+ audio . src = "" ;
141147 } ;
142148 } , [ episode . id , episode . audioUrl , autoPlay , onNext , onReady ] ) ;
143149
@@ -167,35 +173,41 @@ export const PlayerContainer: React.FC<PlayerContainerProps> = ({
167173 useEffect ( ( ) => {
168174 const handleKeyDown = ( e : KeyboardEvent ) => {
169175 // Don't trigger if user is typing in an input
170- if ( e . target instanceof HTMLInputElement || e . target instanceof HTMLTextAreaElement ) {
176+ if (
177+ e . target instanceof HTMLInputElement ||
178+ e . target instanceof HTMLTextAreaElement
179+ ) {
171180 return ;
172181 }
173182
174183 switch ( e . key ) {
175- case ' ' :
184+ case " " :
176185 e . preventDefault ( ) ;
177186 togglePlay ( ) ;
178187 break ;
179- case ' ArrowLeft' :
188+ case " ArrowLeft" :
180189 e . preventDefault ( ) ;
181190 skipSeconds ( - 10 ) ;
182191 break ;
183- case ' ArrowRight' :
192+ case " ArrowRight" :
184193 e . preventDefault ( ) ;
185194 skipSeconds ( 10 ) ;
186195 break ;
187196 }
188197 } ;
189198
190- window . addEventListener ( ' keydown' , handleKeyDown ) ;
191- return ( ) => window . removeEventListener ( ' keydown' , handleKeyDown ) ;
199+ window . addEventListener ( " keydown" , handleKeyDown ) ;
200+ return ( ) => window . removeEventListener ( " keydown" , handleKeyDown ) ;
192201 } , [ isPlaying ] ) ; // Re-bind when isPlaying changes
193202
194203 // Save progress helper
195- const saveProgress = useCallback ( ( currentTime : number , duration : number ) => {
196- storageService . updatePlayback ( episode , podcast , currentTime , duration ) ;
197- onProgress ?.( episode . id , currentTime , duration ) ;
198- } , [ episode , podcast , onProgress ] ) ;
204+ const saveProgress = useCallback (
205+ ( currentTime : number , duration : number ) => {
206+ storageService . updatePlayback ( episode , podcast , currentTime , duration ) ;
207+ onProgress ?.( episode . id , currentTime , duration ) ;
208+ } ,
209+ [ episode , podcast , onProgress ]
210+ ) ;
199211
200212 // Play/pause toggle
201213 const togglePlay = useCallback ( ( ) => {
@@ -206,25 +218,34 @@ export const PlayerContainer: React.FC<PlayerContainerProps> = ({
206218 saveProgress ( audioRef . current . currentTime , audioRef . current . duration ) ;
207219 } else {
208220 audioRef . current . play ( ) . catch ( ( error ) => {
209- setErrorMessage ( ' Playback failed: ' + error . message ) ;
221+ setErrorMessage ( " Playback failed: " + error . message ) ;
210222 } ) ;
211223 }
212224 } , [ isPlaying , saveProgress ] ) ;
213225
214226 // Skip forward/backward
215- const skipSeconds = useCallback ( ( seconds : number ) => {
216- if ( ! audioRef . current ) return ;
217-
218- audioRef . current . currentTime = Math . max ( 0 , Math . min ( duration , audioRef . current . currentTime + seconds ) ) ;
219- } , [ duration ] ) ;
227+ const skipSeconds = useCallback (
228+ ( seconds : number ) => {
229+ if ( ! audioRef . current ) return ;
230+
231+ audioRef . current . currentTime = Math . max (
232+ 0 ,
233+ Math . min ( duration , audioRef . current . currentTime + seconds )
234+ ) ;
235+ } ,
236+ [ duration ]
237+ ) ;
220238
221239 // Seek to percentage
222- const seekToPercentage = useCallback ( ( percentage : number ) => {
223- if ( ! audioRef . current ) return ;
224-
225- const newTime = ( percentage / 100 ) * duration ;
226- audioRef . current . currentTime = newTime ;
227- } , [ duration ] ) ;
240+ const seekToPercentage = useCallback (
241+ ( percentage : number ) => {
242+ if ( ! audioRef . current ) return ;
243+
244+ const newTime = ( percentage / 100 ) * duration ;
245+ audioRef . current . currentTime = newTime ;
246+ } ,
247+ [ duration ]
248+ ) ;
228249
229250 // Change playback speed
230251 const changePlaybackRate = useCallback ( ( rate : number ) => {
0 commit comments