11'use client' ;
22
3- import React , { useRef , useState } from 'react' ;
3+ import React , { useRef , useState , useEffect } from 'react' ;
44import io , { Socket } from 'socket.io-client' ;
55import SimplePeer , { Instance } from 'simple-peer' ;
66import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' ;
@@ -19,36 +19,49 @@ const AudioSharing = () => {
1919 const peerRef = useRef < Instance | null > ( null ) ;
2020 const audioStreamRef = useRef < MediaStream | null > ( null ) ;
2121 const initializedRef = useRef ( false ) ;
22+ const audioElementsRef = useRef < HTMLAudioElement [ ] > ( [ ] ) ;
2223
2324 const SERVER_URL =
2425 process . env . NEXT_PUBLIC_AUDIO_SERVER_URL || 'http://localhost:5555' ;
2526
26- // Add TURN server credentials from environment variables
2727 const TURN_SERVER = process . env . NEXT_PUBLIC_TURN_SERVER || '' ;
2828 const TURN_USERNAME = process . env . NEXT_PUBLIC_TURN_USERNAME ;
2929 const TURN_CREDENTIAL = process . env . NEXT_PUBLIC_TURN_PASSWORD ;
3030
31- if ( ! TURN_SERVER || ! TURN_USERNAME || ! TURN_CREDENTIAL ) {
32- // Log which specific TURN variables are missing
33- console . error ( 'Missing TURN env:' , {
34- server : ! ! TURN_SERVER ,
35- username : ! ! TURN_USERNAME ,
36- credential : ! ! TURN_CREDENTIAL ,
37- } ) ;
38- }
3931 const cleanupAudio = ( ) => {
32+ console . log ( 'Cleaning up audio connections...' ) ;
33+
34+ // Stop and cleanup all audio tracks
4035 if ( audioStreamRef . current ) {
4136 audioStreamRef . current . getTracks ( ) . forEach ( ( track ) => {
4237 track . stop ( ) ;
4338 } ) ;
4439 audioStreamRef . current = null ;
4540 }
41+
42+ // Destroy peer connection
4643 if ( peerRef . current ) {
4744 peerRef . current . destroy ( ) ;
4845 peerRef . current = null ;
4946 }
47+
48+ // Disconnect socket
49+ if ( socketRef . current ) {
50+ socketRef . current . disconnect ( ) ;
51+ socketRef . current = null ;
52+ }
53+
54+ // Stop and remove all audio elements
55+ audioElementsRef . current . forEach ( ( audio ) => {
56+ audio . pause ( ) ;
57+ audio . srcObject = null ;
58+ } ) ;
59+ audioElementsRef . current = [ ] ;
60+
61+ // Reset states
5062 setIsAudioEnabled ( false ) ;
5163 setConnectionStatus ( 'Not Connected' ) ;
64+ initializedRef . current = false ;
5265 } ;
5366
5467 const createPeer = ( stream : MediaStream , initiator : boolean ) => {
@@ -61,10 +74,8 @@ const AudioSharing = () => {
6174 trickle : false ,
6275 config : {
6376 iceServers : [
64- // Maintain existing STUN servers
6577 { urls : 'stun:stun.l.google.com:19302' } ,
6678 { urls : 'stun:global.stun.twilio.com:3478' } ,
67- // Add TURN server configuration
6879 {
6980 urls : TURN_SERVER ,
7081 username : TURN_USERNAME ,
@@ -75,14 +86,15 @@ const AudioSharing = () => {
7586 } ) ;
7687
7788 peer . on ( 'signal' , ( data : SignalData ) => {
78- console . log ( 'Sending signal data:' , data ) ;
89+ console . log ( 'Sending signal data' ) ;
7990 socketRef . current ?. emit ( 'signal' , data ) ;
8091 } ) ;
8192
8293 peer . on ( 'stream' , ( remoteStream : MediaStream ) => {
8394 console . log ( 'Received remote stream' ) ;
8495 const audio = new Audio ( ) ;
8596 audio . srcObject = remoteStream ;
97+ audioElementsRef . current . push ( audio ) ; // Track audio element for cleanup
8698 audio
8799 . play ( )
88100 . catch ( ( error ) => console . error ( 'Error playing audio:' , error ) ) ;
@@ -98,7 +110,6 @@ const AudioSharing = () => {
98110 cleanupAudio ( ) ;
99111 } ) ;
100112
101- // Add connection state logging
102113 peer . on ( 'connect' , ( ) => {
103114 console . log ( 'Peer connection established successfully' ) ;
104115 setConnectionStatus ( 'Connected' ) ;
@@ -129,7 +140,7 @@ const AudioSharing = () => {
129140 } ) ;
130141
131142 socketRef . current . on ( 'signal' , async ( data : SignalData ) => {
132- console . log ( 'Received signal data:' , data ) ;
143+ console . log ( 'Received signal data' ) ;
133144
134145 if ( data . type === 'offer' && ! peerRef . current ) {
135146 try {
@@ -195,6 +206,28 @@ const AudioSharing = () => {
195206 }
196207 } ;
197208
209+ // Cleanup effect when component unmounts
210+ useEffect ( ( ) => {
211+ // Cleanup function that will run when component unmounts
212+ return ( ) => {
213+ console . log ( 'AudioSharing component unmounting, cleaning up...' ) ;
214+ cleanupAudio ( ) ;
215+ } ;
216+ } , [ ] ) ;
217+
218+ // Add window unload handler to ensure cleanup even when page closes
219+ useEffect ( ( ) => {
220+ const handleUnload = ( ) => {
221+ cleanupAudio ( ) ;
222+ } ;
223+
224+ window . addEventListener ( 'beforeunload' , handleUnload ) ;
225+
226+ return ( ) => {
227+ window . removeEventListener ( 'beforeunload' , handleUnload ) ;
228+ } ;
229+ } , [ ] ) ;
230+
198231 return (
199232 < div className = "flex items-center gap-4" >
200233 < button
0 commit comments