Skip to content

Commit 672cb55

Browse files
authored
Merge pull request #195 from CS3219-AY2425S1/fix/cleanup_features
Fix/cleanup features
2 parents 708283b + 44ec91a commit 672cb55

File tree

1 file changed

+77
-28
lines changed

1 file changed

+77
-28
lines changed

peerprep-fe/src/app/collaboration/components/AudioSharing.tsx

Lines changed: 77 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import React, { useRef, useState } from 'react';
3+
import React, { useRef, useState, useEffect } from 'react';
44
import io, { Socket } from 'socket.io-client';
55
import SimplePeer, { Instance } from 'simple-peer';
66
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -15,38 +15,59 @@ 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);
23+
const audioElementsRef = useRef<HTMLAudioElement[]>([]);
24+
const mountCountRef = useRef(0);
25+
const lastCleanupTimeRef = useRef(0);
2226

27+
// Constants
28+
const CLEANUP_THRESHOLD = 1000; // Minimum time between cleanups in ms
2329
const SERVER_URL =
2430
process.env.NEXT_PUBLIC_AUDIO_SERVER_URL || 'http://localhost:5555';
25-
26-
// Add TURN server credentials from environment variables
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-
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-
}
39-
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+
44+
console.log('Cleaning up audio connections...');
45+
lastCleanupTimeRef.current = now;
46+
4047
if (audioStreamRef.current) {
4148
audioStreamRef.current.getTracks().forEach((track) => {
4249
track.stop();
4350
});
4451
audioStreamRef.current = null;
4552
}
53+
4654
if (peerRef.current) {
4755
peerRef.current.destroy();
4856
peerRef.current = null;
4957
}
58+
59+
// Only disconnect socket if we're actually cleaning up (not remounting)
60+
if (force && socketRef.current) {
61+
socketRef.current.disconnect();
62+
socketRef.current = null;
63+
}
64+
65+
audioElementsRef.current.forEach((audio) => {
66+
audio.pause();
67+
audio.srcObject = null;
68+
});
69+
audioElementsRef.current = [];
70+
5071
setIsAudioEnabled(false);
5172
setConnectionStatus('Not Connected');
5273
};
@@ -61,10 +82,8 @@ const AudioSharing = () => {
6182
trickle: false,
6283
config: {
6384
iceServers: [
64-
// Maintain existing STUN servers
6585
{ urls: 'stun:stun.l.google.com:19302' },
6686
{ urls: 'stun:global.stun.twilio.com:3478' },
67-
// Add TURN server configuration
6887
{
6988
urls: TURN_SERVER,
7089
username: TURN_USERNAME,
@@ -75,42 +94,45 @@ const AudioSharing = () => {
7594
});
7695

7796
peer.on('signal', (data: SignalData) => {
78-
console.log('Sending signal data:', data);
7997
socketRef.current?.emit('signal', data);
8098
});
8199

82100
peer.on('stream', (remoteStream: MediaStream) => {
83101
console.log('Received remote stream');
84102
const audio = new Audio();
85103
audio.srcObject = remoteStream;
104+
audioElementsRef.current.push(audio);
86105
audio
87106
.play()
88107
.catch((error) => console.error('Error playing audio:', error));
89108
});
90109

91110
peer.on('error', (err: Error) => {
92111
console.error('Peer connection error:', err);
93-
cleanupAudio();
112+
cleanupAudio(true);
94113
});
95114

96115
peer.on('close', () => {
97116
console.log('Peer connection closed');
98-
cleanupAudio();
117+
cleanupAudio(true);
99118
});
100119

101-
// Add connection state logging
102120
peer.on('connect', () => {
103-
console.log('Peer connection established successfully');
121+
console.log('Peer connection established');
104122
setConnectionStatus('Connected');
105123
});
106124

107125
return peer;
108126
};
109127

110128
const initializeSocketAndPeer = () => {
111-
if (initializedRef.current) return;
112-
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+
}
113134

135+
console.log('Initializing new socket connection');
114136
socketRef.current = io(SERVER_URL, {
115137
transports: ['websocket'],
116138
path: '/socket.io/',
@@ -125,12 +147,10 @@ const AudioSharing = () => {
125147

126148
socketRef.current.on('connect_error', (error: Error) => {
127149
console.error('Connection error:', error);
128-
cleanupAudio();
150+
cleanupAudio(true);
129151
});
130152

131153
socketRef.current.on('signal', async (data: SignalData) => {
132-
console.log('Received signal data:', data);
133-
134154
if (data.type === 'offer' && !peerRef.current) {
135155
try {
136156
const stream = await navigator.mediaDevices.getUserMedia({
@@ -147,7 +167,7 @@ const AudioSharing = () => {
147167
peerRef.current = createPeer(stream, false);
148168
} catch (error) {
149169
console.error('Error accessing audio devices:', error);
150-
cleanupAudio();
170+
cleanupAudio(true);
151171
}
152172
}
153173

@@ -156,7 +176,7 @@ const AudioSharing = () => {
156176
peerRef.current.signal(data as SimplePeer.SignalData);
157177
} catch (error) {
158178
console.error('Error signaling peer:', error);
159-
cleanupAudio();
179+
cleanupAudio(true);
160180
}
161181
}
162182
});
@@ -191,10 +211,39 @@ const AudioSharing = () => {
191211
}
192212
} catch (error) {
193213
console.error('Error toggling audio:', error);
194-
cleanupAudio();
214+
cleanupAudio(true);
195215
}
196216
};
197217

218+
// Mount/unmount handling
219+
useEffect(() => {
220+
mountCountRef.current++;
221+
console.log(`Component mounted (count: ${mountCountRef.current})`);
222+
223+
// Only do full cleanup when actually leaving the page
224+
return () => {
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+
}
232+
};
233+
}, []);
234+
235+
// Handle page unload
236+
useEffect(() => {
237+
const handleUnload = () => {
238+
cleanupAudio(true);
239+
};
240+
241+
window.addEventListener('beforeunload', handleUnload);
242+
return () => {
243+
window.removeEventListener('beforeunload', handleUnload);
244+
};
245+
}, []);
246+
198247
return (
199248
<div className="flex items-center gap-4">
200249
<button

0 commit comments

Comments
 (0)