Skip to content

Commit af19462

Browse files
committed
Fix Audio Sharing cleanup
1 parent cd9a101 commit af19462

File tree

1 file changed

+46
-30
lines changed

1 file changed

+46
-30
lines changed

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

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)