parent
					
						
							
								e9f197740d
							
						
					
				
			
			
				commit
				
					
						6637ecb460
					
				
			
		
					 3 changed files with 117 additions and 71 deletions
				
			
		
							
								
								
									
										62
									
								
								app/javascript/mastodon/hooks/useAudioContext.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								app/javascript/mastodon/hooks/useAudioContext.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| import { useCallback, useEffect, useRef } from 'react'; | ||||
| 
 | ||||
| interface AudioContextOptions { | ||||
|   audioElementRef: React.MutableRefObject<HTMLAudioElement | null>; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Create and return an audio context instance for a given audio element [0]. | ||||
|  * Also returns an associated audio source, a gain node, and play and pause actions | ||||
|  * which should be used instead of `audioElementRef.current.play/pause()`. | ||||
|  * | ||||
|  * [0] https://developer.mozilla.org/en-US/docs/Web/API/AudioContext
 | ||||
|  */ | ||||
| 
 | ||||
| export const useAudioContext = ({ audioElementRef }: AudioContextOptions) => { | ||||
|   const audioContextRef = useRef<AudioContext>(); | ||||
|   const sourceRef = useRef<MediaElementAudioSourceNode>(); | ||||
|   const gainNodeRef = useRef<GainNode>(); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (!audioElementRef.current) { | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|     const context = audioContextRef.current ?? new AudioContext(); | ||||
|     const source = | ||||
|       sourceRef.current ?? | ||||
|       context.createMediaElementSource(audioElementRef.current); | ||||
| 
 | ||||
|     const gainNode = context.createGain(); | ||||
|     gainNode.connect(context.destination); | ||||
|     source.connect(gainNode); | ||||
| 
 | ||||
|     audioContextRef.current = context; | ||||
|     gainNodeRef.current = gainNode; | ||||
|     sourceRef.current = source; | ||||
| 
 | ||||
|     return () => { | ||||
|       if (context.state !== 'closed') { | ||||
|         void context.close(); | ||||
|       } | ||||
|     }; | ||||
|   }, [audioElementRef]); | ||||
| 
 | ||||
|   const playAudio = useCallback(() => { | ||||
|     void audioElementRef.current?.play(); | ||||
|     void audioContextRef.current?.resume(); | ||||
|   }, [audioElementRef]); | ||||
| 
 | ||||
|   const pauseAudio = useCallback(() => { | ||||
|     audioElementRef.current?.pause(); | ||||
|     void audioContextRef.current?.suspend(); | ||||
|   }, [audioElementRef]); | ||||
| 
 | ||||
|   return { | ||||
|     audioContextRef, | ||||
|     sourceRef, | ||||
|     gainNodeRef, | ||||
|     playAudio, | ||||
|     pauseAudio, | ||||
|   }; | ||||
| }; | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue