@@ -15,53 +15,61 @@ const AudioSharing = () => {
1515 const [ connectionStatus , setConnectionStatus ] = useState <
1616 'Not Connected' | 'Connecting' | 'Connected'
1717 > ( 'Not Connected' ) ;
18+
19+ // Use refs for persistent state across remounts
1820 const socketRef = useRef < Socket | null > ( null ) ;
1921 const peerRef = useRef < Instance | null > ( null ) ;
2022 const audioStreamRef = useRef < MediaStream | null > ( null ) ;
21- const initializedRef = useRef ( false ) ;
2223 const audioElementsRef = useRef < HTMLAudioElement [ ] > ( [ ] ) ;
24+ const mountCountRef = useRef ( 0 ) ;
25+ const lastCleanupTimeRef = useRef ( 0 ) ;
2326
27+ // Constants
28+ const CLEANUP_THRESHOLD = 1000 ; // Minimum time between cleanups in ms
2429 const SERVER_URL =
2530 process . env . NEXT_PUBLIC_AUDIO_SERVER_URL || 'http://localhost:5555' ;
26-
2731 const TURN_SERVER = process . env . NEXT_PUBLIC_TURN_SERVER || '' ;
2832 const TURN_USERNAME = process . env . NEXT_PUBLIC_TURN_USERNAME ;
2933 const TURN_CREDENTIAL = process . env . NEXT_PUBLIC_TURN_PASSWORD ;
3034
31- const cleanupAudio = ( ) => {
35+ const cleanupAudio = ( force = false ) => {
36+ const now = Date . now ( ) ;
37+
38+ // Prevent rapid cleanup unless forced
39+ if ( ! force && now - lastCleanupTimeRef . current < CLEANUP_THRESHOLD ) {
40+ console . log ( 'Skipping cleanup due to threshold' ) ;
41+ return ;
42+ }
43+
3244 console . log ( 'Cleaning up audio connections...' ) ;
45+ lastCleanupTimeRef . current = now ;
3346
34- // Stop and cleanup all audio tracks
3547 if ( audioStreamRef . current ) {
3648 audioStreamRef . current . getTracks ( ) . forEach ( ( track ) => {
3749 track . stop ( ) ;
3850 } ) ;
3951 audioStreamRef . current = null ;
4052 }
4153
42- // Destroy peer connection
4354 if ( peerRef . current ) {
4455 peerRef . current . destroy ( ) ;
4556 peerRef . current = null ;
4657 }
4758
48- // Disconnect socket
49- if ( socketRef . current ) {
59+ // Only disconnect socket if we're actually cleaning up (not remounting)
60+ if ( force && socketRef . current ) {
5061 socketRef . current . disconnect ( ) ;
5162 socketRef . current = null ;
5263 }
5364
54- // Stop and remove all audio elements
5565 audioElementsRef . current . forEach ( ( audio ) => {
5666 audio . pause ( ) ;
5767 audio . srcObject = null ;
5868 } ) ;
5969 audioElementsRef . current = [ ] ;
6070
61- // Reset states
6271 setIsAudioEnabled ( false ) ;
6372 setConnectionStatus ( 'Not Connected' ) ;
64- initializedRef . current = false ;
6573 } ;
6674
6775 const createPeer = ( stream : MediaStream , initiator : boolean ) => {
@@ -86,42 +94,45 @@ const AudioSharing = () => {
8694 } ) ;
8795
8896 peer . on ( 'signal' , ( data : SignalData ) => {
89- console . log ( 'Sending signal data' ) ;
9097 socketRef . current ?. emit ( 'signal' , data ) ;
9198 } ) ;
9299
93100 peer . on ( 'stream' , ( remoteStream : MediaStream ) => {
94101 console . log ( 'Received remote stream' ) ;
95102 const audio = new Audio ( ) ;
96103 audio . srcObject = remoteStream ;
97- audioElementsRef . current . push ( audio ) ; // Track audio element for cleanup
104+ audioElementsRef . current . push ( audio ) ;
98105 audio
99106 . play ( )
100107 . catch ( ( error ) => console . error ( 'Error playing audio:' , error ) ) ;
101108 } ) ;
102109
103110 peer . on ( 'error' , ( err : Error ) => {
104111 console . error ( 'Peer connection error:' , err ) ;
105- cleanupAudio ( ) ;
112+ cleanupAudio ( true ) ;
106113 } ) ;
107114
108115 peer . on ( 'close' , ( ) => {
109116 console . log ( 'Peer connection closed' ) ;
110- cleanupAudio ( ) ;
117+ cleanupAudio ( true ) ;
111118 } ) ;
112119
113120 peer . on ( 'connect' , ( ) => {
114- console . log ( 'Peer connection established successfully ' ) ;
121+ console . log ( 'Peer connection established' ) ;
115122 setConnectionStatus ( 'Connected' ) ;
116123 } ) ;
117124
118125 return peer ;
119126 } ;
120127
121128 const initializeSocketAndPeer = ( ) => {
122- if ( initializedRef . current ) return ;
123- initializedRef . current = true ;
129+ // If socket exists and is connected, reuse it
130+ if ( socketRef . current ?. connected ) {
131+ console . log ( 'Reusing existing socket connection' ) ;
132+ return ;
133+ }
124134
135+ console . log ( 'Initializing new socket connection' ) ;
125136 socketRef . current = io ( SERVER_URL , {
126137 transports : [ 'websocket' ] ,
127138 path : '/socket.io/' ,
@@ -136,12 +147,10 @@ const AudioSharing = () => {
136147
137148 socketRef . current . on ( 'connect_error' , ( error : Error ) => {
138149 console . error ( 'Connection error:' , error ) ;
139- cleanupAudio ( ) ;
150+ cleanupAudio ( true ) ;
140151 } ) ;
141152
142153 socketRef . current . on ( 'signal' , async ( data : SignalData ) => {
143- console . log ( 'Received signal data' ) ;
144-
145154 if ( data . type === 'offer' && ! peerRef . current ) {
146155 try {
147156 const stream = await navigator . mediaDevices . getUserMedia ( {
@@ -158,7 +167,7 @@ const AudioSharing = () => {
158167 peerRef . current = createPeer ( stream , false ) ;
159168 } catch ( error ) {
160169 console . error ( 'Error accessing audio devices:' , error ) ;
161- cleanupAudio ( ) ;
170+ cleanupAudio ( true ) ;
162171 }
163172 }
164173
@@ -167,7 +176,7 @@ const AudioSharing = () => {
167176 peerRef . current . signal ( data as SimplePeer . SignalData ) ;
168177 } catch ( error ) {
169178 console . error ( 'Error signaling peer:' , error ) ;
170- cleanupAudio ( ) ;
179+ cleanupAudio ( true ) ;
171180 }
172181 }
173182 } ) ;
@@ -202,27 +211,34 @@ const AudioSharing = () => {
202211 }
203212 } catch ( error ) {
204213 console . error ( 'Error toggling audio:' , error ) ;
205- cleanupAudio ( ) ;
214+ cleanupAudio ( true ) ;
206215 }
207216 } ;
208217
209- // Cleanup effect when component unmounts
218+ // Mount/unmount handling
210219 useEffect ( ( ) => {
211- // Cleanup function that will run when component unmounts
220+ mountCountRef . current ++ ;
221+ console . log ( `Component mounted (count: ${ mountCountRef . current } )` ) ;
222+
223+ // Only do full cleanup when actually leaving the page
212224 return ( ) => {
213- console . log ( 'AudioSharing component unmounting, cleaning up...' ) ;
214- cleanupAudio ( ) ;
225+ mountCountRef . current -- ;
226+ console . log ( `Component unmounting (count: ${ mountCountRef . current } )` ) ;
227+
228+ // If this is the last mount point, do a full cleanup
229+ if ( mountCountRef . current === 0 ) {
230+ cleanupAudio ( true ) ;
231+ }
215232 } ;
216233 } , [ ] ) ;
217234
218- // Add window unload handler to ensure cleanup even when page closes
235+ // Handle page unload
219236 useEffect ( ( ) => {
220237 const handleUnload = ( ) => {
221- cleanupAudio ( ) ;
238+ cleanupAudio ( true ) ;
222239 } ;
223240
224241 window . addEventListener ( 'beforeunload' , handleUnload ) ;
225-
226242 return ( ) => {
227243 window . removeEventListener ( 'beforeunload' , handleUnload ) ;
228244 } ;
0 commit comments