cleanup and using unmount function to keep it clean

This commit is contained in:
talksik
2022-06-19 10:28:37 -05:00
parent aba1ba3d87
commit edbe7b62c0
@@ -22,7 +22,7 @@ import {
getConversationById, getConversationById,
getConversations, getConversations,
} from '../api/NirvanaApi'; } from '../api/NirvanaApi';
import { useAsyncFn, useEffectOnce } from 'react-use'; import { useAsyncFn, useEffectOnce, useUnmount } from 'react-use';
import CreateConversationRequest from '@nirvana/core/requests/CreateConversationRequest.request'; import CreateConversationRequest from '@nirvana/core/requests/CreateConversationRequest.request';
import Peer from 'simple-peer'; import Peer from 'simple-peer';
@@ -431,132 +431,123 @@ function Room({
const { user } = useAuth(); const { user } = useAuth();
const { $ws } = useSockets(); const { $ws } = useSockets();
const [userLocalStream, setUserLocalStream] = useState<MediaStream>();
// have internal state to manage details of this "room" // have internal state to manage details of this "room"
// ============== STREAMING =============== // ============== STREAMING ===============
// handle incoming calls and accept calls and create objects for them // handle incoming calls and accept calls and create objects for them
useEffectOnce(() => { useEffectOnce(() => {
const localPeersForRoom: Peer[] = []; (async () => {
// ?will there be race condition where this room component is rendered but we don't have the latest
// ?list of tunedin folks and so we may just end up calling select few?
// ?in this case, start with initiating event to get all people in room first
if (conversation.tunedInUsers && conversation.tunedInUsers.length > 1) {
// going ahead and calling all of the other folks
const allOtherUserIds = conversation.tunedInUsers.filter(
(memberUserId) => memberUserId !== user._id.toString(),
);
toast.success('calling bunch of people');
// TODO : bring this stream object higher and add this later to the room // TODO : bring this stream object higher and add this later to the room
navigator.mediaDevices // set up local stream for this room - temporary until we figure out global stream handling and passing down
.getUserMedia({ video: videoConstraints, audio: true }) const localMediaStream = await navigator.mediaDevices.getUserMedia({
.then((localMediaStream: MediaStream) => { video: videoConstraints,
// for each person, create peer object audio: true,
allOtherUserIds.forEach((otherUserId) => { });
const connectingToast = toast.loading('calling peer for a snappy experience');
// ========= PEER CREATION ============= setUserLocalStream(localMediaStream);
// make sure this peer gets destroyed when it's time to remove this listener
const localPeerConnection = new Peer({ // ?will there be race condition where this room component is rendered but we don't have the latest
initiator: true, // ?list of tunedin folks and so we may just end up calling select few?
stream: localMediaStream, // ?in this case, start with initiating event to get all people in room first
trickle: true, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times,
config: { if (conversation.tunedInUsers && conversation.tunedInUsers.length > 1) {
iceServers, // going ahead and calling all of the other folks
}, const allOtherUserIds = conversation.tunedInUsers.filter(
(memberUserId) => memberUserId !== user._id.toString(),
);
toast.success('calling bunch of people');
setUserLocalStream(localMediaStream);
// for each person, create peer object
allOtherUserIds.forEach((otherUserId) => {
const connectingToast = toast.loading('calling peer for a snappy experience');
// ========= PEER CREATION =============
// make sure this peer gets destroyed when it's time to remove this listener
const localPeerConnection = new Peer({
initiator: true,
stream: localMediaStream,
trickle: true, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times,
config: {
iceServers,
},
});
// ========= PEER EVENT HANDLERS =============
localPeerConnection.on('signal', (signal) => {
console.log('have a signal to make call to someone ');
$ws.emit(
ServerRequestChannels.RTC_CALL_SOMEONE_FOR_LINE,
new RtcCallRequest(otherUserId, conversation._id.toString(), signal),
);
toast.dismiss(connectingToast);
// notifying globally that we are in the process now
setConversationMap((draft) => {
if (draft[conversation._id.toString()]) {
draft[conversation._id.toString()].room = {
...(draft[conversation._id.toString()].room ?? {}),
[otherUserId]: { peer: localPeerConnection, isConnecting: true },
};
}
}); });
});
// ========= PEER EVENT HANDLERS ============= localPeerConnection.on('stream', (remoteStream: MediaStream) => {
localPeerConnection.on('signal', (signal) => { // globally updating conversation so that other views can render what they want
console.log('have a signal to make call to someone '); toast.success('got stream from remote, going to add to our ');
$ws.emit( setConversationMap((draft) => {
ServerRequestChannels.RTC_CALL_SOMEONE_FOR_LINE, if (draft[conversation._id.toString()].room[otherUserId]) {
new RtcCallRequest(otherUserId, conversation._id.toString(), signal), draft[conversation._id.toString()].room[otherUserId].stream = remoteStream;
); remoteStream.getTracks().forEach((track) => {
// TODO: add particular track to right place
toast.dismiss(connectingToast); });
}
// notifying globally that we are in the process now
setConversationMap((draft) => {
if (draft[conversation._id.toString()]) {
draft[conversation._id.toString()].room = {
...(draft[conversation._id.toString()].room ?? {}),
[otherUserId]: { peer: localPeerConnection, isConnecting: true },
};
}
});
}); });
});
localPeerConnection.on('stream', (remoteStream: MediaStream) => { localPeerConnection.on('connect', () => {
// globally updating conversation so that other views can render what they want toast.success('successfully connected to another peer');
toast.success('got stream from remote, going to add to our '); setConversationMap((draft) => {
if (draft[conversation._id.toString()].room[otherUserId]) {
setConversationMap((draft) => { draft[conversation._id.toString()].room[otherUserId].isConnecting = false;
if (draft[conversation._id.toString()].room[otherUserId]) { }
draft[conversation._id.toString()].room[otherUserId].stream = remoteStream;
remoteStream.getTracks().forEach((track) => {
// TODO: add particular track to right place
});
}
});
}); });
});
localPeerConnection.on('connect', () => { localPeerConnection.on('track', (track, stream) => {
toast.success('successfully connected to another peer'); // TODO: add to room contents
setConversationMap((draft) => {
if (draft[conversation._id.toString()].room[otherUserId]) {
draft[conversation._id.toString()].room[otherUserId].isConnecting = false;
}
});
});
localPeerConnection.on('track', (track, stream) => { toast('a peer added a track to a stream');
// TODO: add to room contents });
toast('a peer added a track to a stream'); localPeerConnection.on('close', () => {
}); // the person will be removed from the tuned in list, but the connections here are decoupled from that flow
// we want to manage the room within the master conversation and remove it for ourselves
localPeerConnection.on('close', () => { // TODO: update the map to remove the user and all contribution contens
// the person will be removed from the tuned in list, but the connections here are decoupled from that flow
// we want to manage the room within the master conversation and remove it for ourselves
// TODO: update the map to remove the user and all contribution contens toast.error('peer connection was closed');
});
toast.error('peer connection was closed'); localPeerConnection.on('error', (err) => {
}); console.error(err);
toast.error('there was a problem with the peer connection');
localPeerConnection.on('error', (err) => {
console.error(err);
toast.error('there was a problem with the peer connection');
});
localPeersForRoom.push(localPeerConnection);
}); });
}); });
}
return () => { })();
// go through all peer connections and destroy them
// remove all room contents as well
localPeersForRoom.forEach((peerConnection) => {
peerConnection.destroy();
});
};
}
// ======= LISTEN FOR INCOMING CALLS AND ACCEPT THEM
return () => {
localPeersForRoom.forEach((peerToClose) => peerToClose.destroy());
};
}); });
useEffectOnce(() => { // ======= LISTEN FOR INCOMING CALLS AND RETURN SIGNALS AND ACCEPT THEM
const localNewbiesForRoom: Peer[] = []; useEffect(() => {
const someoneJoinedChannelNameForRoom = `${ const someoneJoinedChannelNameForRoom = `${
ServerResponseChannels.RTC_NEW_USER_JOINED ServerResponseChannels.RTC_NEW_USER_JOINED
}:${conversation._id.toString()}`; }:${conversation._id.toString()}`;
@@ -570,6 +561,7 @@ function Room({
const peerForMeAndNewbie = new Peer({ const peerForMeAndNewbie = new Peer({
initiator: false, initiator: false,
stream: userLocalStream,
trickle: true, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times trickle: true, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times
config: { config: {
iceServers, iceServers,
@@ -638,8 +630,6 @@ function Room({
console.error(err); console.error(err);
toast.error('there was a problem with the peer connection'); toast.error('there was a problem with the peer connection');
}); });
localNewbiesForRoom.push(peerForMeAndNewbie);
}); });
$ws.on(mastersAnswerReceivedChannelNameForRoom, (res: RtcReceiveAnswerResponse) => { $ws.on(mastersAnswerReceivedChannelNameForRoom, (res: RtcReceiveAnswerResponse) => {
@@ -663,6 +653,20 @@ function Room({
}; };
}); });
// go through all of the peers and destroy and update conversation map
useUnmount(() => {
setConversationMap((draft) => {
if (draft[conversation._id.toString()].room) {
Object.values(draft[conversation._id.toString()].room).forEach((roomPeerContents) => {
roomPeerContents.peer.destroy();
toast('destroyed peer connection as I am leaving room');
});
}
delete draft[conversation._id.toString()].room;
});
});
// TODO: improved listener manager for each peer connection // TODO: improved listener manager for each peer connection
const setPeerListeners = useCallback( const setPeerListeners = useCallback(
(peer) => { (peer) => {